@sendbird/uikit-react-native 3.5.4 → 3.7.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 (251) hide show
  1. package/README.md +11 -27
  2. package/lib/commonjs/components/ChannelInput/SendInput.js +23 -6
  3. package/lib/commonjs/components/ChannelInput/SendInput.js.map +1 -1
  4. package/lib/commonjs/components/ChannelInput/index.js.map +1 -1
  5. package/lib/commonjs/components/ChannelMessageList/index.js +22 -4
  6. package/lib/commonjs/components/ChannelMessageList/index.js.map +1 -1
  7. package/lib/commonjs/components/ChannelThreadMessageList/index.js +349 -0
  8. package/lib/commonjs/components/ChannelThreadMessageList/index.js.map +1 -0
  9. package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js +2 -2
  10. package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js.map +1 -1
  11. package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.js +100 -0
  12. package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.js.map +1 -0
  13. package/lib/commonjs/components/GroupChannelMessageRenderer/index.js +24 -6
  14. package/lib/commonjs/components/GroupChannelMessageRenderer/index.js.map +1 -1
  15. package/lib/commonjs/components/ReactionAddons/MessageReactionAddon.js +23 -6
  16. package/lib/commonjs/components/ReactionAddons/MessageReactionAddon.js.map +1 -1
  17. package/lib/commonjs/components/ThreadChatFlatList/index.js +76 -0
  18. package/lib/commonjs/components/ThreadChatFlatList/index.js.map +1 -0
  19. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.js +41 -0
  20. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.js.map +1 -0
  21. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.js +74 -0
  22. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.js.map +1 -0
  23. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.js +42 -0
  24. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.js.map +1 -0
  25. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.js +94 -0
  26. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.js.map +1 -0
  27. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.user.js +61 -0
  28. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.user.js.map +1 -0
  29. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.js +127 -0
  30. package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.js.map +1 -0
  31. package/lib/commonjs/components/ThreadParentMessageRenderer/index.js +206 -0
  32. package/lib/commonjs/components/ThreadParentMessageRenderer/index.js.map +1 -0
  33. package/lib/commonjs/containers/SendbirdUIKitContainer.js +12 -11
  34. package/lib/commonjs/containers/SendbirdUIKitContainer.js.map +1 -1
  35. package/lib/commonjs/contexts/SendbirdChatCtx.js +7 -0
  36. package/lib/commonjs/contexts/SendbirdChatCtx.js.map +1 -1
  37. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +28 -5
  38. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  39. package/lib/commonjs/domain/groupChannel/module/moduleContext.js +14 -4
  40. package/lib/commonjs/domain/groupChannel/module/moduleContext.js.map +1 -1
  41. package/lib/commonjs/domain/groupChannel/types.js.map +1 -1
  42. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadHeader.js +82 -0
  43. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadHeader.js.map +1 -0
  44. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadInput.js +44 -0
  45. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadInput.js.map +1 -0
  46. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadMessageList.js +127 -0
  47. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadMessageList.js.map +1 -0
  48. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.js +315 -0
  49. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.js.map +1 -0
  50. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.js +27 -0
  51. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.js.map +1 -0
  52. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.js +27 -0
  53. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.js.map +1 -0
  54. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.js +195 -0
  55. package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.js.map +1 -0
  56. package/lib/commonjs/domain/groupChannelThread/index.js +69 -0
  57. package/lib/commonjs/domain/groupChannelThread/index.js.map +1 -0
  58. package/lib/commonjs/domain/groupChannelThread/module/createGroupChannelThreadModule.js +42 -0
  59. package/lib/commonjs/domain/groupChannelThread/module/createGroupChannelThreadModule.js.map +1 -0
  60. package/lib/commonjs/domain/groupChannelThread/module/moduleContext.js +148 -0
  61. package/lib/commonjs/domain/groupChannelThread/module/moduleContext.js.map +1 -0
  62. package/lib/commonjs/domain/groupChannelThread/types.js +6 -0
  63. package/lib/commonjs/domain/groupChannelThread/types.js.map +1 -0
  64. package/lib/commonjs/fragments/createGroupChannelFragment.js +30 -5
  65. package/lib/commonjs/fragments/createGroupChannelFragment.js.map +1 -1
  66. package/lib/commonjs/fragments/createGroupChannelThreadFragment.js +267 -0
  67. package/lib/commonjs/fragments/createGroupChannelThreadFragment.js.map +1 -0
  68. package/lib/commonjs/hooks/useMentionSuggestion.js +5 -2
  69. package/lib/commonjs/hooks/useMentionSuggestion.js.map +1 -1
  70. package/lib/commonjs/index.js +72 -40
  71. package/lib/commonjs/index.js.map +1 -1
  72. package/lib/commonjs/libs/EmojiManager.js.map +1 -1
  73. package/lib/commonjs/libs/InternalLocalCacheStorage.js +65 -19
  74. package/lib/commonjs/libs/InternalLocalCacheStorage.js.map +1 -1
  75. package/lib/commonjs/libs/VoiceMessageStatusManager.js +66 -0
  76. package/lib/commonjs/libs/VoiceMessageStatusManager.js.map +1 -0
  77. package/lib/commonjs/localization/StringSet.type.js.map +1 -1
  78. package/lib/commonjs/localization/createBaseStringSet.js +25 -3
  79. package/lib/commonjs/localization/createBaseStringSet.js.map +1 -1
  80. package/lib/commonjs/platform/createMediaService.native.js.map +1 -1
  81. package/lib/commonjs/types.js.map +1 -1
  82. package/lib/commonjs/version.js +1 -1
  83. package/lib/commonjs/version.js.map +1 -1
  84. package/lib/module/components/ChannelInput/SendInput.js +23 -6
  85. package/lib/module/components/ChannelInput/SendInput.js.map +1 -1
  86. package/lib/module/components/ChannelInput/index.js.map +1 -1
  87. package/lib/module/components/ChannelMessageList/index.js +22 -4
  88. package/lib/module/components/ChannelMessageList/index.js.map +1 -1
  89. package/lib/module/components/ChannelThreadMessageList/index.js +341 -0
  90. package/lib/module/components/ChannelThreadMessageList/index.js.map +1 -0
  91. package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js +2 -2
  92. package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js.map +1 -1
  93. package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.js +92 -0
  94. package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.js.map +1 -0
  95. package/lib/module/components/GroupChannelMessageRenderer/index.js +24 -6
  96. package/lib/module/components/GroupChannelMessageRenderer/index.js.map +1 -1
  97. package/lib/module/components/ReactionAddons/MessageReactionAddon.js +23 -6
  98. package/lib/module/components/ReactionAddons/MessageReactionAddon.js.map +1 -1
  99. package/lib/module/components/ThreadChatFlatList/index.js +66 -0
  100. package/lib/module/components/ThreadChatFlatList/index.js.map +1 -0
  101. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.js +34 -0
  102. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.js.map +1 -0
  103. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.js +67 -0
  104. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.js.map +1 -0
  105. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.js +34 -0
  106. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.js.map +1 -0
  107. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.js +87 -0
  108. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.js.map +1 -0
  109. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.user.js +54 -0
  110. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.user.js.map +1 -0
  111. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.js +119 -0
  112. package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.js.map +1 -0
  113. package/lib/module/components/ThreadParentMessageRenderer/index.js +196 -0
  114. package/lib/module/components/ThreadParentMessageRenderer/index.js.map +1 -0
  115. package/lib/module/containers/SendbirdUIKitContainer.js +13 -12
  116. package/lib/module/containers/SendbirdUIKitContainer.js.map +1 -1
  117. package/lib/module/contexts/SendbirdChatCtx.js +6 -0
  118. package/lib/module/contexts/SendbirdChatCtx.js.map +1 -1
  119. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +30 -6
  120. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  121. package/lib/module/domain/groupChannel/module/moduleContext.js +14 -4
  122. package/lib/module/domain/groupChannel/module/moduleContext.js.map +1 -1
  123. package/lib/module/domain/groupChannel/types.js.map +1 -1
  124. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadHeader.js +73 -0
  125. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadHeader.js.map +1 -0
  126. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadInput.js +34 -0
  127. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadInput.js.map +1 -0
  128. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadMessageList.js +117 -0
  129. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadMessageList.js.map +1 -0
  130. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.js +305 -0
  131. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.js.map +1 -0
  132. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.js +19 -0
  133. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.js.map +1 -0
  134. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.js +19 -0
  135. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.js.map +1 -0
  136. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.js +185 -0
  137. package/lib/module/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.js.map +1 -0
  138. package/lib/module/domain/groupChannelThread/index.js +9 -0
  139. package/lib/module/domain/groupChannelThread/index.js.map +1 -0
  140. package/lib/module/domain/groupChannelThread/module/createGroupChannelThreadModule.js +34 -0
  141. package/lib/module/domain/groupChannelThread/module/createGroupChannelThreadModule.js.map +1 -0
  142. package/lib/module/domain/groupChannelThread/module/moduleContext.js +137 -0
  143. package/lib/module/domain/groupChannelThread/module/moduleContext.js.map +1 -0
  144. package/lib/module/domain/groupChannelThread/types.js +2 -0
  145. package/lib/module/domain/groupChannelThread/types.js.map +1 -0
  146. package/lib/module/fragments/createGroupChannelFragment.js +33 -7
  147. package/lib/module/fragments/createGroupChannelFragment.js.map +1 -1
  148. package/lib/module/fragments/createGroupChannelThreadFragment.js +257 -0
  149. package/lib/module/fragments/createGroupChannelThreadFragment.js.map +1 -0
  150. package/lib/module/hooks/useMentionSuggestion.js +5 -2
  151. package/lib/module/hooks/useMentionSuggestion.js.map +1 -1
  152. package/lib/module/index.js +3 -0
  153. package/lib/module/index.js.map +1 -1
  154. package/lib/module/libs/EmojiManager.js.map +1 -1
  155. package/lib/module/libs/InternalLocalCacheStorage.js +65 -19
  156. package/lib/module/libs/InternalLocalCacheStorage.js.map +1 -1
  157. package/lib/module/libs/VoiceMessageStatusManager.js +59 -0
  158. package/lib/module/libs/VoiceMessageStatusManager.js.map +1 -0
  159. package/lib/module/localization/StringSet.type.js.map +1 -1
  160. package/lib/module/localization/createBaseStringSet.js +27 -4
  161. package/lib/module/localization/createBaseStringSet.js.map +1 -1
  162. package/lib/module/platform/createMediaService.native.js.map +1 -1
  163. package/lib/module/types.js.map +1 -1
  164. package/lib/module/version.js +1 -1
  165. package/lib/module/version.js.map +1 -1
  166. package/lib/typescript/src/components/ChannelInput/index.d.ts +1 -0
  167. package/lib/typescript/src/components/ChannelMessageList/index.d.ts +5 -2
  168. package/lib/typescript/src/components/ChannelThreadMessageList/index.d.ts +55 -0
  169. package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.d.ts +1 -1
  170. package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.d.ts +9 -0
  171. package/lib/typescript/src/components/GroupChannelMessageRenderer/index.d.ts +3 -1
  172. package/lib/typescript/src/components/OpenChannelMessageRenderer/index.d.ts +3 -1
  173. package/lib/typescript/src/components/ReactionAddons/MessageReactionAddon.d.ts +3 -1
  174. package/lib/typescript/src/components/ReactionAddons/index.d.ts +2 -1
  175. package/lib/typescript/src/components/ThreadChatFlatList/index.d.ts +9 -0
  176. package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.d.ts +4 -0
  177. package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.d.ts +4 -0
  178. package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.d.ts +9 -0
  179. package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.d.ts +13 -0
  180. package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.user.d.ts +10 -0
  181. package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.d.ts +10 -0
  182. package/lib/typescript/src/components/ThreadParentMessageRenderer/index.d.ts +20 -0
  183. package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +8 -10
  184. package/lib/typescript/src/contexts/SendbirdChatCtx.d.ts +15 -1
  185. package/lib/typescript/src/domain/groupChannel/types.d.ts +4 -1
  186. package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadHeader.d.ts +4 -0
  187. package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadInput.d.ts +3 -0
  188. package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadMessageList.d.ts +7 -0
  189. package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.d.ts +8 -0
  190. package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.d.ts +3 -0
  191. package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.d.ts +3 -0
  192. package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.d.ts +4 -0
  193. package/lib/typescript/src/domain/groupChannelThread/index.d.ts +8 -0
  194. package/lib/typescript/src/domain/groupChannelThread/module/createGroupChannelThreadModule.d.ts +3 -0
  195. package/lib/typescript/src/domain/groupChannelThread/module/moduleContext.d.ts +3 -0
  196. package/lib/typescript/src/domain/groupChannelThread/types.d.ts +136 -0
  197. package/lib/typescript/src/domain/openChannel/component/OpenChannelHeader.d.ts +1 -1
  198. package/lib/typescript/src/fragments/createGroupChannelThreadFragment.d.ts +5 -0
  199. package/lib/typescript/src/hooks/useChannelInputItems.d.ts +1 -1
  200. package/lib/typescript/src/index.d.ts +3 -0
  201. package/lib/typescript/src/libs/InternalLocalCacheStorage.d.ts +5 -4
  202. package/lib/typescript/src/libs/VoiceMessageStatusManager.d.ts +11 -0
  203. package/lib/typescript/src/localization/StringSet.type.d.ts +23 -0
  204. package/lib/typescript/src/localization/createBaseStringSet.d.ts +1 -1
  205. package/lib/typescript/src/types.d.ts +4 -1
  206. package/lib/typescript/src/version.d.ts +1 -1
  207. package/package.json +27 -22
  208. package/src/components/ChannelInput/SendInput.tsx +24 -5
  209. package/src/components/ChannelInput/index.tsx +1 -0
  210. package/src/components/ChannelMessageList/index.tsx +27 -5
  211. package/src/components/ChannelThreadMessageList/index.tsx +406 -0
  212. package/src/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.tsx +3 -3
  213. package/src/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.tsx +96 -0
  214. package/src/components/GroupChannelMessageRenderer/index.tsx +21 -5
  215. package/src/components/ReactionAddons/MessageReactionAddon.tsx +38 -5
  216. package/src/components/ThreadChatFlatList/index.tsx +63 -0
  217. package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.tsx +36 -0
  218. package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.tsx +61 -0
  219. package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.tsx +45 -0
  220. package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.tsx +107 -0
  221. package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.tsx +133 -0
  222. package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.user.tsx +65 -0
  223. package/src/components/ThreadParentMessageRenderer/index.tsx +194 -0
  224. package/src/containers/SendbirdUIKitContainer.tsx +28 -17
  225. package/src/contexts/SendbirdChatCtx.tsx +20 -0
  226. package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +37 -8
  227. package/src/domain/groupChannel/module/moduleContext.tsx +12 -2
  228. package/src/domain/groupChannel/types.ts +5 -0
  229. package/src/domain/groupChannelThread/component/GroupChannelThreadHeader.tsx +63 -0
  230. package/src/domain/groupChannelThread/component/GroupChannelThreadInput.tsx +38 -0
  231. package/src/domain/groupChannelThread/component/GroupChannelThreadMessageList.tsx +105 -0
  232. package/src/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.tsx +326 -0
  233. package/src/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.tsx +18 -0
  234. package/src/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.tsx +18 -0
  235. package/src/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.tsx +174 -0
  236. package/src/domain/groupChannelThread/index.ts +8 -0
  237. package/src/domain/groupChannelThread/module/createGroupChannelThreadModule.tsx +35 -0
  238. package/src/domain/groupChannelThread/module/moduleContext.tsx +165 -0
  239. package/src/domain/groupChannelThread/types.ts +184 -0
  240. package/src/fragments/createGroupChannelFragment.tsx +38 -8
  241. package/src/fragments/createGroupChannelThreadFragment.tsx +280 -0
  242. package/src/hooks/useMentionSuggestion.ts +13 -9
  243. package/src/index.ts +4 -0
  244. package/src/libs/EmojiManager.ts +2 -2
  245. package/src/libs/InternalLocalCacheStorage.ts +70 -21
  246. package/src/libs/VoiceMessageStatusManager.ts +56 -0
  247. package/src/localization/StringSet.type.ts +27 -0
  248. package/src/localization/createBaseStringSet.ts +33 -4
  249. package/src/platform/createMediaService.native.tsx +9 -1
  250. package/src/types.ts +6 -1
  251. package/src/version.ts +1 -1
@@ -3,6 +3,7 @@ import { Pressable } from 'react-native';
3
3
 
4
4
  import type { Emoji } from '@sendbird/chat';
5
5
  import { createStyleSheet, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
6
+ import { useForceUpdate, useGroupChannelHandler } from '@sendbird/uikit-tools';
6
7
  import type { SendbirdBaseChannel, SendbirdBaseMessage, SendbirdReaction } from '@sendbird/uikit-utils';
7
8
  import { getReactionCount } from '@sendbird/uikit-utils';
8
9
 
@@ -12,6 +13,7 @@ import ReactionRoundedButton from './ReactionRoundedButton';
12
13
 
13
14
  const NUM_COL = 4;
14
15
  const REACTION_MORE_KEY = 'reaction-more-button';
16
+ export type ReactionAddonType = 'default' | 'thread_parent_message';
15
17
 
16
18
  const getUserReacted = (reaction: SendbirdReaction, userId = UNKNOWN_USER_ID) => {
17
19
  return reaction.userIds.indexOf(userId) > -1;
@@ -40,6 +42,7 @@ const createReactionButtons = (
40
42
  onOpenReactionList: () => void,
41
43
  onOpenReactionUserList: (focusIndex: number) => void,
42
44
  currentUserId?: string,
45
+ reactionAddonType?: ReactionAddonType,
43
46
  ) => {
44
47
  const reactions = message.reactions ?? [];
45
48
  const buttons = reactions.map((reaction, index) => {
@@ -57,7 +60,11 @@ const createReactionButtons = (
57
60
  url={getEmoji(reaction.key).url}
58
61
  count={getReactionCount(reaction)}
59
62
  reacted={pressed || getUserReacted(reaction, currentUserId)}
60
- style={[isNotLastOfRow && styles.marginRight, isNotLastOfCol && styles.marginBottom]}
63
+ style={
64
+ reactionAddonType === 'default'
65
+ ? [isNotLastOfRow && styles.marginRight, isNotLastOfCol && styles.marginBottom]
66
+ : [styles.marginRight, styles.marginBottom]
67
+ }
61
68
  />
62
69
  )}
63
70
  </Pressable>
@@ -74,12 +81,30 @@ const createReactionButtons = (
74
81
  return buttons;
75
82
  };
76
83
 
77
- const MessageReactionAddon = ({ channel, message }: { channel: SendbirdBaseChannel; message: SendbirdBaseMessage }) => {
84
+ const MessageReactionAddon = ({
85
+ channel,
86
+ message,
87
+ reactionAddonType = 'default',
88
+ }: {
89
+ channel: SendbirdBaseChannel;
90
+ message: SendbirdBaseMessage;
91
+ reactionAddonType?: ReactionAddonType;
92
+ }) => {
78
93
  const { colors } = useUIKitTheme();
79
- const { emojiManager, currentUser } = useSendbirdChat();
94
+ const { sdk, emojiManager, currentUser } = useSendbirdChat();
80
95
  const { openReactionList, openReactionUserList } = useReaction();
96
+ const forceUpdate = useForceUpdate();
81
97
 
82
- if (!message.reactions?.length) return null;
98
+ useGroupChannelHandler(sdk, {
99
+ async onReactionUpdated(_, event) {
100
+ if (event.messageId === message.messageId) {
101
+ message.applyReactionEvent(event);
102
+ forceUpdate();
103
+ }
104
+ },
105
+ });
106
+
107
+ if (reactionAddonType === 'default' && !message.reactions?.length) return null;
83
108
 
84
109
  const reactionButtons = createReactionButtons(
85
110
  channel,
@@ -89,12 +114,16 @@ const MessageReactionAddon = ({ channel, message }: { channel: SendbirdBaseChann
89
114
  () => openReactionList({ channel, message }),
90
115
  (focusIndex) => openReactionUserList({ channel, message, focusIndex }),
91
116
  currentUser?.userId,
117
+ reactionAddonType,
92
118
  );
93
119
 
120
+ const containerStyle =
121
+ reactionAddonType === 'default' ? styles.reactionContainer : styles.reactionThreadParentMessageContainer;
122
+
94
123
  return (
95
124
  <Pressable
96
125
  style={[
97
- styles.reactionContainer,
126
+ containerStyle,
98
127
  { backgroundColor: colors.background, borderColor: colors.ui.reaction.rounded.enabled.background },
99
128
  ]}
100
129
  >
@@ -112,6 +141,10 @@ const styles = createStyleSheet({
112
141
  borderRadius: 16,
113
142
  borderWidth: 1,
114
143
  },
144
+ reactionThreadParentMessageContainer: {
145
+ flexDirection: 'row',
146
+ flexWrap: 'wrap',
147
+ },
115
148
  marginRight: {
116
149
  marginRight: 4.5,
117
150
  },
@@ -0,0 +1,63 @@
1
+ import React, { forwardRef, useRef } from 'react';
2
+ import { FlatListProps, FlatList as RNFlatList, StyleSheet } from 'react-native';
3
+
4
+ import { useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
5
+ import { NOOP, SendbirdMessage, getMessageUniqId, useFreshCallback } from '@sendbird/uikit-utils';
6
+
7
+ import FlatListInternal from '../ChatFlatList/FlatListInternal';
8
+
9
+ const BOTTOM_DETECT_THRESHOLD = 50;
10
+ const UNREACHABLE_THRESHOLD = Number.MIN_SAFE_INTEGER;
11
+
12
+ type Props = Omit<FlatListProps<SendbirdMessage>, 'onEndReached'> & {
13
+ onBottomReached: () => void;
14
+ onTopReached: () => void;
15
+ onScrolledAwayFromBottom: (value: boolean) => void;
16
+ };
17
+ const ThreadChatFlatList = forwardRef<RNFlatList, Props>(function ThreadChatFlatList(
18
+ { onTopReached, onBottomReached, onScrolledAwayFromBottom, onScroll, ...props },
19
+ ref,
20
+ ) {
21
+ const { select } = useUIKitTheme();
22
+ const contentOffsetY = useRef(0);
23
+
24
+ const _onScroll = useFreshCallback<NonNullable<Props['onScroll']>>((event) => {
25
+ onScroll?.(event);
26
+
27
+ const { contentOffset, contentSize, layoutMeasurement } = event.nativeEvent;
28
+
29
+ const prevOffsetY = contentOffsetY.current;
30
+ const currOffsetY = contentOffset.y;
31
+
32
+ const bottomDetectThreshold = contentSize.height - layoutMeasurement.height - BOTTOM_DETECT_THRESHOLD;
33
+ if (bottomDetectThreshold < prevOffsetY && currOffsetY <= bottomDetectThreshold) {
34
+ onScrolledAwayFromBottom(true);
35
+ } else if (bottomDetectThreshold < currOffsetY && prevOffsetY <= bottomDetectThreshold) {
36
+ onScrolledAwayFromBottom(false);
37
+ }
38
+
39
+ contentOffsetY.current = contentOffset.y;
40
+ });
41
+
42
+ return (
43
+ <FlatListInternal
44
+ bounces={false}
45
+ removeClippedSubviews
46
+ keyboardDismissMode={'on-drag'}
47
+ keyboardShouldPersistTaps={'handled'}
48
+ indicatorStyle={select({ light: 'black', dark: 'white' })}
49
+ {...props}
50
+ ref={ref}
51
+ onEndReached={onBottomReached}
52
+ onScrollToIndexFailed={NOOP}
53
+ onStartReached={onTopReached}
54
+ scrollEventThrottle={16}
55
+ onScroll={_onScroll}
56
+ keyExtractor={getMessageUniqId}
57
+ style={{ flex: 1, ...StyleSheet.flatten(props.style) }}
58
+ maintainVisibleContentPosition={{ minIndexForVisible: 0, autoscrollToTopThreshold: UNREACHABLE_THRESHOLD }}
59
+ />
60
+ );
61
+ });
62
+
63
+ export default ThreadChatFlatList;
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+
3
+ import { Box, PressBox, createStyleSheet } from '@sendbird/uikit-react-native-foundation';
4
+ import { ImageWithPlaceholder } from '@sendbird/uikit-react-native-foundation';
5
+ import { SendbirdFileMessage, getThumbnailUriFromFileMessage } from '@sendbird/uikit-utils';
6
+
7
+ import { ThreadParentMessageRendererProps } from './index';
8
+
9
+ const ThreadParentMessageFileImage = (props: ThreadParentMessageRendererProps) => {
10
+ const fileMessage: SendbirdFileMessage = props.parentMessage as SendbirdFileMessage;
11
+ if (!fileMessage) return null;
12
+
13
+ return (
14
+ <Box style={styles.container}>
15
+ <PressBox onPress={props.onPress} onLongPress={props.onLongPress}>
16
+ <ImageWithPlaceholder source={{ uri: getThumbnailUriFromFileMessage(fileMessage) }} style={styles.image} />
17
+ </PressBox>
18
+ </Box>
19
+ );
20
+ };
21
+
22
+ const styles = createStyleSheet({
23
+ container: {
24
+ borderRadius: 16,
25
+ overflow: 'hidden',
26
+ },
27
+ image: {
28
+ maxWidth: 240,
29
+ width: 240,
30
+ height: 160,
31
+ borderRadius: 16,
32
+ overflow: 'hidden',
33
+ },
34
+ });
35
+
36
+ export default ThreadParentMessageFileImage;
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+
3
+ import { Box, Icon, PressBox, Text, createStyleSheet } from '@sendbird/uikit-react-native-foundation';
4
+ import { useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
5
+ import { SendbirdFileMessage, getFileExtension, getFileType, truncate } from '@sendbird/uikit-utils';
6
+
7
+ import { useLocalization } from './../../hooks/useContext';
8
+ import { ThreadParentMessageRendererProps } from './index';
9
+
10
+ const ThreadParentMessageFile = (props: ThreadParentMessageRendererProps) => {
11
+ const fileMessage: SendbirdFileMessage = props.parentMessage as SendbirdFileMessage;
12
+ if (!fileMessage) return null;
13
+
14
+ const { STRINGS } = useLocalization();
15
+ const { select, colors, palette } = useUIKitTheme();
16
+
17
+ const fileType = getFileType(fileMessage.type || getFileExtension(fileMessage.name));
18
+ const fileName = STRINGS.GROUP_CHANNEL.MESSAGE_BUBBLE_FILE_TITLE(fileMessage) ?? fileMessage.name;
19
+
20
+ return (
21
+ <Box
22
+ style={styles.fileBubbleContainer}
23
+ backgroundColor={select({ light: palette.background100, dark: palette.background400 })}
24
+ >
25
+ <PressBox onPress={props.onPress} onLongPress={props.onLongPress}>
26
+ <Box style={styles.iconBackground}>
27
+ <Icon.File
28
+ fileType={fileType}
29
+ size={24}
30
+ containerStyle={{ backgroundColor: palette.background50, borderRadius: 8 }}
31
+ />
32
+ <Text body3 numberOfLines={1} color={colors.onBackground01} style={styles.name}>
33
+ {truncate(fileName, { mode: 'mid', maxLen: 30 })}
34
+ </Text>
35
+ </Box>
36
+ </PressBox>
37
+ </Box>
38
+ );
39
+ };
40
+
41
+ const styles = createStyleSheet({
42
+ fileBubbleContainer: {
43
+ alignSelf: 'flex-start',
44
+ overflow: 'hidden',
45
+ flexDirection: 'row',
46
+ alignItems: 'center',
47
+ borderRadius: 16,
48
+ paddingHorizontal: 12,
49
+ paddingVertical: 8,
50
+ },
51
+ iconBackground: {
52
+ flexDirection: 'row',
53
+ alignItems: 'center',
54
+ },
55
+ name: {
56
+ flexShrink: 1,
57
+ marginLeft: 8,
58
+ },
59
+ });
60
+
61
+ export default ThreadParentMessageFile;
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+
3
+ import { Box, PressBox, VideoThumbnail, createStyleSheet } from '@sendbird/uikit-react-native-foundation';
4
+ import { SendbirdFileMessage, getThumbnailUriFromFileMessage } from '@sendbird/uikit-utils';
5
+
6
+ import { ThreadParentMessageRendererProps } from './index';
7
+
8
+ type Props = ThreadParentMessageRendererProps<{
9
+ fetchThumbnailFromVideoSource: (uri: string) => Promise<{ path: string } | null>;
10
+ }>;
11
+
12
+ const ThreadParentMessageFileVideo = (props: Props) => {
13
+ const fileMessage: SendbirdFileMessage = props.parentMessage as SendbirdFileMessage;
14
+ if (!fileMessage) return null;
15
+
16
+ const uri = getThumbnailUriFromFileMessage(fileMessage);
17
+
18
+ return (
19
+ <Box style={styles.container}>
20
+ <PressBox activeOpacity={0.8} onPress={props.onPress} onLongPress={props.onLongPress}>
21
+ <VideoThumbnail
22
+ style={styles.image}
23
+ source={uri}
24
+ fetchThumbnailFromVideoSource={props.fetchThumbnailFromVideoSource}
25
+ />
26
+ </PressBox>
27
+ </Box>
28
+ );
29
+ };
30
+
31
+ const styles = createStyleSheet({
32
+ container: {
33
+ borderRadius: 16,
34
+ overflow: 'hidden',
35
+ },
36
+ image: {
37
+ maxWidth: 240,
38
+ width: 240,
39
+ height: 160,
40
+ borderRadius: 16,
41
+ overflow: 'hidden',
42
+ },
43
+ });
44
+
45
+ export default ThreadParentMessageFileVideo;
@@ -0,0 +1,107 @@
1
+ import React, { useEffect, useState } from 'react';
2
+
3
+ import { Box, Icon, PressBox, Text, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
4
+ import { LoadingSpinner, ProgressBar } from '@sendbird/uikit-react-native-foundation';
5
+ import { createStyleSheet } from '@sendbird/uikit-react-native-foundation';
6
+ import { SendbirdFileMessage, millsToMSS } from '@sendbird/uikit-utils';
7
+
8
+ import { ThreadParentMessageRendererProps } from './index';
9
+
10
+ export type VoiceFileMessageState = {
11
+ status: 'preparing' | 'playing' | 'paused';
12
+ currentTime: number;
13
+ duration: number;
14
+ };
15
+
16
+ type Props = ThreadParentMessageRendererProps<{
17
+ durationMetaArrayKey?: string;
18
+ onUnmount: () => void;
19
+ }>;
20
+
21
+ const ThreadParentMessageFileVoice = (props: Props) => {
22
+ const {
23
+ onLongPress,
24
+ onToggleVoiceMessage,
25
+ parentMessage,
26
+ durationMetaArrayKey = 'KEY_VOICE_MESSAGE_DURATION',
27
+ onUnmount,
28
+ } = props;
29
+
30
+ const fileMessage: SendbirdFileMessage = parentMessage as SendbirdFileMessage;
31
+ if (!fileMessage) return null;
32
+
33
+ const { colors } = useUIKitTheme();
34
+
35
+ const [state, setState] = useState<VoiceFileMessageState>(() => {
36
+ const meta = fileMessage.metaArrays.find((it) => it.key === durationMetaArrayKey);
37
+ const value = meta?.value?.[0];
38
+ const initialDuration = value ? parseInt(value, 10) : 0;
39
+ return {
40
+ status: 'paused',
41
+ currentTime: 0,
42
+ duration: initialDuration,
43
+ };
44
+ });
45
+
46
+ useEffect(() => {
47
+ return () => {
48
+ onUnmount();
49
+ };
50
+ }, []);
51
+
52
+ const uiColors = colors.ui.groupChannelMessage['incoming'];
53
+ const remainingTime = state.duration - state.currentTime;
54
+
55
+ return (
56
+ <Box style={styles.container} backgroundColor={uiColors.enabled.background}>
57
+ <PressBox onPress={() => onToggleVoiceMessage?.(state, setState)} onLongPress={onLongPress}>
58
+ <ProgressBar
59
+ current={state.currentTime}
60
+ total={state.duration}
61
+ style={{ minWidth: 136, height: 44 }}
62
+ trackColor={uiColors.enabled.voiceProgressTrack}
63
+ overlay={
64
+ <Box
65
+ flex={1}
66
+ flexDirection={'row'}
67
+ alignItems={'center'}
68
+ justifyContent={'space-between'}
69
+ paddingHorizontal={12}
70
+ >
71
+ {state.status === 'preparing' ? (
72
+ <LoadingSpinner size={24} color={uiColors.enabled.voiceSpinner} />
73
+ ) : (
74
+ <Icon
75
+ size={16}
76
+ containerStyle={{
77
+ backgroundColor: uiColors.enabled.voiceActionIconBackground,
78
+ padding: 6,
79
+ borderRadius: 16,
80
+ }}
81
+ icon={state.status === 'paused' ? 'play' : 'pause'}
82
+ />
83
+ )}
84
+ <Text
85
+ body3
86
+ style={{ lineHeight: undefined, marginLeft: 6, opacity: 0.88 }}
87
+ color={uiColors.enabled.textVoicePlaytime}
88
+ >
89
+ {millsToMSS(state.currentTime === 0 ? state.duration : remainingTime)}
90
+ </Text>
91
+ </Box>
92
+ }
93
+ />
94
+ </PressBox>
95
+ </Box>
96
+ );
97
+ };
98
+
99
+ const styles = createStyleSheet({
100
+ container: {
101
+ borderRadius: 16,
102
+ overflow: 'hidden',
103
+ maxWidth: 136,
104
+ },
105
+ });
106
+
107
+ export default ThreadParentMessageFileVoice;
@@ -0,0 +1,133 @@
1
+ import React from 'react';
2
+
3
+ import {
4
+ Box,
5
+ ImageWithPlaceholder,
6
+ PressBox,
7
+ RegexText,
8
+ type RegexTextPattern,
9
+ Text,
10
+ createStyleSheet,
11
+ useUIKitTheme,
12
+ } from '@sendbird/uikit-react-native-foundation';
13
+ import { SendbirdUserMessage, urlRegexStrict, useFreshCallback } from '@sendbird/uikit-utils';
14
+
15
+ import { useSendbirdChat } from './../../hooks/useContext';
16
+ import { ThreadParentMessageRendererProps } from './index';
17
+
18
+ type Props = ThreadParentMessageRendererProps<{
19
+ regexTextPatterns?: RegexTextPattern[];
20
+ renderRegexTextChildren?: (message: SendbirdUserMessage) => string;
21
+ }>;
22
+
23
+ const ThreadParentMessageUserOg = (props: Props) => {
24
+ const userMessage: SendbirdUserMessage = props.parentMessage as SendbirdUserMessage;
25
+ if (!userMessage) return null;
26
+
27
+ const { sbOptions } = useSendbirdChat();
28
+ const { select, colors, palette } = useUIKitTheme();
29
+ const enableOgtag = sbOptions.uikitWithAppInfo.groupChannel.channel.enableOgtag;
30
+ const onPressMessage = (userMessage: SendbirdUserMessage) =>
31
+ useFreshCallback(() => {
32
+ typeof userMessage.ogMetaData?.url === 'string' && props.onPressURL?.(userMessage.ogMetaData.url);
33
+ });
34
+
35
+ return (
36
+ <Box>
37
+ <PressBox activeOpacity={0.85} onPress={onPressMessage(userMessage)}>
38
+ <Text body3 color={colors.onBackground01} suppressHighlighting>
39
+ <RegexText
40
+ body3
41
+ color={colors.onBackground01}
42
+ patterns={[
43
+ ...(props.regexTextPatterns ?? []),
44
+ {
45
+ regex: urlRegexStrict,
46
+ replacer({ match, parentProps, keyPrefix, index }) {
47
+ return (
48
+ <Text
49
+ {...parentProps}
50
+ key={`${keyPrefix}-${index}`}
51
+ onPress={() => props.onPressURL?.(match)}
52
+ style={[parentProps?.style, styles.urlText]}
53
+ >
54
+ {match}
55
+ </Text>
56
+ );
57
+ },
58
+ },
59
+ ]}
60
+ >
61
+ {props.renderRegexTextChildren?.(userMessage)}
62
+ </RegexText>
63
+ {Boolean(userMessage.updatedAt) && (
64
+ <Text body3 color={colors.onBackground02}>
65
+ {' (edited)'}
66
+ </Text>
67
+ )}
68
+ </Text>
69
+ </PressBox>
70
+ {userMessage.ogMetaData && enableOgtag && (
71
+ <PressBox onPress={onPressMessage(userMessage)} style={styles.container}>
72
+ <Box>
73
+ {!!userMessage.ogMetaData.defaultImage && (
74
+ <ImageWithPlaceholder style={styles.ogImage} source={{ uri: userMessage.ogMetaData.defaultImage.url }} />
75
+ )}
76
+ <Box
77
+ style={styles.ogContainer}
78
+ backgroundColor={select({ dark: palette.background400, light: palette.background100 })}
79
+ >
80
+ <Text numberOfLines={3} body2 color={colors.onBackground01} style={styles.ogTitle}>
81
+ {userMessage.ogMetaData.title}
82
+ </Text>
83
+ {!!userMessage.ogMetaData.description && (
84
+ <Text numberOfLines={1} caption2 color={colors.onBackground01} style={styles.ogDesc}>
85
+ {userMessage.ogMetaData.description}
86
+ </Text>
87
+ )}
88
+ <Text numberOfLines={1} caption2 color={colors.onBackground02}>
89
+ {userMessage.ogMetaData.url}
90
+ </Text>
91
+ </Box>
92
+ </Box>
93
+ </PressBox>
94
+ )}
95
+ </Box>
96
+ );
97
+ };
98
+
99
+ const styles = createStyleSheet({
100
+ container: {
101
+ borderRadius: 16,
102
+ overflow: 'hidden',
103
+ },
104
+ ogContainer: {
105
+ paddingHorizontal: 12,
106
+ paddingTop: 8,
107
+ paddingBottom: 12,
108
+ maxWidth: 240,
109
+ borderBottomLeftRadius: 16,
110
+ borderBottomRightRadius: 16,
111
+ },
112
+ ogImage: {
113
+ width: 240,
114
+ height: 136,
115
+ borderTopLeftRadius: 16,
116
+ borderTopRightRadius: 16,
117
+ },
118
+ ogUrl: {
119
+ marginBottom: 4,
120
+ },
121
+ ogTitle: {
122
+ marginBottom: 4,
123
+ },
124
+ ogDesc: {
125
+ lineHeight: 14,
126
+ marginBottom: 8,
127
+ },
128
+ urlText: {
129
+ textDecorationLine: 'underline',
130
+ },
131
+ });
132
+
133
+ export default ThreadParentMessageUserOg;
@@ -0,0 +1,65 @@
1
+ import React from 'react';
2
+
3
+ import { type RegexTextPattern, Text, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
4
+ import { RegexText, createStyleSheet } from '@sendbird/uikit-react-native-foundation';
5
+ import { SendbirdUserMessage, urlRegexStrict } from '@sendbird/uikit-utils';
6
+
7
+ import { ThreadParentMessageRendererProps } from './index';
8
+
9
+ type Props = ThreadParentMessageRendererProps<{
10
+ regexTextPatterns?: RegexTextPattern[];
11
+ renderRegexTextChildren?: (message: SendbirdUserMessage) => string;
12
+ }>;
13
+
14
+ const ThreadParentMessageUser = (props: Props) => {
15
+ const userMessage: SendbirdUserMessage = props.parentMessage as SendbirdUserMessage;
16
+ if (!userMessage) return null;
17
+
18
+ const { colors } = useUIKitTheme();
19
+
20
+ return (
21
+ <Text body3 color={colors.onBackground01} suppressHighlighting>
22
+ <RegexText
23
+ body3
24
+ color={colors.onBackground01}
25
+ patterns={[
26
+ ...(props.regexTextPatterns ?? []),
27
+ {
28
+ regex: urlRegexStrict,
29
+ replacer({ match, parentProps, keyPrefix, index }) {
30
+ return (
31
+ <Text
32
+ {...parentProps}
33
+ key={`${keyPrefix}-${index}`}
34
+ onPress={() => props.onPressURL?.(match)}
35
+ style={[parentProps?.style, styles.urlText]}
36
+ >
37
+ {match}
38
+ </Text>
39
+ );
40
+ },
41
+ },
42
+ ]}
43
+ >
44
+ {props.renderRegexTextChildren?.(userMessage)}
45
+ </RegexText>
46
+ {Boolean(userMessage.updatedAt) && (
47
+ <Text body3 color={colors.onBackground02}>
48
+ {' (edited)'}
49
+ </Text>
50
+ )}
51
+ </Text>
52
+ );
53
+ };
54
+
55
+ const styles = createStyleSheet({
56
+ bubble: {
57
+ paddingHorizontal: 12,
58
+ paddingVertical: 6,
59
+ },
60
+ urlText: {
61
+ textDecorationLine: 'underline',
62
+ },
63
+ });
64
+
65
+ export default ThreadParentMessageUser;