@@ -40,6 +40,7 @@ import {
40
40
import SBUUtils from '../../libs/SBUUtils' ;
41
41
import ChatFlatList from '../ChatFlatList' ;
42
42
import { ReactionAddons } from '../ReactionAddons' ;
43
+ import { UnreadMessagesFloatingProps } from '../UnreadMessagesFloating' ;
43
44
44
45
type PressActions = { onPress ?: ( ) => void ; onLongPress ?: ( ) => void ; bottomSheetItem ?: BottomSheetItem } ;
45
46
type HandleableMessage = SendbirdUserMessage | SendbirdFileMessage ;
@@ -50,6 +51,7 @@ export type ChannelMessageListProps<T extends SendbirdGroupChannel | SendbirdOpe
50
51
channel : T ;
51
52
messages : SendbirdMessage [ ] ;
52
53
newMessages : SendbirdMessage [ ] ;
54
+ unreadFirstMessage ?: SendbirdMessage ;
53
55
searchItem ?: { startingPoint : number } ;
54
56
55
57
scrolledAwayFromBottom : boolean ;
@@ -68,6 +70,7 @@ export type ChannelMessageListProps<T extends SendbirdGroupChannel | SendbirdOpe
68
70
onResendFailedMessage : ( failedMessage : HandleableMessage ) => Promise < HandleableMessage | void > ;
69
71
onPressParentMessage ?: ( parentMessage : SendbirdMessage , childMessage : HandleableMessage ) => void ;
70
72
onPressMediaMessage ?: ( message : SendbirdFileMessage , deleteMessage : ( ) => Promise < void > , uri : string ) => void ;
73
+ onPressMarkAsUnreadMessage ?: ( message : HandleableMessage ) => void ;
71
74
72
75
renderMessage : ( props : {
73
76
focused : boolean ;
@@ -84,14 +87,18 @@ export type ChannelMessageListProps<T extends SendbirdGroupChannel | SendbirdOpe
84
87
enableMessageGrouping : ChannelMessageListProps < T > [ 'enableMessageGrouping' ] ;
85
88
bottomSheetItem ?: BottomSheetItem ;
86
89
isFirstItem : boolean ;
90
+ isFirstUnreadMessage ?: boolean ;
87
91
hideParentMessage ?: boolean ;
88
92
} ) => React . ReactElement | null ;
89
93
renderNewMessagesButton :
90
94
| null
91
95
| ( ( props : { visible : boolean ; onPress : ( ) => void ; newMessages : SendbirdMessage [ ] } ) => React . ReactElement | null ) ;
92
96
renderScrollToBottomButton : null | ( ( props : { visible : boolean ; onPress : ( ) => void } ) => React . ReactElement | null ) ;
97
+ renderUnreadMessagesFloating ?: null | ( ( props : UnreadMessagesFloatingProps ) => React . ReactElement | null ) ;
98
+ unreadMessagesFloatingProps ?: UnreadMessagesFloatingProps ;
93
99
flatListComponent ?: React . ComponentType < FlatListProps < SendbirdMessage > > ;
94
100
flatListProps ?: Omit < FlatListProps < SendbirdMessage > , 'data' | 'renderItem' > ;
101
+ onViewableItemsChanged ?: FlatListProps < SendbirdMessage > [ 'onViewableItemsChanged' ] ;
95
102
} & {
96
103
ref ?: Ref < FlatList < SendbirdMessage > > | undefined ;
97
104
} ;
@@ -108,21 +115,26 @@ const ChannelMessageList = <T extends SendbirdGroupChannel | SendbirdOpenChannel
108
115
onResendFailedMessage,
109
116
onPressMediaMessage,
110
117
onPressParentMessage,
118
+ onPressMarkAsUnreadMessage,
111
119
currentUserId,
120
+ renderUnreadMessagesFloating,
112
121
renderNewMessagesButton,
113
122
renderScrollToBottomButton,
114
123
renderMessage,
115
124
messages,
116
125
newMessages,
126
+ unreadFirstMessage,
117
127
enableMessageGrouping,
118
128
onScrolledAwayFromBottom,
119
129
scrolledAwayFromBottom,
120
130
onBottomReached,
121
131
onTopReached,
122
132
flatListComponent,
123
133
flatListProps,
134
+ onViewableItemsChanged,
124
135
onPressNewMessagesButton,
125
136
onPressScrollToBottomButton,
137
+ unreadMessagesFloatingProps,
126
138
} : ChannelMessageListProps < T > ,
127
139
ref : React . ForwardedRef < FlatList < SendbirdMessage > > ,
128
140
) => {
@@ -139,6 +151,7 @@ const ChannelMessageList = <T extends SendbirdGroupChannel | SendbirdOpenChannel
139
151
onDeleteMessage,
140
152
onResendFailedMessage,
141
153
onPressMediaMessage,
154
+ onPressMarkAsUnreadMessage,
142
155
} ) ;
143
156
144
157
const renderItem : ListRenderItem < SendbirdMessage > = useFreshCallback ( ( { item, index } ) => {
@@ -147,6 +160,7 @@ const ChannelMessageList = <T extends SendbirdGroupChannel | SendbirdOpenChannel
147
160
message : item ,
148
161
prevMessage : messages [ index + 1 ] ,
149
162
nextMessage : messages [ index - 1 ] ,
163
+ isFirstUnreadMessage : unreadFirstMessage ?. messageId === item . messageId ,
150
164
onPress,
151
165
onLongPress,
152
166
onPressParentMessage,
@@ -166,9 +180,21 @@ const ChannelMessageList = <T extends SendbirdGroupChannel | SendbirdOpenChannel
166
180
{ channel . isFrozen && (
167
181
< ChannelFrozenBanner style = { styles . frozenBanner } text = { STRINGS . LABELS . CHANNEL_MESSAGE_LIST_FROZEN } />
168
182
) }
183
+ { renderUnreadMessagesFloating && (
184
+ < View
185
+ style = { [ channel . isFrozen ? styles . unreadMsgFloatingWhenFrozen : styles . unreadMsgFloating , safeAreaLayout ] }
186
+ >
187
+ { renderUnreadMessagesFloating ( {
188
+ visible : unreadMessagesFloatingProps ?. visible ?? false ,
189
+ onPressClose : ( ) => unreadMessagesFloatingProps ?. onPressClose ( ) ,
190
+ unreadMessageCount : unreadMessagesFloatingProps ?. unreadMessageCount ?? 0 ,
191
+ } ) }
192
+ </ View >
193
+ ) }
169
194
< ChatFlatList
170
195
flatListComponent = { flatListComponent }
171
196
{ ...flatListProps }
197
+ onViewableItemsChanged = { onViewableItemsChanged }
172
198
onTopReached = { onTopReached }
173
199
onBottomReached = { onBottomReached }
174
200
onScrolledAwayFromBottom = { onScrolledAwayFromBottom }
@@ -212,6 +238,7 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
212
238
onReplyInThreadMessage,
213
239
onDeleteMessage,
214
240
onPressMediaMessage,
241
+ onPressMarkAsUnreadMessage,
215
242
} : Pick <
216
243
ChannelMessageListProps < T > ,
217
244
| 'channel'
@@ -222,6 +249,7 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
222
249
| 'onDeleteMessage'
223
250
| 'onResendFailedMessage'
224
251
| 'onPressMediaMessage'
252
+ | 'onPressMarkAsUnreadMessage'
225
253
> ) : CreateMessagePressActions => {
226
254
const handlers = useSBUHandlers ( ) ;
227
255
const { colors } = useUIKitTheme ( ) ;
@@ -281,6 +309,10 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
281
309
}
282
310
} ;
283
311
312
+ const onMarkAsUnread = ( message : HandleableMessage ) => {
313
+ onPressMarkAsUnreadMessage ?.( message ) ;
314
+ } ;
315
+
284
316
const openSheetForFailedMessage = ( message : HandleableMessage ) => {
285
317
openSheet ( {
286
318
sheetItems : [
@@ -323,6 +355,11 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
323
355
title : STRINGS . LABELS . CHANNEL_MESSAGE_COPY ,
324
356
onPress : ( ) => onCopyText ( message ) ,
325
357
} ) ,
358
+ markAsUnread : ( message : HandleableMessage ) => ( {
359
+ icon : 'mark-as-unread' as const ,
360
+ title : STRINGS . LABELS . CHANNEL_MESSAGE_MARK_AS_UNREAD ,
361
+ onPress : ( ) => onMarkAsUnread ( message ) ,
362
+ } ) ,
326
363
edit : ( message : HandleableMessage ) => ( {
327
364
icon : 'edit' as const ,
328
365
title : STRINGS . LABELS . CHANNEL_MESSAGE_EDIT ,
@@ -356,6 +393,9 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
356
393
if ( message . isUserMessage ( ) ) {
357
394
sheetItems . push ( menu . copy ( message ) ) ;
358
395
if ( ! channel . isEphemeral ) {
396
+ if ( channel . isGroupChannel ( ) && sbOptions . uikit . groupChannel . channel . enableMarkAsUnread ) {
397
+ sheetItems . push ( menu . markAsUnread ( message ) ) ;
398
+ }
359
399
if ( isMyMessage ( message , currentUserId ) && message . sendingStatus === 'succeeded' ) {
360
400
sheetItems . push ( menu . edit ( message ) ) ;
361
401
sheetItems . push ( menu . delete ( message ) ) ;
@@ -384,6 +424,9 @@ const useCreateMessagePressActions = <T extends SendbirdGroupChannel | SendbirdO
384
424
} else if ( sbOptions . uikit . groupChannel . channel . replyType === 'quote_reply' ) {
385
425
sheetItems . push ( menu . reply ( message ) ) ;
386
426
}
427
+ if ( sbOptions . uikit . groupChannel . channel . enableMarkAsUnread ) {
428
+ sheetItems . push ( menu . markAsUnread ( message ) ) ;
429
+ }
387
430
}
388
431
}
389
432
}
@@ -446,6 +489,18 @@ const styles = createStyleSheet({
446
489
frozenListPadding : {
447
490
paddingBottom : 32 ,
448
491
} ,
492
+ unreadMsgFloating : {
493
+ position : 'absolute' ,
494
+ zIndex : 999 ,
495
+ top : 12 ,
496
+ alignSelf : 'center' ,
497
+ } ,
498
+ unreadMsgFloatingWhenFrozen : {
499
+ position : 'absolute' ,
500
+ zIndex : 999 ,
501
+ top : 40 ,
502
+ alignSelf : 'center' ,
503
+ } ,
449
504
newMsgButton : {
450
505
position : 'absolute' ,
451
506
zIndex : 999 ,
0 commit comments