Skip to content

Commit db41f1b

Browse files
committed
feat: enable swipe to reply for message bubble
1 parent bf79287 commit db41f1b

File tree

7 files changed

+938
-266
lines changed

7 files changed

+938
-266
lines changed

package/src/components/Channel/Channel.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ import { MessageReplies as MessageRepliesDefault } from '../Message/MessageSimpl
141141
import { MessageRepliesAvatars as MessageRepliesAvatarsDefault } from '../Message/MessageSimple/MessageRepliesAvatars';
142142
import { MessageSimple as MessageSimpleDefault } from '../Message/MessageSimple/MessageSimple';
143143
import { MessageStatus as MessageStatusDefault } from '../Message/MessageSimple/MessageStatus';
144+
import { MessageSwipeLeftContent as MessageSwipeLeftContentDefault } from '../Message/MessageSimple/MessageSwipeLeftContent';
144145
import { MessageTimestamp as MessageTimestampDefault } from '../Message/MessageSimple/MessageTimestamp';
145146
import { ReactionListBottom as ReactionListBottomDefault } from '../Message/MessageSimple/ReactionList/ReactionListBottom';
146147
import { ReactionListTop as ReactionListTopDefault } from '../Message/MessageSimple/ReactionList/ReactionListTop';
@@ -295,6 +296,7 @@ export type ChannelPropsWithContext<
295296
| 'deletedMessagesVisibilityType'
296297
| 'disableTypingIndicator'
297298
| 'dismissKeyboardOnMessageTouch'
299+
| 'enableSwipeToReply'
298300
| 'FileAttachment'
299301
| 'FileAttachmentIcon'
300302
| 'FileAttachmentGroup'
@@ -348,6 +350,7 @@ export type ChannelPropsWithContext<
348350
| 'messageTextNumberOfLines'
349351
| 'MessageTimestamp'
350352
| 'MessageUserReactions'
353+
| 'MessageSwipeLeftContent'
351354
| 'myMessageTheme'
352355
| 'onLongPressMessage'
353356
| 'onPressInMessage'
@@ -528,6 +531,7 @@ const ChannelWithContext = <
528531
EmptyStateIndicator = EmptyStateIndicatorDefault,
529532
enableMessageGroupingByUser = true,
530533
enableOfflineSupport,
534+
enableSwipeToReply = true,
531535
enforceUniqueReaction = false,
532536
FileAttachment = FileAttachmentDefault,
533537
FileAttachmentGroup = FileAttachmentGroupDefault,
@@ -620,6 +624,7 @@ const ChannelWithContext = <
620624
MessageRepliesAvatars = MessageRepliesAvatarsDefault,
621625
MessageSimple = MessageSimpleDefault,
622626
MessageStatus = MessageStatusDefault,
627+
MessageSwipeLeftContent = MessageSwipeLeftContentDefault,
623628
MessageSystem = MessageSystemDefault,
624629
MessageText,
625630
messageTextNumberOfLines,
@@ -1802,13 +1807,15 @@ const ChannelWithContext = <
18021807
CardFooter,
18031808
CardHeader,
18041809
channelId,
1810+
clearQuotedMessageState,
18051811
DateHeader,
18061812
deletedMessagesVisibilityType,
18071813
deleteMessage,
18081814
deleteReaction,
18091815
disableTypingIndicator,
18101816
dismissKeyboardOnMessageTouch,
18111817
enableMessageGroupingByUser,
1818+
enableSwipeToReply,
18121819
FileAttachment,
18131820
FileAttachmentGroup,
18141821
FileAttachmentIcon,
@@ -1862,6 +1869,7 @@ const ChannelWithContext = <
18621869
MessageRepliesAvatars,
18631870
MessageSimple,
18641871
MessageStatus,
1872+
MessageSwipeLeftContent,
18651873
MessageSystem,
18661874
MessageText,
18671875
messageTextNumberOfLines,

package/src/components/Channel/hooks/useCreateMessagesContext.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ export const useCreateMessagesContext = <
1515
CardFooter,
1616
CardHeader,
1717
channelId,
18+
clearQuotedMessageState,
1819
DateHeader,
1920
deletedMessagesVisibilityType,
2021
deleteMessage,
2122
deleteReaction,
2223
disableTypingIndicator,
2324
dismissKeyboardOnMessageTouch,
2425
enableMessageGroupingByUser,
26+
enableSwipeToReply,
2527
FileAttachment,
2628
FileAttachmentGroup,
2729
FileAttachmentIcon,
@@ -74,6 +76,7 @@ export const useCreateMessagesContext = <
7476
MessageRepliesAvatars,
7577
MessageSimple,
7678
MessageStatus,
79+
MessageSwipeLeftContent,
7780
MessageSystem,
7881
MessageText,
7982
messageTextNumberOfLines,
@@ -128,13 +131,15 @@ export const useCreateMessagesContext = <
128131
CardCover,
129132
CardFooter,
130133
CardHeader,
134+
clearQuotedMessageState,
131135
DateHeader,
132136
deletedMessagesVisibilityType,
133137
deleteMessage,
134138
deleteReaction,
135139
disableTypingIndicator,
136140
dismissKeyboardOnMessageTouch,
137141
enableMessageGroupingByUser,
142+
enableSwipeToReply,
138143
FileAttachment,
139144
FileAttachmentGroup,
140145
FileAttachmentIcon,
@@ -187,6 +192,7 @@ export const useCreateMessagesContext = <
187192
MessageRepliesAvatars,
188193
MessageSimple,
189194
MessageStatus,
195+
MessageSwipeLeftContent,
190196
MessageSystem,
191197
MessageText,
192198
messageTextNumberOfLines,

package/src/components/Message/MessageSimple/MessageSimple.tsx

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import React, { useState } from 'react';
1+
import React, { useRef, useState } from 'react';
22
import { LayoutChangeEvent, StyleSheet, View } from 'react-native';
3+
import { Swipeable } from 'react-native-gesture-handler';
34

45
import {
56
MessageContextValue,
@@ -22,7 +23,9 @@ const styles = StyleSheet.create({
2223
contentContainer: {},
2324
contentWrapper: {
2425
flexDirection: 'row',
26+
overflow: 'visible',
2527
},
28+
2629
lastMessageContainer: {
2730
marginBottom: 12,
2831
},
@@ -56,7 +59,9 @@ export type MessageSimplePropsWithContext<
5659
> &
5760
Pick<
5861
MessagesContextValue<StreamChatGenerics>,
62+
| 'clearQuotedMessageState'
5963
| 'enableMessageGroupingByUser'
64+
| 'enableSwipeToReply'
6065
| 'myMessageTheme'
6166
| 'MessageAvatar'
6267
| 'MessageContent'
@@ -66,9 +71,11 @@ export type MessageSimplePropsWithContext<
6671
| 'MessagePinnedHeader'
6772
| 'MessageReplies'
6873
| 'MessageStatus'
74+
| 'MessageSwipeLeftContent'
6975
| 'ReactionListBottom'
7076
| 'reactionListPosition'
7177
| 'ReactionListTop'
78+
| 'setQuotedMessageState'
7279
>;
7380

7481
const MessageSimpleWithContext = <
@@ -77,9 +84,13 @@ const MessageSimpleWithContext = <
7784
props: MessageSimplePropsWithContext<StreamChatGenerics>,
7885
) => {
7986
const [messageContentWidth, setMessageContentWidth] = useState(0);
87+
const swipeableRef = useRef<Swipeable | null>(null);
88+
8089
const {
8190
alignment,
91+
clearQuotedMessageState,
8292
enableMessageGroupingByUser,
93+
enableSwipeToReply,
8394
groupStyles,
8495
hasReactions,
8596
isMyMessage,
@@ -94,11 +105,13 @@ const MessageSimpleWithContext = <
94105
MessagePinnedHeader,
95106
MessageReplies,
96107
MessageStatus,
108+
MessageSwipeLeftContent,
97109
onlyEmojis,
98110
otherAttachments,
99111
ReactionListBottom,
100112
reactionListPosition,
101113
ReactionListTop,
114+
setQuotedMessageState,
102115
showMessageStatus,
103116
} = props;
104117

@@ -234,7 +247,25 @@ const MessageSimpleWithContext = <
234247
{message.pinned ? <MessagePinnedHeader /> : null}
235248
</View>
236249

237-
<View style={[styles.contentWrapper, contentWrapper]}>
250+
<Swipeable
251+
containerStyle={[styles.contentWrapper, contentWrapper]}
252+
friction={2}
253+
leftThreshold={enableSwipeToReply ? 100 : 0}
254+
onSwipeableWillOpen={() => {
255+
if (!swipeableRef.current) return;
256+
clearQuotedMessageState();
257+
setQuotedMessageState(message);
258+
swipeableRef.current.close();
259+
}}
260+
ref={swipeableRef}
261+
renderLeftActions={() => {
262+
if (alignment === 'left' && enableSwipeToReply) {
263+
return MessageSwipeLeftContent ? <MessageSwipeLeftContent /> : null;
264+
} else {
265+
return null;
266+
}
267+
}}
268+
>
238269
<MessageContent
239270
backgroundColor={backgroundColor}
240271
noBorder={noBorder}
@@ -243,7 +274,7 @@ const MessageSimpleWithContext = <
243274
{reactionListPosition === 'top' && ReactionListTop ? (
244275
<ReactionListTop messageContentWidth={messageContentWidth} />
245276
) : null}
246-
</View>
277+
</Swipeable>
247278

248279
{reactionListPosition === 'bottom' && ReactionListBottom ? <ReactionListBottom /> : null}
249280
<MessageReplies noBorder={noBorder} repliesCurveColor={repliesCurveColor} />
@@ -394,7 +425,9 @@ export const MessageSimple = <
394425
showMessageStatus,
395426
} = useMessageContext<StreamChatGenerics>();
396427
const {
428+
clearQuotedMessageState,
397429
enableMessageGroupingByUser,
430+
enableSwipeToReply,
398431
MessageAvatar,
399432
MessageContent,
400433
MessageDeleted,
@@ -403,18 +436,22 @@ export const MessageSimple = <
403436
MessagePinnedHeader,
404437
MessageReplies,
405438
MessageStatus,
439+
MessageSwipeLeftContent,
406440
myMessageTheme,
407441
ReactionListBottom,
408442
reactionListPosition,
409443
ReactionListTop,
444+
setQuotedMessageState,
410445
} = useMessagesContext<StreamChatGenerics>();
411446

412447
return (
413448
<MemoizedMessageSimple<StreamChatGenerics>
414449
{...{
415450
alignment,
416451
channel,
452+
clearQuotedMessageState,
417453
enableMessageGroupingByUser,
454+
enableSwipeToReply,
418455
groupStyles,
419456
hasReactions,
420457
isMyMessage,
@@ -429,12 +466,14 @@ export const MessageSimple = <
429466
MessagePinnedHeader,
430467
MessageReplies,
431468
MessageStatus,
469+
MessageSwipeLeftContent,
432470
myMessageTheme,
433471
onlyEmojis,
434472
otherAttachments,
435473
ReactionListBottom,
436474
reactionListPosition,
437475
ReactionListTop,
476+
setQuotedMessageState,
438477
showMessageStatus,
439478
}}
440479
{...props}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react';
2+
import { StyleSheet, View } from 'react-native';
3+
4+
import { useTheme } from '../../../contexts/themeContext/ThemeContext';
5+
import { CurveLineLeftUp } from '../../../icons';
6+
7+
export const MessageSwipeLeftContent = () => {
8+
const {
9+
theme: {
10+
colors: { grey },
11+
messageSimple: {
12+
swipeLeftContent: { container },
13+
},
14+
},
15+
} = useTheme();
16+
return (
17+
<View style={[styles.container, container]}>
18+
<CurveLineLeftUp pathFill={grey} />
19+
</View>
20+
);
21+
};
22+
23+
const styles = StyleSheet.create({
24+
container: {
25+
justifyContent: 'center',
26+
paddingHorizontal: 16,
27+
},
28+
});

0 commit comments

Comments
 (0)