@sendbird/uikit-react-native 2.4.2 → 2.5.0-rc.1
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/ChannelMessageList/index.js +319 -0
- package/lib/commonjs/components/ChannelMessageList/index.js.map +1 -0
- package/lib/commonjs/components/ChatFlatList.js +30 -50
- package/lib/commonjs/components/ChatFlatList.js.map +1 -1
- package/lib/commonjs/components/MessageSearchResultItem.js +132 -0
- package/lib/commonjs/components/MessageSearchResultItem.js.map +1 -0
- package/lib/commonjs/components/ScrollToBottomButton.js +1 -1
- package/lib/commonjs/components/ScrollToBottomButton.js.map +1 -1
- package/lib/commonjs/constants.js +6 -2
- package/lib/commonjs/constants.js.map +1 -1
- package/lib/commonjs/containers/GroupChannelPreviewContainer.js +2 -2
- package/lib/commonjs/containers/GroupChannelPreviewContainer.js.map +1 -1
- package/lib/commonjs/containers/SendbirdUIKitContainer.js +4 -2
- package/lib/commonjs/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/commonjs/contexts/SendbirdChatCtx.js +4 -2
- package/lib/commonjs/contexts/SendbirdChatCtx.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js +4 -2
- package/lib/commonjs/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +84 -301
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelSuggestedMentionList.js +2 -0
- package/lib/commonjs/domain/groupChannel/component/GroupChannelSuggestedMentionList.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/module/moduleContext.js +9 -2
- 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/groupChannelSettings/component/GroupChannelSettingsMenu.js +18 -4
- package/lib/commonjs/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js.map +1 -1
- package/lib/commonjs/domain/groupChannelSettings/types.js.map +1 -1
- package/lib/commonjs/domain/messageSearch/component/MessageSearchHeader.js +105 -0
- package/lib/commonjs/domain/messageSearch/component/MessageSearchHeader.js.map +1 -0
- package/lib/commonjs/domain/messageSearch/component/MessageSearchList.js +40 -0
- package/lib/commonjs/domain/messageSearch/component/MessageSearchList.js.map +1 -0
- package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusEmpty.js +22 -0
- package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusEmpty.js.map +1 -0
- package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusError.js +26 -0
- package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusError.js.map +1 -0
- package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusLoading.js +22 -0
- package/lib/commonjs/domain/messageSearch/component/MessageSearchStatusLoading.js.map +1 -0
- package/lib/commonjs/domain/messageSearch/index.js +62 -0
- package/lib/commonjs/domain/messageSearch/index.js.map +1 -0
- package/lib/commonjs/domain/messageSearch/module/createMessageSearchModule.js +36 -0
- package/lib/commonjs/domain/messageSearch/module/createMessageSearchModule.js.map +1 -0
- package/lib/commonjs/domain/messageSearch/module/moduleContext.js +25 -0
- package/lib/commonjs/domain/messageSearch/module/moduleContext.js.map +1 -0
- package/lib/commonjs/domain/messageSearch/types.js +6 -0
- package/lib/commonjs/domain/messageSearch/types.js.map +1 -0
- package/lib/commonjs/domain/openChannel/component/OpenChannelMessageList.js +38 -279
- package/lib/commonjs/domain/openChannel/component/OpenChannelMessageList.js.map +1 -1
- package/lib/commonjs/domain/openChannel/module/moduleContext.js +9 -2
- package/lib/commonjs/domain/openChannel/module/moduleContext.js.map +1 -1
- package/lib/commonjs/domain/openChannel/types.js.map +1 -1
- package/lib/commonjs/fragments/createGroupChannelFragment.js +107 -15
- package/lib/commonjs/fragments/createGroupChannelFragment.js.map +1 -1
- package/lib/commonjs/fragments/createGroupChannelSettingsFragment.js +2 -0
- package/lib/commonjs/fragments/createGroupChannelSettingsFragment.js.map +1 -1
- package/lib/commonjs/fragments/createMessageSearchFragment.js +145 -0
- package/lib/commonjs/fragments/createMessageSearchFragment.js.map +1 -0
- package/lib/commonjs/fragments/createOpenChannelFragment.js +40 -8
- package/lib/commonjs/fragments/createOpenChannelFragment.js.map +1 -1
- package/lib/commonjs/hooks/useMentionSuggestion.js +17 -0
- package/lib/commonjs/hooks/useMentionSuggestion.js.map +1 -1
- package/lib/commonjs/index.js +60 -40
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/localization/StringSet.type.js.map +1 -1
- package/lib/commonjs/localization/createBaseStringSet.js +33 -20
- package/lib/commonjs/localization/createBaseStringSet.js.map +1 -1
- package/lib/commonjs/utils/pubsub.js +21 -0
- package/lib/commonjs/utils/pubsub.js.map +1 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/components/ChannelMessageList/index.js +311 -0
- package/lib/module/components/ChannelMessageList/index.js.map +1 -0
- package/lib/module/components/ChatFlatList.js +32 -52
- package/lib/module/components/ChatFlatList.js.map +1 -1
- package/lib/module/components/MessageSearchResultItem.js +124 -0
- package/lib/module/components/MessageSearchResultItem.js.map +1 -0
- package/lib/module/components/ScrollToBottomButton.js +1 -1
- package/lib/module/components/ScrollToBottomButton.js.map +1 -1
- package/lib/module/constants.js +3 -1
- package/lib/module/constants.js.map +1 -1
- package/lib/module/containers/GroupChannelPreviewContainer.js +2 -2
- package/lib/module/containers/GroupChannelPreviewContainer.js.map +1 -1
- package/lib/module/containers/SendbirdUIKitContainer.js +4 -2
- package/lib/module/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/module/contexts/SendbirdChatCtx.js +4 -2
- package/lib/module/contexts/SendbirdChatCtx.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelHeader.js +4 -2
- package/lib/module/domain/groupChannel/component/GroupChannelHeader.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +88 -305
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelSuggestedMentionList.js +2 -0
- package/lib/module/domain/groupChannel/component/GroupChannelSuggestedMentionList.js.map +1 -1
- package/lib/module/domain/groupChannel/module/moduleContext.js +9 -2
- 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/groupChannelSettings/component/GroupChannelSettingsMenu.js +18 -4
- package/lib/module/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js.map +1 -1
- package/lib/module/domain/groupChannelSettings/types.js.map +1 -1
- package/lib/module/domain/messageSearch/component/MessageSearchHeader.js +96 -0
- package/lib/module/domain/messageSearch/component/MessageSearchHeader.js.map +1 -0
- package/lib/module/domain/messageSearch/component/MessageSearchList.js +32 -0
- package/lib/module/domain/messageSearch/component/MessageSearchList.js.map +1 -0
- package/lib/module/domain/messageSearch/component/MessageSearchStatusEmpty.js +14 -0
- package/lib/module/domain/messageSearch/component/MessageSearchStatusEmpty.js.map +1 -0
- package/lib/module/domain/messageSearch/component/MessageSearchStatusError.js +18 -0
- package/lib/module/domain/messageSearch/component/MessageSearchStatusError.js.map +1 -0
- package/lib/module/domain/messageSearch/component/MessageSearchStatusLoading.js +14 -0
- package/lib/module/domain/messageSearch/component/MessageSearchStatusLoading.js.map +1 -0
- package/lib/module/domain/messageSearch/index.js +8 -0
- package/lib/module/domain/messageSearch/index.js.map +1 -0
- package/lib/module/domain/messageSearch/module/createMessageSearchModule.js +28 -0
- package/lib/module/domain/messageSearch/module/createMessageSearchModule.js.map +1 -0
- package/lib/module/domain/messageSearch/module/moduleContext.js +14 -0
- package/lib/module/domain/messageSearch/module/moduleContext.js.map +1 -0
- package/lib/module/domain/messageSearch/types.js +2 -0
- package/lib/module/domain/messageSearch/types.js.map +1 -0
- package/lib/module/domain/openChannel/component/OpenChannelMessageList.js +40 -281
- package/lib/module/domain/openChannel/component/OpenChannelMessageList.js.map +1 -1
- package/lib/module/domain/openChannel/module/moduleContext.js +9 -2
- package/lib/module/domain/openChannel/module/moduleContext.js.map +1 -1
- package/lib/module/domain/openChannel/types.js.map +1 -1
- package/lib/module/fragments/createGroupChannelFragment.js +109 -17
- package/lib/module/fragments/createGroupChannelFragment.js.map +1 -1
- package/lib/module/fragments/createGroupChannelSettingsFragment.js +2 -0
- package/lib/module/fragments/createGroupChannelSettingsFragment.js.map +1 -1
- package/lib/module/fragments/createMessageSearchFragment.js +135 -0
- package/lib/module/fragments/createMessageSearchFragment.js.map +1 -0
- package/lib/module/fragments/createOpenChannelFragment.js +41 -9
- package/lib/module/fragments/createOpenChannelFragment.js.map +1 -1
- package/lib/module/hooks/useMentionSuggestion.js +18 -1
- package/lib/module/hooks/useMentionSuggestion.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/localization/StringSet.type.js.map +1 -1
- package/lib/module/localization/createBaseStringSet.js +34 -21
- package/lib/module/localization/createBaseStringSet.js.map +1 -1
- package/lib/module/utils/pubsub.js +14 -0
- package/lib/module/utils/pubsub.js.map +1 -0
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/src/components/ChannelMessageList/index.d.ts +55 -0
- package/lib/typescript/src/components/ChatFlatList.d.ts +7 -8
- package/lib/typescript/src/components/MessageRenderer/index.d.ts +4 -0
- package/lib/typescript/src/components/MessageSearchResultItem.d.ts +2 -0
- package/lib/typescript/src/components/OpenChannelMessageRenderer/index.d.ts +1 -0
- package/lib/typescript/src/components/ScrollToBottomButton.d.ts +1 -1
- package/lib/typescript/src/constants.d.ts +3 -1
- package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +2 -1
- package/lib/typescript/src/contexts/SendbirdChatCtx.d.ts +3 -1
- package/lib/typescript/src/domain/groupChannel/component/GroupChannelHeader.d.ts +1 -1
- package/lib/typescript/src/domain/groupChannel/component/GroupChannelMessageList.d.ts +3 -32
- package/lib/typescript/src/domain/groupChannel/types.d.ts +23 -35
- package/lib/typescript/src/domain/groupChannelSettings/component/GroupChannelSettingsMenu.d.ts +1 -1
- package/lib/typescript/src/domain/groupChannelSettings/types.d.ts +2 -0
- package/lib/typescript/src/domain/messageSearch/component/MessageSearchHeader.d.ts +3 -0
- package/lib/typescript/src/domain/messageSearch/component/MessageSearchList.d.ts +3 -0
- package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusEmpty.d.ts +2 -0
- package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusError.d.ts +3 -0
- package/lib/typescript/src/domain/messageSearch/component/MessageSearchStatusLoading.d.ts +2 -0
- package/lib/typescript/src/domain/messageSearch/index.d.ts +7 -0
- package/lib/typescript/src/domain/messageSearch/module/createMessageSearchModule.d.ts +3 -0
- package/lib/typescript/src/domain/messageSearch/module/moduleContext.d.ts +3 -0
- package/lib/typescript/src/domain/messageSearch/types.d.ts +53 -0
- package/lib/typescript/src/domain/openChannel/component/OpenChannelMessageList.d.ts +1 -37
- package/lib/typescript/src/domain/openChannel/types.d.ts +17 -36
- package/lib/typescript/src/fragments/createMessageSearchFragment.d.ts +3 -0
- package/lib/typescript/src/hooks/useMentionSuggestion.d.ts +3 -2
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/localization/StringSet.type.d.ts +17 -3
- package/lib/typescript/src/utils/pubsub.d.ts +6 -0
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +8 -7
- package/src/components/ChannelMessageList/index.tsx +392 -0
- package/src/components/ChatFlatList.tsx +33 -51
- package/src/components/MessageSearchResultItem.tsx +125 -0
- package/src/components/ScrollToBottomButton.tsx +3 -4
- package/src/constants.ts +3 -1
- package/src/containers/GroupChannelPreviewContainer.tsx +2 -2
- package/src/containers/SendbirdUIKitContainer.tsx +2 -0
- package/src/contexts/SendbirdChatCtx.tsx +7 -1
- package/src/domain/groupChannel/component/GroupChannelHeader.tsx +9 -3
- package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +73 -316
- package/src/domain/groupChannel/component/GroupChannelSuggestedMentionList.tsx +2 -1
- package/src/domain/groupChannel/module/moduleContext.tsx +10 -2
- package/src/domain/groupChannel/types.ts +49 -38
- package/src/domain/groupChannelSettings/component/GroupChannelSettingsMenu.tsx +29 -13
- package/src/domain/groupChannelSettings/types.ts +2 -0
- package/src/domain/messageSearch/component/MessageSearchHeader.tsx +98 -0
- package/src/domain/messageSearch/component/MessageSearchList.tsx +26 -0
- package/src/domain/messageSearch/component/MessageSearchStatusEmpty.tsx +15 -0
- package/src/domain/messageSearch/component/MessageSearchStatusError.tsx +16 -0
- package/src/domain/messageSearch/component/MessageSearchStatusLoading.tsx +15 -0
- package/src/domain/messageSearch/index.ts +7 -0
- package/src/domain/messageSearch/module/createMessageSearchModule.tsx +21 -0
- package/src/domain/messageSearch/module/moduleContext.tsx +16 -0
- package/src/domain/messageSearch/types.ts +55 -0
- package/src/domain/openChannel/component/OpenChannelMessageList.tsx +35 -303
- package/src/domain/openChannel/module/moduleContext.tsx +8 -2
- package/src/domain/openChannel/types.ts +40 -38
- package/src/fragments/createGroupChannelFragment.tsx +114 -17
- package/src/fragments/createGroupChannelSettingsFragment.tsx +2 -0
- package/src/fragments/createMessageSearchFragment.tsx +159 -0
- package/src/fragments/createOpenChannelFragment.tsx +48 -12
- package/src/hooks/useMentionSuggestion.ts +23 -3
- package/src/index.ts +3 -0
- package/src/localization/StringSet.type.ts +20 -2
- package/src/localization/createBaseStringSet.ts +22 -2
- package/src/utils/pubsub.ts +20 -0
- package/src/version.ts +0 -2
|
@@ -1,20 +1,38 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { Animated, Easing } from 'react-native';
|
|
2
3
|
|
|
3
4
|
import { useGroupChannelMessages } from '@sendbird/uikit-chat-hooks';
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
NOOP,
|
|
7
|
+
PASS,
|
|
8
|
+
SendbirdFileMessage,
|
|
9
|
+
SendbirdGroupChannel,
|
|
10
|
+
SendbirdUserMessage,
|
|
11
|
+
messageComparator,
|
|
12
|
+
useFreshCallback,
|
|
13
|
+
useRefTracker,
|
|
14
|
+
} from '@sendbird/uikit-utils';
|
|
5
15
|
|
|
6
16
|
import MessageRenderer from '../components/MessageRenderer';
|
|
7
17
|
import NewMessagesButton from '../components/NewMessagesButton';
|
|
8
18
|
import ScrollToBottomButton from '../components/ScrollToBottomButton';
|
|
9
19
|
import StatusComposition from '../components/StatusComposition';
|
|
20
|
+
import { MESSAGE_FOCUS_ANIMATION_DELAY, MESSAGE_SEARCH_SAFE_SCROLL_DELAY } from '../constants';
|
|
10
21
|
import createGroupChannelModule from '../domain/groupChannel/module/createGroupChannelModule';
|
|
11
|
-
import type {
|
|
22
|
+
import type {
|
|
23
|
+
GroupChannelFragment,
|
|
24
|
+
GroupChannelModule,
|
|
25
|
+
GroupChannelProps,
|
|
26
|
+
GroupChannelPubSubContextPayload,
|
|
27
|
+
} from '../domain/groupChannel/types';
|
|
12
28
|
import { useSendbirdChat } from '../hooks/useContext';
|
|
29
|
+
import pubsub from '../utils/pubsub';
|
|
13
30
|
|
|
14
31
|
const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): GroupChannelFragment => {
|
|
15
32
|
const GroupChannelModule = createGroupChannelModule(initModule);
|
|
16
33
|
|
|
17
34
|
return ({
|
|
35
|
+
searchItem,
|
|
18
36
|
renderNewMessagesButton = (props) => <NewMessagesButton {...props} />,
|
|
19
37
|
renderScrollToBottomButton = (props) => <ScrollToBottomButton {...props} />,
|
|
20
38
|
renderMessage,
|
|
@@ -38,30 +56,48 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
|
|
|
38
56
|
}) => {
|
|
39
57
|
const { sdk, currentUser } = useSendbirdChat();
|
|
40
58
|
|
|
59
|
+
const [internalSearchItem, setInternalSearchItem] = useState(searchItem);
|
|
60
|
+
const navigateFromMessageSearch = useCallback(() => Boolean(searchItem), []);
|
|
61
|
+
|
|
62
|
+
const [groupChannelPubSub] = useState(() => pubsub<GroupChannelPubSubContextPayload>());
|
|
63
|
+
const [scrolledAwayFromBottom, setScrolledAwayFromBottom] = useState(false);
|
|
64
|
+
const scrolledAwayFromBottomRef = useRefTracker(scrolledAwayFromBottom);
|
|
65
|
+
|
|
41
66
|
const {
|
|
67
|
+
loading,
|
|
42
68
|
messages,
|
|
43
|
-
|
|
44
|
-
|
|
69
|
+
newMessages,
|
|
70
|
+
resetNewMessages,
|
|
45
71
|
next,
|
|
46
72
|
prev,
|
|
73
|
+
hasNext,
|
|
47
74
|
sendFileMessage,
|
|
48
75
|
sendUserMessage,
|
|
49
76
|
updateFileMessage,
|
|
50
77
|
updateUserMessage,
|
|
51
78
|
resendMessage,
|
|
52
79
|
deleteMessage,
|
|
53
|
-
|
|
80
|
+
resetWithStartingPoint,
|
|
54
81
|
} = useGroupChannelMessages(sdk, channel, currentUser?.userId, {
|
|
55
82
|
collectionCreator,
|
|
56
83
|
queryCreator,
|
|
57
84
|
sortComparator,
|
|
58
85
|
onChannelDeleted,
|
|
59
86
|
enableCollectionWithoutLocalCache: !queryCreator,
|
|
87
|
+
shouldCountNewMessages: () => scrolledAwayFromBottomRef.current,
|
|
88
|
+
onMessagesReceived(messages) {
|
|
89
|
+
groupChannelPubSub.publish({ type: 'MESSAGES_RECEIVED', data: { messages } });
|
|
90
|
+
},
|
|
91
|
+
startingPoint: internalSearchItem?.startingPoint,
|
|
60
92
|
});
|
|
61
93
|
|
|
94
|
+
const MessageComponent: GroupChannelProps['MessageList']['renderMessage'] = useCallback(
|
|
95
|
+
withFocusingAnimation(renderMessage ? (props) => <>{renderMessage(props)}</> : MessageRenderer),
|
|
96
|
+
[renderMessage],
|
|
97
|
+
);
|
|
98
|
+
|
|
62
99
|
const _renderMessage: GroupChannelProps['MessageList']['renderMessage'] = useFreshCallback((props) => {
|
|
63
|
-
|
|
64
|
-
return <MessageRenderer {...props} />;
|
|
100
|
+
return <MessageComponent {...props} />;
|
|
65
101
|
});
|
|
66
102
|
|
|
67
103
|
const memoizedFlatListProps = useMemo(
|
|
@@ -70,19 +106,34 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
|
|
|
70
106
|
contentContainerStyle: { flexGrow: 1 },
|
|
71
107
|
...flatListProps,
|
|
72
108
|
}),
|
|
73
|
-
[
|
|
109
|
+
[flatListProps],
|
|
74
110
|
);
|
|
75
111
|
|
|
112
|
+
const onResetMessageList = useCallback((callback?: () => void) => {
|
|
113
|
+
resetWithStartingPoint(Number.MAX_SAFE_INTEGER, callback);
|
|
114
|
+
setInternalSearchItem(undefined);
|
|
115
|
+
}, []);
|
|
116
|
+
|
|
117
|
+
const onPending = (message: SendbirdFileMessage | SendbirdUserMessage) => {
|
|
118
|
+
groupChannelPubSub.publish({ type: 'MESSAGE_SENT_PENDING', data: { message } });
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const onSent = (message: SendbirdFileMessage | SendbirdUserMessage) => {
|
|
122
|
+
groupChannelPubSub.publish({ type: 'MESSAGE_SENT_SUCCESS', data: { message } });
|
|
123
|
+
};
|
|
124
|
+
|
|
76
125
|
const onPressSendUserMessage: GroupChannelProps['Input']['onPressSendUserMessage'] = useFreshCallback(
|
|
77
126
|
async (params) => {
|
|
78
127
|
const processedParams = await onBeforeSendUserMessage(params);
|
|
79
|
-
await sendUserMessage(processedParams);
|
|
128
|
+
const message = await sendUserMessage(processedParams, onPending);
|
|
129
|
+
onSent(message);
|
|
80
130
|
},
|
|
81
131
|
);
|
|
82
132
|
const onPressSendFileMessage: GroupChannelProps['Input']['onPressSendFileMessage'] = useFreshCallback(
|
|
83
133
|
async (params) => {
|
|
84
134
|
const processedParams = await onBeforeSendFileMessage(params);
|
|
85
|
-
await sendFileMessage(processedParams);
|
|
135
|
+
const message = await sendFileMessage(processedParams, onPending);
|
|
136
|
+
onSent(message);
|
|
86
137
|
},
|
|
87
138
|
);
|
|
88
139
|
const onPressUpdateUserMessage: GroupChannelProps['Input']['onPressUpdateUserMessage'] = useFreshCallback(
|
|
@@ -97,11 +148,16 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
|
|
|
97
148
|
await updateFileMessage(message.messageId, processedParams);
|
|
98
149
|
},
|
|
99
150
|
);
|
|
151
|
+
const onScrolledAwayFromBottom = useFreshCallback((value: boolean) => {
|
|
152
|
+
if (!value) resetNewMessages();
|
|
153
|
+
setScrolledAwayFromBottom(value);
|
|
154
|
+
});
|
|
100
155
|
|
|
101
156
|
/** @deprecated **/
|
|
102
157
|
const onSendFileMessage: GroupChannelProps['Input']['onSendFileMessage'] = useFreshCallback(async (file) => {
|
|
103
158
|
const processedParams = await onBeforeSendFileMessage({ file });
|
|
104
|
-
await sendFileMessage(processedParams);
|
|
159
|
+
const message = await sendFileMessage(processedParams, onPending);
|
|
160
|
+
onSent(message);
|
|
105
161
|
});
|
|
106
162
|
/** @deprecated **/
|
|
107
163
|
const onSendUserMessage: GroupChannelProps['Input']['onSendUserMessage'] = useFreshCallback(
|
|
@@ -112,7 +168,8 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
|
|
|
112
168
|
mentionedMessageTemplate: mention?.messageTemplate,
|
|
113
169
|
mentionType: mention?.type,
|
|
114
170
|
});
|
|
115
|
-
await sendUserMessage(processedParams);
|
|
171
|
+
const message = await sendUserMessage(processedParams, onPending);
|
|
172
|
+
onSent(message);
|
|
116
173
|
},
|
|
117
174
|
);
|
|
118
175
|
/** @deprecated **/
|
|
@@ -138,28 +195,39 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
|
|
|
138
195
|
return (
|
|
139
196
|
<GroupChannelModule.Provider
|
|
140
197
|
channel={channel}
|
|
198
|
+
groupChannelPubSub={groupChannelPubSub}
|
|
141
199
|
enableTypingIndicator={enableTypingIndicator}
|
|
142
200
|
keyboardAvoidOffset={keyboardAvoidOffset}
|
|
143
201
|
>
|
|
144
|
-
<GroupChannelModule.Header
|
|
202
|
+
<GroupChannelModule.Header
|
|
203
|
+
shouldHideRight={navigateFromMessageSearch}
|
|
204
|
+
onPressHeaderLeft={onPressHeaderLeft}
|
|
205
|
+
onPressHeaderRight={onPressHeaderRight}
|
|
206
|
+
/>
|
|
145
207
|
<StatusComposition loading={loading} LoadingComponent={<GroupChannelModule.StatusLoading />}>
|
|
146
208
|
<GroupChannelModule.MessageList
|
|
147
209
|
channel={channel}
|
|
210
|
+
searchItem={internalSearchItem}
|
|
211
|
+
onResetMessageList={onResetMessageList}
|
|
148
212
|
enableMessageGrouping={enableMessageGrouping}
|
|
149
213
|
currentUserId={currentUser?.userId}
|
|
150
214
|
renderMessage={_renderMessage}
|
|
151
215
|
messages={messages}
|
|
152
|
-
|
|
153
|
-
newMessagesFromMembers={newMessagesFromMembers}
|
|
216
|
+
newMessages={newMessages}
|
|
154
217
|
onTopReached={prev}
|
|
155
218
|
onBottomReached={next}
|
|
219
|
+
hasNext={hasNext}
|
|
220
|
+
scrolledAwayFromBottom={scrolledAwayFromBottom}
|
|
221
|
+
onScrolledAwayFromBottom={onScrolledAwayFromBottom}
|
|
156
222
|
renderNewMessagesButton={renderNewMessagesButton}
|
|
157
223
|
renderScrollToBottomButton={renderScrollToBottomButton}
|
|
158
224
|
onResendFailedMessage={resendMessage}
|
|
159
225
|
onDeleteMessage={deleteMessage}
|
|
160
|
-
onPressImageMessage={onPressImageMessage}
|
|
161
226
|
onPressMediaMessage={onPressMediaMessage}
|
|
162
227
|
flatListProps={memoizedFlatListProps}
|
|
228
|
+
nextMessages={newMessages}
|
|
229
|
+
newMessagesFromMembers={newMessages}
|
|
230
|
+
onPressImageMessage={onPressImageMessage}
|
|
163
231
|
/>
|
|
164
232
|
<GroupChannelModule.Input
|
|
165
233
|
SuggestedMentionList={GroupChannelModule.SuggestedMentionList}
|
|
@@ -187,4 +255,33 @@ function shouldRenderInput(channel: SendbirdGroupChannel) {
|
|
|
187
255
|
return true;
|
|
188
256
|
}
|
|
189
257
|
|
|
258
|
+
function withFocusingAnimation<P extends unknown & { focused: boolean }>(Component: React.ComponentType<P>) {
|
|
259
|
+
return React.memo<P>((props) => {
|
|
260
|
+
const translateY = useRef(new Animated.Value(0)).current;
|
|
261
|
+
|
|
262
|
+
useEffect(() => {
|
|
263
|
+
if (props.focused) {
|
|
264
|
+
setTimeout(() => {
|
|
265
|
+
Animated.sequence(
|
|
266
|
+
[
|
|
267
|
+
{ toValue: -10, duration: 500 },
|
|
268
|
+
{ toValue: 0, duration: 100 },
|
|
269
|
+
{ toValue: -10, duration: 200 },
|
|
270
|
+
{ toValue: 0, duration: 100 },
|
|
271
|
+
].map((value) =>
|
|
272
|
+
Animated.timing(translateY, { ...value, useNativeDriver: true, easing: Easing.inOut(Easing.ease) }),
|
|
273
|
+
),
|
|
274
|
+
).start();
|
|
275
|
+
}, MESSAGE_SEARCH_SAFE_SCROLL_DELAY + MESSAGE_FOCUS_ANIMATION_DELAY);
|
|
276
|
+
}
|
|
277
|
+
}, [props.focused]);
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<Animated.View style={{ transform: [{ translateY }] }}>
|
|
281
|
+
<Component {...props} />
|
|
282
|
+
</Animated.View>
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
190
287
|
export default createGroupChannelFragment;
|
|
@@ -18,6 +18,7 @@ const createGroupChannelSettingsFragment = (
|
|
|
18
18
|
channel,
|
|
19
19
|
onPressMenuModeration,
|
|
20
20
|
onPressMenuMembers,
|
|
21
|
+
onPressMenuSearchInChannel,
|
|
21
22
|
onPressMenuLeaveChannel,
|
|
22
23
|
onPressMenuNotification,
|
|
23
24
|
menuItemsCreator,
|
|
@@ -40,6 +41,7 @@ const createGroupChannelSettingsFragment = (
|
|
|
40
41
|
menuItemsCreator={menuItemsCreator}
|
|
41
42
|
onPressMenuModeration={onPressMenuModeration}
|
|
42
43
|
onPressMenuMembers={onPressMenuMembers}
|
|
44
|
+
onPressMenuSearchInChannel={onPressMenuSearchInChannel}
|
|
43
45
|
onPressMenuLeaveChannel={onPressMenuLeaveChannel}
|
|
44
46
|
onPressMenuNotification={onPressMenuNotification}
|
|
45
47
|
/>
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { MessageSearchOrder } from '@sendbird/chat/message';
|
|
4
|
+
import {
|
|
5
|
+
Logger,
|
|
6
|
+
NOOP,
|
|
7
|
+
SendbirdBaseMessage,
|
|
8
|
+
SendbirdChatSDK,
|
|
9
|
+
SendbirdGroupChannel,
|
|
10
|
+
SendbirdMessageSearchQuery,
|
|
11
|
+
useFreshCallback,
|
|
12
|
+
useSafeAreaPadding,
|
|
13
|
+
} from '@sendbird/uikit-utils';
|
|
14
|
+
|
|
15
|
+
import { MessageSearchResultItem } from '../components/MessageSearchResultItem';
|
|
16
|
+
import StatusComposition from '../components/StatusComposition';
|
|
17
|
+
import { createMessageSearchModule } from '../domain/messageSearch';
|
|
18
|
+
import type { MessageSearchFragment, MessageSearchModule, MessageSearchProps } from '../domain/messageSearch/types';
|
|
19
|
+
import { useSendbirdChat } from '../hooks/useContext';
|
|
20
|
+
|
|
21
|
+
type DefaultMessageSearchQueryParams = {
|
|
22
|
+
keyword: string;
|
|
23
|
+
channelUrl: string;
|
|
24
|
+
messageTimestampFrom: number;
|
|
25
|
+
order: MessageSearchOrder;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type SearchQueryOptions = DefaultMessageSearchQueryParams & {
|
|
29
|
+
queryCreator?: (params: DefaultMessageSearchQueryParams) => SendbirdMessageSearchQuery;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function getMessageSearchQuery(sdk: SendbirdChatSDK, options: SearchQueryOptions) {
|
|
33
|
+
if (options.queryCreator) return options.queryCreator(options);
|
|
34
|
+
return sdk.createMessageSearchQuery(options);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const createMessageSearchFragment = (initModule?: Partial<MessageSearchModule>): MessageSearchFragment => {
|
|
38
|
+
const MessageSearchModule = createMessageSearchModule(initModule);
|
|
39
|
+
|
|
40
|
+
return ({ onPressHeaderLeft = NOOP, channel, queryCreator, renderSearchResultItem, onPressSearchResultItem }) => {
|
|
41
|
+
const padding = useSafeAreaPadding(['left', 'right', 'bottom']);
|
|
42
|
+
|
|
43
|
+
const { sdk } = useSendbirdChat();
|
|
44
|
+
const { keyword, setKeyword, search, searchResults, loading, next, error, query } = useMessageSearch(sdk, {
|
|
45
|
+
channel,
|
|
46
|
+
queryCreator,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const renderItem: MessageSearchProps['List']['renderSearchResultItem'] = useFreshCallback((props) => {
|
|
50
|
+
if (renderSearchResultItem) return renderSearchResultItem(props);
|
|
51
|
+
return <MessageSearchResultItem {...props} />;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<MessageSearchModule.Provider>
|
|
56
|
+
<MessageSearchModule.Header
|
|
57
|
+
keyword={keyword}
|
|
58
|
+
onChangeKeyword={setKeyword}
|
|
59
|
+
onPressHeaderLeft={onPressHeaderLeft}
|
|
60
|
+
onPressHeaderRight={search}
|
|
61
|
+
/>
|
|
62
|
+
<StatusComposition
|
|
63
|
+
loading={loading}
|
|
64
|
+
LoadingComponent={<MessageSearchModule.StatusLoading />}
|
|
65
|
+
error={Boolean(error)}
|
|
66
|
+
ErrorComponent={<MessageSearchModule.StatusError onPressRetry={search} />}
|
|
67
|
+
>
|
|
68
|
+
{query && (
|
|
69
|
+
<MessageSearchModule.List
|
|
70
|
+
channel={channel}
|
|
71
|
+
onPressSearchResultItem={onPressSearchResultItem}
|
|
72
|
+
messages={searchResults}
|
|
73
|
+
renderSearchResultItem={renderItem}
|
|
74
|
+
flatListProps={{
|
|
75
|
+
keyboardDismissMode: 'on-drag',
|
|
76
|
+
keyboardShouldPersistTaps: 'handled',
|
|
77
|
+
onEndReached: next,
|
|
78
|
+
ListEmptyComponent: MessageSearchModule.StatusEmpty,
|
|
79
|
+
contentContainerStyle: { flexGrow: 1, ...padding },
|
|
80
|
+
}}
|
|
81
|
+
/>
|
|
82
|
+
)}
|
|
83
|
+
</StatusComposition>
|
|
84
|
+
</MessageSearchModule.Provider>
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const useMessageSearch = (
|
|
90
|
+
sdk: SendbirdChatSDK,
|
|
91
|
+
{ channel, queryCreator }: { channel: SendbirdGroupChannel; queryCreator: SearchQueryOptions['queryCreator'] },
|
|
92
|
+
) => {
|
|
93
|
+
const [query, setQuery] = useState<SendbirdMessageSearchQuery>();
|
|
94
|
+
const [keyword, setKeyword] = useState('');
|
|
95
|
+
const [loading, setLoading] = useState(false);
|
|
96
|
+
const [error, setError] = useState<unknown>(null);
|
|
97
|
+
const [searchResults, setSearchResults] = useState<SendbirdBaseMessage[]>([]);
|
|
98
|
+
const queryInProgress = useRef(false);
|
|
99
|
+
|
|
100
|
+
const search = useFreshCallback(async () => {
|
|
101
|
+
if (keyword.length <= 0) return;
|
|
102
|
+
if (queryInProgress.current) return;
|
|
103
|
+
|
|
104
|
+
const query = getMessageSearchQuery(sdk, {
|
|
105
|
+
keyword,
|
|
106
|
+
channelUrl: channel.url,
|
|
107
|
+
messageTimestampFrom: Math.max(channel.joinedAt, channel.invitedAt),
|
|
108
|
+
order: MessageSearchOrder.TIMESTAMP,
|
|
109
|
+
queryCreator,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
setQuery(query);
|
|
113
|
+
setLoading(true);
|
|
114
|
+
setError(null);
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
queryInProgress.current = true;
|
|
118
|
+
const result = await query.next();
|
|
119
|
+
setSearchResults(result);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
Logger.warn('[MessageSearchFragment] search failure', err);
|
|
122
|
+
setError(err);
|
|
123
|
+
} finally {
|
|
124
|
+
queryInProgress.current = false;
|
|
125
|
+
setLoading(false);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const next = useFreshCallback(async () => {
|
|
130
|
+
if (!query?.hasNext) return;
|
|
131
|
+
if (queryInProgress.current) return;
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
queryInProgress.current = true;
|
|
135
|
+
const result = await query.next();
|
|
136
|
+
setSearchResults((prev) => [...prev, ...result]);
|
|
137
|
+
} catch (err) {
|
|
138
|
+
Logger.warn('[MessageSearchFragment] next failure', err);
|
|
139
|
+
setError(err);
|
|
140
|
+
} finally {
|
|
141
|
+
queryInProgress.current = false;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
keyword,
|
|
147
|
+
setKeyword,
|
|
148
|
+
|
|
149
|
+
query,
|
|
150
|
+
loading,
|
|
151
|
+
error,
|
|
152
|
+
searchResults,
|
|
153
|
+
|
|
154
|
+
search,
|
|
155
|
+
next,
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export default createMessageSearchFragment;
|
|
@@ -1,17 +1,31 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { useMemo, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import { SendbirdError } from '@sendbird/chat';
|
|
4
4
|
import { useOpenChannelMessages } from '@sendbird/uikit-chat-hooks';
|
|
5
5
|
import { useToast } from '@sendbird/uikit-react-native-foundation';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
NOOP,
|
|
8
|
+
PASS,
|
|
9
|
+
SBErrorCode,
|
|
10
|
+
SendbirdFileMessage,
|
|
11
|
+
SendbirdUserMessage,
|
|
12
|
+
messageComparator,
|
|
13
|
+
useFreshCallback,
|
|
14
|
+
} from '@sendbird/uikit-utils';
|
|
7
15
|
|
|
8
16
|
import OpenChannelMessageRenderer from '../components/OpenChannelMessageRenderer';
|
|
9
17
|
import ScrollToBottomButton from '../components/ScrollToBottomButton';
|
|
10
18
|
import StatusComposition from '../components/StatusComposition';
|
|
11
19
|
import { UNKNOWN_USER_ID } from '../constants';
|
|
12
20
|
import { createOpenChannelModule } from '../domain/openChannel';
|
|
13
|
-
import type {
|
|
21
|
+
import type {
|
|
22
|
+
OpenChannelFragment,
|
|
23
|
+
OpenChannelModule,
|
|
24
|
+
OpenChannelProps,
|
|
25
|
+
OpenChannelPubSubContextPayload,
|
|
26
|
+
} from '../domain/openChannel/types';
|
|
14
27
|
import { useLocalization, useSendbirdChat, useUserProfile } from '../hooks/useContext';
|
|
28
|
+
import pubsub from '../utils/pubsub';
|
|
15
29
|
|
|
16
30
|
const createOpenChannelFragment = (initModule?: Partial<OpenChannelModule>): OpenChannelFragment => {
|
|
17
31
|
const OpenChannelModule = createOpenChannelModule(initModule);
|
|
@@ -40,16 +54,19 @@ const createOpenChannelFragment = (initModule?: Partial<OpenChannelModule>): Ope
|
|
|
40
54
|
sortComparator = messageComparator,
|
|
41
55
|
}) => {
|
|
42
56
|
const { sdk, currentUser } = useSendbirdChat();
|
|
57
|
+
|
|
43
58
|
const { STRINGS } = useLocalization();
|
|
44
59
|
const { show: showToast } = useToast();
|
|
45
60
|
const { show: showUserProfile } = useUserProfile();
|
|
46
61
|
|
|
62
|
+
const [openChannelPubSub] = useState(() => pubsub<OpenChannelPubSubContextPayload>());
|
|
63
|
+
|
|
47
64
|
const {
|
|
48
65
|
messages,
|
|
49
|
-
|
|
50
|
-
newMessagesFromMembers,
|
|
66
|
+
newMessages,
|
|
51
67
|
next,
|
|
52
68
|
prev,
|
|
69
|
+
hasNext,
|
|
53
70
|
sendFileMessage,
|
|
54
71
|
sendUserMessage,
|
|
55
72
|
updateFileMessage,
|
|
@@ -64,8 +81,9 @@ const createOpenChannelFragment = (initModule?: Partial<OpenChannelModule>): Ope
|
|
|
64
81
|
onError(error) {
|
|
65
82
|
if (error instanceof SendbirdError) {
|
|
66
83
|
switch (error.code) {
|
|
67
|
-
case SBErrorCode.
|
|
68
|
-
case SBErrorCode.
|
|
84
|
+
case SBErrorCode.RESOURCE_NOT_FOUND:
|
|
85
|
+
case SBErrorCode.CHANNEL_NOT_FOUND:
|
|
86
|
+
case SBErrorCode.BANNED_USER_SEND_MESSAGE_NOT_ALLOWED: {
|
|
69
87
|
return showToast(STRINGS.TOAST.GET_CHANNEL_ERROR, 'error');
|
|
70
88
|
}
|
|
71
89
|
}
|
|
@@ -73,6 +91,9 @@ const createOpenChannelFragment = (initModule?: Partial<OpenChannelModule>): Ope
|
|
|
73
91
|
|
|
74
92
|
showToast(STRINGS.TOAST.UNKNOWN_ERROR, 'error');
|
|
75
93
|
},
|
|
94
|
+
onMessagesReceived(messages) {
|
|
95
|
+
openChannelPubSub.publish({ type: 'MESSAGES_RECEIVED', data: { messages } });
|
|
96
|
+
},
|
|
76
97
|
});
|
|
77
98
|
|
|
78
99
|
const isOperator = channel.isOperator(currentUser?.userId ?? UNKNOWN_USER_ID);
|
|
@@ -91,16 +112,25 @@ const createOpenChannelFragment = (initModule?: Partial<OpenChannelModule>): Ope
|
|
|
91
112
|
[loading, flatListProps],
|
|
92
113
|
);
|
|
93
114
|
|
|
115
|
+
const onPending = (message: SendbirdFileMessage | SendbirdUserMessage) => {
|
|
116
|
+
openChannelPubSub.publish({ type: 'MESSAGE_SENT_PENDING', data: { message } });
|
|
117
|
+
};
|
|
118
|
+
const onSent = (message: SendbirdFileMessage | SendbirdUserMessage) => {
|
|
119
|
+
openChannelPubSub.publish({ type: 'MESSAGE_SENT_SUCCESS', data: { message } });
|
|
120
|
+
};
|
|
121
|
+
|
|
94
122
|
const onPressSendUserMessage: OpenChannelProps['Input']['onPressSendUserMessage'] = useFreshCallback(
|
|
95
123
|
async (params) => {
|
|
96
124
|
const processedParams = await onBeforeSendUserMessage(params);
|
|
97
|
-
await sendUserMessage(processedParams);
|
|
125
|
+
const message = await sendUserMessage(processedParams, onPending);
|
|
126
|
+
onSent(message);
|
|
98
127
|
},
|
|
99
128
|
);
|
|
100
129
|
const onPressSendFileMessage: OpenChannelProps['Input']['onPressSendFileMessage'] = useFreshCallback(
|
|
101
130
|
async (params) => {
|
|
102
131
|
const processedParams = await onBeforeSendFileMessage(params);
|
|
103
|
-
await sendFileMessage(processedParams);
|
|
132
|
+
const message = await sendFileMessage(processedParams, onPending);
|
|
133
|
+
onSent(message);
|
|
104
134
|
},
|
|
105
135
|
);
|
|
106
136
|
const onPressUpdateUserMessage: OpenChannelProps['Input']['onPressUpdateUserMessage'] = useFreshCallback(
|
|
@@ -117,7 +147,11 @@ const createOpenChannelFragment = (initModule?: Partial<OpenChannelModule>): Ope
|
|
|
117
147
|
);
|
|
118
148
|
|
|
119
149
|
return (
|
|
120
|
-
<OpenChannelModule.Provider
|
|
150
|
+
<OpenChannelModule.Provider
|
|
151
|
+
openChannelPubSub={openChannelPubSub}
|
|
152
|
+
channel={channel}
|
|
153
|
+
keyboardAvoidOffset={keyboardAvoidOffset}
|
|
154
|
+
>
|
|
121
155
|
<OpenChannelModule.Header
|
|
122
156
|
onPressHeaderLeft={onPressHeaderLeft}
|
|
123
157
|
rightIconName={isOperator ? 'info' : 'members'}
|
|
@@ -126,14 +160,16 @@ const createOpenChannelFragment = (initModule?: Partial<OpenChannelModule>): Ope
|
|
|
126
160
|
<StatusComposition loading={loading} LoadingComponent={<OpenChannelModule.StatusLoading />}>
|
|
127
161
|
<OpenChannelModule.MessageList
|
|
128
162
|
channel={channel}
|
|
163
|
+
hasNext={hasNext}
|
|
129
164
|
enableMessageGrouping={enableMessageGrouping}
|
|
130
165
|
currentUserId={currentUser?.userId}
|
|
131
166
|
renderMessage={_renderMessage}
|
|
132
167
|
messages={messages}
|
|
133
|
-
|
|
134
|
-
newMessagesFromMembers={newMessagesFromMembers}
|
|
168
|
+
newMessages={newMessages}
|
|
135
169
|
onTopReached={prev}
|
|
136
170
|
onBottomReached={next}
|
|
171
|
+
scrolledAwayFromBottom={false}
|
|
172
|
+
onScrolledAwayFromBottom={NOOP}
|
|
137
173
|
renderNewMessagesButton={renderNewMessagesButton}
|
|
138
174
|
renderScrollToBottomButton={renderScrollToBottomButton}
|
|
139
175
|
onResendFailedMessage={resendMessage}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { useCallback, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import { useChannelHandler } from '@sendbird/uikit-chat-hooks';
|
|
4
|
+
import type { SendbirdChatSDK, SendbirdGroupChannel, SendbirdMember, SendbirdUser } from '@sendbird/uikit-utils';
|
|
5
|
+
import { isDifferentChannel, useAsyncEffect, useDebounceEffect, useUniqHandlerId } from '@sendbird/uikit-utils';
|
|
5
6
|
|
|
6
7
|
import { useSendbirdChat } from '../hooks/useContext';
|
|
7
8
|
import type { Range } from '../types';
|
|
@@ -9,8 +10,9 @@ import type { Range } from '../types';
|
|
|
9
10
|
const useMentionSuggestion = (params: {
|
|
10
11
|
text: string;
|
|
11
12
|
selection: Range;
|
|
12
|
-
channel: SendbirdGroupChannel;
|
|
13
13
|
mentionedUsers: { user: SendbirdUser; range: Range }[];
|
|
14
|
+
sdk: SendbirdChatSDK;
|
|
15
|
+
channel: SendbirdGroupChannel;
|
|
14
16
|
}) => {
|
|
15
17
|
const { text, selection, channel, mentionedUsers } = params;
|
|
16
18
|
|
|
@@ -20,6 +22,24 @@ const useMentionSuggestion = (params: {
|
|
|
20
22
|
setFreshChannel(await channel.refresh());
|
|
21
23
|
}, [channel.url]);
|
|
22
24
|
|
|
25
|
+
const id = useUniqHandlerId('useMentionSuggestion');
|
|
26
|
+
|
|
27
|
+
useChannelHandler(params.sdk, id, {
|
|
28
|
+
onUserJoined(eventChannel) {
|
|
29
|
+
if (isDifferentChannel(eventChannel, channel)) return;
|
|
30
|
+
setFreshChannel(eventChannel);
|
|
31
|
+
},
|
|
32
|
+
onUserLeft(eventChannel) {
|
|
33
|
+
if (isDifferentChannel(eventChannel, channel)) return;
|
|
34
|
+
setFreshChannel(eventChannel);
|
|
35
|
+
},
|
|
36
|
+
onUserBanned(eventChannel) {
|
|
37
|
+
if (isDifferentChannel(eventChannel, channel)) return;
|
|
38
|
+
if (!eventChannel.isGroupChannel()) return;
|
|
39
|
+
setFreshChannel(eventChannel);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
23
43
|
const { mentionManager, currentUser } = useSendbirdChat();
|
|
24
44
|
const [members, setMembers] = useState<SendbirdMember[]>([]);
|
|
25
45
|
|
package/src/index.ts
CHANGED
|
@@ -32,6 +32,7 @@ export { default as createGroupChannelRegisterOperatorFragment } from './fragmen
|
|
|
32
32
|
export { default as createGroupChannelMutedMembersFragment } from './fragments/createGroupChannelMutedMembersFragment';
|
|
33
33
|
export { default as createGroupChannelBannedUsersFragment } from './fragments/createGroupChannelBannedUsersFragment';
|
|
34
34
|
export { default as createGroupChannelNotificationsFragment } from './fragments/createGroupChannelNotificationsFragment';
|
|
35
|
+
export { default as createMessageSearchFragment } from './fragments/createMessageSearchFragment';
|
|
35
36
|
|
|
36
37
|
/** Fragments - open channels **/
|
|
37
38
|
export { default as createOpenChannelFragment } from './fragments/createOpenChannelFragment';
|
|
@@ -91,6 +92,8 @@ export * from './domain/groupChannelNotifications/types';
|
|
|
91
92
|
|
|
92
93
|
export * from './domain/groupChannelUserList/types';
|
|
93
94
|
|
|
95
|
+
export * from './domain/messageSearch/types';
|
|
96
|
+
|
|
94
97
|
/** Feature - open channels **/
|
|
95
98
|
export * from './domain/openChannel';
|
|
96
99
|
export * from './domain/openChannel/types';
|