@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.
- package/README.md +67 -42
- package/lib/commonjs/components/ChannelInput/EditInput.js +2 -11
- package/lib/commonjs/components/ChannelInput/EditInput.js.map +1 -1
- package/lib/commonjs/components/ChannelInput/MessageToReplyPreview.js +145 -0
- package/lib/commonjs/components/ChannelInput/MessageToReplyPreview.js.map +1 -0
- package/lib/commonjs/components/ChannelInput/SendInput.js +149 -323
- package/lib/commonjs/components/ChannelInput/SendInput.js.map +1 -1
- package/lib/commonjs/components/ChannelInput/VoiceMessageInput.js +238 -0
- package/lib/commonjs/components/ChannelInput/VoiceMessageInput.js.map +1 -0
- package/lib/commonjs/components/ChannelInput/index.js +34 -3
- package/lib/commonjs/components/ChannelInput/index.js.map +1 -1
- package/lib/commonjs/components/ChannelMessageList/index.js +148 -116
- package/lib/commonjs/components/ChannelMessageList/index.js.map +1 -1
- package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js +24 -13
- package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js.map +1 -1
- package/lib/commonjs/components/GroupChannelMessageRenderer/index.js +134 -6
- package/lib/commonjs/components/GroupChannelMessageRenderer/index.js.map +1 -1
- package/lib/commonjs/components/MessageSearchResultItem.js +1 -0
- package/lib/commonjs/components/MessageSearchResultItem.js.map +1 -1
- package/lib/commonjs/components/OpenChannelMessageRenderer/index.js +1 -0
- package/lib/commonjs/components/OpenChannelMessageRenderer/index.js.map +1 -1
- package/lib/commonjs/components/ReactionBottomSheets/ReactionUserListBottomSheet.js +2 -2
- package/lib/commonjs/components/ReactionBottomSheets/ReactionUserListBottomSheet.js.map +1 -1
- package/lib/commonjs/components/ReactionBottomSheets/index.js.map +1 -1
- package/lib/commonjs/components/StatusComposition.js.map +1 -1
- package/lib/commonjs/constants.js +5 -1
- package/lib/commonjs/constants.js.map +1 -1
- package/lib/commonjs/containers/GroupChannelPreviewContainer.js +1 -0
- package/lib/commonjs/containers/GroupChannelPreviewContainer.js.map +1 -1
- package/lib/commonjs/containers/InternalErrorBoundaryContainer.js.map +1 -1
- package/lib/commonjs/containers/SendbirdUIKitContainer.js +72 -34
- package/lib/commonjs/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/commonjs/contexts/PlatformServiceCtx.js +16 -12
- package/lib/commonjs/contexts/PlatformServiceCtx.js.map +1 -1
- package/lib/commonjs/contexts/ReactionCtx.js +3 -2
- package/lib/commonjs/contexts/ReactionCtx.js.map +1 -1
- package/lib/commonjs/contexts/SendbirdChatCtx.js +2 -0
- package/lib/commonjs/contexts/SendbirdChatCtx.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js +14 -4
- package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +28 -42
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/module/moduleContext.js +109 -5
- package/lib/commonjs/domain/groupChannel/module/moduleContext.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/types.js.map +1 -1
- package/lib/commonjs/domain/userList/types.js.map +1 -1
- package/lib/commonjs/fragments/createGroupChannelFragment.js +34 -7
- package/lib/commonjs/fragments/createGroupChannelFragment.js.map +1 -1
- package/lib/commonjs/fragments/createMessageSearchFragment.js +1 -1
- package/lib/commonjs/fragments/createMessageSearchFragment.js.map +1 -1
- package/lib/commonjs/hooks/useChannelInputItems.js +211 -0
- package/lib/commonjs/hooks/useChannelInputItems.js.map +1 -0
- package/lib/commonjs/hooks/useConnection.js +1 -1
- package/lib/commonjs/hooks/useConnection.js.map +1 -1
- package/lib/commonjs/hooks/useVoiceMessageInput.js +207 -0
- package/lib/commonjs/hooks/useVoiceMessageInput.js.map +1 -0
- package/lib/commonjs/index.js +36 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/libs/MentionManager.js.map +1 -1
- package/lib/commonjs/libs/SBUUtils.js +4 -0
- package/lib/commonjs/libs/SBUUtils.js.map +1 -1
- package/lib/commonjs/libs/VoiceMessageConfig.js +30 -0
- package/lib/commonjs/libs/VoiceMessageConfig.js.map +1 -0
- package/lib/commonjs/localization/StringSet.type.js.map +1 -1
- package/lib/commonjs/localization/createBaseStringSet.js +24 -9
- package/lib/commonjs/localization/createBaseStringSet.js.map +1 -1
- package/lib/commonjs/platform/createFileService.expo.js +10 -0
- package/lib/commonjs/platform/createFileService.expo.js.map +1 -1
- package/lib/commonjs/platform/createFileService.native.js +19 -0
- package/lib/commonjs/platform/createFileService.native.js.map +1 -1
- package/lib/commonjs/platform/createPlayerService.expo.js +137 -0
- package/lib/commonjs/platform/createPlayerService.expo.js.map +1 -0
- package/lib/commonjs/platform/createPlayerService.native.js +139 -0
- package/lib/commonjs/platform/createPlayerService.native.js.map +1 -0
- package/lib/commonjs/platform/createRecorderService.expo.js +158 -0
- package/lib/commonjs/platform/createRecorderService.expo.js.map +1 -0
- package/lib/commonjs/platform/createRecorderService.native.js +157 -0
- package/lib/commonjs/platform/createRecorderService.native.js.map +1 -0
- package/lib/commonjs/platform/types.js.map +1 -1
- package/lib/commonjs/types.js +7 -0
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/utils/promise.js +138 -0
- package/lib/commonjs/utils/promise.js.map +1 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/components/ChannelInput/EditInput.js +3 -12
- package/lib/module/components/ChannelInput/EditInput.js.map +1 -1
- package/lib/module/components/ChannelInput/MessageToReplyPreview.js +137 -0
- package/lib/module/components/ChannelInput/MessageToReplyPreview.js.map +1 -0
- package/lib/module/components/ChannelInput/SendInput.js +152 -326
- package/lib/module/components/ChannelInput/SendInput.js.map +1 -1
- package/lib/module/components/ChannelInput/VoiceMessageInput.js +228 -0
- package/lib/module/components/ChannelInput/VoiceMessageInput.js.map +1 -0
- package/lib/module/components/ChannelInput/index.js +36 -5
- package/lib/module/components/ChannelInput/index.js.map +1 -1
- package/lib/module/components/ChannelMessageList/index.js +149 -117
- package/lib/module/components/ChannelMessageList/index.js.map +1 -1
- package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js +24 -13
- package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js.map +1 -1
- package/lib/module/components/GroupChannelMessageRenderer/index.js +132 -7
- package/lib/module/components/GroupChannelMessageRenderer/index.js.map +1 -1
- package/lib/module/components/MessageSearchResultItem.js +2 -1
- package/lib/module/components/MessageSearchResultItem.js.map +1 -1
- package/lib/module/components/OpenChannelMessageRenderer/index.js +1 -0
- package/lib/module/components/OpenChannelMessageRenderer/index.js.map +1 -1
- package/lib/module/components/ReactionBottomSheets/ReactionUserListBottomSheet.js +2 -2
- package/lib/module/components/ReactionBottomSheets/ReactionUserListBottomSheet.js.map +1 -1
- package/lib/module/components/ReactionBottomSheets/index.js.map +1 -1
- package/lib/module/components/StatusComposition.js.map +1 -1
- package/lib/module/constants.js +2 -0
- package/lib/module/constants.js.map +1 -1
- package/lib/module/containers/GroupChannelPreviewContainer.js +2 -1
- package/lib/module/containers/GroupChannelPreviewContainer.js.map +1 -1
- package/lib/module/containers/InternalErrorBoundaryContainer.js.map +1 -1
- package/lib/module/containers/SendbirdUIKitContainer.js +74 -36
- package/lib/module/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/module/contexts/PlatformServiceCtx.js +14 -11
- package/lib/module/contexts/PlatformServiceCtx.js.map +1 -1
- package/lib/module/contexts/ReactionCtx.js +3 -2
- package/lib/module/contexts/ReactionCtx.js.map +1 -1
- package/lib/module/contexts/SendbirdChatCtx.js +2 -0
- package/lib/module/contexts/SendbirdChatCtx.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelHeader.js +15 -5
- package/lib/module/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +29 -43
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/module/domain/groupChannel/module/moduleContext.js +111 -7
- package/lib/module/domain/groupChannel/module/moduleContext.js.map +1 -1
- package/lib/module/domain/groupChannel/types.js.map +1 -1
- package/lib/module/domain/userList/types.js.map +1 -1
- package/lib/module/fragments/createGroupChannelFragment.js +36 -9
- package/lib/module/fragments/createGroupChannelFragment.js.map +1 -1
- package/lib/module/fragments/createMessageSearchFragment.js +1 -1
- package/lib/module/fragments/createMessageSearchFragment.js.map +1 -1
- package/lib/module/hooks/useChannelInputItems.js +203 -0
- package/lib/module/hooks/useChannelInputItems.js.map +1 -0
- package/lib/module/hooks/useConnection.js +1 -1
- package/lib/module/hooks/useConnection.js.map +1 -1
- package/lib/module/hooks/useVoiceMessageInput.js +199 -0
- package/lib/module/hooks/useVoiceMessageInput.js.map +1 -0
- package/lib/module/index.js +8 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/libs/MentionManager.js.map +1 -1
- package/lib/module/libs/SBUUtils.js +4 -0
- package/lib/module/libs/SBUUtils.js.map +1 -1
- package/lib/module/libs/VoiceMessageConfig.js +23 -0
- package/lib/module/libs/VoiceMessageConfig.js.map +1 -0
- package/lib/module/localization/StringSet.type.js.map +1 -1
- package/lib/module/localization/createBaseStringSet.js +25 -10
- package/lib/module/localization/createBaseStringSet.js.map +1 -1
- package/lib/module/platform/createFileService.expo.js +10 -0
- package/lib/module/platform/createFileService.expo.js.map +1 -1
- package/lib/module/platform/createFileService.native.js +19 -0
- package/lib/module/platform/createFileService.native.js.map +1 -1
- package/lib/module/platform/createPlayerService.expo.js +129 -0
- package/lib/module/platform/createPlayerService.expo.js.map +1 -0
- package/lib/module/platform/createPlayerService.native.js +132 -0
- package/lib/module/platform/createPlayerService.native.js.map +1 -0
- package/lib/module/platform/createRecorderService.expo.js +150 -0
- package/lib/module/platform/createRecorderService.expo.js.map +1 -0
- package/lib/module/platform/createRecorderService.native.js +149 -0
- package/lib/module/platform/createRecorderService.native.js.map +1 -0
- package/lib/module/platform/types.js.map +1 -1
- package/lib/module/types.js +5 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/utils/promise.js +132 -0
- package/lib/module/utils/promise.js.map +1 -0
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/src/components/ChannelCover.d.ts +2 -1
- package/lib/typescript/src/components/ChannelInput/AttachmentsButton.d.ts +2 -1
- package/lib/typescript/src/components/ChannelInput/MessageToReplyPreview.d.ts +7 -0
- package/lib/typescript/src/components/ChannelInput/VoiceMessageInput.d.ts +11 -0
- package/lib/typescript/src/components/ChannelInput/index.d.ts +9 -3
- package/lib/typescript/src/components/ChannelMessageList/index.d.ts +4 -1
- package/lib/typescript/src/components/FileViewer.d.ts +2 -1
- package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageDateSeparator.d.ts +2 -1
- package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageFocusAnimation.d.ts +1 -1
- package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageOutgoingStatus.d.ts +1 -1
- package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.d.ts +4 -2
- package/lib/typescript/src/components/GroupChannelMessageRenderer/index.d.ts +3 -0
- package/lib/typescript/src/components/NewMessagesButton.d.ts +1 -1
- package/lib/typescript/src/components/OpenChannelMessageRenderer/OpenChannelMessageDateSeparator.d.ts +2 -1
- package/lib/typescript/src/components/OpenChannelMessageRenderer/index.d.ts +2 -0
- package/lib/typescript/src/components/ProviderLayout.d.ts +1 -1
- package/lib/typescript/src/components/ReactionAddons/BottomSheetReactionAddon.d.ts +2 -1
- package/lib/typescript/src/components/ReactionAddons/MessageReactionAddon.d.ts +2 -1
- package/lib/typescript/src/components/ReactionAddons/ReactionRoundedButton.d.ts +3 -2
- package/lib/typescript/src/components/ReactionAddons/index.d.ts +3 -2
- package/lib/typescript/src/components/ReactionBottomSheets/ReactionListBottomSheet.d.ts +2 -1
- package/lib/typescript/src/components/ReactionBottomSheets/ReactionUserListBottomSheet.d.ts +2 -1
- package/lib/typescript/src/components/ReactionBottomSheets/index.d.ts +4 -4
- package/lib/typescript/src/components/ScrollToBottomButton.d.ts +1 -1
- package/lib/typescript/src/components/StatusComposition.d.ts +4 -4
- package/lib/typescript/src/components/TypedPlaceholder.d.ts +2 -1
- package/lib/typescript/src/components/UserActionBar.d.ts +2 -1
- package/lib/typescript/src/components/UserSelectableBar.d.ts +2 -1
- package/lib/typescript/src/constants.d.ts +2 -0
- package/lib/typescript/src/containers/GroupChannelPreviewContainer.d.ts +2 -1
- package/lib/typescript/src/containers/InternalErrorBoundaryContainer.d.ts +3 -3
- package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +19 -8
- package/lib/typescript/src/contexts/LocalizationCtx.d.ts +1 -1
- package/lib/typescript/src/contexts/PlatformServiceCtx.d.ts +8 -8
- package/lib/typescript/src/contexts/ReactionCtx.d.ts +5 -2
- package/lib/typescript/src/contexts/SendbirdChatCtx.d.ts +6 -3
- package/lib/typescript/src/contexts/UserProfileCtx.d.ts +1 -1
- package/lib/typescript/src/domain/groupChannel/component/GroupChannelHeader.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannel/component/GroupChannelInput.d.ts +1 -1
- package/lib/typescript/src/domain/groupChannel/component/GroupChannelMessageList.d.ts +1 -1
- package/lib/typescript/src/domain/groupChannel/component/GroupChannelStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannel/component/GroupChannelStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannel/component/GroupChannelSuggestedMentionList.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannel/types.d.ts +48 -0
- package/lib/typescript/src/domain/groupChannelBannedUsers/component/GroupChannelBannedUsersHeader.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelBannedUsers/component/GroupChannelBannedUsersList.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelBannedUsers/component/GroupChannelBannedUsersStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelBannedUsers/component/GroupChannelBannedUsersStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListHeader.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListList.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelList/component/GroupChannelListTypeSelector.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelModeration/component/GroupChannelModerationHeader.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelModeration/component/GroupChannelModerationMenu.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelMutedMembers/component/GroupChannelMutedMembersHeader.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelMutedMembers/component/GroupChannelMutedMembersList.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelMutedMembers/component/GroupChannelMutedMembersStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelMutedMembers/component/GroupChannelMutedMembersStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelNotifications/component/GroupChannelNotificationsHeader.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelNotifications/component/GroupChannelNotificationsView.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelOperators/component/GroupChannelOperatorsHeader.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelOperators/component/GroupChannelOperatorsList.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelOperators/component/GroupChannelOperatorsStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelOperators/component/GroupChannelOperatorsStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelSettings/component/GroupChannelSettingsHeader.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelSettings/component/GroupChannelSettingsInfo.d.ts +2 -1
- package/lib/typescript/src/domain/groupChannelSettings/component/GroupChannelSettingsMenu.d.ts +2 -1
- package/lib/typescript/src/domain/messageSearch/component/MessageSearchHeader.d.ts +2 -1
- package/lib/typescript/src/domain/messageSearch/component/MessageSearchList.d.ts +2 -1
- package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/openChannel/component/OpenChannelHeader.d.ts +2 -2
- package/lib/typescript/src/domain/openChannel/component/OpenChannelInput.d.ts +1 -1
- package/lib/typescript/src/domain/openChannel/component/OpenChannelMessageList.d.ts +1 -1
- package/lib/typescript/src/domain/openChannel/component/OpenChannelStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/openChannel/component/OpenChannelStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelBannedUsers/component/OpenChannelBannedUsersHeader.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelBannedUsers/component/OpenChannelBannedUsersList.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelBannedUsers/component/OpenChannelBannedUsersStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelBannedUsers/component/OpenChannelBannedUsersStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelCreate/component/OpenChannelCreateHeader.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelCreate/component/OpenChannelCreateProfileInput.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelCreate/component/OpenChannelCreateStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelList/component/OpenChannelListHeader.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelList/component/OpenChannelListList.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelList/component/OpenChannelListStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelList/component/OpenChannelListStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelModeration/component/OpenChannelModerationHeader.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelModeration/component/OpenChannelModerationMenu.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelMutedParticipants/component/OpenChannelMutedParticipantsHeader.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelMutedParticipants/component/OpenChannelMutedParticipantsList.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelMutedParticipants/component/OpenChannelMutedParticipantsStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelMutedParticipants/component/OpenChannelMutedParticipantsStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelOperators/component/OpenChannelOperatorsHeader.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelOperators/component/OpenChannelOperatorsList.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelOperators/component/OpenChannelOperatorsStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelOperators/component/OpenChannelOperatorsStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelSettings/component/OpenChannelSettingsHeader.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelSettings/component/OpenChannelSettingsInfo.d.ts +2 -1
- package/lib/typescript/src/domain/openChannelSettings/component/OpenChannelSettingsMenu.d.ts +2 -1
- package/lib/typescript/src/domain/userList/component/UserListHeader.d.ts +3 -3
- package/lib/typescript/src/domain/userList/component/UserListList.d.ts +1 -1
- package/lib/typescript/src/domain/userList/component/UserListStatusEmpty.d.ts +2 -1
- package/lib/typescript/src/domain/userList/component/UserListStatusLoading.d.ts +2 -1
- package/lib/typescript/src/domain/userList/types.d.ts +2 -2
- package/lib/typescript/src/hooks/useChannelInputItems.d.ts +10 -0
- package/lib/typescript/src/hooks/useVoiceMessageInput.d.ts +53 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/libs/MentionManager.d.ts +2 -1
- package/lib/typescript/src/libs/SBUUtils.d.ts +1 -0
- package/lib/typescript/src/libs/VoiceMessageConfig.d.ts +25 -0
- package/lib/typescript/src/localization/StringSet.type.d.ts +7 -0
- package/lib/typescript/src/platform/createPlayerService.expo.d.ts +7 -0
- package/lib/typescript/src/platform/createPlayerService.native.d.ts +9 -0
- package/lib/typescript/src/platform/createRecorderService.expo.d.ts +7 -0
- package/lib/typescript/src/platform/createRecorderService.native.d.ts +9 -0
- package/lib/typescript/src/platform/types.d.ts +100 -1
- package/lib/typescript/src/types.d.ts +5 -1
- package/lib/typescript/src/utils/promise.d.ts +7 -0
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +10 -12
- package/src/components/ChannelInput/EditInput.tsx +3 -15
- package/src/components/ChannelInput/MessageToReplyPreview.tsx +133 -0
- package/src/components/ChannelInput/SendInput.tsx +131 -329
- package/src/components/ChannelInput/VoiceMessageInput.tsx +206 -0
- package/src/components/ChannelInput/index.tsx +37 -6
- package/src/components/ChannelMessageList/index.tsx +145 -113
- package/src/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.tsx +24 -11
- package/src/components/GroupChannelMessageRenderer/index.tsx +113 -4
- package/src/components/MessageSearchResultItem.tsx +2 -1
- package/src/components/OpenChannelMessageRenderer/index.tsx +1 -0
- package/src/components/ReactionBottomSheets/ReactionUserListBottomSheet.tsx +2 -2
- package/src/components/ReactionBottomSheets/index.tsx +3 -2
- package/src/components/StatusComposition.tsx +3 -3
- package/src/constants.ts +2 -0
- package/src/containers/GroupChannelPreviewContainer.tsx +2 -0
- package/src/containers/InternalErrorBoundaryContainer.tsx +1 -1
- package/src/containers/SendbirdUIKitContainer.tsx +103 -59
- package/src/contexts/PlatformServiceCtx.tsx +22 -20
- package/src/contexts/ReactionCtx.tsx +7 -5
- package/src/contexts/SendbirdChatCtx.tsx +10 -2
- package/src/domain/groupChannel/component/GroupChannelHeader.tsx +14 -3
- package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +30 -43
- package/src/domain/groupChannel/module/moduleContext.tsx +119 -7
- package/src/domain/groupChannel/types.ts +45 -0
- package/src/domain/userList/types.ts +2 -2
- package/src/fragments/createGroupChannelFragment.tsx +43 -8
- package/src/fragments/createMessageSearchFragment.tsx +1 -1
- package/src/hooks/useChannelInputItems.ts +215 -0
- package/src/hooks/useConnection.ts +1 -1
- package/src/hooks/useVoiceMessageInput.ts +237 -0
- package/src/index.ts +9 -1
- package/src/libs/MentionManager.tsx +1 -1
- package/src/libs/SBUUtils.ts +5 -0
- package/src/libs/VoiceMessageConfig.ts +28 -0
- package/src/localization/StringSet.type.ts +8 -0
- package/src/localization/createBaseStringSet.ts +27 -11
- package/src/platform/createFileService.expo.ts +10 -0
- package/src/platform/createFileService.native.ts +19 -0
- package/src/platform/createPlayerService.expo.tsx +142 -0
- package/src/platform/createPlayerService.native.tsx +148 -0
- package/src/platform/createRecorderService.expo.tsx +160 -0
- package/src/platform/createRecorderService.native.tsx +170 -0
- package/src/platform/types.ts +114 -1
- package/src/types.ts +6 -1
- package/src/utils/promise.ts +139 -0
- 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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
{
|
|
43
|
+
{renderSubtitle()}
|
|
33
44
|
</View>
|
|
34
45
|
</View>
|
|
35
46
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import React, { useContext, useEffect
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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={
|
|
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
|
-
|
|
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.
|
|
105
|
-
<GroupChannelContexts.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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.
|
|
11
|
-
left?: React.
|
|
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;
|