@sendbird/uikit-react-native 3.1.2 → 3.3.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 (337) hide show
  1. package/README.md +67 -42
  2. package/lib/commonjs/components/ChannelInput/EditInput.js +2 -11
  3. package/lib/commonjs/components/ChannelInput/EditInput.js.map +1 -1
  4. package/lib/commonjs/components/ChannelInput/MessageToReplyPreview.js +145 -0
  5. package/lib/commonjs/components/ChannelInput/MessageToReplyPreview.js.map +1 -0
  6. package/lib/commonjs/components/ChannelInput/SendInput.js +149 -323
  7. package/lib/commonjs/components/ChannelInput/SendInput.js.map +1 -1
  8. package/lib/commonjs/components/ChannelInput/VoiceMessageInput.js +238 -0
  9. package/lib/commonjs/components/ChannelInput/VoiceMessageInput.js.map +1 -0
  10. package/lib/commonjs/components/ChannelInput/index.js +34 -3
  11. package/lib/commonjs/components/ChannelInput/index.js.map +1 -1
  12. package/lib/commonjs/components/ChannelMessageList/index.js +148 -116
  13. package/lib/commonjs/components/ChannelMessageList/index.js.map +1 -1
  14. package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js +24 -13
  15. package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js.map +1 -1
  16. package/lib/commonjs/components/GroupChannelMessageRenderer/index.js +134 -6
  17. package/lib/commonjs/components/GroupChannelMessageRenderer/index.js.map +1 -1
  18. package/lib/commonjs/components/MessageSearchResultItem.js +1 -0
  19. package/lib/commonjs/components/MessageSearchResultItem.js.map +1 -1
  20. package/lib/commonjs/components/OpenChannelMessageRenderer/index.js +1 -0
  21. package/lib/commonjs/components/OpenChannelMessageRenderer/index.js.map +1 -1
  22. package/lib/commonjs/components/ReactionBottomSheets/ReactionUserListBottomSheet.js +2 -2
  23. package/lib/commonjs/components/ReactionBottomSheets/ReactionUserListBottomSheet.js.map +1 -1
  24. package/lib/commonjs/components/ReactionBottomSheets/index.js.map +1 -1
  25. package/lib/commonjs/components/StatusComposition.js.map +1 -1
  26. package/lib/commonjs/constants.js +5 -1
  27. package/lib/commonjs/constants.js.map +1 -1
  28. package/lib/commonjs/containers/GroupChannelPreviewContainer.js +1 -0
  29. package/lib/commonjs/containers/GroupChannelPreviewContainer.js.map +1 -1
  30. package/lib/commonjs/containers/InternalErrorBoundaryContainer.js.map +1 -1
  31. package/lib/commonjs/containers/SendbirdUIKitContainer.js +72 -34
  32. package/lib/commonjs/containers/SendbirdUIKitContainer.js.map +1 -1
  33. package/lib/commonjs/contexts/PlatformServiceCtx.js +16 -12
  34. package/lib/commonjs/contexts/PlatformServiceCtx.js.map +1 -1
  35. package/lib/commonjs/contexts/ReactionCtx.js +3 -2
  36. package/lib/commonjs/contexts/ReactionCtx.js.map +1 -1
  37. package/lib/commonjs/contexts/SendbirdChatCtx.js +2 -0
  38. package/lib/commonjs/contexts/SendbirdChatCtx.js.map +1 -1
  39. package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js +14 -4
  40. package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
  41. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +28 -42
  42. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  43. package/lib/commonjs/domain/groupChannel/module/moduleContext.js +109 -5
  44. package/lib/commonjs/domain/groupChannel/module/moduleContext.js.map +1 -1
  45. package/lib/commonjs/domain/groupChannel/types.js.map +1 -1
  46. package/lib/commonjs/domain/userList/types.js.map +1 -1
  47. package/lib/commonjs/fragments/createGroupChannelFragment.js +34 -7
  48. package/lib/commonjs/fragments/createGroupChannelFragment.js.map +1 -1
  49. package/lib/commonjs/fragments/createMessageSearchFragment.js +1 -1
  50. package/lib/commonjs/fragments/createMessageSearchFragment.js.map +1 -1
  51. package/lib/commonjs/hooks/useChannelInputItems.js +211 -0
  52. package/lib/commonjs/hooks/useChannelInputItems.js.map +1 -0
  53. package/lib/commonjs/hooks/useConnection.js +1 -1
  54. package/lib/commonjs/hooks/useConnection.js.map +1 -1
  55. package/lib/commonjs/hooks/useVoiceMessageInput.js +207 -0
  56. package/lib/commonjs/hooks/useVoiceMessageInput.js.map +1 -0
  57. package/lib/commonjs/index.js +36 -0
  58. package/lib/commonjs/index.js.map +1 -1
  59. package/lib/commonjs/libs/MentionManager.js.map +1 -1
  60. package/lib/commonjs/libs/SBUUtils.js +4 -0
  61. package/lib/commonjs/libs/SBUUtils.js.map +1 -1
  62. package/lib/commonjs/libs/VoiceMessageConfig.js +30 -0
  63. package/lib/commonjs/libs/VoiceMessageConfig.js.map +1 -0
  64. package/lib/commonjs/localization/StringSet.type.js.map +1 -1
  65. package/lib/commonjs/localization/createBaseStringSet.js +24 -9
  66. package/lib/commonjs/localization/createBaseStringSet.js.map +1 -1
  67. package/lib/commonjs/platform/createFileService.expo.js +10 -0
  68. package/lib/commonjs/platform/createFileService.expo.js.map +1 -1
  69. package/lib/commonjs/platform/createFileService.native.js +19 -0
  70. package/lib/commonjs/platform/createFileService.native.js.map +1 -1
  71. package/lib/commonjs/platform/createPlayerService.expo.js +137 -0
  72. package/lib/commonjs/platform/createPlayerService.expo.js.map +1 -0
  73. package/lib/commonjs/platform/createPlayerService.native.js +139 -0
  74. package/lib/commonjs/platform/createPlayerService.native.js.map +1 -0
  75. package/lib/commonjs/platform/createRecorderService.expo.js +158 -0
  76. package/lib/commonjs/platform/createRecorderService.expo.js.map +1 -0
  77. package/lib/commonjs/platform/createRecorderService.native.js +157 -0
  78. package/lib/commonjs/platform/createRecorderService.native.js.map +1 -0
  79. package/lib/commonjs/platform/types.js.map +1 -1
  80. package/lib/commonjs/types.js +7 -0
  81. package/lib/commonjs/types.js.map +1 -1
  82. package/lib/commonjs/utils/promise.js +138 -0
  83. package/lib/commonjs/utils/promise.js.map +1 -0
  84. package/lib/commonjs/version.js +1 -1
  85. package/lib/commonjs/version.js.map +1 -1
  86. package/lib/module/components/ChannelInput/EditInput.js +3 -12
  87. package/lib/module/components/ChannelInput/EditInput.js.map +1 -1
  88. package/lib/module/components/ChannelInput/MessageToReplyPreview.js +137 -0
  89. package/lib/module/components/ChannelInput/MessageToReplyPreview.js.map +1 -0
  90. package/lib/module/components/ChannelInput/SendInput.js +152 -326
  91. package/lib/module/components/ChannelInput/SendInput.js.map +1 -1
  92. package/lib/module/components/ChannelInput/VoiceMessageInput.js +228 -0
  93. package/lib/module/components/ChannelInput/VoiceMessageInput.js.map +1 -0
  94. package/lib/module/components/ChannelInput/index.js +36 -5
  95. package/lib/module/components/ChannelInput/index.js.map +1 -1
  96. package/lib/module/components/ChannelMessageList/index.js +149 -117
  97. package/lib/module/components/ChannelMessageList/index.js.map +1 -1
  98. package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js +24 -13
  99. package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js.map +1 -1
  100. package/lib/module/components/GroupChannelMessageRenderer/index.js +132 -7
  101. package/lib/module/components/GroupChannelMessageRenderer/index.js.map +1 -1
  102. package/lib/module/components/MessageSearchResultItem.js +2 -1
  103. package/lib/module/components/MessageSearchResultItem.js.map +1 -1
  104. package/lib/module/components/OpenChannelMessageRenderer/index.js +1 -0
  105. package/lib/module/components/OpenChannelMessageRenderer/index.js.map +1 -1
  106. package/lib/module/components/ReactionBottomSheets/ReactionUserListBottomSheet.js +2 -2
  107. package/lib/module/components/ReactionBottomSheets/ReactionUserListBottomSheet.js.map +1 -1
  108. package/lib/module/components/ReactionBottomSheets/index.js.map +1 -1
  109. package/lib/module/components/StatusComposition.js.map +1 -1
  110. package/lib/module/constants.js +2 -0
  111. package/lib/module/constants.js.map +1 -1
  112. package/lib/module/containers/GroupChannelPreviewContainer.js +2 -1
  113. package/lib/module/containers/GroupChannelPreviewContainer.js.map +1 -1
  114. package/lib/module/containers/InternalErrorBoundaryContainer.js.map +1 -1
  115. package/lib/module/containers/SendbirdUIKitContainer.js +74 -36
  116. package/lib/module/containers/SendbirdUIKitContainer.js.map +1 -1
  117. package/lib/module/contexts/PlatformServiceCtx.js +14 -11
  118. package/lib/module/contexts/PlatformServiceCtx.js.map +1 -1
  119. package/lib/module/contexts/ReactionCtx.js +3 -2
  120. package/lib/module/contexts/ReactionCtx.js.map +1 -1
  121. package/lib/module/contexts/SendbirdChatCtx.js +2 -0
  122. package/lib/module/contexts/SendbirdChatCtx.js.map +1 -1
  123. package/lib/module/domain/groupChannel/component/GroupChannelHeader.js +15 -5
  124. package/lib/module/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
  125. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +29 -43
  126. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  127. package/lib/module/domain/groupChannel/module/moduleContext.js +111 -7
  128. package/lib/module/domain/groupChannel/module/moduleContext.js.map +1 -1
  129. package/lib/module/domain/groupChannel/types.js.map +1 -1
  130. package/lib/module/domain/userList/types.js.map +1 -1
  131. package/lib/module/fragments/createGroupChannelFragment.js +36 -9
  132. package/lib/module/fragments/createGroupChannelFragment.js.map +1 -1
  133. package/lib/module/fragments/createMessageSearchFragment.js +1 -1
  134. package/lib/module/fragments/createMessageSearchFragment.js.map +1 -1
  135. package/lib/module/hooks/useChannelInputItems.js +203 -0
  136. package/lib/module/hooks/useChannelInputItems.js.map +1 -0
  137. package/lib/module/hooks/useConnection.js +1 -1
  138. package/lib/module/hooks/useConnection.js.map +1 -1
  139. package/lib/module/hooks/useVoiceMessageInput.js +199 -0
  140. package/lib/module/hooks/useVoiceMessageInput.js.map +1 -0
  141. package/lib/module/index.js +8 -0
  142. package/lib/module/index.js.map +1 -1
  143. package/lib/module/libs/MentionManager.js.map +1 -1
  144. package/lib/module/libs/SBUUtils.js +4 -0
  145. package/lib/module/libs/SBUUtils.js.map +1 -1
  146. package/lib/module/libs/VoiceMessageConfig.js +23 -0
  147. package/lib/module/libs/VoiceMessageConfig.js.map +1 -0
  148. package/lib/module/localization/StringSet.type.js.map +1 -1
  149. package/lib/module/localization/createBaseStringSet.js +25 -10
  150. package/lib/module/localization/createBaseStringSet.js.map +1 -1
  151. package/lib/module/platform/createFileService.expo.js +10 -0
  152. package/lib/module/platform/createFileService.expo.js.map +1 -1
  153. package/lib/module/platform/createFileService.native.js +19 -0
  154. package/lib/module/platform/createFileService.native.js.map +1 -1
  155. package/lib/module/platform/createPlayerService.expo.js +129 -0
  156. package/lib/module/platform/createPlayerService.expo.js.map +1 -0
  157. package/lib/module/platform/createPlayerService.native.js +132 -0
  158. package/lib/module/platform/createPlayerService.native.js.map +1 -0
  159. package/lib/module/platform/createRecorderService.expo.js +150 -0
  160. package/lib/module/platform/createRecorderService.expo.js.map +1 -0
  161. package/lib/module/platform/createRecorderService.native.js +149 -0
  162. package/lib/module/platform/createRecorderService.native.js.map +1 -0
  163. package/lib/module/platform/types.js.map +1 -1
  164. package/lib/module/types.js +5 -1
  165. package/lib/module/types.js.map +1 -1
  166. package/lib/module/utils/promise.js +132 -0
  167. package/lib/module/utils/promise.js.map +1 -0
  168. package/lib/module/version.js +1 -1
  169. package/lib/module/version.js.map +1 -1
  170. package/lib/typescript/src/components/ChannelCover.d.ts +2 -1
  171. package/lib/typescript/src/components/ChannelInput/AttachmentsButton.d.ts +2 -1
  172. package/lib/typescript/src/components/ChannelInput/MessageToReplyPreview.d.ts +7 -0
  173. package/lib/typescript/src/components/ChannelInput/VoiceMessageInput.d.ts +11 -0
  174. package/lib/typescript/src/components/ChannelInput/index.d.ts +9 -3
  175. package/lib/typescript/src/components/ChannelMessageList/index.d.ts +4 -1
  176. package/lib/typescript/src/components/FileViewer.d.ts +2 -1
  177. package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageDateSeparator.d.ts +2 -1
  178. package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageFocusAnimation.d.ts +1 -1
  179. package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageOutgoingStatus.d.ts +1 -1
  180. package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.d.ts +4 -2
  181. package/lib/typescript/src/components/GroupChannelMessageRenderer/index.d.ts +3 -0
  182. package/lib/typescript/src/components/NewMessagesButton.d.ts +1 -1
  183. package/lib/typescript/src/components/OpenChannelMessageRenderer/OpenChannelMessageDateSeparator.d.ts +2 -1
  184. package/lib/typescript/src/components/OpenChannelMessageRenderer/index.d.ts +2 -0
  185. package/lib/typescript/src/components/ProviderLayout.d.ts +1 -1
  186. package/lib/typescript/src/components/ReactionAddons/BottomSheetReactionAddon.d.ts +2 -1
  187. package/lib/typescript/src/components/ReactionAddons/MessageReactionAddon.d.ts +2 -1
  188. package/lib/typescript/src/components/ReactionAddons/ReactionRoundedButton.d.ts +3 -2
  189. package/lib/typescript/src/components/ReactionAddons/index.d.ts +3 -2
  190. package/lib/typescript/src/components/ReactionBottomSheets/ReactionListBottomSheet.d.ts +2 -1
  191. package/lib/typescript/src/components/ReactionBottomSheets/ReactionUserListBottomSheet.d.ts +2 -1
  192. package/lib/typescript/src/components/ReactionBottomSheets/index.d.ts +4 -4
  193. package/lib/typescript/src/components/ScrollToBottomButton.d.ts +1 -1
  194. package/lib/typescript/src/components/StatusComposition.d.ts +4 -4
  195. package/lib/typescript/src/components/TypedPlaceholder.d.ts +2 -1
  196. package/lib/typescript/src/components/UserActionBar.d.ts +2 -1
  197. package/lib/typescript/src/components/UserSelectableBar.d.ts +2 -1
  198. package/lib/typescript/src/constants.d.ts +2 -0
  199. package/lib/typescript/src/containers/GroupChannelPreviewContainer.d.ts +2 -1
  200. package/lib/typescript/src/containers/InternalErrorBoundaryContainer.d.ts +3 -3
  201. package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +19 -8
  202. package/lib/typescript/src/contexts/LocalizationCtx.d.ts +1 -1
  203. package/lib/typescript/src/contexts/PlatformServiceCtx.d.ts +8 -8
  204. package/lib/typescript/src/contexts/ReactionCtx.d.ts +5 -2
  205. package/lib/typescript/src/contexts/SendbirdChatCtx.d.ts +6 -3
  206. package/lib/typescript/src/contexts/UserProfileCtx.d.ts +1 -1
  207. package/lib/typescript/src/domain/groupChannel/component/GroupChannelHeader.d.ts +2 -1
  208. package/lib/typescript/src/domain/groupChannel/component/GroupChannelInput.d.ts +1 -1
  209. package/lib/typescript/src/domain/groupChannel/component/GroupChannelMessageList.d.ts +1 -1
  210. package/lib/typescript/src/domain/groupChannel/component/GroupChannelStatusEmpty.d.ts +2 -1
  211. package/lib/typescript/src/domain/groupChannel/component/GroupChannelStatusLoading.d.ts +2 -1
  212. package/lib/typescript/src/domain/groupChannel/component/GroupChannelSuggestedMentionList.d.ts +2 -1
  213. package/lib/typescript/src/domain/groupChannel/types.d.ts +48 -0
  214. package/lib/typescript/src/domain/groupChannelBannedUsers/component/GroupChannelBannedUsersHeader.d.ts +2 -1
  215. package/lib/typescript/src/domain/groupChannelBannedUsers/component/GroupChannelBannedUsersList.d.ts +2 -1
  216. package/lib/typescript/src/domain/groupChannelBannedUsers/component/GroupChannelBannedUsersStatusEmpty.d.ts +2 -1
  217. package/lib/typescript/src/domain/groupChannelBannedUsers/component/GroupChannelBannedUsersStatusLoading.d.ts +2 -1
  218. package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListHeader.d.ts +2 -1
  219. package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListList.d.ts +2 -1
  220. package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListStatusEmpty.d.ts +2 -1
  221. package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListStatusLoading.d.ts +2 -1
  222. package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListTypeSelector.d.ts +2 -1
  223. package/lib/typescript/src/domain/groupChannelModeration/component/GroupChannelModerationHeader.d.ts +2 -1
  224. package/lib/typescript/src/domain/groupChannelModeration/component/GroupChannelModerationMenu.d.ts +2 -1
  225. package/lib/typescript/src/domain/groupChannelMutedMembers/component/GroupChannelMutedMembersHeader.d.ts +2 -1
  226. package/lib/typescript/src/domain/groupChannelMutedMembers/component/GroupChannelMutedMembersList.d.ts +2 -1
  227. package/lib/typescript/src/domain/groupChannelMutedMembers/component/GroupChannelMutedMembersStatusEmpty.d.ts +2 -1
  228. package/lib/typescript/src/domain/groupChannelMutedMembers/component/GroupChannelMutedMembersStatusLoading.d.ts +2 -1
  229. package/lib/typescript/src/domain/groupChannelNotifications/component/GroupChannelNotificationsHeader.d.ts +2 -1
  230. package/lib/typescript/src/domain/groupChannelNotifications/component/GroupChannelNotificationsView.d.ts +2 -1
  231. package/lib/typescript/src/domain/groupChannelOperators/component/GroupChannelOperatorsHeader.d.ts +2 -1
  232. package/lib/typescript/src/domain/groupChannelOperators/component/GroupChannelOperatorsList.d.ts +2 -1
  233. package/lib/typescript/src/domain/groupChannelOperators/component/GroupChannelOperatorsStatusEmpty.d.ts +2 -1
  234. package/lib/typescript/src/domain/groupChannelOperators/component/GroupChannelOperatorsStatusLoading.d.ts +2 -1
  235. package/lib/typescript/src/domain/groupChannelSettings/component/GroupChannelSettingsHeader.d.ts +2 -1
  236. package/lib/typescript/src/domain/groupChannelSettings/component/GroupChannelSettingsInfo.d.ts +2 -1
  237. package/lib/typescript/src/domain/groupChannelSettings/component/GroupChannelSettingsMenu.d.ts +2 -1
  238. package/lib/typescript/src/domain/messageSearch/component/MessageSearchHeader.d.ts +2 -1
  239. package/lib/typescript/src/domain/messageSearch/component/MessageSearchList.d.ts +2 -1
  240. package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusEmpty.d.ts +2 -1
  241. package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusLoading.d.ts +2 -1
  242. package/lib/typescript/src/domain/openChannel/component/OpenChannelHeader.d.ts +2 -2
  243. package/lib/typescript/src/domain/openChannel/component/OpenChannelInput.d.ts +1 -1
  244. package/lib/typescript/src/domain/openChannel/component/OpenChannelMessageList.d.ts +1 -1
  245. package/lib/typescript/src/domain/openChannel/component/OpenChannelStatusEmpty.d.ts +2 -1
  246. package/lib/typescript/src/domain/openChannel/component/OpenChannelStatusLoading.d.ts +2 -1
  247. package/lib/typescript/src/domain/openChannelBannedUsers/component/OpenChannelBannedUsersHeader.d.ts +2 -1
  248. package/lib/typescript/src/domain/openChannelBannedUsers/component/OpenChannelBannedUsersList.d.ts +2 -1
  249. package/lib/typescript/src/domain/openChannelBannedUsers/component/OpenChannelBannedUsersStatusEmpty.d.ts +2 -1
  250. package/lib/typescript/src/domain/openChannelBannedUsers/component/OpenChannelBannedUsersStatusLoading.d.ts +2 -1
  251. package/lib/typescript/src/domain/openChannelCreate/component/OpenChannelCreateHeader.d.ts +2 -1
  252. package/lib/typescript/src/domain/openChannelCreate/component/OpenChannelCreateProfileInput.d.ts +2 -1
  253. package/lib/typescript/src/domain/openChannelCreate/component/OpenChannelCreateStatusLoading.d.ts +2 -1
  254. package/lib/typescript/src/domain/openChannelList/component/OpenChannelListHeader.d.ts +2 -1
  255. package/lib/typescript/src/domain/openChannelList/component/OpenChannelListList.d.ts +2 -1
  256. package/lib/typescript/src/domain/openChannelList/component/OpenChannelListStatusEmpty.d.ts +2 -1
  257. package/lib/typescript/src/domain/openChannelList/component/OpenChannelListStatusLoading.d.ts +2 -1
  258. package/lib/typescript/src/domain/openChannelModeration/component/OpenChannelModerationHeader.d.ts +2 -1
  259. package/lib/typescript/src/domain/openChannelModeration/component/OpenChannelModerationMenu.d.ts +2 -1
  260. package/lib/typescript/src/domain/openChannelMutedParticipants/component/OpenChannelMutedParticipantsHeader.d.ts +2 -1
  261. package/lib/typescript/src/domain/openChannelMutedParticipants/component/OpenChannelMutedParticipantsList.d.ts +2 -1
  262. package/lib/typescript/src/domain/openChannelMutedParticipants/component/OpenChannelMutedParticipantsStatusEmpty.d.ts +2 -1
  263. package/lib/typescript/src/domain/openChannelMutedParticipants/component/OpenChannelMutedParticipantsStatusLoading.d.ts +2 -1
  264. package/lib/typescript/src/domain/openChannelOperators/component/OpenChannelOperatorsHeader.d.ts +2 -1
  265. package/lib/typescript/src/domain/openChannelOperators/component/OpenChannelOperatorsList.d.ts +2 -1
  266. package/lib/typescript/src/domain/openChannelOperators/component/OpenChannelOperatorsStatusEmpty.d.ts +2 -1
  267. package/lib/typescript/src/domain/openChannelOperators/component/OpenChannelOperatorsStatusLoading.d.ts +2 -1
  268. package/lib/typescript/src/domain/openChannelSettings/component/OpenChannelSettingsHeader.d.ts +2 -1
  269. package/lib/typescript/src/domain/openChannelSettings/component/OpenChannelSettingsInfo.d.ts +2 -1
  270. package/lib/typescript/src/domain/openChannelSettings/component/OpenChannelSettingsMenu.d.ts +2 -1
  271. package/lib/typescript/src/domain/userList/component/UserListHeader.d.ts +3 -3
  272. package/lib/typescript/src/domain/userList/component/UserListList.d.ts +1 -1
  273. package/lib/typescript/src/domain/userList/component/UserListStatusEmpty.d.ts +2 -1
  274. package/lib/typescript/src/domain/userList/component/UserListStatusLoading.d.ts +2 -1
  275. package/lib/typescript/src/domain/userList/types.d.ts +2 -2
  276. package/lib/typescript/src/hooks/useChannelInputItems.d.ts +10 -0
  277. package/lib/typescript/src/hooks/useVoiceMessageInput.d.ts +53 -0
  278. package/lib/typescript/src/index.d.ts +4 -0
  279. package/lib/typescript/src/libs/MentionManager.d.ts +2 -1
  280. package/lib/typescript/src/libs/SBUUtils.d.ts +1 -0
  281. package/lib/typescript/src/libs/VoiceMessageConfig.d.ts +25 -0
  282. package/lib/typescript/src/localization/StringSet.type.d.ts +7 -0
  283. package/lib/typescript/src/platform/createPlayerService.expo.d.ts +7 -0
  284. package/lib/typescript/src/platform/createPlayerService.native.d.ts +9 -0
  285. package/lib/typescript/src/platform/createRecorderService.expo.d.ts +7 -0
  286. package/lib/typescript/src/platform/createRecorderService.native.d.ts +9 -0
  287. package/lib/typescript/src/platform/types.d.ts +100 -1
  288. package/lib/typescript/src/types.d.ts +5 -1
  289. package/lib/typescript/src/utils/promise.d.ts +7 -0
  290. package/lib/typescript/src/version.d.ts +1 -1
  291. package/package.json +10 -12
  292. package/src/components/ChannelInput/EditInput.tsx +3 -15
  293. package/src/components/ChannelInput/MessageToReplyPreview.tsx +133 -0
  294. package/src/components/ChannelInput/SendInput.tsx +131 -329
  295. package/src/components/ChannelInput/VoiceMessageInput.tsx +206 -0
  296. package/src/components/ChannelInput/index.tsx +37 -6
  297. package/src/components/ChannelMessageList/index.tsx +145 -113
  298. package/src/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.tsx +24 -11
  299. package/src/components/GroupChannelMessageRenderer/index.tsx +113 -4
  300. package/src/components/MessageSearchResultItem.tsx +2 -1
  301. package/src/components/OpenChannelMessageRenderer/index.tsx +1 -0
  302. package/src/components/ReactionBottomSheets/ReactionUserListBottomSheet.tsx +2 -2
  303. package/src/components/ReactionBottomSheets/index.tsx +3 -2
  304. package/src/components/StatusComposition.tsx +3 -3
  305. package/src/constants.ts +2 -0
  306. package/src/containers/GroupChannelPreviewContainer.tsx +2 -0
  307. package/src/containers/InternalErrorBoundaryContainer.tsx +1 -1
  308. package/src/containers/SendbirdUIKitContainer.tsx +103 -59
  309. package/src/contexts/PlatformServiceCtx.tsx +22 -20
  310. package/src/contexts/ReactionCtx.tsx +7 -5
  311. package/src/contexts/SendbirdChatCtx.tsx +10 -2
  312. package/src/domain/groupChannel/component/GroupChannelHeader.tsx +14 -3
  313. package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +30 -43
  314. package/src/domain/groupChannel/module/moduleContext.tsx +119 -7
  315. package/src/domain/groupChannel/types.ts +45 -0
  316. package/src/domain/userList/types.ts +2 -2
  317. package/src/fragments/createGroupChannelFragment.tsx +43 -8
  318. package/src/fragments/createMessageSearchFragment.tsx +1 -1
  319. package/src/hooks/useChannelInputItems.ts +215 -0
  320. package/src/hooks/useConnection.ts +1 -1
  321. package/src/hooks/useVoiceMessageInput.ts +237 -0
  322. package/src/index.ts +9 -1
  323. package/src/libs/MentionManager.tsx +1 -1
  324. package/src/libs/SBUUtils.ts +5 -0
  325. package/src/libs/VoiceMessageConfig.ts +28 -0
  326. package/src/localization/StringSet.type.ts +8 -0
  327. package/src/localization/createBaseStringSet.ts +27 -11
  328. package/src/platform/createFileService.expo.ts +10 -0
  329. package/src/platform/createFileService.native.ts +19 -0
  330. package/src/platform/createPlayerService.expo.tsx +142 -0
  331. package/src/platform/createPlayerService.native.tsx +148 -0
  332. package/src/platform/createRecorderService.expo.tsx +160 -0
  333. package/src/platform/createRecorderService.native.tsx +170 -0
  334. package/src/platform/types.ts +114 -1
  335. package/src/types.ts +6 -1
  336. package/src/utils/promise.ts +139 -0
  337. package/src/version.ts +1 -1
@@ -1,37 +1,39 @@
1
- import React from 'react';
1
+ import React, { useEffect } from 'react';
2
2
 
3
+ import { useAppState } from '@sendbird/uikit-utils';
4
+
5
+ import VoiceMessageConfig from '../libs/VoiceMessageConfig';
3
6
  import type {
4
7
  ClipboardServiceInterface,
5
8
  FileServiceInterface,
6
9
  MediaServiceInterface,
7
10
  NotificationServiceInterface,
11
+ PlayerServiceInterface,
12
+ RecorderServiceInterface,
8
13
  } from '../platform/types';
9
14
 
10
- type Props = React.PropsWithChildren<{
11
- fileService: FileServiceInterface;
12
- clipboardService: ClipboardServiceInterface;
13
- notificationService: NotificationServiceInterface;
14
- mediaService: MediaServiceInterface;
15
- }>;
16
-
17
15
  export type PlatformServiceContextType = {
18
16
  fileService: FileServiceInterface;
19
17
  clipboardService: ClipboardServiceInterface;
20
18
  notificationService: NotificationServiceInterface;
21
19
  mediaService: MediaServiceInterface;
20
+ recorderService: RecorderServiceInterface;
21
+ playerService: PlayerServiceInterface;
22
22
  };
23
+ type Props = React.PropsWithChildren<PlatformServiceContextType & { voiceMessageConfig: VoiceMessageConfig }>;
23
24
 
24
25
  export const PlatformServiceContext = React.createContext<PlatformServiceContextType | null>(null);
25
- export const PlatformServiceProvider = ({
26
- children,
27
- fileService,
28
- clipboardService,
29
- notificationService,
30
- mediaService,
31
- }: Props) => {
32
- return (
33
- <PlatformServiceContext.Provider value={{ fileService, clipboardService, notificationService, mediaService }}>
34
- {children}
35
- </PlatformServiceContext.Provider>
36
- );
26
+ export const PlatformServiceProvider = ({ children, voiceMessageConfig, ...services }: Props) => {
27
+ useEffect(() => {
28
+ services.recorderService.options.minDuration = voiceMessageConfig.recorder.minDuration;
29
+ services.recorderService.options.maxDuration = voiceMessageConfig.recorder.maxDuration;
30
+ }, [voiceMessageConfig]);
31
+
32
+ useAppState('change', (state) => {
33
+ if (state !== 'active') {
34
+ Promise.allSettled([services.playerService.reset(), services.recorderService.reset()]);
35
+ }
36
+ });
37
+
38
+ return <PlatformServiceContext.Provider value={services}>{children}</PlatformServiceContext.Provider>;
37
39
  };
@@ -3,7 +3,7 @@ import React, { useCallback, useContext, useReducer, useRef, useState } from 're
3
3
  import type { SendbirdBaseChannel, SendbirdBaseMessage } from '@sendbird/uikit-utils';
4
4
  import { NOOP } from '@sendbird/uikit-utils';
5
5
 
6
- import { ReactionBottomSheets } from '../components/ReactionBottomSheets';
6
+ import { ReactionBottomSheetProps, ReactionBottomSheets } from '../components/ReactionBottomSheets';
7
7
  import { LocalizationContext } from '../contexts/LocalizationCtx';
8
8
  import { SendbirdChatContext } from '../contexts/SendbirdChatCtx';
9
9
  import { UserProfileContext } from '../contexts/UserProfileCtx';
@@ -19,10 +19,12 @@ export type ReactionContextType = {
19
19
  focusIndex: number;
20
20
  } & State;
21
21
 
22
- type Props = React.PropsWithChildren<{}>;
22
+ type Props = React.PropsWithChildren<{
23
+ onPressUserProfile?: ReactionBottomSheetProps['onPressUserProfile'];
24
+ }>;
23
25
 
24
26
  export const ReactionContext = React.createContext<ReactionContextType | null>(null);
25
- export const ReactionProvider = ({ children }: Props) => {
27
+ export const ReactionProvider = ({ children, onPressUserProfile }: Props) => {
26
28
  const chatCtx = useContext(SendbirdChatContext);
27
29
  const localizationCtx = useContext(LocalizationContext);
28
30
  const userProfileCtx = useContext(UserProfileContext);
@@ -73,11 +75,11 @@ export const ReactionProvider = ({ children }: Props) => {
73
75
  focusIndex: reactionUserListFocusIndex,
74
76
  };
75
77
 
76
- const sheetProps = {
78
+ const sheetProps: Omit<ReactionBottomSheetProps, 'visible' | 'onClose'> = {
77
79
  chatCtx,
78
80
  reactionCtx,
79
81
  localizationCtx,
80
- userProfileCtx,
82
+ onPressUserProfile: onPressUserProfile ?? userProfileCtx.show,
81
83
  onDismiss: () => {
82
84
  setState({});
83
85
  closeResolver.current?.();
@@ -13,6 +13,7 @@ import { confirmAndMarkAsDelivered, useAppState, useForceUpdate } from '@sendbir
13
13
  import type EmojiManager from '../libs/EmojiManager';
14
14
  import type ImageCompressionConfig from '../libs/ImageCompressionConfig';
15
15
  import type MentionManager from '../libs/MentionManager';
16
+ import type VoiceMessageConfig from '../libs/VoiceMessageConfig';
16
17
  import type { FileType } from '../platform/types';
17
18
 
18
19
  export interface ChatRelatedFeaturesInUIKit {
@@ -23,18 +24,23 @@ export interface ChatRelatedFeaturesInUIKit {
23
24
 
24
25
  interface Props extends ChatRelatedFeaturesInUIKit, React.PropsWithChildren {
25
26
  sdkInstance: SendbirdChatSDK;
27
+
26
28
  emojiManager: EmojiManager;
27
29
  mentionManager: MentionManager;
28
30
  imageCompressionConfig: ImageCompressionConfig;
31
+ voiceMessageConfig: VoiceMessageConfig;
29
32
  }
30
33
 
31
34
  export type SendbirdChatContextType = {
32
35
  sdk: SendbirdChatSDK;
36
+ currentUser?: SendbirdUser;
37
+ setCurrentUser: React.Dispatch<React.SetStateAction<SendbirdUser | undefined>>;
38
+
39
+ // feature related instances
33
40
  emojiManager: EmojiManager;
34
41
  mentionManager: MentionManager;
35
42
  imageCompressionConfig: ImageCompressionConfig;
36
- currentUser?: SendbirdUser;
37
- setCurrentUser: React.Dispatch<React.SetStateAction<SendbirdUser | undefined>>;
43
+ voiceMessageConfig: VoiceMessageConfig;
38
44
 
39
45
  // helper functions
40
46
  updateCurrentUserInfo: (nickname?: string, profile?: string | FileType) => Promise<SendbirdUser>;
@@ -84,6 +90,7 @@ export const SendbirdChatProvider = ({
84
90
  emojiManager,
85
91
  mentionManager,
86
92
  imageCompressionConfig,
93
+ voiceMessageConfig,
87
94
  enableAutoPushTokenRegistration,
88
95
  enableUseUserIdForNickname,
89
96
  enableImageCompression,
@@ -155,6 +162,7 @@ export const SendbirdChatProvider = ({
155
162
  emojiManager,
156
163
  mentionManager,
157
164
  imageCompressionConfig,
165
+ voiceMessageConfig,
158
166
  currentUser,
159
167
  setCurrentUser,
160
168
 
@@ -4,7 +4,8 @@ import { View } from 'react-native';
4
4
  import { Header, Icon, createStyleSheet, useHeaderStyle } from '@sendbird/uikit-react-native-foundation';
5
5
 
6
6
  import ChannelCover from '../../../components/ChannelCover';
7
- import { useLocalization } from '../../../hooks/useContext';
7
+ import { useLocalization, useSendbirdChat } from '../../../hooks/useContext';
8
+ import { TypingIndicatorType } from '../../../types';
8
9
  import { GroupChannelContexts } from '../module/moduleContext';
9
10
  import type { GroupChannelProps } from '../types';
10
11
 
@@ -13,11 +14,21 @@ const GroupChannelHeader = ({
13
14
  onPressHeaderLeft,
14
15
  onPressHeaderRight,
15
16
  }: GroupChannelProps['Header']) => {
17
+ const { sbOptions } = useSendbirdChat();
16
18
  const { headerTitle, channel } = useContext(GroupChannelContexts.Fragment);
17
19
  const { typingUsers } = useContext(GroupChannelContexts.TypingIndicator);
18
20
  const { STRINGS } = useLocalization();
19
21
  const { HeaderComponent } = useHeaderStyle();
20
- const subtitle = STRINGS.LABELS.TYPING_INDICATOR_TYPINGS(typingUsers);
22
+
23
+ const renderSubtitle = () => {
24
+ const subtitle = STRINGS.LABELS.TYPING_INDICATOR_TYPINGS(typingUsers);
25
+
26
+ if (!subtitle) return null;
27
+ if (!sbOptions.uikit.groupChannel.channel.enableTypingIndicator) return null;
28
+ if (!sbOptions.uikit.groupChannel.channel.typingIndicatorTypes.has(TypingIndicatorType.Text)) return null;
29
+
30
+ return <Header.Subtitle style={styles.subtitle}>{subtitle}</Header.Subtitle>;
31
+ };
21
32
 
22
33
  const isHidden = shouldHideRight();
23
34
 
@@ -29,7 +40,7 @@ const GroupChannelHeader = ({
29
40
  <ChannelCover channel={channel} size={34} containerStyle={styles.avatarGroup} />
30
41
  <View style={{ flexShrink: 1 }}>
31
42
  <Header.Title h2>{headerTitle}</Header.Title>
32
- {Boolean(subtitle) && subtitle && <Header.Subtitle style={styles.subtitle}>{subtitle}</Header.Subtitle>}
43
+ {renderSubtitle()}
33
44
  </View>
34
45
  </View>
35
46
  }
@@ -1,5 +1,4 @@
1
- import React, { useContext, useEffect, useRef } from 'react';
2
- import type { FlatList } from 'react-native';
1
+ import React, { useContext, useEffect } from 'react';
3
2
 
4
3
  import { useChannelHandler } from '@sendbird/uikit-chat-hooks';
5
4
  import { useToast } from '@sendbird/uikit-react-native-foundation';
@@ -18,45 +17,32 @@ const GroupChannelMessageList = (props: GroupChannelProps['MessageList']) => {
18
17
  const { sdk } = useSendbirdChat();
19
18
  const { setMessageToEdit, setMessageToReply } = useContext(GroupChannelContexts.Fragment);
20
19
  const { subscribe } = useContext(GroupChannelContexts.PubSub);
20
+ const { flatListRef, lazyScrollToBottom, lazyScrollToIndex } = useContext(GroupChannelContexts.MessageList);
21
21
 
22
22
  const id = useUniqHandlerId('GroupChannelMessageList');
23
- const ref = useRef<FlatList<SendbirdMessage>>(null);
24
23
  const isFirstMount = useIsFirstMount();
25
24
 
26
- // FIXME: Workaround, should run after data has been applied to UI.
27
- const lazyScrollToBottom = (animated = false, timeout = 0) => {
28
- setTimeout(() => {
29
- ref.current?.scrollToOffset({ offset: 0, animated });
30
- }, timeout);
31
- };
25
+ const scrollToMessageWithCreatedAt = useFreshCallback(
26
+ (createdAt: number, focusAnimated: boolean, timeout: number): boolean => {
27
+ const foundMessageIndex = props.messages.findIndex((it) => it.createdAt === createdAt);
28
+ const isIncludedInList = foundMessageIndex > -1;
32
29
 
33
- // FIXME: Workaround, should run after data has been applied to UI.
34
- const lazyScrollToIndex = (index = 0, animated = false, timeout = 0) => {
35
- setTimeout(() => {
36
- ref.current?.scrollToIndex({ index, animated, viewPosition: 0.5 });
37
- }, timeout);
38
- };
39
-
40
- const scrollToMessage = useFreshCallback((createdAt: number, focusAnimated = false): boolean => {
41
- const foundMessageIndex = props.messages.findIndex((it) => it.createdAt === createdAt);
42
- const isIncludedInList = foundMessageIndex > -1;
43
-
44
- if (isIncludedInList) {
45
- if (focusAnimated) {
46
- setTimeout(() => props.onUpdateSearchItem({ startingPoint: createdAt }), MESSAGE_FOCUS_ANIMATION_DELAY);
47
- }
48
- lazyScrollToIndex(foundMessageIndex, true, isFirstMount ? MESSAGE_SEARCH_SAFE_SCROLL_DELAY : 0);
49
- } else {
50
- if (props.channel.messageOffsetTimestamp <= createdAt) {
51
- if (focusAnimated) props.onUpdateSearchItem({ startingPoint: createdAt });
52
- props.onResetMessageListWithStartingPoint(createdAt);
30
+ if (isIncludedInList) {
31
+ if (focusAnimated) {
32
+ setTimeout(() => props.onUpdateSearchItem({ startingPoint: createdAt }), MESSAGE_FOCUS_ANIMATION_DELAY);
33
+ }
34
+ lazyScrollToIndex({ index: foundMessageIndex, animated: true, timeout });
53
35
  } else {
54
- return false;
36
+ if (props.channel.messageOffsetTimestamp <= createdAt) {
37
+ if (focusAnimated) props.onUpdateSearchItem({ startingPoint: createdAt });
38
+ props.onResetMessageListWithStartingPoint(createdAt);
39
+ } else {
40
+ return false;
41
+ }
55
42
  }
56
- }
57
-
58
- return true;
59
- });
43
+ return true;
44
+ },
45
+ );
60
46
 
61
47
  const scrollToBottom = useFreshCallback((animated = false) => {
62
48
  if (props.hasNext()) {
@@ -65,10 +51,10 @@ const GroupChannelMessageList = (props: GroupChannelProps['MessageList']) => {
65
51
 
66
52
  props.onResetMessageList(() => {
67
53
  props.onScrolledAwayFromBottom(false);
68
- lazyScrollToBottom(animated);
54
+ lazyScrollToBottom({ animated });
69
55
  });
70
56
  } else {
71
- lazyScrollToBottom(animated);
57
+ lazyScrollToBottom({ animated });
72
58
  }
73
59
  });
74
60
 
@@ -79,7 +65,7 @@ const GroupChannelMessageList = (props: GroupChannelProps['MessageList']) => {
79
65
  const isRecentMessage = recentMessage && recentMessage.messageId === event.messageId;
80
66
  const scrollReachedBottomAndCanScroll = !props.scrolledAwayFromBottom && !props.hasNext();
81
67
  if (isRecentMessage && scrollReachedBottomAndCanScroll) {
82
- lazyScrollToBottom(true, 250);
68
+ lazyScrollToBottom({ animated: true, timeout: 250 });
83
69
  }
84
70
  },
85
71
  });
@@ -87,6 +73,7 @@ const GroupChannelMessageList = (props: GroupChannelProps['MessageList']) => {
87
73
  useEffect(() => {
88
74
  return subscribe(({ type }) => {
89
75
  switch (type) {
76
+ case 'TYPING_BUBBLE_RENDERED':
90
77
  case 'MESSAGES_RECEIVED': {
91
78
  if (!props.scrolledAwayFromBottom) {
92
79
  scrollToBottom(true);
@@ -102,24 +89,24 @@ const GroupChannelMessageList = (props: GroupChannelProps['MessageList']) => {
102
89
  });
103
90
  }, [props.scrolledAwayFromBottom]);
104
91
 
105
- // Only trigger once when message list mount with initial props.searchItem
106
- // - Search screen + searchItem > mount message list
107
- // - Reset message list + searchItem > re-mount message list
108
92
  useEffect(() => {
93
+ // Only trigger once when message list mount with initial props.searchItem
94
+ // - Search screen + searchItem > mount message list
95
+ // - Reset message list + searchItem > re-mount message list
109
96
  if (isFirstMount && props.searchItem) {
110
- scrollToMessage(props.searchItem.startingPoint);
97
+ scrollToMessageWithCreatedAt(props.searchItem.startingPoint, false, MESSAGE_SEARCH_SAFE_SCROLL_DELAY);
111
98
  }
112
99
  }, [isFirstMount]);
113
100
 
114
101
  const onPressParentMessage = useFreshCallback((message: SendbirdMessage) => {
115
- const canScrollToParent = scrollToMessage(message.createdAt, true);
102
+ const canScrollToParent = scrollToMessageWithCreatedAt(message.createdAt, true, 0);
116
103
  if (!canScrollToParent) toast.show(STRINGS.TOAST.FIND_PARENT_MSG_ERROR, 'error');
117
104
  });
118
105
 
119
106
  return (
120
107
  <ChannelMessageList
121
108
  {...props}
122
- ref={ref}
109
+ ref={flatListRef}
123
110
  onReplyMessage={setMessageToReply}
124
111
  onEditMessage={setMessageToEdit}
125
112
  onPressParentMessage={onPressParentMessage}
@@ -1,20 +1,28 @@
1
- import React, { createContext, useCallback, useState } from 'react';
1
+ import React, { createContext, useCallback, useRef, useState } from 'react';
2
+ import type { FlatList } from 'react-native';
2
3
 
3
4
  import { useChannelHandler } from '@sendbird/uikit-chat-hooks';
4
5
  import {
6
+ ContextValue,
7
+ Logger,
5
8
  NOOP,
6
9
  SendbirdFileMessage,
7
10
  SendbirdGroupChannel,
11
+ SendbirdMessage,
8
12
  SendbirdUser,
9
13
  SendbirdUserMessage,
14
+ getGroupChannelChatAvailableState,
10
15
  isDifferentChannel,
16
+ useFreshCallback,
11
17
  useUniqHandlerId,
12
18
  } from '@sendbird/uikit-utils';
13
19
 
14
20
  import ProviderLayout from '../../../components/ProviderLayout';
21
+ import { MESSAGE_FOCUS_ANIMATION_DELAY } from '../../../constants';
15
22
  import { useLocalization, useSendbirdChat } from '../../../hooks/useContext';
16
23
  import type { PubSub } from '../../../utils/pubsub';
17
24
  import type { GroupChannelContextsType, GroupChannelModule, GroupChannelPubSubContextPayload } from '../types';
25
+ import { GroupChannelProps } from '../types';
18
26
 
19
27
  export const GroupChannelContexts: GroupChannelContextsType = {
20
28
  Fragment: createContext({
@@ -30,6 +38,16 @@ export const GroupChannelContexts: GroupChannelContextsType = {
30
38
  publish: NOOP,
31
39
  subscribe: () => NOOP,
32
40
  } as PubSub<GroupChannelPubSubContextPayload>),
41
+ MessageList: createContext({
42
+ flatListRef: { current: null },
43
+ scrollToMessage: () => false,
44
+ lazyScrollToBottom: () => {
45
+ // noop
46
+ },
47
+ lazyScrollToIndex: () => {
48
+ // noop
49
+ },
50
+ } as MessageListContextValue),
33
51
  };
34
52
 
35
53
  export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
@@ -38,6 +56,8 @@ export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
38
56
  enableTypingIndicator,
39
57
  keyboardAvoidOffset = 0,
40
58
  groupChannelPubSub,
59
+ messages,
60
+ onUpdateSearchItem,
41
61
  }) => {
42
62
  if (!channel) throw new Error('GroupChannel is not provided to GroupChannelModule');
43
63
 
@@ -49,6 +69,11 @@ export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
49
69
  const [messageToEdit, setMessageToEdit] = useState<SendbirdUserMessage | SendbirdFileMessage>();
50
70
  const [messageToReply, setMessageToReply] = useState<SendbirdUserMessage | SendbirdFileMessage>();
51
71
 
72
+ const { flatListRef, lazyScrollToIndex, lazyScrollToBottom, scrollToMessage } = useScrollActions({
73
+ messages,
74
+ onUpdateSearchItem,
75
+ });
76
+
52
77
  const updateInputMode = (mode: 'send' | 'edit' | 'reply', message?: SendbirdUserMessage | SendbirdFileMessage) => {
53
78
  if (mode === 'send' || !message) {
54
79
  setMessageToEdit(undefined);
@@ -73,7 +98,9 @@ export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
73
98
  },
74
99
  onChannelFrozen(frozenChannel) {
75
100
  if (frozenChannel.url === channel.url) {
76
- setMessageToReply(undefined);
101
+ if (frozenChannel.isGroupChannel() && getGroupChannelChatAvailableState(channel).frozen) {
102
+ setMessageToReply(undefined);
103
+ }
77
104
  }
78
105
  },
79
106
  onUserMuted(mutedChannel, user) {
@@ -101,12 +128,97 @@ export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
101
128
  setMessageToReply: useCallback((message) => updateInputMode('reply', message), []),
102
129
  }}
103
130
  >
104
- <GroupChannelContexts.TypingIndicator.Provider value={{ typingUsers }}>
105
- <GroupChannelContexts.PubSub.Provider value={groupChannelPubSub}>
106
- {children}
107
- </GroupChannelContexts.PubSub.Provider>
108
- </GroupChannelContexts.TypingIndicator.Provider>
131
+ <GroupChannelContexts.PubSub.Provider value={groupChannelPubSub}>
132
+ <GroupChannelContexts.TypingIndicator.Provider value={{ typingUsers }}>
133
+ <GroupChannelContexts.MessageList.Provider
134
+ value={{
135
+ flatListRef,
136
+ scrollToMessage,
137
+ lazyScrollToIndex,
138
+ lazyScrollToBottom,
139
+ }}
140
+ >
141
+ {children}
142
+ </GroupChannelContexts.MessageList.Provider>
143
+ </GroupChannelContexts.TypingIndicator.Provider>
144
+ </GroupChannelContexts.PubSub.Provider>
109
145
  </GroupChannelContexts.Fragment.Provider>
110
146
  </ProviderLayout>
111
147
  );
112
148
  };
149
+
150
+ type MessageListContextValue = ContextValue<GroupChannelContextsType['MessageList']>;
151
+ const useScrollActions = (params: Pick<GroupChannelProps['Provider'], 'messages' | 'onUpdateSearchItem'>) => {
152
+ const { messages, onUpdateSearchItem } = params;
153
+ const flatListRef = useRef<FlatList<SendbirdMessage>>(null);
154
+
155
+ // FIXME: Workaround, should run after data has been applied to UI.
156
+ const lazyScrollToBottom = useFreshCallback<MessageListContextValue['lazyScrollToIndex']>((params) => {
157
+ if (!flatListRef.current) {
158
+ logFlatListRefWarning();
159
+ return;
160
+ }
161
+
162
+ setTimeout(() => {
163
+ flatListRef.current?.scrollToOffset({ offset: 0, animated: params?.animated ?? false });
164
+ }, params?.timeout ?? 0);
165
+ });
166
+
167
+ // FIXME: Workaround, should run after data has been applied to UI.
168
+ const lazyScrollToIndex = useFreshCallback<MessageListContextValue['lazyScrollToIndex']>((params) => {
169
+ if (!flatListRef.current) {
170
+ logFlatListRefWarning();
171
+ return;
172
+ }
173
+
174
+ setTimeout(() => {
175
+ flatListRef.current?.scrollToIndex({
176
+ index: params?.index ?? 0,
177
+ animated: params?.animated ?? false,
178
+ viewPosition: params?.viewPosition ?? 0.5,
179
+ });
180
+ }, params?.timeout ?? 0);
181
+ });
182
+
183
+ const scrollToMessage = useFreshCallback<MessageListContextValue['scrollToMessage']>((messageId, options) => {
184
+ if (!flatListRef.current) {
185
+ logFlatListRefWarning();
186
+ return false;
187
+ }
188
+
189
+ const foundMessageIndex = messages.findIndex((it) => it.messageId === messageId);
190
+ const isIncludedInList = foundMessageIndex > -1;
191
+
192
+ if (isIncludedInList) {
193
+ if (options?.focusAnimated) {
194
+ setTimeout(
195
+ () => onUpdateSearchItem({ startingPoint: messages[foundMessageIndex].createdAt }),
196
+ MESSAGE_FOCUS_ANIMATION_DELAY,
197
+ );
198
+ }
199
+ lazyScrollToIndex({
200
+ index: foundMessageIndex,
201
+ animated: true,
202
+ timeout: 0,
203
+ viewPosition: options?.viewPosition,
204
+ });
205
+ return true;
206
+ } else {
207
+ return false;
208
+ }
209
+ });
210
+
211
+ return {
212
+ flatListRef,
213
+ lazyScrollToIndex,
214
+ lazyScrollToBottom,
215
+ scrollToMessage,
216
+ };
217
+ };
218
+
219
+ const logFlatListRefWarning = () => {
220
+ Logger.warn(
221
+ 'Cannot find flatListRef.current, please render FlatList and pass the flatListRef' +
222
+ 'or please try again after FlatList has been rendered.',
223
+ );
224
+ };
@@ -1,4 +1,5 @@
1
1
  import type React from 'react';
2
+ import type { FlatList } from 'react-native';
2
3
 
3
4
  import type { UseGroupChannelMessagesOptions } from '@sendbird/uikit-chat-hooks';
4
5
  import type {
@@ -95,6 +96,10 @@ export interface GroupChannelProps {
95
96
  enableTypingIndicator: boolean;
96
97
  keyboardAvoidOffset?: number;
97
98
  groupChannelPubSub: PubSub<GroupChannelPubSubContextPayload>;
99
+
100
+ messages: SendbirdMessage[];
101
+ // Changing the search item will trigger the focus animation on messages.
102
+ onUpdateSearchItem: (searchItem?: GroupChannelProps['MessageList']['searchItem']) => void;
98
103
  };
99
104
  }
100
105
 
@@ -117,6 +122,42 @@ export interface GroupChannelContextsType {
117
122
  typingUsers: SendbirdUser[];
118
123
  }>;
119
124
  PubSub: React.Context<PubSub<GroupChannelPubSubContextPayload>>;
125
+ MessageList: React.Context<{
126
+ /**
127
+ * ref object for FlatList of MessageList
128
+ * */
129
+ flatListRef: React.MutableRefObject<FlatList | null>;
130
+ /**
131
+ * Function that scrolls to a message within a group channel.
132
+ * @param messageId {number} - The id of the message to scroll.
133
+ * @param options {object} - Scroll options (optional).
134
+ * @param options.focusAnimated {boolean} - Enable a shake animation on the message component upon completion of scrolling.
135
+ * @param options.viewPosition {number} - Position information to adjust the visible area during scrolling. bottom(0) ~ top(1.0)
136
+ *
137
+ * @example
138
+ * ```
139
+ * const { scrollToMessage } = useContext(GroupChannelContexts.MessageList);
140
+ * const messageIncludedInMessageList = scrollToMessage(lastMessage.messageId, { focusAnimated: true, viewPosition: 1 });
141
+ * if (!messageIncludedInMessageList) console.warn('Message not found in the message list.');
142
+ * ```
143
+ * */
144
+ scrollToMessage: (messageId: number, options?: { focusAnimated?: boolean; viewPosition?: number }) => boolean;
145
+ /**
146
+ * Call the FlatList function asynchronously to scroll to bottom lazily
147
+ * to avoid scrolling before data rendering has been committed.
148
+ * */
149
+ lazyScrollToBottom: (params?: { animated?: boolean; timeout?: number }) => void;
150
+ /**
151
+ * Call the FlatList function asynchronously to scroll to index lazily.
152
+ * to avoid scrolling before data rendering has been committed.
153
+ * */
154
+ lazyScrollToIndex: (params?: {
155
+ index?: number;
156
+ animated?: boolean;
157
+ timeout?: number;
158
+ viewPosition?: number;
159
+ }) => void;
160
+ }>;
120
161
  }
121
162
  export interface GroupChannelModule {
122
163
  Provider: CommonComponent<GroupChannelProps['Provider']>;
@@ -142,4 +183,8 @@ export type GroupChannelPubSubContextPayload =
142
183
  data: {
143
184
  messages: SendbirdMessage[];
144
185
  };
186
+ }
187
+ | {
188
+ type: 'TYPING_BUBBLE_RENDERED';
189
+ data?: undefined;
145
190
  };
@@ -7,8 +7,8 @@ import type { CommonComponent } from '../../types';
7
7
  export interface UserListProps<User> {
8
8
  /** Props for `UserListModule.Header` **/
9
9
  Header: {
10
- right?: React.ReactElement;
11
- left?: React.ReactElement;
10
+ right?: React.ReactNode;
11
+ left?: React.ReactNode;
12
12
  onPressHeaderLeft: () => void;
13
13
  onPressHeaderRight: (selectedUsers: User[]) => Promise<void>;
14
14
  shouldActivateHeaderRight?: (selectedUsers: User[]) => boolean;