@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,7 +1,8 @@
1
- import React, { useCallback, useMemo, useState } from 'react';
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
2
 
3
3
  import { ReplyType } from '@sendbird/chat/message';
4
4
  import { useGroupChannelMessages } from '@sendbird/uikit-chat-hooks';
5
+ import { Box } from '@sendbird/uikit-react-native-foundation';
5
6
  import {
6
7
  NOOP,
7
8
  PASS,
@@ -14,7 +15,9 @@ import {
14
15
  useRefTracker,
15
16
  } from '@sendbird/uikit-utils';
16
17
 
17
- import GroupChannelMessageRenderer from '../components/GroupChannelMessageRenderer';
18
+ import GroupChannelMessageRenderer, {
19
+ GroupChannelTypingIndicatorBubble,
20
+ } from '../components/GroupChannelMessageRenderer';
18
21
  import NewMessagesButton from '../components/NewMessagesButton';
19
22
  import ScrollToBottomButton from '../components/ScrollToBottomButton';
20
23
  import StatusComposition from '../components/StatusComposition';
@@ -25,7 +28,7 @@ import type {
25
28
  GroupChannelProps,
26
29
  GroupChannelPubSubContextPayload,
27
30
  } from '../domain/groupChannel/types';
28
- import { useSendbirdChat } from '../hooks/useContext';
31
+ import { usePlatformService, useSendbirdChat } from '../hooks/useContext';
29
32
  import pubsub from '../utils/pubsub';
30
33
 
31
34
  const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): GroupChannelFragment => {
@@ -52,6 +55,7 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
52
55
  sortComparator = messageComparator,
53
56
  flatListProps,
54
57
  }) => {
58
+ const { playerService, recorderService } = usePlatformService();
55
59
  const { sdk, currentUser, sbOptions } = useSendbirdChat();
56
60
 
57
61
  const [internalSearchItem, setInternalSearchItem] = useState(searchItem);
@@ -97,9 +101,38 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
97
101
  enableCollectionWithoutLocalCache: true,
98
102
  });
99
103
 
104
+ const onBlurFragment = () => {
105
+ return Promise.allSettled([playerService.reset(), recorderService.reset()]);
106
+ };
107
+ const _onPressHeaderLeft = useFreshCallback(async () => {
108
+ await onBlurFragment();
109
+ onPressHeaderLeft();
110
+ });
111
+ const _onPressHeaderRight = useFreshCallback(async () => {
112
+ await onBlurFragment();
113
+ onPressHeaderRight();
114
+ });
115
+ const _onPressMediaMessage: NonNullable<GroupChannelProps['MessageList']['onPressMediaMessage']> = useFreshCallback(
116
+ async (message, deleteMessage, uri) => {
117
+ await onBlurFragment();
118
+ onPressMediaMessage(message, deleteMessage, uri);
119
+ },
120
+ );
121
+
122
+ useEffect(() => {
123
+ return () => {
124
+ onBlurFragment();
125
+ };
126
+ }, []);
127
+
100
128
  const renderItem: GroupChannelProps['MessageList']['renderMessage'] = useFreshCallback((props) => {
101
- if (renderMessage) return renderMessage(props);
102
- return <GroupChannelMessageRenderer {...props} />;
129
+ const content = renderMessage ? renderMessage(props) : <GroupChannelMessageRenderer {...props} />;
130
+ return (
131
+ <Box>
132
+ {content}
133
+ {props.isFirstItem && !hasNext() && <GroupChannelTypingIndicatorBubble />}
134
+ </Box>
135
+ );
103
136
  });
104
137
 
105
138
  const memoizedFlatListProps = useMemo(
@@ -171,11 +204,13 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
171
204
  groupChannelPubSub={groupChannelPubSub}
172
205
  enableTypingIndicator={enableTypingIndicator ?? sbOptions.uikit.groupChannel.channel.enableTypingIndicator}
173
206
  keyboardAvoidOffset={keyboardAvoidOffset}
207
+ messages={messages}
208
+ onUpdateSearchItem={onUpdateSearchItem}
174
209
  >
175
210
  <GroupChannelModule.Header
176
211
  shouldHideRight={navigateFromMessageSearch}
177
- onPressHeaderLeft={onPressHeaderLeft}
178
- onPressHeaderRight={onPressHeaderRight}
212
+ onPressHeaderLeft={_onPressHeaderLeft}
213
+ onPressHeaderRight={_onPressHeaderRight}
179
214
  />
180
215
  <StatusComposition loading={loading} LoadingComponent={<GroupChannelModule.StatusLoading />}>
181
216
  <GroupChannelModule.MessageList
@@ -198,7 +233,7 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
198
233
  renderScrollToBottomButton={renderScrollToBottomButton}
199
234
  onResendFailedMessage={resendMessage}
200
235
  onDeleteMessage={deleteMessage}
201
- onPressMediaMessage={onPressMediaMessage}
236
+ onPressMediaMessage={_onPressMediaMessage}
202
237
  flatListProps={memoizedFlatListProps}
203
238
  />
204
239
  <GroupChannelModule.Input
@@ -104,7 +104,7 @@ const useMessageSearch = (
104
104
  const query = getMessageSearchQuery(sdk, {
105
105
  keyword,
106
106
  channelUrl: channel.url,
107
- messageTimestampFrom: Math.max(channel.joinedAt, channel.invitedAt),
107
+ messageTimestampFrom: channel.messageOffsetTimestamp,
108
108
  order: MessageSearchOrder.TIMESTAMP,
109
109
  queryCreator,
110
110
  });
@@ -0,0 +1,215 @@
1
+ import { BottomSheetItem, useAlert, useToast } from '@sendbird/uikit-react-native-foundation';
2
+ import { SendbirdChannel, isImage, shouldCompressImage, useIIFE } from '@sendbird/uikit-utils';
3
+
4
+ import SBUError from '../libs/SBUError';
5
+ import SBUUtils from '../libs/SBUUtils';
6
+ import { FileType } from '../platform/types';
7
+ import { useLocalization, usePlatformService, useSendbirdChat } from './useContext';
8
+
9
+ export const useChannelInputItems = (channel: SendbirdChannel, sendFileMessage: (file: FileType) => void) => {
10
+ const { sbOptions, imageCompressionConfig } = useSendbirdChat();
11
+ const { STRINGS } = useLocalization();
12
+ const { fileService, mediaService } = usePlatformService();
13
+ const { alert } = useAlert();
14
+ const toast = useToast();
15
+
16
+ const sheetItems: BottomSheetItem['sheetItems'] = [];
17
+ const input = useIIFE(() => {
18
+ switch (true) {
19
+ case channel.isOpenChannel():
20
+ return sbOptions.uikit.openChannel.channel.input;
21
+ case channel.isGroupChannel():
22
+ return sbOptions.uikit.groupChannel.channel.input;
23
+ default:
24
+ return {
25
+ enableDocument: true,
26
+ camera: { enablePhoto: true, enableVideo: true },
27
+ gallery: { enablePhoto: true, enableVideo: true },
28
+ };
29
+ }
30
+ });
31
+
32
+ if (input.camera.enablePhoto) {
33
+ sheetItems.push({
34
+ title: STRINGS.LABELS.CHANNEL_INPUT_ATTACHMENT_CAMERA_PHOTO,
35
+ icon: 'camera',
36
+ onPress: async () => {
37
+ const mediaFile = await fileService.openCamera({
38
+ mediaType: 'photo',
39
+ onOpenFailure: (error) => {
40
+ if (error.code === SBUError.CODE.ERR_PERMISSIONS_DENIED) {
41
+ alert({
42
+ title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
43
+ message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
44
+ STRINGS.LABELS.PERMISSION_CAMERA,
45
+ STRINGS.LABELS.PERMISSION_APP_NAME,
46
+ ),
47
+ buttons: [{ text: STRINGS.DIALOG.ALERT_PERMISSIONS_OK, onPress: () => SBUUtils.openSettings() }],
48
+ });
49
+ } else {
50
+ toast.show(STRINGS.TOAST.OPEN_CAMERA_ERROR, 'error');
51
+ }
52
+ },
53
+ });
54
+
55
+ if (mediaFile) {
56
+ // Image compression
57
+ if (
58
+ isImage(mediaFile.uri, mediaFile.type) &&
59
+ shouldCompressImage(mediaFile.type, sbOptions.chat.imageCompressionEnabled)
60
+ ) {
61
+ await SBUUtils.safeRun(async () => {
62
+ const compressed = await mediaService.compressImage({
63
+ uri: mediaFile.uri,
64
+ maxWidth: imageCompressionConfig.width,
65
+ maxHeight: imageCompressionConfig.height,
66
+ compressionRate: imageCompressionConfig.compressionRate,
67
+ });
68
+
69
+ if (compressed) {
70
+ mediaFile.uri = compressed.uri;
71
+ mediaFile.size = compressed.size;
72
+ }
73
+ });
74
+ }
75
+
76
+ sendFileMessage(mediaFile);
77
+ }
78
+ },
79
+ });
80
+ }
81
+
82
+ if (input.camera.enableVideo) {
83
+ sheetItems.push({
84
+ title: STRINGS.LABELS.CHANNEL_INPUT_ATTACHMENT_CAMERA_VIDEO,
85
+ icon: 'camera',
86
+ onPress: async () => {
87
+ const mediaFile = await fileService.openCamera({
88
+ mediaType: 'video',
89
+ onOpenFailure: (error) => {
90
+ if (error.code === SBUError.CODE.ERR_PERMISSIONS_DENIED) {
91
+ alert({
92
+ title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
93
+ message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
94
+ STRINGS.LABELS.PERMISSION_CAMERA,
95
+ STRINGS.LABELS.PERMISSION_APP_NAME,
96
+ ),
97
+ buttons: [{ text: STRINGS.DIALOG.ALERT_PERMISSIONS_OK, onPress: () => SBUUtils.openSettings() }],
98
+ });
99
+ } else {
100
+ toast.show(STRINGS.TOAST.OPEN_CAMERA_ERROR, 'error');
101
+ }
102
+ },
103
+ });
104
+
105
+ if (mediaFile) {
106
+ sendFileMessage(mediaFile);
107
+ }
108
+ },
109
+ });
110
+ }
111
+
112
+ if (input.gallery.enablePhoto || input.gallery.enableVideo) {
113
+ const mediaType = (() => {
114
+ switch (true) {
115
+ case input.gallery.enablePhoto && input.gallery.enableVideo:
116
+ return 'all';
117
+ case input.gallery.enablePhoto && !input.gallery.enableVideo:
118
+ return 'photo';
119
+ case !input.gallery.enablePhoto && input.gallery.enableVideo:
120
+ return 'video';
121
+ default:
122
+ return 'all';
123
+ }
124
+ })();
125
+
126
+ sheetItems.push({
127
+ title: STRINGS.LABELS.CHANNEL_INPUT_ATTACHMENT_PHOTO_LIBRARY,
128
+ icon: 'photo',
129
+ onPress: async () => {
130
+ const mediaFiles = await fileService.openMediaLibrary({
131
+ selectionLimit: 1,
132
+ mediaType,
133
+ onOpenFailure: (error) => {
134
+ if (error.code === SBUError.CODE.ERR_PERMISSIONS_DENIED) {
135
+ alert({
136
+ title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
137
+ message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
138
+ STRINGS.LABELS.PERMISSION_DEVICE_STORAGE,
139
+ STRINGS.LABELS.PERMISSION_APP_NAME,
140
+ ),
141
+ buttons: [{ text: STRINGS.DIALOG.ALERT_PERMISSIONS_OK, onPress: () => SBUUtils.openSettings() }],
142
+ });
143
+ } else {
144
+ toast.show(STRINGS.TOAST.OPEN_PHOTO_LIBRARY_ERROR, 'error');
145
+ }
146
+ },
147
+ });
148
+
149
+ if (mediaFiles && mediaFiles[0]) {
150
+ const mediaFile = mediaFiles[0];
151
+
152
+ // Image compression
153
+ if (
154
+ isImage(mediaFile.uri, mediaFile.type) &&
155
+ shouldCompressImage(mediaFile.type, sbOptions.chat.imageCompressionEnabled)
156
+ ) {
157
+ await SBUUtils.safeRun(async () => {
158
+ const compressed = await mediaService.compressImage({
159
+ uri: mediaFile.uri,
160
+ maxWidth: imageCompressionConfig.width,
161
+ maxHeight: imageCompressionConfig.height,
162
+ compressionRate: imageCompressionConfig.compressionRate,
163
+ });
164
+
165
+ if (compressed) {
166
+ mediaFile.uri = compressed.uri;
167
+ mediaFile.size = compressed.size;
168
+ }
169
+ });
170
+ }
171
+
172
+ sendFileMessage(mediaFile);
173
+ }
174
+ },
175
+ });
176
+ }
177
+
178
+ if (input.enableDocument) {
179
+ sheetItems.push({
180
+ title: STRINGS.LABELS.CHANNEL_INPUT_ATTACHMENT_FILES,
181
+ icon: 'document',
182
+ onPress: async () => {
183
+ const documentFile = await fileService.openDocument({
184
+ onOpenFailure: () => toast.show(STRINGS.TOAST.OPEN_FILES_ERROR, 'error'),
185
+ });
186
+
187
+ if (documentFile) {
188
+ // Image compression
189
+ if (
190
+ isImage(documentFile.uri, documentFile.type) &&
191
+ shouldCompressImage(documentFile.type, sbOptions.chat.imageCompressionEnabled)
192
+ ) {
193
+ await SBUUtils.safeRun(async () => {
194
+ const compressed = await mediaService.compressImage({
195
+ uri: documentFile.uri,
196
+ maxWidth: imageCompressionConfig.width,
197
+ maxHeight: imageCompressionConfig.height,
198
+ compressionRate: imageCompressionConfig.compressionRate,
199
+ });
200
+
201
+ if (compressed) {
202
+ documentFile.uri = compressed.uri;
203
+ documentFile.size = compressed.size;
204
+ }
205
+ });
206
+ }
207
+
208
+ sendFileMessage(documentFile);
209
+ }
210
+ },
211
+ });
212
+ }
213
+
214
+ return sheetItems;
215
+ };
@@ -67,7 +67,7 @@ const useConnection = () => {
67
67
  Logger.warn('[useConnection]', 'clear cached-data');
68
68
  await sdk.clearCachedData().catch((e) => Logger.warn('[useConnection]', 'clear cached-data failure', e));
69
69
  } else if (sdk.currentUser) {
70
- await initEmoji(sdk, emojiManager);
70
+ await Promise.allSettled([initEmoji(sdk, emojiManager), initDashboardConfigs(sdk)]);
71
71
 
72
72
  Logger.debug('[useConnection]', 'connected! (offline)');
73
73
  setCurrentUser(sdk.currentUser);
@@ -0,0 +1,237 @@
1
+ import { useRef, useState } from 'react';
2
+
3
+ import { useAlert } from '@sendbird/uikit-react-native-foundation';
4
+ import { Logger, getVoiceMessageFileObject, matchesOneOf } from '@sendbird/uikit-utils';
5
+
6
+ import SBUUtils from '../libs/SBUUtils';
7
+ import { FileType } from '../platform/types';
8
+ import { useLocalization, usePlatformService } from './useContext';
9
+
10
+ type State = {
11
+ /**
12
+ * Status
13
+ *
14
+ * idle:
15
+ * - cancel(): idle
16
+ * - startRecording(): recording
17
+ * recording:
18
+ * - cancel(): idle
19
+ * - stopRecording(): recording_completed
20
+ * - send(): recording_completed > idle
21
+ * recording_completed:
22
+ * - cancel(): idle
23
+ * - playPlayer(): playing
24
+ * - send(): idle
25
+ * playing:
26
+ * - cancel(): idle
27
+ * - pausePlayer(): playing_paused
28
+ * - send(): idle
29
+ * playing_paused:
30
+ * - cancel(): idle
31
+ * - playPlayer(): playing
32
+ * - send(): idle
33
+ * */
34
+ status: 'idle' | 'recording' | 'recording_completed' | 'playing' | 'playing_paused';
35
+ recordingTime: {
36
+ currentTime: number;
37
+ minDuration: number;
38
+ maxDuration: number;
39
+ };
40
+ playingTime: {
41
+ currentTime: number;
42
+ duration: number;
43
+ };
44
+ };
45
+
46
+ export interface VoiceMessageInputResult {
47
+ actions: {
48
+ cancel: () => Promise<void>;
49
+ startRecording: () => Promise<void>;
50
+ stopRecording: () => Promise<void>;
51
+ playPlayer: () => Promise<void>;
52
+ pausePlayer: () => Promise<void>;
53
+ send: () => Promise<void>;
54
+ };
55
+ state: State;
56
+ }
57
+
58
+ type Props = {
59
+ onClose: () => Promise<void>;
60
+ onSend: (voiceFile: FileType, duration: number) => void;
61
+ };
62
+
63
+ const useVoiceMessageInput = ({ onSend, onClose }: Props): VoiceMessageInputResult => {
64
+ const { alert } = useAlert();
65
+ const { STRINGS } = useLocalization();
66
+ const { recorderService, playerService, fileService } = usePlatformService();
67
+ const [status, setStatus] = useState<State['status']>('idle');
68
+
69
+ const [recordingTime, setRecordingTime] = useState({
70
+ currentTime: 0,
71
+ minDuration: recorderService.options.minDuration,
72
+ maxDuration: recorderService.options.maxDuration,
73
+ });
74
+ const [playingTime, setPlayingTime] = useState({
75
+ currentTime: 0,
76
+ duration: 0,
77
+ });
78
+
79
+ const recordingPath = useRef<{ recordFilePath: string; uri: string }>();
80
+ const getVoiceMessageRecordingPath = () => {
81
+ if (!recordingPath.current) throw new Error('No recording path');
82
+ return recordingPath.current;
83
+ };
84
+ const setVoiceMessageRecordingPath = (path: { recordFilePath: string; uri: string }) => {
85
+ recordingPath.current = path;
86
+ };
87
+
88
+ const clear = async () => {
89
+ recordingPath.current = undefined;
90
+ await playerService.reset();
91
+ await recorderService.reset();
92
+ setRecordingTime({
93
+ currentTime: 0,
94
+ minDuration: recorderService.options.minDuration,
95
+ maxDuration: recorderService.options.maxDuration,
96
+ });
97
+ setPlayingTime({
98
+ currentTime: 0,
99
+ duration: 0,
100
+ });
101
+ setStatus('idle');
102
+ };
103
+
104
+ return {
105
+ state: {
106
+ status,
107
+ recordingTime,
108
+ playingTime,
109
+ },
110
+ actions: {
111
+ async cancel() {
112
+ await clear();
113
+ },
114
+ async startRecording() {
115
+ const granted = await recorderService.requestPermission();
116
+ if (!granted) {
117
+ await onClose();
118
+ alert({
119
+ title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
120
+ message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
121
+ STRINGS.LABELS.PERMISSION_MICROPHONE,
122
+ STRINGS.LABELS.PERMISSION_APP_NAME,
123
+ ),
124
+ buttons: [{ text: STRINGS.DIALOG.ALERT_PERMISSIONS_OK, onPress: () => SBUUtils.openSettings() }],
125
+ });
126
+ Logger.error('Failed to request permission for recorder');
127
+ return;
128
+ }
129
+
130
+ if (matchesOneOf(status, ['idle'])) {
131
+ // Before start recording, if player is not idle, reset it.
132
+ if (playerService.state !== 'idle') {
133
+ await playerService.reset();
134
+ }
135
+
136
+ const unsubscribeRecording = recorderService.addRecordingListener(({ currentTime }) => {
137
+ setRecordingTime({
138
+ currentTime,
139
+ maxDuration: recorderService.options.maxDuration,
140
+ minDuration: recorderService.options.minDuration,
141
+ });
142
+ setPlayingTime((prev) => ({ ...prev, duration: currentTime }));
143
+ });
144
+
145
+ const unsubscribeState = recorderService.addStateListener((state) => {
146
+ switch (state) {
147
+ case 'recording':
148
+ setStatus('recording');
149
+ break;
150
+ case 'completed':
151
+ setStatus('recording_completed');
152
+ unsubscribeRecording();
153
+ unsubscribeState();
154
+ break;
155
+ }
156
+ });
157
+
158
+ if (SBUUtils.isExpo()) {
159
+ await recorderService.record();
160
+ if (recorderService.uri) {
161
+ setVoiceMessageRecordingPath({ recordFilePath: recorderService.uri, uri: recorderService.uri });
162
+ }
163
+ } else {
164
+ setVoiceMessageRecordingPath(fileService.createRecordFilePath(recorderService.options.extension));
165
+ await recorderService.record(getVoiceMessageRecordingPath().recordFilePath);
166
+ }
167
+ }
168
+ },
169
+ async stopRecording() {
170
+ if (matchesOneOf(status, ['recording'])) {
171
+ await recorderService.stop();
172
+ }
173
+ },
174
+ async playPlayer() {
175
+ const granted = await playerService.requestPermission();
176
+ if (!granted) {
177
+ alert({
178
+ title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
179
+ message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
180
+ STRINGS.LABELS.PERMISSION_DEVICE_STORAGE,
181
+ STRINGS.LABELS.PERMISSION_APP_NAME,
182
+ ),
183
+ buttons: [{ text: STRINGS.DIALOG.ALERT_PERMISSIONS_OK, onPress: () => SBUUtils.openSettings() }],
184
+ });
185
+ Logger.error('Failed to request permission for player');
186
+ return;
187
+ }
188
+
189
+ if (matchesOneOf(status, ['recording_completed', 'playing_paused'])) {
190
+ const unsubscribePlayback = playerService.addPlaybackListener(({ currentTime, duration }) => {
191
+ setPlayingTime({ currentTime, duration });
192
+ });
193
+
194
+ const unsubscribeState = playerService.addStateListener((state) => {
195
+ switch (state) {
196
+ case 'playing':
197
+ setStatus('playing');
198
+ break;
199
+ case 'paused': {
200
+ setStatus('playing_paused');
201
+ unsubscribeState();
202
+ unsubscribePlayback();
203
+ break;
204
+ }
205
+ case 'stopped': {
206
+ setStatus('playing_paused');
207
+ unsubscribeState();
208
+ unsubscribePlayback();
209
+ setPlayingTime((prev) => ({ ...prev, currentTime: 0 }));
210
+ break;
211
+ }
212
+ }
213
+ });
214
+
215
+ await playerService.play(getVoiceMessageRecordingPath().recordFilePath);
216
+ }
217
+ },
218
+ async pausePlayer() {
219
+ if (matchesOneOf(status, ['playing'])) {
220
+ await playerService.pause();
221
+ }
222
+ },
223
+ async send() {
224
+ if (
225
+ matchesOneOf(status, ['recording', 'recording_completed', 'playing', 'playing_paused']) &&
226
+ recordingPath.current
227
+ ) {
228
+ const voiceFile = getVoiceMessageFileObject(recordingPath.current.uri, recorderService.options.extension);
229
+ onSend(voiceFile, Math.floor(recordingTime.currentTime));
230
+ await clear();
231
+ }
232
+ },
233
+ },
234
+ };
235
+ };
236
+
237
+ export default useVoiceMessageInput;
package/src/index.ts CHANGED
@@ -2,6 +2,8 @@ import { Platform } from 'react-native';
2
2
 
3
3
  import { Logger } from '@sendbird/uikit-utils';
4
4
 
5
+ import { PromisePolyfill } from './utils/promise';
6
+
5
7
  /** Components **/
6
8
  export { default as ChannelInput } from './components/ChannelInput';
7
9
  export { default as ChannelMessageList } from './components/ChannelMessageList';
@@ -69,10 +71,14 @@ export { default as createNativeFileService } from './platform/createFileService
69
71
  export { default as createNativeClipboardService } from './platform/createClipboardService.native';
70
72
  export { default as createNativeNotificationService } from './platform/createNotificationService.native';
71
73
  export { default as createNativeMediaService } from './platform/createMediaService.native';
74
+ export { default as createNativePlayerService } from './platform/createPlayerService.native';
75
+ export { default as createNativeRecorderService } from './platform/createRecorderService.native';
72
76
  export { default as createExpoFileService } from './platform/createFileService.expo';
73
77
  export { default as createExpoClipboardService } from './platform/createClipboardService.expo';
74
78
  export { default as createExpoNotificationService } from './platform/createNotificationService.expo';
75
79
  export { default as createExpoMediaService } from './platform/createMediaService.expo';
80
+ export { default as createExpoPlayerService } from './platform/createPlayerService.expo';
81
+ export { default as createExpoRecorderService } from './platform/createRecorderService.expo';
76
82
  export * from './platform/types';
77
83
 
78
84
  /** Feature - shared **/
@@ -128,8 +134,10 @@ export { default as SendbirdUIKitContainer, SendbirdUIKit } from './containers/S
128
134
  export type { SendbirdUIKitContainerProps } from './containers/SendbirdUIKitContainer';
129
135
  export { default as SBUError } from './libs/SBUError';
130
136
  export { default as SBUUtils } from './libs/SBUUtils';
131
-
132
137
  export * from './types';
133
138
 
134
139
  Logger.setLogLevel(__DEV__ ? 'warn' : 'none');
135
140
  Logger.setTitle(`[UIKIT_${Platform.OS}]`);
141
+
142
+ // NOTE: In Hermes, not all implementations of Promise are included
143
+ PromisePolyfill.apply();
@@ -142,7 +142,7 @@ class MentionManager {
142
142
  ],
143
143
  };
144
144
  },
145
- { leftText: text, components: [] as (string | JSX.Element)[] },
145
+ { leftText: text, components: [] as (string | React.ReactNode)[] },
146
146
  );
147
147
 
148
148
  return [leftText, ...components];
@@ -37,4 +37,9 @@ export default class SBUUtils {
37
37
  await callback();
38
38
  } catch (e) {}
39
39
  }
40
+
41
+ static isExpo() {
42
+ const _g = global ?? window;
43
+ return typeof _g === 'object' && 'expo' in _g;
44
+ }
40
45
  }
@@ -0,0 +1,28 @@
1
+ export interface VoiceMessageConfigInterface {
2
+ recorder: {
3
+ minDuration: number;
4
+ maxDuration: number;
5
+ };
6
+ }
7
+
8
+ class VoiceMessageConfig {
9
+ static DEFAULT = {
10
+ RECORDER: {
11
+ MIN_DURATION: 1000,
12
+ MAX_DURATION: 600 * 1000,
13
+ EXTENSION: 'm4a',
14
+
15
+ BIT_RATE: 12000,
16
+ SAMPLE_RATE: 11025,
17
+ CHANNELS: 1,
18
+ },
19
+ };
20
+
21
+ constructor(private _config: VoiceMessageConfigInterface) {}
22
+
23
+ get recorder() {
24
+ return this._config.recorder;
25
+ }
26
+ }
27
+
28
+ export default VoiceMessageConfig;