@sendbird/uikit-react-native 2.4.2 → 2.5.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/lib/commonjs/components/ChannelMessageList/index.js +319 -0
  2. package/lib/commonjs/components/ChannelMessageList/index.js.map +1 -0
  3. package/lib/commonjs/components/ChatFlatList.js +30 -50
  4. package/lib/commonjs/components/ChatFlatList.js.map +1 -1
  5. package/lib/commonjs/components/MessageSearchResultItem.js +132 -0
  6. package/lib/commonjs/components/MessageSearchResultItem.js.map +1 -0
  7. package/lib/commonjs/components/ScrollToBottomButton.js +1 -1
  8. package/lib/commonjs/components/ScrollToBottomButton.js.map +1 -1
  9. package/lib/commonjs/constants.js +6 -2
  10. package/lib/commonjs/constants.js.map +1 -1
  11. package/lib/commonjs/containers/GroupChannelPreviewContainer.js +2 -2
  12. package/lib/commonjs/containers/GroupChannelPreviewContainer.js.map +1 -1
  13. package/lib/commonjs/containers/SendbirdUIKitContainer.js +4 -2
  14. package/lib/commonjs/containers/SendbirdUIKitContainer.js.map +1 -1
  15. package/lib/commonjs/contexts/SendbirdChatCtx.js +4 -2
  16. package/lib/commonjs/contexts/SendbirdChatCtx.js.map +1 -1
  17. package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js +4 -2
  18. package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
  19. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +84 -301
  20. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  21. package/lib/commonjs/domain/groupChannel/component/GroupChannelSuggestedMentionList.js +2 -0
  22. package/lib/commonjs/domain/groupChannel/component/GroupChannelSuggestedMentionList.js.map +1 -1
  23. package/lib/commonjs/domain/groupChannel/module/moduleContext.js +9 -2
  24. package/lib/commonjs/domain/groupChannel/module/moduleContext.js.map +1 -1
  25. package/lib/commonjs/domain/groupChannel/types.js.map +1 -1
  26. package/lib/commonjs/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js +18 -4
  27. package/lib/commonjs/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js.map +1 -1
  28. package/lib/commonjs/domain/groupChannelSettings/types.js.map +1 -1
  29. package/lib/commonjs/domain/messageSearch/component/MessageSearchHeader.js +105 -0
  30. package/lib/commonjs/domain/messageSearch/component/MessageSearchHeader.js.map +1 -0
  31. package/lib/commonjs/domain/messageSearch/component/MessageSearchList.js +40 -0
  32. package/lib/commonjs/domain/messageSearch/component/MessageSearchList.js.map +1 -0
  33. package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusEmpty.js +22 -0
  34. package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusEmpty.js.map +1 -0
  35. package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusError.js +26 -0
  36. package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusError.js.map +1 -0
  37. package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusLoading.js +22 -0
  38. package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusLoading.js.map +1 -0
  39. package/lib/commonjs/domain/messageSearch/index.js +62 -0
  40. package/lib/commonjs/domain/messageSearch/index.js.map +1 -0
  41. package/lib/commonjs/domain/messageSearch/module/createMessageSearchModule.js +36 -0
  42. package/lib/commonjs/domain/messageSearch/module/createMessageSearchModule.js.map +1 -0
  43. package/lib/commonjs/domain/messageSearch/module/moduleContext.js +25 -0
  44. package/lib/commonjs/domain/messageSearch/module/moduleContext.js.map +1 -0
  45. package/lib/commonjs/domain/messageSearch/types.js +6 -0
  46. package/lib/commonjs/domain/messageSearch/types.js.map +1 -0
  47. package/lib/commonjs/domain/openChannel/component/OpenChannelMessageList.js +38 -279
  48. package/lib/commonjs/domain/openChannel/component/OpenChannelMessageList.js.map +1 -1
  49. package/lib/commonjs/domain/openChannel/module/moduleContext.js +9 -2
  50. package/lib/commonjs/domain/openChannel/module/moduleContext.js.map +1 -1
  51. package/lib/commonjs/domain/openChannel/types.js.map +1 -1
  52. package/lib/commonjs/fragments/createGroupChannelFragment.js +107 -15
  53. package/lib/commonjs/fragments/createGroupChannelFragment.js.map +1 -1
  54. package/lib/commonjs/fragments/createGroupChannelSettingsFragment.js +2 -0
  55. package/lib/commonjs/fragments/createGroupChannelSettingsFragment.js.map +1 -1
  56. package/lib/commonjs/fragments/createMessageSearchFragment.js +145 -0
  57. package/lib/commonjs/fragments/createMessageSearchFragment.js.map +1 -0
  58. package/lib/commonjs/fragments/createOpenChannelFragment.js +40 -8
  59. package/lib/commonjs/fragments/createOpenChannelFragment.js.map +1 -1
  60. package/lib/commonjs/hooks/useMentionSuggestion.js +17 -0
  61. package/lib/commonjs/hooks/useMentionSuggestion.js.map +1 -1
  62. package/lib/commonjs/index.js +60 -40
  63. package/lib/commonjs/index.js.map +1 -1
  64. package/lib/commonjs/localization/StringSet.type.js.map +1 -1
  65. package/lib/commonjs/localization/createBaseStringSet.js +33 -20
  66. package/lib/commonjs/localization/createBaseStringSet.js.map +1 -1
  67. package/lib/commonjs/utils/pubsub.js +21 -0
  68. package/lib/commonjs/utils/pubsub.js.map +1 -0
  69. package/lib/commonjs/version.js +1 -1
  70. package/lib/commonjs/version.js.map +1 -1
  71. package/lib/module/components/ChannelMessageList/index.js +311 -0
  72. package/lib/module/components/ChannelMessageList/index.js.map +1 -0
  73. package/lib/module/components/ChatFlatList.js +32 -52
  74. package/lib/module/components/ChatFlatList.js.map +1 -1
  75. package/lib/module/components/MessageSearchResultItem.js +124 -0
  76. package/lib/module/components/MessageSearchResultItem.js.map +1 -0
  77. package/lib/module/components/ScrollToBottomButton.js +1 -1
  78. package/lib/module/components/ScrollToBottomButton.js.map +1 -1
  79. package/lib/module/constants.js +3 -1
  80. package/lib/module/constants.js.map +1 -1
  81. package/lib/module/containers/GroupChannelPreviewContainer.js +2 -2
  82. package/lib/module/containers/GroupChannelPreviewContainer.js.map +1 -1
  83. package/lib/module/containers/SendbirdUIKitContainer.js +4 -2
  84. package/lib/module/containers/SendbirdUIKitContainer.js.map +1 -1
  85. package/lib/module/contexts/SendbirdChatCtx.js +4 -2
  86. package/lib/module/contexts/SendbirdChatCtx.js.map +1 -1
  87. package/lib/module/domain/groupChannel/component/GroupChannelHeader.js +4 -2
  88. package/lib/module/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
  89. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +88 -305
  90. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  91. package/lib/module/domain/groupChannel/component/GroupChannelSuggestedMentionList.js +2 -0
  92. package/lib/module/domain/groupChannel/component/GroupChannelSuggestedMentionList.js.map +1 -1
  93. package/lib/module/domain/groupChannel/module/moduleContext.js +9 -2
  94. package/lib/module/domain/groupChannel/module/moduleContext.js.map +1 -1
  95. package/lib/module/domain/groupChannel/types.js.map +1 -1
  96. package/lib/module/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js +18 -4
  97. package/lib/module/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js.map +1 -1
  98. package/lib/module/domain/groupChannelSettings/types.js.map +1 -1
  99. package/lib/module/domain/messageSearch/component/MessageSearchHeader.js +96 -0
  100. package/lib/module/domain/messageSearch/component/MessageSearchHeader.js.map +1 -0
  101. package/lib/module/domain/messageSearch/component/MessageSearchList.js +32 -0
  102. package/lib/module/domain/messageSearch/component/MessageSearchList.js.map +1 -0
  103. package/lib/module/domain/messageSearch/component/MessageSearchStatusEmpty.js +14 -0
  104. package/lib/module/domain/messageSearch/component/MessageSearchStatusEmpty.js.map +1 -0
  105. package/lib/module/domain/messageSearch/component/MessageSearchStatusError.js +18 -0
  106. package/lib/module/domain/messageSearch/component/MessageSearchStatusError.js.map +1 -0
  107. package/lib/module/domain/messageSearch/component/MessageSearchStatusLoading.js +14 -0
  108. package/lib/module/domain/messageSearch/component/MessageSearchStatusLoading.js.map +1 -0
  109. package/lib/module/domain/messageSearch/index.js +8 -0
  110. package/lib/module/domain/messageSearch/index.js.map +1 -0
  111. package/lib/module/domain/messageSearch/module/createMessageSearchModule.js +28 -0
  112. package/lib/module/domain/messageSearch/module/createMessageSearchModule.js.map +1 -0
  113. package/lib/module/domain/messageSearch/module/moduleContext.js +14 -0
  114. package/lib/module/domain/messageSearch/module/moduleContext.js.map +1 -0
  115. package/lib/module/domain/messageSearch/types.js +2 -0
  116. package/lib/module/domain/messageSearch/types.js.map +1 -0
  117. package/lib/module/domain/openChannel/component/OpenChannelMessageList.js +40 -281
  118. package/lib/module/domain/openChannel/component/OpenChannelMessageList.js.map +1 -1
  119. package/lib/module/domain/openChannel/module/moduleContext.js +9 -2
  120. package/lib/module/domain/openChannel/module/moduleContext.js.map +1 -1
  121. package/lib/module/domain/openChannel/types.js.map +1 -1
  122. package/lib/module/fragments/createGroupChannelFragment.js +109 -17
  123. package/lib/module/fragments/createGroupChannelFragment.js.map +1 -1
  124. package/lib/module/fragments/createGroupChannelSettingsFragment.js +2 -0
  125. package/lib/module/fragments/createGroupChannelSettingsFragment.js.map +1 -1
  126. package/lib/module/fragments/createMessageSearchFragment.js +135 -0
  127. package/lib/module/fragments/createMessageSearchFragment.js.map +1 -0
  128. package/lib/module/fragments/createOpenChannelFragment.js +41 -9
  129. package/lib/module/fragments/createOpenChannelFragment.js.map +1 -1
  130. package/lib/module/hooks/useMentionSuggestion.js +18 -1
  131. package/lib/module/hooks/useMentionSuggestion.js.map +1 -1
  132. package/lib/module/index.js +2 -0
  133. package/lib/module/index.js.map +1 -1
  134. package/lib/module/localization/StringSet.type.js.map +1 -1
  135. package/lib/module/localization/createBaseStringSet.js +34 -21
  136. package/lib/module/localization/createBaseStringSet.js.map +1 -1
  137. package/lib/module/utils/pubsub.js +14 -0
  138. package/lib/module/utils/pubsub.js.map +1 -0
  139. package/lib/module/version.js +1 -1
  140. package/lib/module/version.js.map +1 -1
  141. package/lib/typescript/src/components/ChannelMessageList/index.d.ts +55 -0
  142. package/lib/typescript/src/components/ChatFlatList.d.ts +7 -8
  143. package/lib/typescript/src/components/MessageRenderer/index.d.ts +4 -0
  144. package/lib/typescript/src/components/MessageSearchResultItem.d.ts +2 -0
  145. package/lib/typescript/src/components/OpenChannelMessageRenderer/index.d.ts +1 -0
  146. package/lib/typescript/src/components/ScrollToBottomButton.d.ts +1 -1
  147. package/lib/typescript/src/constants.d.ts +3 -1
  148. package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +2 -1
  149. package/lib/typescript/src/contexts/SendbirdChatCtx.d.ts +3 -1
  150. package/lib/typescript/src/domain/groupChannel/component/GroupChannelHeader.d.ts +1 -1
  151. package/lib/typescript/src/domain/groupChannel/component/GroupChannelMessageList.d.ts +3 -32
  152. package/lib/typescript/src/domain/groupChannel/types.d.ts +23 -35
  153. package/lib/typescript/src/domain/groupChannelSettings/component/GroupChannelSettingsMenu.d.ts +1 -1
  154. package/lib/typescript/src/domain/groupChannelSettings/types.d.ts +2 -0
  155. package/lib/typescript/src/domain/messageSearch/component/MessageSearchHeader.d.ts +3 -0
  156. package/lib/typescript/src/domain/messageSearch/component/MessageSearchList.d.ts +3 -0
  157. package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusEmpty.d.ts +2 -0
  158. package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusError.d.ts +3 -0
  159. package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusLoading.d.ts +2 -0
  160. package/lib/typescript/src/domain/messageSearch/index.d.ts +7 -0
  161. package/lib/typescript/src/domain/messageSearch/module/createMessageSearchModule.d.ts +3 -0
  162. package/lib/typescript/src/domain/messageSearch/module/moduleContext.d.ts +3 -0
  163. package/lib/typescript/src/domain/messageSearch/types.d.ts +53 -0
  164. package/lib/typescript/src/domain/openChannel/component/OpenChannelMessageList.d.ts +1 -37
  165. package/lib/typescript/src/domain/openChannel/types.d.ts +17 -36
  166. package/lib/typescript/src/fragments/createMessageSearchFragment.d.ts +3 -0
  167. package/lib/typescript/src/hooks/useMentionSuggestion.d.ts +3 -2
  168. package/lib/typescript/src/index.d.ts +2 -0
  169. package/lib/typescript/src/localization/StringSet.type.d.ts +17 -3
  170. package/lib/typescript/src/utils/pubsub.d.ts +6 -0
  171. package/lib/typescript/src/version.d.ts +1 -1
  172. package/package.json +8 -7
  173. package/src/components/ChannelMessageList/index.tsx +392 -0
  174. package/src/components/ChatFlatList.tsx +33 -51
  175. package/src/components/MessageSearchResultItem.tsx +125 -0
  176. package/src/components/ScrollToBottomButton.tsx +3 -4
  177. package/src/constants.ts +3 -1
  178. package/src/containers/GroupChannelPreviewContainer.tsx +2 -2
  179. package/src/containers/SendbirdUIKitContainer.tsx +2 -0
  180. package/src/contexts/SendbirdChatCtx.tsx +7 -1
  181. package/src/domain/groupChannel/component/GroupChannelHeader.tsx +9 -3
  182. package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +73 -316
  183. package/src/domain/groupChannel/component/GroupChannelSuggestedMentionList.tsx +2 -1
  184. package/src/domain/groupChannel/module/moduleContext.tsx +10 -2
  185. package/src/domain/groupChannel/types.ts +49 -38
  186. package/src/domain/groupChannelSettings/component/GroupChannelSettingsMenu.tsx +29 -13
  187. package/src/domain/groupChannelSettings/types.ts +2 -0
  188. package/src/domain/messageSearch/component/MessageSearchHeader.tsx +98 -0
  189. package/src/domain/messageSearch/component/MessageSearchList.tsx +26 -0
  190. package/src/domain/messageSearch/component/MessageSearchStatusEmpty.tsx +15 -0
  191. package/src/domain/messageSearch/component/MessageSearchStatusError.tsx +16 -0
  192. package/src/domain/messageSearch/component/MessageSearchStatusLoading.tsx +15 -0
  193. package/src/domain/messageSearch/index.ts +7 -0
  194. package/src/domain/messageSearch/module/createMessageSearchModule.tsx +21 -0
  195. package/src/domain/messageSearch/module/moduleContext.tsx +16 -0
  196. package/src/domain/messageSearch/types.ts +55 -0
  197. package/src/domain/openChannel/component/OpenChannelMessageList.tsx +35 -303
  198. package/src/domain/openChannel/module/moduleContext.tsx +8 -2
  199. package/src/domain/openChannel/types.ts +40 -38
  200. package/src/fragments/createGroupChannelFragment.tsx +114 -17
  201. package/src/fragments/createGroupChannelSettingsFragment.tsx +2 -0
  202. package/src/fragments/createMessageSearchFragment.tsx +159 -0
  203. package/src/fragments/createOpenChannelFragment.tsx +48 -12
  204. package/src/hooks/useMentionSuggestion.ts +23 -3
  205. package/src/index.ts +3 -0
  206. package/src/localization/StringSet.type.ts +20 -2
  207. package/src/localization/createBaseStringSet.ts +22 -2
  208. package/src/utils/pubsub.ts +20 -0
  209. package/src/version.ts +0 -2
@@ -1,321 +1,53 @@
1
- import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
2
- import { ListRenderItem, Platform, View } from 'react-native';
1
+ import React, { useContext, useEffect, useRef, useState } from 'react';
2
+ import type { FlatList } from 'react-native';
3
3
 
4
- import type { BottomSheetItem } from '@sendbird/uikit-react-native-foundation';
5
- import {
6
- ChannelFrozenBanner,
7
- createStyleSheet,
8
- useAlert,
9
- useBottomSheet,
10
- useToast,
11
- useUIKitTheme,
12
- } from '@sendbird/uikit-react-native-foundation';
13
- import type { SendbirdFileMessage, SendbirdMessage, SendbirdUserMessage } from '@sendbird/uikit-utils';
14
- import {
15
- Logger,
16
- getAvailableUriFromFileMessage,
17
- getFileExtension,
18
- getFileType,
19
- isMyMessage,
20
- messageKeyExtractor,
21
- toMegabyte,
22
- useFreshCallback,
23
- useSafeAreaPadding,
24
- } from '@sendbird/uikit-utils';
4
+ import { SendbirdMessage, useFreshCallback } from '@sendbird/uikit-utils';
25
5
 
26
- import type { ChatFlatListRef } from '../../../components/ChatFlatList';
27
- import ChatFlatList from '../../../components/ChatFlatList';
28
- import { useLocalization, usePlatformService } from '../../../hooks/useContext';
29
- import SBUUtils from '../../../libs/SBUUtils';
6
+ import ChannelMessageList from '../../../components/ChannelMessageList';
30
7
  import { OpenChannelContexts } from '../module/moduleContext';
31
8
  import type { OpenChannelProps } from '../types';
32
9
 
33
- const HANDLE_NEXT_MSG_SEPARATELY = Platform.select({ default: true });
34
-
35
- const OpenChannelMessageList = ({
36
- currentUserId,
37
- channel,
38
- messages,
39
- renderMessage,
40
- nextMessages,
41
- newMessagesFromMembers,
42
- onBottomReached,
43
- onTopReached,
44
- renderNewMessagesButton,
45
- renderScrollToBottomButton,
46
- onResendFailedMessage,
47
- onDeleteMessage,
48
- onPressMediaMessage,
49
- flatListProps,
50
- enableMessageGrouping,
51
- }: OpenChannelProps['MessageList']) => {
52
- const { STRINGS } = useLocalization();
53
- const { colors } = useUIKitTheme();
54
-
55
- const [scrollLeaveBottom, setScrollLeaveBottom] = useState(false);
56
- const [newMessagesInternalBuffer, setNewMessagesInternalBuffer] = useState(() => newMessagesFromMembers);
57
-
58
- const scrollRef = useRef<ChatFlatListRef>(null);
59
-
60
- const safeAreaLayout = useSafeAreaPadding(['left', 'right']);
61
- const getMessagePressActions = useGetMessagePressActions({
62
- channel,
63
- currentUserId,
64
- onDeleteMessage,
65
- onResendFailedMessage,
66
- onPressMediaMessage,
67
- });
68
-
69
- const renderItem: ListRenderItem<SendbirdMessage> = useFreshCallback(({ item, index }) => {
70
- const { onPress, onLongPress } = getMessagePressActions(item);
71
- return renderMessage({
72
- message: item,
73
- prevMessage: messages[index + 1],
74
- nextMessage: messages[index - 1],
75
- onPress,
76
- onLongPress,
77
- enableMessageGrouping,
78
- channel,
79
- currentUserId,
80
- });
81
- });
82
-
83
- if (!HANDLE_NEXT_MSG_SEPARATELY) {
84
- useEffect(() => {
85
- if (newMessagesInternalBuffer.length !== 0) {
86
- setNewMessagesInternalBuffer((prev) => prev.concat(newMessagesFromMembers));
87
- }
88
- onBottomReached();
89
- }, [newMessagesFromMembers]);
90
- }
91
-
92
- const onLeaveScrollBottom = useCallback((val: boolean) => {
93
- if (!HANDLE_NEXT_MSG_SEPARATELY) setNewMessagesInternalBuffer([]);
94
- setScrollLeaveBottom(val);
95
- }, []);
96
-
97
- return (
98
- <View style={[{ flex: 1, backgroundColor: colors.background }, safeAreaLayout]}>
99
- {channel.isFrozen && (
100
- <ChannelFrozenBanner style={styles.frozenBanner} text={STRINGS.OPEN_CHANNEL.LIST_BANNER_FROZEN} />
101
- )}
102
- <ChatFlatList
103
- nextMessages={nextMessages}
104
- onBottomReached={onBottomReached}
105
- onTopReached={onTopReached}
106
- onLeaveScrollBottom={onLeaveScrollBottom}
107
- currentUserId={currentUserId}
108
- {...flatListProps}
109
- ref={scrollRef}
110
- data={messages}
111
- renderItem={renderItem}
112
- keyExtractor={messageKeyExtractor}
113
- contentContainerStyle={[
114
- // { minHeight: '100%', justifyContent: 'flex-end' },
115
- channel.isFrozen && styles.frozenListPadding,
116
- flatListProps?.contentContainerStyle,
117
- ]}
118
- />
119
- {renderNewMessagesButton && (
120
- <View style={[styles.newMsgButton, safeAreaLayout]}>
121
- {renderNewMessagesButton({
122
- visible: scrollLeaveBottom,
123
- onPress: () => scrollRef.current?.scrollToBottom(false),
124
- newMessages: !HANDLE_NEXT_MSG_SEPARATELY ? newMessagesInternalBuffer : newMessagesFromMembers,
125
- })}
126
- </View>
127
- )}
128
- {renderScrollToBottomButton && (
129
- <View pointerEvents={scrollLeaveBottom ? 'auto' : 'none'} style={[styles.scrollButton, safeAreaLayout]}>
130
- {renderScrollToBottomButton({
131
- visible: scrollLeaveBottom,
132
- onPress: () => scrollRef.current?.scrollToBottom(false),
133
- })}
134
- </View>
135
- )}
136
- </View>
137
- );
138
- };
139
-
140
- type HandleableMessage = SendbirdUserMessage | SendbirdFileMessage;
141
- const useGetMessagePressActions = ({
142
- currentUserId,
143
- onResendFailedMessage,
144
- onDeleteMessage,
145
- onPressMediaMessage,
146
- }: Pick<
147
- OpenChannelProps['MessageList'],
148
- 'channel' | 'currentUserId' | 'onResendFailedMessage' | 'onDeleteMessage' | 'onPressMediaMessage'
149
- >) => {
150
- const { colors } = useUIKitTheme();
151
- const { STRINGS } = useLocalization();
152
- const toast = useToast();
153
- const { openSheet } = useBottomSheet();
154
- const { alert } = useAlert();
155
- const { clipboardService, fileService } = usePlatformService();
10
+ const OpenChannelMessageList = (props: OpenChannelProps['MessageList']) => {
156
11
  const { setMessageToEdit } = useContext(OpenChannelContexts.Fragment);
12
+ const { subscribe } = useContext(OpenChannelContexts.PubSub);
157
13
 
158
- const handleFailedMessage = (message: HandleableMessage) => {
159
- openSheet({
160
- sheetItems: [
161
- {
162
- title: STRINGS.LABELS.CHANNEL_MESSAGE_FAILED_RETRY,
163
- onPress: () =>
164
- onResendFailedMessage(message).catch(() => toast.show(STRINGS.TOAST.RESEND_MSG_ERROR, 'error')),
165
- },
166
- {
167
- title: STRINGS.LABELS.CHANNEL_MESSAGE_FAILED_REMOVE,
168
- titleColor: colors.ui.dialog.default.none.destructive,
169
- onPress: () => confirmDelete(message),
170
- },
171
- ],
172
- });
173
- };
174
- const confirmDelete = (message: HandleableMessage) => {
175
- alert({
176
- title: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_TITLE,
177
- buttons: [
178
- {
179
- text: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_CANCEL,
180
- },
181
- {
182
- text: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE_CONFIRM_OK,
183
- style: 'destructive',
184
- onPress: () => onDeleteMessage(message).catch(() => toast.show(STRINGS.TOAST.DELETE_MSG_ERROR, 'error')),
185
- },
186
- ],
187
- });
188
- };
189
-
190
- return (msg: SendbirdMessage) => {
191
- if (!msg.isUserMessage() && !msg.isFileMessage()) {
192
- return { onPress: undefined, onLongPress: undefined };
193
- }
194
-
195
- const sheetItems: BottomSheetItem['sheetItems'] = [];
196
- const response: { onPress?: () => void; onLongPress?: () => void } = {
197
- onPress: undefined,
198
- onLongPress: undefined,
199
- };
14
+ const ref = useRef<FlatList<SendbirdMessage>>(null);
15
+ const [scrolledAwayFromBottom, setScrolledAwayFromBottom] = useState(false);
200
16
 
201
- if (msg.isUserMessage()) {
202
- sheetItems.push({
203
- icon: 'copy',
204
- title: STRINGS.LABELS.CHANNEL_MESSAGE_COPY,
205
- onPress: () => {
206
- clipboardService.setString(msg.message || '');
207
- toast.show(STRINGS.TOAST.COPY_OK, 'success');
208
- },
209
- });
210
-
211
- if (isMyMessage(msg, currentUserId) && msg.sendingStatus === 'succeeded') {
212
- sheetItems.push(
213
- {
214
- icon: 'edit',
215
- title: STRINGS.LABELS.CHANNEL_MESSAGE_EDIT,
216
- onPress: () => setMessageToEdit(msg),
217
- },
218
- {
219
- icon: 'delete',
220
- title: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE,
221
- onPress: () => confirmDelete(msg),
222
- },
223
- );
224
- }
225
- }
226
-
227
- if (msg.isFileMessage()) {
228
- sheetItems.push({
229
- icon: 'download',
230
- title: STRINGS.LABELS.CHANNEL_MESSAGE_SAVE,
231
- onPress: async () => {
232
- if (toMegabyte(msg.size) > 4) {
233
- toast.show(STRINGS.TOAST.DOWNLOAD_START, 'success');
234
- }
235
-
236
- fileService
237
- .save({ fileUrl: msg.url, fileName: msg.name, fileType: msg.type })
238
- .then((response) => {
239
- toast.show(STRINGS.TOAST.DOWNLOAD_OK, 'success');
240
- Logger.log('File saved to', response);
241
- })
242
- .catch((err) => {
243
- toast.show(STRINGS.TOAST.DOWNLOAD_ERROR, 'error');
244
- Logger.log('File save failure', err);
245
- });
246
- },
247
- });
248
-
249
- if (isMyMessage(msg, currentUserId) && msg.sendingStatus === 'succeeded') {
250
- sheetItems.push({
251
- icon: 'delete',
252
- title: STRINGS.LABELS.CHANNEL_MESSAGE_DELETE,
253
- onPress: () => confirmDelete(msg),
254
- });
255
- }
17
+ const scrollToBottom = useFreshCallback((animated = false) => {
18
+ // FIXME: Workaround, should run after data has been applied to UI.
19
+ setTimeout(() => {
20
+ ref.current?.scrollToOffset({ offset: 0, animated });
21
+ }, 0);
22
+ });
256
23
 
257
- const fileType = getFileType(msg.type || getFileExtension(msg.name));
258
- switch (fileType) {
259
- case 'image':
260
- case 'video':
261
- case 'audio': {
262
- response.onPress = () => {
263
- onPressMediaMessage?.(msg, () => onDeleteMessage(msg), getAvailableUriFromFileMessage(msg));
264
- };
24
+ useEffect(() => {
25
+ return subscribe(({ type }) => {
26
+ switch (type) {
27
+ case 'MESSAGES_RECEIVED': {
28
+ scrollToBottom(false);
265
29
  break;
266
30
  }
267
- default: {
268
- response.onPress = () => SBUUtils.openURL(msg.url);
31
+ case 'MESSAGE_SENT_SUCCESS':
32
+ case 'MESSAGE_SENT_PENDING': {
33
+ scrollToBottom(false);
269
34
  break;
270
35
  }
271
36
  }
272
- }
273
-
274
- if (sheetItems.length > 0) {
275
- response.onLongPress = () => {
276
- openSheet({ sheetItems });
277
- };
278
- }
279
-
280
- if (msg.sendingStatus === 'failed') {
281
- response.onLongPress = () => handleFailedMessage(msg);
282
- response.onPress = () => {
283
- onResendFailedMessage(msg).catch(() => toast.show(STRINGS.TOAST.RESEND_MSG_ERROR, 'error'));
284
- };
285
- }
286
-
287
- if (msg.sendingStatus === 'pending') {
288
- response.onLongPress = undefined;
289
- response.onPress = undefined;
290
- }
37
+ });
38
+ }, []);
291
39
 
292
- return response;
293
- };
40
+ return (
41
+ <ChannelMessageList
42
+ {...props}
43
+ ref={ref}
44
+ onPressScrollToBottomButton={scrollToBottom}
45
+ onPressNewMessagesButton={scrollToBottom}
46
+ scrolledAwayFromBottom={scrolledAwayFromBottom}
47
+ onScrolledAwayFromBottom={setScrolledAwayFromBottom}
48
+ onEditMessage={setMessageToEdit}
49
+ />
50
+ );
294
51
  };
295
52
 
296
- const styles = createStyleSheet({
297
- frozenBanner: {
298
- position: 'absolute',
299
- zIndex: 999,
300
- top: 8,
301
- left: 8,
302
- right: 8,
303
- },
304
- frozenListPadding: {
305
- paddingBottom: 32,
306
- },
307
- newMsgButton: {
308
- position: 'absolute',
309
- zIndex: 999,
310
- bottom: 10,
311
- alignSelf: 'center',
312
- },
313
- scrollButton: {
314
- position: 'absolute',
315
- zIndex: 998,
316
- bottom: 10,
317
- right: 16,
318
- },
319
- });
320
-
321
53
  export default React.memo(OpenChannelMessageList);
@@ -5,7 +5,8 @@ import { NOOP, SendbirdFileMessage, SendbirdUserMessage } from '@sendbird/uikit-
5
5
 
6
6
  import ProviderLayout from '../../../components/ProviderLayout';
7
7
  import { useLocalization } from '../../../hooks/useContext';
8
- import type { OpenChannelContextsType, OpenChannelModule } from '../types';
8
+ import type { PubSub } from '../../../utils/pubsub';
9
+ import type { OpenChannelContextsType, OpenChannelModule, OpenChannelPubSubContextPayload } from '../types';
9
10
 
10
11
  export const OpenChannelContexts: OpenChannelContextsType = {
11
12
  Fragment: createContext({
@@ -13,12 +14,17 @@ export const OpenChannelContexts: OpenChannelContextsType = {
13
14
  channel: {} as SendbirdOpenChannel,
14
15
  setMessageToEdit: NOOP,
15
16
  }),
17
+ PubSub: createContext({
18
+ publish: NOOP,
19
+ subscribe: () => NOOP,
20
+ } as PubSub<OpenChannelPubSubContextPayload>),
16
21
  };
17
22
 
18
23
  export const OpenChannelContextsProvider: OpenChannelModule['Provider'] = ({
19
24
  children,
20
25
  channel,
21
26
  keyboardAvoidOffset,
27
+ openChannelPubSub,
22
28
  }) => {
23
29
  const { STRINGS } = useLocalization();
24
30
  const [messageToEdit, setMessageToEdit] = useState<SendbirdUserMessage | SendbirdFileMessage>();
@@ -34,7 +40,7 @@ export const OpenChannelContextsProvider: OpenChannelModule['Provider'] = ({
34
40
  setMessageToEdit,
35
41
  }}
36
42
  >
37
- {children}
43
+ <OpenChannelContexts.PubSub.Provider value={openChannelPubSub}>{children}</OpenChannelContexts.PubSub.Provider>
38
44
  </OpenChannelContexts.Fragment.Provider>
39
45
  </ProviderLayout>
40
46
  );
@@ -1,5 +1,4 @@
1
1
  import type React from 'react';
2
- import type { FlatListProps } from 'react-native';
3
2
 
4
3
  import type { UseOpenChannelMessagesOptions } from '@sendbird/uikit-chat-hooks';
5
4
  import type { Icon } from '@sendbird/uikit-react-native-foundation';
@@ -16,8 +15,10 @@ import type {
16
15
  } from '@sendbird/uikit-utils';
17
16
 
18
17
  import type { ChannelInputProps } from '../../components/ChannelInput';
19
- import type { UserProfileContextType } from '../../contexts/UserProfileCtx';
18
+ import type { ChannelMessageListProps } from '../../components/ChannelMessageList';
20
19
  import type { CommonComponent } from '../../types';
20
+ import type { PubSub } from '../../utils/pubsub';
21
+ import type { GroupChannelPubSubContextPayload } from '../groupChannel/types';
21
22
 
22
23
  export type OpenChannelProps = {
23
24
  Fragment: {
@@ -50,42 +51,27 @@ export type OpenChannelProps = {
50
51
  onPressHeaderRight: () => void;
51
52
  };
52
53
 
53
- MessageList: {
54
- enableMessageGrouping: boolean;
55
- currentUserId?: string;
56
- channel: SendbirdOpenChannel;
57
- messages: SendbirdMessage[];
58
- nextMessages: SendbirdMessage[];
59
- newMessagesFromMembers: SendbirdMessage[];
60
- onTopReached: () => void;
61
- onBottomReached: () => void;
62
-
63
- onResendFailedMessage: (failedMessage: SendbirdUserMessage | SendbirdFileMessage) => Promise<void>;
64
- onDeleteMessage: (message: SendbirdUserMessage | SendbirdFileMessage) => Promise<void>;
65
- onPressMediaMessage?: (message: SendbirdFileMessage, deleteMessage: () => Promise<void>, uri: string) => void;
66
-
67
- renderMessage: (props: {
68
- message: SendbirdMessage;
69
- prevMessage?: SendbirdMessage;
70
- nextMessage?: SendbirdMessage;
71
- onPress?: () => void;
72
- onLongPress?: () => void;
73
- onPressAvatar?: UserProfileContextType['show'];
74
- channel: OpenChannelProps['MessageList']['channel'];
75
- currentUserId?: OpenChannelProps['MessageList']['currentUserId'];
76
- enableMessageGrouping: OpenChannelProps['MessageList']['enableMessageGrouping'];
77
- }) => React.ReactElement | null;
78
- renderNewMessagesButton: null | CommonComponent<{
79
- visible: boolean;
80
- onPress: () => void;
81
- newMessages: SendbirdMessage[];
82
- }>;
83
- renderScrollToBottomButton: null | CommonComponent<{
84
- visible: boolean;
85
- onPress: () => void;
86
- }>;
87
- flatListProps?: Omit<FlatListProps<SendbirdMessage>, 'data' | 'renderItem'>;
88
- };
54
+ MessageList: Pick<
55
+ ChannelMessageListProps<SendbirdOpenChannel>,
56
+ | 'enableMessageGrouping'
57
+ | 'currentUserId'
58
+ | 'channel'
59
+ | 'messages'
60
+ | 'newMessages'
61
+ | 'scrolledAwayFromBottom'
62
+ | 'onScrolledAwayFromBottom'
63
+ | 'onTopReached'
64
+ | 'onBottomReached'
65
+ | 'onResendFailedMessage'
66
+ | 'onDeleteMessage'
67
+ | 'onPressMediaMessage'
68
+ | 'renderMessage'
69
+ | 'renderNewMessagesButton'
70
+ | 'renderScrollToBottomButton'
71
+ | 'flatListProps'
72
+ | 'onPressImageMessage'
73
+ | 'hasNext'
74
+ >;
89
75
  Input: Pick<
90
76
  ChannelInputProps,
91
77
  | 'shouldRenderInput'
@@ -98,6 +84,7 @@ export type OpenChannelProps = {
98
84
  Provider: {
99
85
  channel: SendbirdOpenChannel;
100
86
  keyboardAvoidOffset?: number;
87
+ openChannelPubSub: PubSub<OpenChannelPubSubContextPayload>;
101
88
  };
102
89
  };
103
90
 
@@ -114,6 +101,7 @@ export type OpenChannelContextsType = {
114
101
  setMessageToEdit: (msg?: SendbirdUserMessage | SendbirdFileMessage) => void;
115
102
  keyboardAvoidOffset?: number;
116
103
  }>;
104
+ PubSub: React.Context<PubSub<GroupChannelPubSubContextPayload>>;
117
105
  };
118
106
  export interface OpenChannelModule {
119
107
  Provider: CommonComponent<OpenChannelProps['Provider']>;
@@ -125,3 +113,17 @@ export interface OpenChannelModule {
125
113
  }
126
114
 
127
115
  export type OpenChannelFragment = CommonComponent<OpenChannelProps['Fragment']>;
116
+
117
+ export type OpenChannelPubSubContextPayload =
118
+ | {
119
+ type: 'MESSAGE_SENT_PENDING' | 'MESSAGE_SENT_SUCCESS';
120
+ data: {
121
+ message: SendbirdUserMessage | SendbirdFileMessage;
122
+ };
123
+ }
124
+ | {
125
+ type: 'MESSAGES_RECEIVED';
126
+ data: {
127
+ messages: SendbirdMessage[];
128
+ };
129
+ };