@sendbird/uikit-react-native 3.5.4 → 3.6.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/lib/commonjs/components/ChannelInput/SendInput.js +23 -6
- package/lib/commonjs/components/ChannelInput/SendInput.js.map +1 -1
- package/lib/commonjs/components/ChannelInput/index.js.map +1 -1
- package/lib/commonjs/components/ChannelMessageList/index.js +22 -4
- package/lib/commonjs/components/ChannelMessageList/index.js.map +1 -1
- package/lib/commonjs/components/ChannelThreadMessageList/index.js +349 -0
- package/lib/commonjs/components/ChannelThreadMessageList/index.js.map +1 -0
- package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js +2 -2
- package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js.map +1 -1
- package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.js +100 -0
- package/lib/commonjs/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.js.map +1 -0
- package/lib/commonjs/components/GroupChannelMessageRenderer/index.js +24 -6
- package/lib/commonjs/components/GroupChannelMessageRenderer/index.js.map +1 -1
- package/lib/commonjs/components/ReactionAddons/MessageReactionAddon.js +23 -6
- package/lib/commonjs/components/ReactionAddons/MessageReactionAddon.js.map +1 -1
- package/lib/commonjs/components/ThreadChatFlatList/index.js +76 -0
- package/lib/commonjs/components/ThreadChatFlatList/index.js.map +1 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.js +41 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.js.map +1 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.js +74 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.js.map +1 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.js +42 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.js.map +1 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.js +94 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.js.map +1 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.user.js +61 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.user.js.map +1 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.js +127 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.js.map +1 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/index.js +206 -0
- package/lib/commonjs/components/ThreadParentMessageRenderer/index.js.map +1 -0
- package/lib/commonjs/containers/SendbirdUIKitContainer.js +3 -0
- package/lib/commonjs/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/commonjs/contexts/SendbirdChatCtx.js +7 -0
- package/lib/commonjs/contexts/SendbirdChatCtx.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +28 -5
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/module/moduleContext.js +14 -4
- 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/groupChannelThread/component/GroupChannelThreadHeader.js +82 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadHeader.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadInput.js +44 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadInput.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadMessageList.js +127 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadMessageList.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.js +315 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.js +27 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.js +27 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.js +195 -0
- package/lib/commonjs/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/index.js +69 -0
- package/lib/commonjs/domain/groupChannelThread/index.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/module/createGroupChannelThreadModule.js +42 -0
- package/lib/commonjs/domain/groupChannelThread/module/createGroupChannelThreadModule.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/module/moduleContext.js +148 -0
- package/lib/commonjs/domain/groupChannelThread/module/moduleContext.js.map +1 -0
- package/lib/commonjs/domain/groupChannelThread/types.js +6 -0
- package/lib/commonjs/domain/groupChannelThread/types.js.map +1 -0
- package/lib/commonjs/fragments/createGroupChannelFragment.js +30 -5
- package/lib/commonjs/fragments/createGroupChannelFragment.js.map +1 -1
- package/lib/commonjs/fragments/createGroupChannelThreadFragment.js +267 -0
- package/lib/commonjs/fragments/createGroupChannelThreadFragment.js.map +1 -0
- package/lib/commonjs/hooks/useMentionSuggestion.js +5 -2
- package/lib/commonjs/hooks/useMentionSuggestion.js.map +1 -1
- package/lib/commonjs/index.js +72 -40
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/libs/VoiceMessageStatusManager.js +66 -0
- package/lib/commonjs/libs/VoiceMessageStatusManager.js.map +1 -0
- package/lib/commonjs/localization/StringSet.type.js.map +1 -1
- package/lib/commonjs/localization/createBaseStringSet.js +25 -3
- package/lib/commonjs/localization/createBaseStringSet.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/components/ChannelInput/SendInput.js +23 -6
- package/lib/module/components/ChannelInput/SendInput.js.map +1 -1
- package/lib/module/components/ChannelInput/index.js.map +1 -1
- package/lib/module/components/ChannelMessageList/index.js +22 -4
- package/lib/module/components/ChannelMessageList/index.js.map +1 -1
- package/lib/module/components/ChannelThreadMessageList/index.js +341 -0
- package/lib/module/components/ChannelThreadMessageList/index.js.map +1 -0
- package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js +2 -2
- package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.js.map +1 -1
- package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.js +92 -0
- package/lib/module/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.js.map +1 -0
- package/lib/module/components/GroupChannelMessageRenderer/index.js +24 -6
- package/lib/module/components/GroupChannelMessageRenderer/index.js.map +1 -1
- package/lib/module/components/ReactionAddons/MessageReactionAddon.js +23 -6
- package/lib/module/components/ReactionAddons/MessageReactionAddon.js.map +1 -1
- package/lib/module/components/ThreadChatFlatList/index.js +66 -0
- package/lib/module/components/ThreadChatFlatList/index.js.map +1 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.js +34 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.js.map +1 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.js +67 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.js.map +1 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.js +34 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.js.map +1 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.js +87 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.js.map +1 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.user.js +54 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.user.js.map +1 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.js +119 -0
- package/lib/module/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.js.map +1 -0
- package/lib/module/components/ThreadParentMessageRenderer/index.js +196 -0
- package/lib/module/components/ThreadParentMessageRenderer/index.js.map +1 -0
- package/lib/module/containers/SendbirdUIKitContainer.js +3 -0
- package/lib/module/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/module/contexts/SendbirdChatCtx.js +6 -0
- package/lib/module/contexts/SendbirdChatCtx.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +30 -6
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/module/domain/groupChannel/module/moduleContext.js +14 -4
- 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/groupChannelThread/component/GroupChannelThreadHeader.js +73 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadHeader.js.map +1 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadInput.js +34 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadInput.js.map +1 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadMessageList.js +117 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadMessageList.js.map +1 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.js +305 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.js.map +1 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.js +19 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.js.map +1 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.js +19 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.js.map +1 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.js +185 -0
- package/lib/module/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.js.map +1 -0
- package/lib/module/domain/groupChannelThread/index.js +9 -0
- package/lib/module/domain/groupChannelThread/index.js.map +1 -0
- package/lib/module/domain/groupChannelThread/module/createGroupChannelThreadModule.js +34 -0
- package/lib/module/domain/groupChannelThread/module/createGroupChannelThreadModule.js.map +1 -0
- package/lib/module/domain/groupChannelThread/module/moduleContext.js +137 -0
- package/lib/module/domain/groupChannelThread/module/moduleContext.js.map +1 -0
- package/lib/module/domain/groupChannelThread/types.js +2 -0
- package/lib/module/domain/groupChannelThread/types.js.map +1 -0
- package/lib/module/fragments/createGroupChannelFragment.js +33 -7
- package/lib/module/fragments/createGroupChannelFragment.js.map +1 -1
- package/lib/module/fragments/createGroupChannelThreadFragment.js +257 -0
- package/lib/module/fragments/createGroupChannelThreadFragment.js.map +1 -0
- package/lib/module/hooks/useMentionSuggestion.js +5 -2
- package/lib/module/hooks/useMentionSuggestion.js.map +1 -1
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/libs/VoiceMessageStatusManager.js +59 -0
- package/lib/module/libs/VoiceMessageStatusManager.js.map +1 -0
- package/lib/module/localization/StringSet.type.js.map +1 -1
- package/lib/module/localization/createBaseStringSet.js +27 -4
- package/lib/module/localization/createBaseStringSet.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/src/components/ChannelInput/index.d.ts +1 -0
- package/lib/typescript/src/components/ChannelMessageList/index.d.ts +5 -2
- package/lib/typescript/src/components/ChannelThreadMessageList/index.d.ts +55 -0
- package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.d.ts +1 -1
- package/lib/typescript/src/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.d.ts +9 -0
- package/lib/typescript/src/components/GroupChannelMessageRenderer/index.d.ts +3 -1
- package/lib/typescript/src/components/OpenChannelMessageRenderer/index.d.ts +3 -1
- package/lib/typescript/src/components/ReactionAddons/MessageReactionAddon.d.ts +3 -1
- package/lib/typescript/src/components/ReactionAddons/index.d.ts +2 -1
- package/lib/typescript/src/components/ThreadChatFlatList/index.d.ts +9 -0
- package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.d.ts +4 -0
- package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.d.ts +4 -0
- package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.d.ts +9 -0
- package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.d.ts +13 -0
- package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.user.d.ts +10 -0
- package/lib/typescript/src/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.d.ts +10 -0
- package/lib/typescript/src/components/ThreadParentMessageRenderer/index.d.ts +20 -0
- package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +2 -4
- package/lib/typescript/src/contexts/SendbirdChatCtx.d.ts +15 -1
- package/lib/typescript/src/domain/groupChannel/types.d.ts +4 -1
- package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadHeader.d.ts +4 -0
- package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadInput.d.ts +3 -0
- package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadMessageList.d.ts +7 -0
- package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.d.ts +8 -0
- package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.d.ts +3 -0
- package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.d.ts +3 -0
- package/lib/typescript/src/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.d.ts +4 -0
- package/lib/typescript/src/domain/groupChannelThread/index.d.ts +8 -0
- package/lib/typescript/src/domain/groupChannelThread/module/createGroupChannelThreadModule.d.ts +3 -0
- package/lib/typescript/src/domain/groupChannelThread/module/moduleContext.d.ts +3 -0
- package/lib/typescript/src/domain/groupChannelThread/types.d.ts +136 -0
- package/lib/typescript/src/domain/openChannel/component/OpenChannelHeader.d.ts +1 -1
- package/lib/typescript/src/fragments/createGroupChannelThreadFragment.d.ts +5 -0
- package/lib/typescript/src/hooks/useChannelInputItems.d.ts +1 -1
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/libs/VoiceMessageStatusManager.d.ts +11 -0
- package/lib/typescript/src/localization/StringSet.type.d.ts +23 -0
- package/lib/typescript/src/localization/createBaseStringSet.d.ts +1 -1
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +6 -6
- package/src/components/ChannelInput/SendInput.tsx +24 -5
- package/src/components/ChannelInput/index.tsx +1 -0
- package/src/components/ChannelMessageList/index.tsx +27 -5
- package/src/components/ChannelThreadMessageList/index.tsx +406 -0
- package/src/components/GroupChannelMessageRenderer/GroupChannelMessageParentMessage.tsx +3 -3
- package/src/components/GroupChannelMessageRenderer/GroupChannelMessageReplyInfo.tsx +96 -0
- package/src/components/GroupChannelMessageRenderer/index.tsx +21 -5
- package/src/components/ReactionAddons/MessageReactionAddon.tsx +38 -5
- package/src/components/ThreadChatFlatList/index.tsx +63 -0
- package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.image.tsx +36 -0
- package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.tsx +61 -0
- package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.video.tsx +45 -0
- package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.file.voice.tsx +107 -0
- package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.user.og.tsx +133 -0
- package/src/components/ThreadParentMessageRenderer/ThreadParentMessage.user.tsx +65 -0
- package/src/components/ThreadParentMessageRenderer/index.tsx +194 -0
- package/src/containers/SendbirdUIKitContainer.tsx +4 -3
- package/src/contexts/SendbirdChatCtx.tsx +20 -0
- package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +37 -8
- package/src/domain/groupChannel/module/moduleContext.tsx +12 -2
- package/src/domain/groupChannel/types.ts +5 -0
- package/src/domain/groupChannelThread/component/GroupChannelThreadHeader.tsx +63 -0
- package/src/domain/groupChannelThread/component/GroupChannelThreadInput.tsx +38 -0
- package/src/domain/groupChannelThread/component/GroupChannelThreadMessageList.tsx +105 -0
- package/src/domain/groupChannelThread/component/GroupChannelThreadParentMessageInfo.tsx +326 -0
- package/src/domain/groupChannelThread/component/GroupChannelThreadStatusEmpty.tsx +18 -0
- package/src/domain/groupChannelThread/component/GroupChannelThreadStatusLoading.tsx +18 -0
- package/src/domain/groupChannelThread/component/GroupChannelThreadSuggestedMentionList.tsx +174 -0
- package/src/domain/groupChannelThread/index.ts +8 -0
- package/src/domain/groupChannelThread/module/createGroupChannelThreadModule.tsx +35 -0
- package/src/domain/groupChannelThread/module/moduleContext.tsx +165 -0
- package/src/domain/groupChannelThread/types.ts +184 -0
- package/src/fragments/createGroupChannelFragment.tsx +38 -8
- package/src/fragments/createGroupChannelThreadFragment.tsx +280 -0
- package/src/hooks/useMentionSuggestion.ts +13 -9
- package/src/index.ts +4 -0
- package/src/libs/VoiceMessageStatusManager.ts +56 -0
- package/src/localization/StringSet.type.ts +27 -0
- package/src/localization/createBaseStringSet.ts +33 -4
- package/src/version.ts +1 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { type RegexTextPattern, Text, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
|
|
4
|
+
import { RegexText, createStyleSheet } from '@sendbird/uikit-react-native-foundation';
|
|
5
|
+
import { SendbirdUserMessage, urlRegexStrict } from '@sendbird/uikit-utils';
|
|
6
|
+
|
|
7
|
+
import { ThreadParentMessageRendererProps } from './index';
|
|
8
|
+
|
|
9
|
+
type Props = ThreadParentMessageRendererProps<{
|
|
10
|
+
regexTextPatterns?: RegexTextPattern[];
|
|
11
|
+
renderRegexTextChildren?: (message: SendbirdUserMessage) => string;
|
|
12
|
+
}>;
|
|
13
|
+
|
|
14
|
+
const ThreadParentMessageUser = (props: Props) => {
|
|
15
|
+
const userMessage: SendbirdUserMessage = props.parentMessage as SendbirdUserMessage;
|
|
16
|
+
if (!userMessage) return null;
|
|
17
|
+
|
|
18
|
+
const { colors } = useUIKitTheme();
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Text body3 color={colors.onBackground01} suppressHighlighting>
|
|
22
|
+
<RegexText
|
|
23
|
+
body3
|
|
24
|
+
color={colors.onBackground01}
|
|
25
|
+
patterns={[
|
|
26
|
+
...(props.regexTextPatterns ?? []),
|
|
27
|
+
{
|
|
28
|
+
regex: urlRegexStrict,
|
|
29
|
+
replacer({ match, parentProps, keyPrefix, index }) {
|
|
30
|
+
return (
|
|
31
|
+
<Text
|
|
32
|
+
{...parentProps}
|
|
33
|
+
key={`${keyPrefix}-${index}`}
|
|
34
|
+
onPress={() => props.onPressURL?.(match)}
|
|
35
|
+
style={[parentProps?.style, styles.urlText]}
|
|
36
|
+
>
|
|
37
|
+
{match}
|
|
38
|
+
</Text>
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
]}
|
|
43
|
+
>
|
|
44
|
+
{props.renderRegexTextChildren?.(userMessage)}
|
|
45
|
+
</RegexText>
|
|
46
|
+
{Boolean(userMessage.updatedAt) && (
|
|
47
|
+
<Text body3 color={colors.onBackground02}>
|
|
48
|
+
{' (edited)'}
|
|
49
|
+
</Text>
|
|
50
|
+
)}
|
|
51
|
+
</Text>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const styles = createStyleSheet({
|
|
56
|
+
bubble: {
|
|
57
|
+
paddingHorizontal: 12,
|
|
58
|
+
paddingVertical: 6,
|
|
59
|
+
},
|
|
60
|
+
urlText: {
|
|
61
|
+
textDecorationLine: 'underline',
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export default ThreadParentMessageUser;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import { RegexTextPattern, Text, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
|
|
4
|
+
import {
|
|
5
|
+
SendbirdFileMessage,
|
|
6
|
+
type SendbirdUser,
|
|
7
|
+
SendbirdUserMessage,
|
|
8
|
+
getMessageType,
|
|
9
|
+
isMyMessage,
|
|
10
|
+
isVoiceMessage,
|
|
11
|
+
} from '@sendbird/uikit-utils';
|
|
12
|
+
|
|
13
|
+
import { VOICE_MESSAGE_META_ARRAY_DURATION_KEY } from '../../constants';
|
|
14
|
+
import SBUUtils from '../../libs/SBUUtils';
|
|
15
|
+
import { usePlatformService, useSendbirdChat } from './../../hooks/useContext';
|
|
16
|
+
import ThreadParentMessageFile from './ThreadParentMessage.file';
|
|
17
|
+
import ThreadParentMessageFileImage from './ThreadParentMessage.file.image';
|
|
18
|
+
import ThreadParentMessageFileVideo from './ThreadParentMessage.file.video';
|
|
19
|
+
import ThreadParentMessageFileVoice, { VoiceFileMessageState } from './ThreadParentMessage.file.voice';
|
|
20
|
+
import ThreadParentMessageUser from './ThreadParentMessage.user';
|
|
21
|
+
import ThreadParentMessageUserOg from './ThreadParentMessage.user.og';
|
|
22
|
+
|
|
23
|
+
export type ThreadParentMessageRendererProps<AdditionalProps = unknown> = {
|
|
24
|
+
parentMessage: SendbirdUserMessage | SendbirdFileMessage;
|
|
25
|
+
onPress?: () => void;
|
|
26
|
+
onLongPress?: () => void;
|
|
27
|
+
onPressURL?: (url: string) => void;
|
|
28
|
+
onPressMentionedUser?: (mentionedUser?: SendbirdUser) => void;
|
|
29
|
+
onToggleVoiceMessage?: (
|
|
30
|
+
state: VoiceFileMessageState,
|
|
31
|
+
setState: React.Dispatch<React.SetStateAction<VoiceFileMessageState>>,
|
|
32
|
+
) => Promise<void>;
|
|
33
|
+
} & AdditionalProps;
|
|
34
|
+
|
|
35
|
+
const ThreadParentMessageRenderer = (props: ThreadParentMessageRendererProps) => {
|
|
36
|
+
const playerUnsubscribes = useRef<(() => void)[]>([]);
|
|
37
|
+
const { sbOptions, currentUser, mentionManager } = useSendbirdChat();
|
|
38
|
+
const { palette } = useUIKitTheme();
|
|
39
|
+
const { mediaService, playerService } = usePlatformService();
|
|
40
|
+
const parentMessage = props.parentMessage;
|
|
41
|
+
|
|
42
|
+
const resetPlayer = async () => {
|
|
43
|
+
playerUnsubscribes.current.forEach((unsubscribe) => {
|
|
44
|
+
try {
|
|
45
|
+
unsubscribe();
|
|
46
|
+
} catch {}
|
|
47
|
+
});
|
|
48
|
+
playerUnsubscribes.current.length = 0;
|
|
49
|
+
await playerService.reset();
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const messageProps: ThreadParentMessageRendererProps = {
|
|
53
|
+
onPressURL: (url) => SBUUtils.openURL(url),
|
|
54
|
+
onToggleVoiceMessage: async (state, setState) => {
|
|
55
|
+
if (isVoiceMessage(parentMessage) && parentMessage.sendingStatus === 'succeeded') {
|
|
56
|
+
if (playerService.uri === parentMessage.url) {
|
|
57
|
+
if (playerService.state === 'playing') {
|
|
58
|
+
await playerService.pause();
|
|
59
|
+
} else {
|
|
60
|
+
await playerService.play(parentMessage.url);
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
if (playerService.state !== 'idle') {
|
|
64
|
+
await resetPlayer();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const shouldSeekToTime = state.duration > state.currentTime && state.currentTime > 0;
|
|
68
|
+
let seekFinished = !shouldSeekToTime;
|
|
69
|
+
|
|
70
|
+
const forPlayback = playerService.addPlaybackListener(({ stopped, currentTime, duration }) => {
|
|
71
|
+
if (seekFinished) {
|
|
72
|
+
setState((prevState) => ({ ...prevState, currentTime: stopped ? 0 : currentTime, duration }));
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
const forState = playerService.addStateListener((state) => {
|
|
76
|
+
switch (state) {
|
|
77
|
+
case 'preparing':
|
|
78
|
+
setState((prevState) => ({ ...prevState, status: 'preparing' }));
|
|
79
|
+
break;
|
|
80
|
+
case 'playing':
|
|
81
|
+
setState((prevState) => ({ ...prevState, status: 'playing' }));
|
|
82
|
+
break;
|
|
83
|
+
case 'idle':
|
|
84
|
+
case 'paused': {
|
|
85
|
+
setState((prevState) => ({ ...prevState, status: 'paused' }));
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case 'stopped':
|
|
89
|
+
setState((prevState) => ({ ...prevState, status: 'paused' }));
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
playerUnsubscribes.current.push(forPlayback, forState);
|
|
94
|
+
|
|
95
|
+
await playerService.play(parentMessage.url);
|
|
96
|
+
if (shouldSeekToTime) {
|
|
97
|
+
await playerService.seek(state.currentTime);
|
|
98
|
+
seekFinished = true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
...props,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const userMessageProps: {
|
|
107
|
+
renderRegexTextChildren: (message: SendbirdUserMessage) => string;
|
|
108
|
+
regexTextPatterns: RegexTextPattern[];
|
|
109
|
+
} = {
|
|
110
|
+
renderRegexTextChildren: (message) => {
|
|
111
|
+
if (
|
|
112
|
+
mentionManager.shouldUseMentionedMessageTemplate(message, sbOptions.uikit.groupChannel.channel.enableMention)
|
|
113
|
+
) {
|
|
114
|
+
return message.mentionedMessageTemplate;
|
|
115
|
+
} else {
|
|
116
|
+
return message.message;
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
regexTextPatterns: [
|
|
120
|
+
{
|
|
121
|
+
regex: mentionManager.templateRegex,
|
|
122
|
+
replacer({ match, groups, parentProps, index, keyPrefix }) {
|
|
123
|
+
const user = parentMessage.mentionedUsers?.find((it) => it.userId === groups[2]);
|
|
124
|
+
if (user) {
|
|
125
|
+
const mentionColor =
|
|
126
|
+
!isMyMessage(parentMessage, currentUser?.userId) && user.userId === currentUser?.userId
|
|
127
|
+
? palette.onBackgroundLight01
|
|
128
|
+
: parentProps?.color;
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<Text
|
|
132
|
+
{...parentProps}
|
|
133
|
+
key={`${keyPrefix}-${index}`}
|
|
134
|
+
color={mentionColor}
|
|
135
|
+
onPress={() => messageProps.onPressMentionedUser?.(user)}
|
|
136
|
+
onLongPress={messageProps.onLongPress}
|
|
137
|
+
style={[
|
|
138
|
+
parentProps?.style,
|
|
139
|
+
{ fontWeight: '700' },
|
|
140
|
+
user.userId === currentUser?.userId && { backgroundColor: palette.highlight },
|
|
141
|
+
]}
|
|
142
|
+
>
|
|
143
|
+
{`${mentionManager.asMentionedMessageText(user)}`}
|
|
144
|
+
</Text>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return match;
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
switch (getMessageType(props.parentMessage)) {
|
|
154
|
+
case 'user': {
|
|
155
|
+
return <ThreadParentMessageUser {...userMessageProps} {...messageProps} />;
|
|
156
|
+
}
|
|
157
|
+
case 'user.opengraph': {
|
|
158
|
+
return <ThreadParentMessageUserOg {...userMessageProps} {...messageProps} />;
|
|
159
|
+
}
|
|
160
|
+
case 'file':
|
|
161
|
+
case 'file.audio': {
|
|
162
|
+
return <ThreadParentMessageFile {...messageProps} />;
|
|
163
|
+
}
|
|
164
|
+
case 'file.video': {
|
|
165
|
+
return (
|
|
166
|
+
<ThreadParentMessageFileVideo
|
|
167
|
+
fetchThumbnailFromVideoSource={(uri) => mediaService.getVideoThumbnail({ url: uri, timeMills: 1000 })}
|
|
168
|
+
{...messageProps}
|
|
169
|
+
/>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
case 'file.image': {
|
|
173
|
+
return <ThreadParentMessageFileImage {...messageProps} />;
|
|
174
|
+
}
|
|
175
|
+
case 'file.voice': {
|
|
176
|
+
return (
|
|
177
|
+
<ThreadParentMessageFileVoice
|
|
178
|
+
durationMetaArrayKey={VOICE_MESSAGE_META_ARRAY_DURATION_KEY}
|
|
179
|
+
onUnmount={() => {
|
|
180
|
+
if (isVoiceMessage(parentMessage) && playerService.uri === parentMessage.url) {
|
|
181
|
+
resetPlayer();
|
|
182
|
+
}
|
|
183
|
+
}}
|
|
184
|
+
{...messageProps}
|
|
185
|
+
/>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
default: {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export default React.memo(ThreadParentMessageRenderer);
|
|
@@ -38,6 +38,7 @@ import InternalLocalCacheStorage from '../libs/InternalLocalCacheStorage';
|
|
|
38
38
|
import MentionConfig, { MentionConfigInterface } from '../libs/MentionConfig';
|
|
39
39
|
import MentionManager from '../libs/MentionManager';
|
|
40
40
|
import VoiceMessageConfig, { VoiceMessageConfigInterface } from '../libs/VoiceMessageConfig';
|
|
41
|
+
import VoiceMessageStatusManager from '../libs/VoiceMessageStatusManager';
|
|
41
42
|
import StringSetEn from '../localization/StringSet.en';
|
|
42
43
|
import type { StringSet } from '../localization/StringSet.type';
|
|
43
44
|
import SBUDynamicModule from '../platform/dynamicModule';
|
|
@@ -64,7 +65,6 @@ export const SendbirdUIKit = Object.freeze({
|
|
|
64
65
|
},
|
|
65
66
|
});
|
|
66
67
|
|
|
67
|
-
type UnimplementedFeatures = 'threadReplySelectType' | 'replyType' | 'enableReactionsSupergroup';
|
|
68
68
|
export type ChatOmittedInitParams = Omit<
|
|
69
69
|
SendbirdChatParams<[GroupChannelModule, OpenChannelModule]>,
|
|
70
70
|
(typeof chatOmitKeys)[number]
|
|
@@ -102,8 +102,7 @@ export type SendbirdUIKitContainerProps = React.PropsWithChildren<{
|
|
|
102
102
|
Partial<ChatRelatedFeaturesInUIKit>;
|
|
103
103
|
uikitOptions?: PartialDeep<{
|
|
104
104
|
common: SBUConfig['common'];
|
|
105
|
-
groupChannel: Omit<SBUConfig['groupChannel']['channel'],
|
|
106
|
-
replyType: Extract<SBUConfig['groupChannel']['channel']['replyType'], 'none' | 'quote_reply'>;
|
|
105
|
+
groupChannel: Omit<SBUConfig['groupChannel']['channel'], 'enableReactionsSupergroup'> & {
|
|
107
106
|
/**
|
|
108
107
|
* @deprecated Currently, this feature is turned off by default. If you wish to use this feature, contact us: {@link https://dashboard.sendbird.com/settings/contact_us?category=feedback_and_feature_requests&product=UIKit}
|
|
109
108
|
*/
|
|
@@ -180,6 +179,7 @@ const SendbirdUIKitContainer = (props: SendbirdUIKitContainerProps) => {
|
|
|
180
179
|
const { imageCompressionConfig, voiceMessageConfig, mentionConfig } = useConfigInstance(props);
|
|
181
180
|
const emojiManager = useMemo(() => new EmojiManager(internalStorage), [internalStorage]);
|
|
182
181
|
const mentionManager = useMemo(() => new MentionManager(mentionConfig), [mentionConfig]);
|
|
182
|
+
const voiceMessageStatusManager = useMemo(() => new VoiceMessageStatusManager(), []);
|
|
183
183
|
|
|
184
184
|
useLayoutEffect(() => {
|
|
185
185
|
if (!isFirstMount) {
|
|
@@ -227,6 +227,7 @@ const SendbirdUIKitContainer = (props: SendbirdUIKitContainerProps) => {
|
|
|
227
227
|
mentionManager={mentionManager}
|
|
228
228
|
imageCompressionConfig={imageCompressionConfig}
|
|
229
229
|
voiceMessageConfig={voiceMessageConfig}
|
|
230
|
+
voiceMessageStatusManager={voiceMessageStatusManager}
|
|
230
231
|
enableAutoPushTokenRegistration={
|
|
231
232
|
chatOptions.enableAutoPushTokenRegistration ?? SendbirdUIKit.DEFAULT.AUTO_PUSH_TOKEN_REGISTRATION
|
|
232
233
|
}
|
|
@@ -14,7 +14,9 @@ import type EmojiManager from '../libs/EmojiManager';
|
|
|
14
14
|
import type ImageCompressionConfig from '../libs/ImageCompressionConfig';
|
|
15
15
|
import type MentionManager from '../libs/MentionManager';
|
|
16
16
|
import type VoiceMessageConfig from '../libs/VoiceMessageConfig';
|
|
17
|
+
import VoiceMessageStatusManager from '../libs/VoiceMessageStatusManager';
|
|
17
18
|
import type { FileType } from '../platform/types';
|
|
19
|
+
import pubsub, { type PubSub } from '../utils/pubsub';
|
|
18
20
|
|
|
19
21
|
export interface ChatRelatedFeaturesInUIKit {
|
|
20
22
|
enableAutoPushTokenRegistration: boolean;
|
|
@@ -27,10 +29,18 @@ interface Props extends ChatRelatedFeaturesInUIKit, React.PropsWithChildren {
|
|
|
27
29
|
|
|
28
30
|
emojiManager: EmojiManager;
|
|
29
31
|
mentionManager: MentionManager;
|
|
32
|
+
voiceMessageStatusManager: VoiceMessageStatusManager;
|
|
30
33
|
imageCompressionConfig: ImageCompressionConfig;
|
|
31
34
|
voiceMessageConfig: VoiceMessageConfig;
|
|
32
35
|
}
|
|
33
36
|
|
|
37
|
+
export type GroupChannelFragmentOptionsPubSubContextPayload = {
|
|
38
|
+
type: 'OVERRIDE_SEARCH_ITEM_STARTING_POINT';
|
|
39
|
+
data: {
|
|
40
|
+
startingPoint: number;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
34
44
|
export type SendbirdChatContextType = {
|
|
35
45
|
sdk: SendbirdChatSDK;
|
|
36
46
|
currentUser?: SendbirdUser;
|
|
@@ -39,6 +49,7 @@ export type SendbirdChatContextType = {
|
|
|
39
49
|
// feature related instances
|
|
40
50
|
emojiManager: EmojiManager;
|
|
41
51
|
mentionManager: MentionManager;
|
|
52
|
+
voiceMessageStatusManager: VoiceMessageStatusManager;
|
|
42
53
|
imageCompressionConfig: ImageCompressionConfig;
|
|
43
54
|
voiceMessageConfig: VoiceMessageConfig;
|
|
44
55
|
|
|
@@ -46,6 +57,9 @@ export type SendbirdChatContextType = {
|
|
|
46
57
|
updateCurrentUserInfo: (nickname?: string, profile?: string | FileType) => Promise<SendbirdUser>;
|
|
47
58
|
markAsDeliveredWithChannel: (channel: SendbirdGroupChannel) => void;
|
|
48
59
|
|
|
60
|
+
groupChannelFragmentOptions: {
|
|
61
|
+
pubsub: PubSub<GroupChannelFragmentOptionsPubSubContextPayload>;
|
|
62
|
+
};
|
|
49
63
|
sbOptions: {
|
|
50
64
|
// UIKit options
|
|
51
65
|
uikit: SBUConfig;
|
|
@@ -80,6 +94,7 @@ export type SendbirdChatContextType = {
|
|
|
80
94
|
broadcastChannelEnabled: boolean;
|
|
81
95
|
superGroupChannelEnabled: boolean;
|
|
82
96
|
reactionEnabled: boolean;
|
|
97
|
+
uploadSizeLimit: number | undefined;
|
|
83
98
|
};
|
|
84
99
|
};
|
|
85
100
|
};
|
|
@@ -90,6 +105,7 @@ export const SendbirdChatProvider = ({
|
|
|
90
105
|
sdkInstance,
|
|
91
106
|
emojiManager,
|
|
92
107
|
mentionManager,
|
|
108
|
+
voiceMessageStatusManager,
|
|
93
109
|
imageCompressionConfig,
|
|
94
110
|
voiceMessageConfig,
|
|
95
111
|
enableAutoPushTokenRegistration,
|
|
@@ -164,11 +180,15 @@ export const SendbirdChatProvider = ({
|
|
|
164
180
|
mentionManager,
|
|
165
181
|
imageCompressionConfig,
|
|
166
182
|
voiceMessageConfig,
|
|
183
|
+
voiceMessageStatusManager,
|
|
167
184
|
currentUser,
|
|
168
185
|
setCurrentUser,
|
|
169
186
|
|
|
170
187
|
updateCurrentUserInfo,
|
|
171
188
|
markAsDeliveredWithChannel,
|
|
189
|
+
groupChannelFragmentOptions: {
|
|
190
|
+
pubsub: pubsub<GroupChannelFragmentOptionsPubSubContextPayload>(),
|
|
191
|
+
},
|
|
172
192
|
|
|
173
193
|
// TODO: Options should be moved to the common area at the higher level to be passed to the context of each product.
|
|
174
194
|
// For example, common -> chat context, common -> calls context
|
|
@@ -2,11 +2,12 @@ import React, { useContext, useEffect } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { useChannelHandler } from '@sendbird/uikit-chat-hooks';
|
|
4
4
|
import { useToast } from '@sendbird/uikit-react-native-foundation';
|
|
5
|
-
import
|
|
6
|
-
import { isDifferentChannel, useFreshCallback,
|
|
5
|
+
import { SendbirdMessage, SendbirdSendableMessage, useIsFirstMount } from '@sendbird/uikit-utils';
|
|
6
|
+
import { isDifferentChannel, useFreshCallback, useUniqHandlerId } from '@sendbird/uikit-utils';
|
|
7
7
|
|
|
8
8
|
import ChannelMessageList from '../../../components/ChannelMessageList';
|
|
9
9
|
import { MESSAGE_FOCUS_ANIMATION_DELAY, MESSAGE_SEARCH_SAFE_SCROLL_DELAY } from '../../../constants';
|
|
10
|
+
import { GroupChannelFragmentOptionsPubSubContextPayload } from '../../../contexts/SendbirdChatCtx';
|
|
10
11
|
import { useLocalization, useSendbirdChat } from '../../../hooks/useContext';
|
|
11
12
|
import { GroupChannelContexts } from '../module/moduleContext';
|
|
12
13
|
import type { GroupChannelProps } from '../types';
|
|
@@ -14,10 +15,12 @@ import type { GroupChannelProps } from '../types';
|
|
|
14
15
|
const GroupChannelMessageList = (props: GroupChannelProps['MessageList']) => {
|
|
15
16
|
const toast = useToast();
|
|
16
17
|
const { STRINGS } = useLocalization();
|
|
17
|
-
const { sdk } = useSendbirdChat();
|
|
18
|
+
const { sdk, sbOptions, groupChannelFragmentOptions } = useSendbirdChat();
|
|
18
19
|
const { setMessageToEdit, setMessageToReply } = useContext(GroupChannelContexts.Fragment);
|
|
19
20
|
const { subscribe } = useContext(GroupChannelContexts.PubSub);
|
|
20
|
-
const { flatListRef, lazyScrollToBottom, lazyScrollToIndex } = useContext(
|
|
21
|
+
const { flatListRef, lazyScrollToBottom, lazyScrollToIndex, onPressReplyMessageInThread } = useContext(
|
|
22
|
+
GroupChannelContexts.MessageList,
|
|
23
|
+
);
|
|
21
24
|
|
|
22
25
|
const id = useUniqHandlerId('GroupChannelMessageList');
|
|
23
26
|
const isFirstMount = useIsFirstMount();
|
|
@@ -90,6 +93,17 @@ const GroupChannelMessageList = (props: GroupChannelProps['MessageList']) => {
|
|
|
90
93
|
});
|
|
91
94
|
}, [props.scrolledAwayFromBottom]);
|
|
92
95
|
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
return groupChannelFragmentOptions.pubsub.subscribe((payload: GroupChannelFragmentOptionsPubSubContextPayload) => {
|
|
98
|
+
switch (payload.type) {
|
|
99
|
+
case 'OVERRIDE_SEARCH_ITEM_STARTING_POINT': {
|
|
100
|
+
scrollToMessageWithCreatedAt(payload.data.startingPoint, false, MESSAGE_SEARCH_SAFE_SCROLL_DELAY);
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}, []);
|
|
106
|
+
|
|
93
107
|
useEffect(() => {
|
|
94
108
|
// Only trigger once when message list mount with initial props.searchItem
|
|
95
109
|
// - Search screen + searchItem > mount message list
|
|
@@ -99,16 +113,31 @@ const GroupChannelMessageList = (props: GroupChannelProps['MessageList']) => {
|
|
|
99
113
|
}
|
|
100
114
|
}, [isFirstMount]);
|
|
101
115
|
|
|
102
|
-
const onPressParentMessage = useFreshCallback(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
116
|
+
const onPressParentMessage = useFreshCallback(
|
|
117
|
+
(parentMessage: SendbirdMessage, childMessage: SendbirdSendableMessage) => {
|
|
118
|
+
if (
|
|
119
|
+
onPressReplyMessageInThread &&
|
|
120
|
+
sbOptions.uikit.groupChannel.channel.replyType === 'thread' &&
|
|
121
|
+
sbOptions.uikit.groupChannel.channel.threadReplySelectType === 'thread'
|
|
122
|
+
) {
|
|
123
|
+
if (parentMessage.createdAt >= props.channel.messageOffsetTimestamp) {
|
|
124
|
+
onPressReplyMessageInThread(parentMessage as SendbirdSendableMessage, childMessage.createdAt);
|
|
125
|
+
} else {
|
|
126
|
+
toast.show(STRINGS.TOAST.FIND_PARENT_MSG_ERROR, 'error');
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
const canScrollToParent = scrollToMessageWithCreatedAt(parentMessage.createdAt, true, 0);
|
|
130
|
+
if (!canScrollToParent) toast.show(STRINGS.TOAST.FIND_PARENT_MSG_ERROR, 'error');
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
);
|
|
106
134
|
|
|
107
135
|
return (
|
|
108
136
|
<ChannelMessageList
|
|
109
137
|
{...props}
|
|
110
138
|
ref={flatListRef}
|
|
111
139
|
onReplyMessage={setMessageToReply}
|
|
140
|
+
onReplyInThreadMessage={setMessageToReply}
|
|
112
141
|
onEditMessage={setMessageToEdit}
|
|
113
142
|
onPressParentMessage={onPressParentMessage}
|
|
114
143
|
onPressNewMessagesButton={scrollToBottom}
|
|
@@ -58,12 +58,13 @@ export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
|
|
|
58
58
|
groupChannelPubSub,
|
|
59
59
|
messages,
|
|
60
60
|
onUpdateSearchItem,
|
|
61
|
+
onPressReplyMessageInThread,
|
|
61
62
|
}) => {
|
|
62
63
|
if (!channel) throw new Error('GroupChannel is not provided to GroupChannelModule');
|
|
63
64
|
|
|
64
65
|
const handlerId = useUniqHandlerId('GroupChannelContextsProvider');
|
|
65
66
|
const { STRINGS } = useLocalization();
|
|
66
|
-
const { currentUser, sdk } = useSendbirdChat();
|
|
67
|
+
const { currentUser, sdk, sbOptions } = useSendbirdChat();
|
|
67
68
|
|
|
68
69
|
const [typingUsers, setTypingUsers] = useState<SendbirdUser[]>([]);
|
|
69
70
|
const [messageToEdit, setMessageToEdit] = useState<SendbirdUserMessage | SendbirdFileMessage>();
|
|
@@ -90,6 +91,14 @@ export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
|
|
|
90
91
|
}
|
|
91
92
|
};
|
|
92
93
|
|
|
94
|
+
const onPressMessageToReply = (parentMessage?: SendbirdUserMessage | SendbirdFileMessage) => {
|
|
95
|
+
if (sbOptions.uikit.groupChannel.channel.replyType === 'thread' && parentMessage) {
|
|
96
|
+
onPressReplyMessageInThread?.(parentMessage, Number.MAX_SAFE_INTEGER);
|
|
97
|
+
} else if (sbOptions.uikit.groupChannel.channel.replyType === 'quote_reply') {
|
|
98
|
+
updateInputMode('reply', parentMessage);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
93
102
|
useChannelHandler(sdk, handlerId, {
|
|
94
103
|
onMessageDeleted(_, messageId) {
|
|
95
104
|
if (messageToReply?.messageId === messageId) {
|
|
@@ -125,7 +134,7 @@ export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
|
|
|
125
134
|
messageToEdit,
|
|
126
135
|
setMessageToEdit: useCallback((message) => updateInputMode('edit', message), []),
|
|
127
136
|
messageToReply,
|
|
128
|
-
setMessageToReply: useCallback((message) =>
|
|
137
|
+
setMessageToReply: useCallback((message) => onPressMessageToReply(message), []),
|
|
129
138
|
}}
|
|
130
139
|
>
|
|
131
140
|
<GroupChannelContexts.PubSub.Provider value={groupChannelPubSub}>
|
|
@@ -136,6 +145,7 @@ export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
|
|
|
136
145
|
scrollToMessage,
|
|
137
146
|
lazyScrollToIndex,
|
|
138
147
|
lazyScrollToBottom,
|
|
148
|
+
onPressReplyMessageInThread,
|
|
139
149
|
}}
|
|
140
150
|
>
|
|
141
151
|
{children}
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
SendbirdFileMessageUpdateParams,
|
|
12
12
|
SendbirdGroupChannel,
|
|
13
13
|
SendbirdMessage,
|
|
14
|
+
SendbirdSendableMessage,
|
|
14
15
|
SendbirdUser,
|
|
15
16
|
SendbirdUserMessage,
|
|
16
17
|
SendbirdUserMessageCreateParams,
|
|
@@ -30,6 +31,7 @@ export interface GroupChannelProps {
|
|
|
30
31
|
onPressHeaderLeft: GroupChannelProps['Header']['onPressHeaderLeft'];
|
|
31
32
|
onPressHeaderRight: GroupChannelProps['Header']['onPressHeaderRight'];
|
|
32
33
|
onPressMediaMessage?: GroupChannelProps['MessageList']['onPressMediaMessage'];
|
|
34
|
+
onPressReplyMessageInThread?: GroupChannelProps['Provider']['onPressReplyMessageInThread'];
|
|
33
35
|
|
|
34
36
|
onBeforeSendUserMessage?: OnBeforeHandler<SendbirdUserMessageCreateParams>;
|
|
35
37
|
onBeforeSendFileMessage?: OnBeforeHandler<SendbirdFileMessageCreateParams>;
|
|
@@ -114,6 +116,7 @@ export interface GroupChannelProps {
|
|
|
114
116
|
messages: SendbirdMessage[];
|
|
115
117
|
// Changing the search item will trigger the focus animation on messages.
|
|
116
118
|
onUpdateSearchItem: (searchItem?: GroupChannelProps['MessageList']['searchItem']) => void;
|
|
119
|
+
onPressReplyMessageInThread: (parentMessage: SendbirdSendableMessage, startingPoint?: number) => void;
|
|
117
120
|
};
|
|
118
121
|
}
|
|
119
122
|
|
|
@@ -171,6 +174,8 @@ export interface GroupChannelContextsType {
|
|
|
171
174
|
timeout?: number;
|
|
172
175
|
viewPosition?: number;
|
|
173
176
|
}) => void;
|
|
177
|
+
|
|
178
|
+
onPressReplyMessageInThread?: (parentMessage: SendbirdSendableMessage, startingPoint?: number) => void;
|
|
174
179
|
}>;
|
|
175
180
|
}
|
|
176
181
|
export interface GroupChannelModule {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { Icon, Text, createStyleSheet, useHeaderStyle, useUIKitTheme } from '@sendbird/uikit-react-native-foundation';
|
|
5
|
+
|
|
6
|
+
import { useLocalization, useSendbirdChat } from '../../../hooks/useContext';
|
|
7
|
+
import { GroupChannelThreadContexts } from '../module/moduleContext';
|
|
8
|
+
import type { GroupChannelThreadProps } from '../types';
|
|
9
|
+
|
|
10
|
+
const GroupChannelThreadHeader = ({ onPressLeft, onPressSubtitle }: GroupChannelThreadProps['Header']) => {
|
|
11
|
+
const { headerTitle, channel } = useContext(GroupChannelThreadContexts.Fragment);
|
|
12
|
+
const { HeaderComponent } = useHeaderStyle();
|
|
13
|
+
const { STRINGS } = useLocalization();
|
|
14
|
+
const { select, colors, palette } = useUIKitTheme();
|
|
15
|
+
const { currentUser } = useSendbirdChat();
|
|
16
|
+
|
|
17
|
+
const renderSubtitle = () => {
|
|
18
|
+
if (!currentUser) return null;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Text
|
|
22
|
+
onPress={onPressSubtitle}
|
|
23
|
+
caption2
|
|
24
|
+
style={styles.subtitle}
|
|
25
|
+
color={select({ light: palette.primary300, dark: palette.primary200 })}
|
|
26
|
+
numberOfLines={1}
|
|
27
|
+
>
|
|
28
|
+
{STRINGS.GROUP_CHANNEL_THREAD.HEADER_SUBTITLE(currentUser.userId, channel)}
|
|
29
|
+
</Text>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<HeaderComponent
|
|
35
|
+
clearTitleMargin
|
|
36
|
+
title={
|
|
37
|
+
<View style={styles.titleContainer}>
|
|
38
|
+
<View style={{ flexShrink: 1 }}>
|
|
39
|
+
<Text h2 color={colors.onBackground01} numberOfLines={1}>
|
|
40
|
+
{headerTitle}
|
|
41
|
+
</Text>
|
|
42
|
+
{renderSubtitle()}
|
|
43
|
+
</View>
|
|
44
|
+
</View>
|
|
45
|
+
}
|
|
46
|
+
left={<Icon icon={'arrow-left'} size={24} />}
|
|
47
|
+
onPressLeft={onPressLeft}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const styles = createStyleSheet({
|
|
53
|
+
titleContainer: {
|
|
54
|
+
maxWidth: '100%',
|
|
55
|
+
flexDirection: 'row',
|
|
56
|
+
width: '100%',
|
|
57
|
+
},
|
|
58
|
+
subtitle: {
|
|
59
|
+
marginTop: 2,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export default GroupChannelThreadHeader;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
import { getGroupChannelChatAvailableState } from '@sendbird/uikit-utils';
|
|
4
|
+
|
|
5
|
+
import ChannelInput from '../../../components/ChannelInput';
|
|
6
|
+
import { GroupChannelThreadContexts } from '../module/moduleContext';
|
|
7
|
+
import type { GroupChannelThreadProps } from '../types';
|
|
8
|
+
|
|
9
|
+
const GroupChannelThreadInput = ({ inputDisabled, ...props }: GroupChannelThreadProps['Input']) => {
|
|
10
|
+
const {
|
|
11
|
+
channel,
|
|
12
|
+
keyboardAvoidOffset = 0,
|
|
13
|
+
messageToEdit,
|
|
14
|
+
setMessageToEdit,
|
|
15
|
+
parentMessage,
|
|
16
|
+
} = useContext(GroupChannelThreadContexts.Fragment);
|
|
17
|
+
|
|
18
|
+
const chatAvailableState = getGroupChannelChatAvailableState(channel);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<ChannelInput
|
|
22
|
+
channel={channel}
|
|
23
|
+
messageToEdit={messageToEdit}
|
|
24
|
+
setMessageToEdit={setMessageToEdit}
|
|
25
|
+
messageForThread={parentMessage}
|
|
26
|
+
keyboardAvoidOffset={keyboardAvoidOffset}
|
|
27
|
+
inputMuted={chatAvailableState.muted}
|
|
28
|
+
inputFrozen={chatAvailableState.frozen}
|
|
29
|
+
inputDisabled={inputDisabled ?? chatAvailableState.disabled}
|
|
30
|
+
MessageToReplyPreview={() => {
|
|
31
|
+
return null;
|
|
32
|
+
}}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default React.memo(GroupChannelThreadInput);
|