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",