Skip to content

Commit 1727b18

Browse files
committed
Implement GroupChannel thread.
1 parent 14c23fb commit 1727b18

File tree

48 files changed

+3392
-70
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+3392
-70
lines changed
458 Bytes
Loading
756 Bytes
Loading
1.06 KB
Loading

packages/uikit-react-native-foundation/src/assets/icon/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ const IconAssets = {
6464
'streaming': require('./icon-streaming.png'),
6565
'supergroup': require('./icon-supergroup.png'),
6666
'theme': require('./icon-theme.png'),
67+
'thread': require('./icon-thread.png'),
6768
'thumbnail-none': require('./icon-thumbnail-none.png'),
6869
'unarchive': require('./icon-unarchive.png'),
6970
'user': require('./icon-user.png'),

packages/uikit-react-native-foundation/src/ui/GroupChannelMessage/MessageContainer.tsx

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const MessageContainer = (props: Props) => {
2323

2424
MessageContainer.Incoming = function MessageContainerIncoming({
2525
children,
26+
replyInfo,
2627
groupedWithNext,
2728
groupedWithPrev,
2829
message,
@@ -34,43 +35,48 @@ MessageContainer.Incoming = function MessageContainerIncoming({
3435
const color = colors.ui.groupChannelMessage.incoming;
3536

3637
return (
37-
<Box flexDirection={'row'} justifyContent={'flex-start'} alignItems={'flex-end'}>
38-
<Box width={26} marginRight={12}>
39-
{(message.isFileMessage() || message.isUserMessage()) && !groupedWithNext && (
40-
<Pressable onPress={onPressAvatar}>
41-
<Avatar size={26} uri={message.sender?.profileUrl} />
42-
</Pressable>
43-
)}
44-
</Box>
45-
<Box flexShrink={1}>
46-
{parentMessage}
47-
{!groupedWithPrev && !message.parentMessage && (
48-
<Box marginLeft={12} marginBottom={4}>
49-
{(message.isFileMessage() || message.isUserMessage()) && (
50-
<Text caption1 color={color.enabled.textSenderName} numberOfLines={1}>
51-
{strings?.senderName ?? message.sender.nickname}
52-
</Text>
53-
)}
54-
</Box>
55-
)}
56-
57-
<Box flexDirection={'row'} alignItems={'flex-end'}>
58-
<Box style={styles.bubble}>{children}</Box>
59-
{!groupedWithNext && (
60-
<Box marginLeft={4}>
61-
<Text caption4 color={color.enabled.textTime}>
62-
{strings?.sentDate ?? getMessageTimeFormat(new Date(message.createdAt))}
63-
</Text>
38+
<Box flexDirection={'column'} justifyContent={'flex-start'} alignItems={'flex-start'}>
39+
<Box flexDirection={'row'} justifyContent={'flex-start'} alignItems={'flex-end'}>
40+
<Box width={26} marginRight={12}>
41+
{(message.isFileMessage() || message.isUserMessage()) && !groupedWithNext && (
42+
<Pressable onPress={onPressAvatar}>
43+
<Avatar size={26} uri={message.sender?.profileUrl} />
44+
</Pressable>
45+
)}
46+
</Box>
47+
<Box flexShrink={1}>
48+
{parentMessage}
49+
{!groupedWithPrev && !message.parentMessage && (
50+
<Box marginLeft={12} marginBottom={4}>
51+
{(message.isFileMessage() || message.isUserMessage()) && (
52+
<Text caption1 color={color.enabled.textSenderName} numberOfLines={1}>
53+
{strings?.senderName ?? message.sender.nickname}
54+
</Text>
55+
)}
6456
</Box>
6557
)}
58+
<Box flexDirection={'row'} alignItems={'flex-end'}>
59+
<Box style={styles.bubble}>{children}</Box>
60+
{!groupedWithNext && (
61+
<Box marginLeft={4}>
62+
<Text caption4 color={color.enabled.textTime}>
63+
{strings?.sentDate ?? getMessageTimeFormat(new Date(message.createdAt))}
64+
</Text>
65+
</Box>
66+
)}
67+
</Box>
6668
</Box>
6769
</Box>
70+
<Box marginLeft={40} marginTop={4} flexDirection={'row'} height={20}>
71+
{replyInfo}
72+
</Box>
6873
</Box>
6974
);
7075
};
7176

7277
MessageContainer.Outgoing = function MessageContainerOutgoing({
7378
children,
79+
replyInfo,
7480
message,
7581
groupedWithNext,
7682
strings,
@@ -96,6 +102,9 @@ MessageContainer.Outgoing = function MessageContainerOutgoing({
96102
</Box>
97103
<Box style={styles.bubble}>{children}</Box>
98104
</Box>
105+
<Box marginTop={4} flexDirection={'row-reverse'} height={20}>
106+
{replyInfo}
107+
</Box>
99108
</Box>
100109
);
101110
};

packages/uikit-react-native-foundation/src/ui/GroupChannelMessage/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export type GroupChannelMessageProps<T extends SendbirdMessage, AdditionalProps
2828
children?: React.ReactNode;
2929
sendingStatus?: React.ReactNode;
3030
parentMessage?: React.ReactNode;
31+
replyInfo?: React.ReactNode;
3132

3233
groupedWithPrev: boolean;
3334
groupedWithNext: boolean;

packages/uikit-react-native/src/components/ChannelInput/SendInput.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
5353
channel,
5454
messageToReply,
5555
setMessageToReply,
56+
messageToThread,
5657
},
5758
ref,
5859
) {
@@ -68,16 +69,21 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
6869
visible: voiceMessageInputVisible,
6970
setVisible: setVoiceMessageInputVisible,
7071
} = useDeferredModalState();
71-
72+
7273
const messageReplyParams = useIIFE(() => {
7374
const { groupChannel } = sbOptions.uikit;
74-
if (!channel.isGroupChannel() || groupChannel.channel.replyType === 'none' || !messageToReply) return {};
75+
if (!channel.isGroupChannel() || groupChannel.channel.replyType === 'none'
76+
|| (groupChannel.channel.replyType === 'quote_reply' && !messageToReply)
77+
|| (groupChannel.channel.replyType === 'thread' && !messageToThread)) {
78+
return {};
79+
}
80+
7581
return {
76-
parentMessageId: messageToReply.messageId,
82+
parentMessageId: messageToReply?.messageId ?? messageToThread?.messageId,
7783
isReplyToChannel: true,
7884
};
7985
});
80-
86+
8187
const messageMentionParams = useIIFE(() => {
8288
const { groupChannel } = sbOptions.uikit;
8389
if (!channel.isGroupChannel() || !groupChannel.channel.enableMention) return {};
@@ -152,6 +158,7 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
152158
if (inputFrozen) return STRINGS.LABELS.CHANNEL_INPUT_PLACEHOLDER_DISABLED;
153159
if (inputDisabled) return STRINGS.LABELS.CHANNEL_INPUT_PLACEHOLDER_DISABLED;
154160
if (messageToReply) return STRINGS.LABELS.CHANNEL_INPUT_PLACEHOLDER_REPLY;
161+
if (messageToThread) return STRINGS.LABELS.CHANNEL_INPUT_PLACEHOLDER_THREAD;
155162

156163
return STRINGS.LABELS.CHANNEL_INPUT_PLACEHOLDER_ACTIVE;
157164
};

packages/uikit-react-native/src/components/ChannelInput/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export type ChannelInputProps = {
6565
// reply - only available on group channel
6666
messageToReply?: undefined | SendbirdUserMessage | SendbirdFileMessage;
6767
setMessageToReply?: (message?: undefined | SendbirdUserMessage | SendbirdFileMessage) => void;
68+
messageToThread?: undefined | SendbirdUserMessage | SendbirdFileMessage;
6869

6970
// mention
7071
SuggestedMentionList?: CommonComponent<SuggestedMentionListProps>;

packages/uikit-react-native/src/components/ChannelMessageList/index.tsx

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ export type ChannelMessageListProps<T extends SendbirdGroupChannel | SendbirdOpe
5757

5858
onEditMessage: (message: HandleableMessage) => void;
5959
onReplyMessage?: (message: HandleableMessage) => void; // only available on group channel
60+
onReplyInThreadMessage?: (message: HandleableMessage) => void; // only available on group channel
6061
onDeleteMessage: (message: HandleableMessage) => Promise<void>;
6162
onResendFailedMessage: (failedMessage: HandleableMessage) => Promise<HandleableMessage | void>;
62-
onPressParentMessage?: (parentMessage: SendbirdMessage) => void;
63+
onPressParentMessage?: (parentMessage: SendbirdMessage, childMessage: HandleableMessage) => void;
6364
onPressMediaMessage?: (message: SendbirdFileMessage, deleteMessage: () => Promise<void>, uri: string) => void;
6465

6566
renderMessage: (props: {
@@ -70,12 +71,14 @@ export type ChannelMessageListProps<T extends SendbirdGroupChannel | SendbirdOpe
7071
onPress?: () => void;
7172
onLongPress?: () => void;
7273
onPressParentMessage?: ChannelMessageListProps<T>['onPressParentMessage'];
74+
onReplyInThreadMessage?: ChannelMessageListProps<T>['onReplyInThreadMessage'];
7375
onShowUserProfile?: UserProfileContextType['show'];
7476
channel: T;
7577
currentUserId?: ChannelMessageListProps<T>['currentUserId'];
7678
enableMessageGrouping: ChannelMessageListProps<T>['enableMessageGrouping'];
7779
bottomSheetItem?: BottomSheetItem;
7880
isFirstItem: boolean;
81+
hideParentMessage?: boolean;
7982
}) => React.ReactElement | null;
8083
renderNewMessagesButton:
8184
| null
@@ -93,6 +96,7 @@ const ChannelMessageList = <T extends SendbirdGroupChannel | SendbirdOpenChannel
9396
channel,
9497
onEditMessage,
9598
onReplyMessage,
99+
onReplyInThreadMessage,
96100
onDeleteMessage,
97101
onResendFailedMessage,
98102
onPressMediaMessage,
@@ -123,6 +127,7 @@ const ChannelMessageList = <T extends SendbirdGroupChannel | SendbirdOpenChannel
123127
currentUserId,
124128
onEditMessage,
125129
onReplyMessage,
130+
onReplyInThreadMessage,
126131
onDeleteMessage,
127132
onResendFailedMessage,
128133
onPressMediaMessage,
@@ -139,6 +144,7 @@ const ChannelMessageList = <T extends SendbirdGroupChannel | SendbirdOpenChannel
139144
onPress,
140145
onLongPress,
141146
onPressParentMessage,
147+
onReplyInThreadMessage,
142148
onShowUserProfile: show,
143149
enableMessageGrouping,
144150
channel,
@@ -196,6 +202,7 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
196202
onResendFailedMessage,
197203
onEditMessage,
198204
onReplyMessage,
205+
onReplyInThreadMessage,
199206
onDeleteMessage,
200207
onPressMediaMessage,
201208
}: Pick<
@@ -204,6 +211,7 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
204211
| 'currentUserId'
205212
| 'onEditMessage'
206213
| 'onReplyMessage'
214+
| 'onReplyInThreadMessage'
207215
| 'onDeleteMessage'
208216
| 'onResendFailedMessage'
209217
| 'onPressMediaMessage'
@@ -322,6 +330,12 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
322330
title: STRINGS.LABELS.CHANNEL_MESSAGE_REPLY,
323331
onPress: () => onReplyMessage?.(message),
324332
}),
333+
replyInThread: (message: HandleableMessage) => ({
334+
disabled: Boolean(message.parentMessageId),
335+
icon: 'thread' as const,
336+
title: STRINGS.LABELS.CHANNEL_MESSAGE_THREAD,
337+
onPress: () => onReplyInThreadMessage?.(message),
338+
}),
325339
download: (message: HandleableMessage) => ({
326340
icon: 'download' as const,
327341
title: STRINGS.LABELS.CHANNEL_MESSAGE_SAVE,
@@ -336,8 +350,12 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
336350
sheetItems.push(menu.edit(message));
337351
sheetItems.push(menu.delete(message));
338352
}
339-
if (channel.isGroupChannel() && sbOptions.uikit.groupChannel.channel.replyType === 'quote_reply') {
340-
sheetItems.push(menu.reply(message));
353+
if (channel.isGroupChannel()) {
354+
if (sbOptions.uikit.groupChannel.channel.replyType === 'thread' && onReplyInThreadMessage !== undefined) {
355+
sheetItems.push(menu.replyInThread(message));
356+
} else if (sbOptions.uikit.groupChannel.channel.replyType === 'quote_reply') {
357+
sheetItems.push(menu.reply(message));
358+
}
341359
}
342360
}
343361
}
@@ -350,8 +368,14 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
350368
if (isMyMessage(message, currentUserId) && message.sendingStatus === 'succeeded') {
351369
sheetItems.push(menu.delete(message));
352370
}
353-
if (channel.isGroupChannel() && sbOptions.uikit.groupChannel.channel.replyType === 'quote_reply') {
354-
sheetItems.push(menu.reply(message));
371+
if (channel.isGroupChannel()) {
372+
if (channel.isGroupChannel()) {
373+
if (sbOptions.uikit.groupChannel.channel.replyType === 'thread' && onReplyInThreadMessage !== undefined) {
374+
sheetItems.push(menu.replyInThread(message));
375+
} else if (sbOptions.uikit.groupChannel.channel.replyType === 'quote_reply') {
376+
sheetItems.push(menu.reply(message));
377+
}
378+
}
355379
}
356380
}
357381
}

packages/uikit-react-native/src/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type Props = {
3030
channel: SendbirdGroupChannel;
3131
message: SendbirdUserMessage | SendbirdFileMessage;
3232
childMessage: SendbirdUserMessage | SendbirdFileMessage;
33-
onPress?: (message: SendbirdMessage) => void;
33+
onPress?: (parentMessage: SendbirdMessage, childMessage: SendbirdUserMessage | SendbirdFileMessage) => void;
3434
};
3535

3636
const GroupChannelMessageParentMessage = ({ variant, channel, message, childMessage, onPress }: Props) => {
@@ -135,7 +135,7 @@ const GroupChannelMessageParentMessage = ({ variant, channel, message, childMess
135135
paddingLeft={variant === 'outgoing' ? 0 : 12}
136136
paddingRight={variant === 'outgoing' ? 12 : 0}
137137
>
138-
<PressBox onPress={() => onPress?.(parentMessage)} style={styles.senderLabel}>
138+
<PressBox onPress={() => onPress?.(parentMessage, childMessage)} style={styles.senderLabel}>
139139
<Icon icon={'reply-filled'} size={13} color={colors.onBackground03} containerStyle={{ marginRight: 4 }} />
140140
<Text caption1 color={colors.onBackground03}>
141141
{STRINGS.LABELS.REPLY_FROM_SENDER_TO_RECEIVER(childMessage, parentMessage, currentUser?.userId)}
@@ -147,7 +147,7 @@ const GroupChannelMessageParentMessage = ({ variant, channel, message, childMess
147147
justifyContent={variant === 'outgoing' ? 'flex-end' : 'flex-start'}
148148
style={styles.messageContainer}
149149
>
150-
<PressBox onPress={() => onPress?.(parentMessage)}>{parentMessageComponent}</PressBox>
150+
<PressBox onPress={() => onPress?.(parentMessage, childMessage)}>{parentMessageComponent}</PressBox>
151151
</Box>
152152
</Box>
153153
);

0 commit comments

Comments
 (0)