From 5dc42122a80aea3bddba1fb0a681ec522e1adf50 Mon Sep 17 00:00:00 2001 From: Josh Perez <60019601+josh-signal@users.noreply.github.com> Date: Thu, 4 Aug 2022 21:29:44 -0400 Subject: [PATCH] Use for group story replies --- stylesheets/components/StoryViewer.scss | 1 - .../components/StoryViewsNRepliesModal.scss | 3 +- .../StoryViewsNRepliesModal.stories.tsx | 42 ++++- ts/components/StoryViewsNRepliesModal.tsx | 153 +++++++++++------- ts/components/conversation/Message.tsx | 2 +- ts/state/selectors/stories.ts | 11 +- ts/types/Stories.ts | 28 ++-- ts/util/lint/exceptions.json | 7 + 8 files changed, 169 insertions(+), 78 deletions(-) diff --git a/stylesheets/components/StoryViewer.scss b/stylesheets/components/StoryViewer.scss index b6da2b2d4014..204828bedef5 100644 --- a/stylesheets/components/StoryViewer.scss +++ b/stylesheets/components/StoryViewer.scss @@ -34,7 +34,6 @@ @include color-svg('../images/icons/v2/x-24.svg', $color-gray-15); } right: 28px; - top: 0; z-index: $z-index-above-above-base; } diff --git a/stylesheets/components/StoryViewsNRepliesModal.scss b/stylesheets/components/StoryViewsNRepliesModal.scss index 38ea5251c4f0..7d7d70c3c46f 100644 --- a/stylesheets/components/StoryViewsNRepliesModal.scss +++ b/stylesheets/components/StoryViewsNRepliesModal.scss @@ -13,6 +13,7 @@ &__replies { flex: 1; + margin: 0 -16px; max-height: 75vh; overflow-y: overlay; @@ -127,7 +128,7 @@ align-items: center; display: flex; justify-content: space-between; - padding: 12px 0; + padding: 12px 16px; &--container { display: flex; diff --git a/ts/components/StoryViewsNRepliesModal.stories.tsx b/ts/components/StoryViewsNRepliesModal.stories.tsx index 3c6583537c56..aab6825001b4 100644 --- a/ts/components/StoryViewsNRepliesModal.stories.tsx +++ b/ts/components/StoryViewsNRepliesModal.stories.tsx @@ -10,6 +10,7 @@ import enMessages from '../../_locales/en/messages.json'; import { IMAGE_JPEG } from '../types/MIME'; import { SendStatus } from '../messages/MessageSendState'; import { StoryViewsNRepliesModal } from './StoryViewsNRepliesModal'; +import { UUID } from '../types/UUID'; import { fakeAttachment } from '../test-both/helpers/fakeAttachment'; import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation'; import { setupI18n } from '../util/setupI18n'; @@ -69,6 +70,9 @@ function getViewsAndReplies() { const p3 = getDefaultConversation(); const p4 = getDefaultConversation(); const p5 = getDefaultConversation(); + const p6 = getDefaultConversation({ + isMe: true, + }); const views = [ { @@ -100,20 +104,52 @@ function getViewsAndReplies() { const replies = [ { - ...p2, + author: p2, body: 'So cute ❤️', + conversationId: p2.id, + id: UUID.generate().toString(), timestamp: Date.now() - 24 * durations.MINUTE, }, { - ...p3, + author: p3, body: "That's awesome", + conversationId: p3.id, + id: UUID.generate().toString(), timestamp: Date.now() - 13 * durations.MINUTE, }, { - ...p4, + author: p3, + body: 'Very awesome', + conversationId: p3.id, + id: UUID.generate().toString(), + timestamp: Date.now() - 13 * durations.MINUTE, + }, + { + author: p3, + body: 'Did I mention how awesome this is?', + conversationId: p3.id, + id: UUID.generate().toString(), + timestamp: Date.now() - 12 * durations.MINUTE, + }, + { + author: p4, + conversationId: p4.id, + id: UUID.generate().toString(), reactionEmoji: '❤️', timestamp: Date.now() - 5 * durations.MINUTE, }, + { + author: p6, + body: 'Thanks everyone!', + conversationId: p6.id, + id: UUID.generate().toString(), + sendStateByConversationId: { + [p1.id]: { + status: SendStatus.Pending, + }, + }, + timestamp: Date.now(), + }, ]; return { diff --git a/ts/components/StoryViewsNRepliesModal.tsx b/ts/components/StoryViewsNRepliesModal.tsx index bcdff61f3665..66294c308593 100644 --- a/ts/components/StoryViewsNRepliesModal.tsx +++ b/ts/components/StoryViewsNRepliesModal.tsx @@ -16,7 +16,7 @@ import { CompositionInput } from './CompositionInput'; import { ContactName } from './conversation/ContactName'; import { EmojiButton } from './emoji/EmojiButton'; import { Emojify } from './conversation/Emojify'; -import { MessageBody } from './conversation/MessageBody'; +import { Message, TextDirection } from './conversation/Message'; import { MessageTimestamp } from './conversation/MessageTimestamp'; import { Modal } from './Modal'; import { Quote } from './conversation/Quote'; @@ -24,8 +24,58 @@ import { ReactionPicker } from './conversation/ReactionPicker'; import { Tabs } from './Tabs'; import { Theme } from '../util/theme'; import { ThemeType } from '../types/Util'; +import { WidthBreakpoint } from './_util'; import { getAvatarColor } from '../types/Colors'; import { getStoryReplyText } from '../util/getStoryReplyText'; +import { shouldNeverBeCalled } from '../util/shouldNeverBeCalled'; + +// Menu is disabled so these actions are inaccessible. We also don't support +// link previews, tap to view messages, attachments, or gifts. Just regular +// text messages and reactions. +const MESSAGE_DEFAULT_PROPS = { + canDeleteForEveryone: false, + canDownload: false, + canReact: false, + canReply: false, + canRetry: false, + canRetryDeleteForEveryone: false, + checkForAccount: shouldNeverBeCalled, + clearSelectedMessage: shouldNeverBeCalled, + containerWidthBreakpoint: WidthBreakpoint.Medium, + deleteMessage: shouldNeverBeCalled, + deleteMessageForEveryone: shouldNeverBeCalled, + displayTapToViewMessage: shouldNeverBeCalled, + doubleCheckMissingQuoteReference: shouldNeverBeCalled, + downloadAttachment: shouldNeverBeCalled, + isBlocked: false, + isMessageRequestAccepted: true, + kickOffAttachmentDownload: shouldNeverBeCalled, + markAttachmentAsCorrupted: shouldNeverBeCalled, + markViewed: shouldNeverBeCalled, + messageExpanded: shouldNeverBeCalled, + openConversation: shouldNeverBeCalled, + openGiftBadge: shouldNeverBeCalled, + openLink: shouldNeverBeCalled, + previews: [], + reactToMessage: shouldNeverBeCalled, + renderAudioAttachment: () =>
, + renderEmojiPicker: () =>
, + renderReactionPicker: () =>
, + replyToMessage: shouldNeverBeCalled, + retryDeleteForEveryone: shouldNeverBeCalled, + retrySend: shouldNeverBeCalled, + scrollToQuotedMessage: shouldNeverBeCalled, + showContactDetail: shouldNeverBeCalled, + showContactModal: shouldNeverBeCalled, + showExpiredIncomingTapToViewToast: shouldNeverBeCalled, + showExpiredOutgoingTapToViewToast: shouldNeverBeCalled, + showForwardMessageModal: shouldNeverBeCalled, + showMessageDetail: shouldNeverBeCalled, + showVisualAttachment: shouldNeverBeCalled, + startConversation: shouldNeverBeCalled, + theme: ThemeType.dark, + viewStory: shouldNeverBeCalled, +}; enum Tab { Replies = 'Replies', @@ -79,6 +129,7 @@ export const StoryViewsNRepliesModal = ({ storyPreviewAttachment, views, }: PropsType): JSX.Element | null => { + const containerElementRef = useRef(null); const inputApiRef = useRef(); const [bottom, setBottom] = useState(null); const [messageBodyText, setMessageBodyText] = useState(''); @@ -211,30 +262,34 @@ export const StoryViewsNRepliesModal = ({ if (replies.length) { repliesElement = ( -
- {replies.map(reply => +
+ {replies.map((reply, index) => reply.reactionEmoji ? (
{i18n('StoryViewsNRepliesModal__reacted')} @@ -249,54 +304,34 @@ export const StoryViewsNRepliesModal = ({
) : ( -
- + -
-
- -
- - - - -
) )} diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index ea55530d68ba..2c5d03c56319 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -263,7 +263,7 @@ export type PropsData = { isTapToViewExpired?: boolean; isTapToViewError?: boolean; - readStatus: ReadStatus; + readStatus?: ReadStatus; expirationLength?: number; expirationTimestamp?: number; diff --git a/ts/state/selectors/stories.ts b/ts/state/selectors/stories.ts index 48192b4acdfa..9235e108e962 100644 --- a/ts/state/selectors/stories.ts +++ b/ts/state/selectors/stories.ts @@ -80,8 +80,10 @@ function getAvatarData( ConversationType, | 'acceptedMessageRequest' | 'avatarPath' + | 'badges' | 'color' | 'isMe' + | 'id' | 'name' | 'profileName' | 'sharedGroupNames' @@ -90,8 +92,10 @@ function getAvatarData( return pick(conversation, [ 'acceptedMessageRequest', 'avatarPath', + 'badges', 'color', 'isMe', + 'id', 'name', 'profileName', 'sharedGroupNames', @@ -212,11 +216,12 @@ export const getStoryReplies = createSelector( const conversation = conversationSelector(reaction.fromId); return { - ...getAvatarData(conversation), + author: getAvatarData(conversation), contactNameColor: contactNameColorSelector( foundStory.conversationId, conversation.id ), + conversationId: reaction.fromId, id: getReactionUniqueId(reaction), reactionEmoji: reaction.emoji, timestamp: reaction.timestamp, @@ -231,12 +236,14 @@ export const getStoryReplies = createSelector( : conversationSelector(reply.sourceUuid || reply.source); return { - ...getAvatarData(conversation), + author: getAvatarData(conversation), ...pick(reply, ['body', 'deletedForEveryone', 'id', 'timestamp']), contactNameColor: contactNameColorSelector( reply.conversationId, conversation.id ), + conversationId: conversation.id, + readStatus: reply.readStatus, }; }); diff --git a/ts/types/Stories.ts b/ts/types/Stories.ts index 5ec3e7e37e5c..7f35aa0fc9e6 100644 --- a/ts/types/Stories.ts +++ b/ts/types/Stories.ts @@ -5,25 +5,31 @@ import type { AttachmentType } from './Attachment'; import type { ContactNameColorType } from './Colors'; import type { ConversationType } from '../state/ducks/conversations'; import type { LocalizerType } from './Util'; +import type { ReadStatus } from '../messages/MessageReadStatus'; import type { SendStatus } from '../messages/MessageSendState'; import type { StoryDistributionListDataType } from '../state/ducks/storyDistributionLists'; -export type ReplyType = Pick< - ConversationType, - | 'acceptedMessageRequest' - | 'avatarPath' - | 'color' - | 'isMe' - | 'name' - | 'profileName' - | 'sharedGroupNames' - | 'title' -> & { +export type ReplyType = { + author: Pick< + ConversationType, + | 'acceptedMessageRequest' + | 'avatarPath' + | 'badges' + | 'color' + | 'id' + | 'isMe' + | 'name' + | 'profileName' + | 'sharedGroupNames' + | 'title' + >; body?: string; contactNameColor?: ContactNameColorType; + conversationId: string; deletedForEveryone?: boolean; id: string; reactionEmoji?: string; + readStatus?: ReadStatus; timestamp: number; }; diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index e1b405ab22e5..154316911fbd 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -9231,6 +9231,13 @@ "reasonCategory": "usageTrusted", "updated": "2022-02-15T17:57:06.507Z" }, + { + "rule": "React-useRef", + "path": "ts/components/StoryViewsNRepliesModal.tsx", + "line": " const containerElementRef = useRef(null);", + "reasonCategory": "usageTrusted", + "updated": "2022-08-04T00:52:01.080Z" + }, { "rule": "React-useRef", "path": "ts/components/TextAttachment.tsx",