stream-chat-react 12.10.0 → 12.11.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/dist/components/Attachment/Attachment.js +2 -1
- package/dist/components/Attachment/AttachmentContainer.d.ts +1 -1
- package/dist/components/Attachment/AttachmentContainer.js +2 -2
- package/dist/components/Attachment/Card.js +3 -3
- package/dist/components/Attachment/VoiceRecording.d.ts +1 -1
- package/dist/components/Attachment/VoiceRecording.js +2 -2
- package/dist/components/Attachment/attachment-sizing.js +2 -1
- package/dist/components/Attachment/components/FileSizeIndicator.d.ts +1 -1
- package/dist/components/Attachment/components/FileSizeIndicator.js +1 -1
- package/dist/components/Attachment/hooks/useAudioController.js +3 -1
- package/dist/components/Attachment/utils.d.ts +1 -1
- package/dist/components/Attachment/utils.js +12 -3
- package/dist/components/AutoCompleteTextarea/List.js +3 -2
- package/dist/components/AutoCompleteTextarea/Textarea.js +3 -3
- package/dist/components/AutoCompleteTextarea/utils.js +2 -2
- package/dist/components/Avatar/ChannelAvatar.js +1 -1
- package/dist/components/Channel/Channel.d.ts +1 -1
- package/dist/components/Channel/Channel.js +27 -12
- package/dist/components/Channel/channelState.js +9 -3
- package/dist/components/Channel/hooks/useCreateChannelStateContext.js +5 -3
- package/dist/components/Channel/hooks/useMentionsHandlers.js +5 -2
- package/dist/components/Channel/utils.js +2 -1
- package/dist/components/ChannelHeader/ChannelHeader.js +1 -1
- package/dist/components/ChannelList/ChannelList.js +13 -8
- package/dist/components/ChannelList/hooks/useChannelListShape.d.ts +2 -2
- package/dist/components/ChannelList/hooks/useChannelListShape.js +48 -20
- package/dist/components/ChannelList/hooks/useChannelUpdatedListener.js +2 -1
- package/dist/components/ChannelList/hooks/useMessageNewListener.js +3 -1
- package/dist/components/ChannelList/hooks/usePaginatedChannels.js +4 -2
- package/dist/components/ChannelList/hooks/useSelectedChannelState.js +1 -1
- package/dist/components/ChannelPreview/ChannelPreview.js +2 -2
- package/dist/components/ChannelPreview/ChannelPreviewMessenger.js +1 -1
- package/dist/components/ChannelPreview/icons.js +0 -1
- package/dist/components/ChannelPreview/utils.js +3 -3
- package/dist/components/ChannelSearch/ChannelSearch.js +5 -3
- package/dist/components/ChannelSearch/SearchResults.js +1 -1
- package/dist/components/ChannelSearch/hooks/useChannelSearch.d.ts +4 -2
- package/dist/components/ChannelSearch/hooks/useChannelSearch.js +61 -36
- package/dist/components/ChannelSearch/index.d.ts +1 -1
- package/dist/components/Chat/hooks/useChat.js +4 -2
- package/dist/components/Chat/hooks/useCreateChatClient.js +3 -1
- package/dist/components/ChatAutoComplete/ChatAutoComplete.js +1 -1
- package/dist/components/ChatView/ChatView.js +0 -1
- package/dist/components/Dialog/PromptDialog.d.ts +1 -1
- package/dist/components/Dialog/PromptDialog.js +1 -1
- package/dist/components/EventComponent/EventComponent.js +1 -1
- package/dist/components/Gallery/Image.js +1 -1
- package/dist/components/Gallery/ModalGallery.js +1 -2
- package/dist/components/InfiniteScrollPaginator/InfiniteScroll.js +5 -2
- package/dist/components/InfiniteScrollPaginator/InfiniteScrollPaginator.js +1 -1
- package/dist/components/LoadMore/LoadMorePaginator.js +1 -1
- package/dist/components/MML/MML.js +1 -0
- package/dist/components/MediaRecorder/transcode/wav.js +6 -3
- package/dist/components/Message/FixedHeightMessage.js +6 -8
- package/dist/components/Message/Message.js +2 -1
- package/dist/components/Message/MessageEditedTimestamp.js +1 -1
- package/dist/components/Message/MessageSimple.js +2 -5
- package/dist/components/Message/MessageStatus.js +1 -1
- package/dist/components/Message/MessageText.js +7 -7
- package/dist/components/Message/QuotedMessage.js +2 -2
- package/dist/components/Message/Timestamp.js +9 -1
- package/dist/components/Message/hooks/useActionHandler.js +1 -1
- package/dist/components/Message/hooks/useFlagHandler.js +2 -1
- package/dist/components/Message/hooks/useMarkUnreadHandler.js +2 -1
- package/dist/components/Message/hooks/useMessageTextStreaming.d.ts +1 -1
- package/dist/components/Message/hooks/useMessageTextStreaming.js +1 -1
- package/dist/components/Message/hooks/useMuteHandler.js +7 -4
- package/dist/components/Message/hooks/usePinHandler.js +1 -1
- package/dist/components/Message/hooks/useReactionHandler.js +10 -5
- package/dist/components/Message/hooks/useRetryHandler.js +1 -1
- package/dist/components/Message/hooks/useUserRole.js +1 -1
- package/dist/components/Message/renderText/renderText.js +2 -2
- package/dist/components/Message/utils.js +3 -3
- package/dist/components/MessageActions/MessageActionsBox.js +7 -3
- package/dist/components/MessageInput/AttachmentPreviewList/AttachmentPreviewList.js +1 -1
- package/dist/components/MessageInput/AttachmentPreviewList/FileAttachmentPreview.js +4 -2
- package/dist/components/MessageInput/AttachmentPreviewList/UnsupportedAttachmentPreview.js +4 -2
- package/dist/components/MessageInput/AttachmentSelector.js +1 -1
- package/dist/components/MessageInput/DefaultTriggerProvider.js +1 -1
- package/dist/components/MessageInput/DropzoneProvider.js +1 -1
- package/dist/components/MessageInput/MessageInput.js +1 -1
- package/dist/components/MessageInput/MessageInputFlat.js +4 -3
- package/dist/components/MessageInput/QuotedMessagePreview.js +1 -1
- package/dist/components/MessageInput/hooks/useAttachments.js +12 -4
- package/dist/components/MessageInput/hooks/useLinkPreviews.js +3 -1
- package/dist/components/MessageInput/hooks/useMessageInputState.js +4 -3
- package/dist/components/MessageInput/hooks/useMessageInputText.js +3 -1
- package/dist/components/MessageInput/hooks/useSubmitHandler.js +5 -3
- package/dist/components/MessageInput/hooks/useUserTrigger.js +2 -2
- package/dist/components/MessageInput/hooks/utils.js +6 -2
- package/dist/components/MessageList/ConnectionStatus.js +1 -1
- package/dist/components/MessageList/MessageList.js +5 -5
- package/dist/components/MessageList/MessageListNotifications.js +3 -1
- package/dist/components/MessageList/VirtualizedMessageList.js +17 -10
- package/dist/components/MessageList/VirtualizedMessageListComponents.js +2 -2
- package/dist/components/MessageList/hooks/MessageList/useMessageListElements.js +1 -3
- package/dist/components/MessageList/hooks/MessageList/useMessageListScrollManager.js +2 -1
- package/dist/components/MessageList/hooks/MessageList/useScrollLocationLogic.js +3 -2
- package/dist/components/MessageList/hooks/MessageList/useUnreadMessagesNotification.js +6 -2
- package/dist/components/MessageList/hooks/VirtualizedMessageList/usePrependMessagesCount.js +2 -1
- package/dist/components/MessageList/hooks/VirtualizedMessageList/useUnreadMessagesNotificationVirtualized.js +7 -3
- package/dist/components/MessageList/utils.js +28 -11
- package/dist/components/Modal/Modal.d.ts +1 -1
- package/dist/components/Modal/Modal.js +1 -1
- package/dist/components/Modal/ModalHeader.js +1 -1
- package/dist/components/Poll/Poll.js +1 -1
- package/dist/components/Poll/PollActions/PollActions.js +6 -4
- package/dist/components/Poll/PollActions/PollAnswerList.js +1 -1
- package/dist/components/Poll/PollActions/PollResults/PollOptionVotesList.js +1 -1
- package/dist/components/Poll/PollActions/PollResults/PollOptionWithLatestVotes.js +4 -2
- package/dist/components/Poll/PollActions/PollResults/PollResults.js +2 -1
- package/dist/components/Poll/PollContent.js +1 -1
- package/dist/components/Poll/PollCreationDialog/OptionFieldSet.d.ts +1 -1
- package/dist/components/Poll/PollCreationDialog/OptionFieldSet.js +11 -4
- package/dist/components/Poll/PollCreationDialog/PollCreationDialog.js +13 -4
- package/dist/components/Poll/PollCreationDialog/PollCreationDialogControls.js +6 -3
- package/dist/components/Poll/PollOptionList.js +1 -1
- package/dist/components/Poll/PollOptionSelector.js +12 -5
- package/dist/components/Poll/hooks/useManagePollVotesRealtime.js +9 -4
- package/dist/components/Poll/hooks/usePollAnswerPagination.js +8 -2
- package/dist/components/Poll/hooks/usePollOptionVotesPagination.js +8 -2
- package/dist/components/ReactFileUtilities/FileIcon/mimeTypes.d.ts +1 -1
- package/dist/components/ReactFileUtilities/ImageDropzone.js +3 -1
- package/dist/components/ReactFileUtilities/UploadButton.js +1 -1
- package/dist/components/ReactFileUtilities/utils.js +3 -1
- package/dist/components/Reactions/ReactionSelector.js +3 -1
- package/dist/components/Reactions/ReactionSelectorWithButton.js +1 -1
- package/dist/components/Reactions/ReactionsList.d.ts +2 -2
- package/dist/components/Reactions/ReactionsList.js +7 -4
- package/dist/components/Reactions/ReactionsListModal.d.ts +1 -2
- package/dist/components/Reactions/ReactionsListModal.js +1 -1
- package/dist/components/Reactions/SpriteImage.js +6 -2
- package/dist/components/Reactions/hooks/useFetchReactions.js +1 -1
- package/dist/components/Reactions/hooks/useProcessReactions.js +1 -1
- package/dist/components/Reactions/index.d.ts +1 -0
- package/dist/components/Reactions/index.js +1 -0
- package/dist/components/Reactions/reactionOptions.js +20 -5
- package/dist/components/Thread/Thread.js +4 -3
- package/dist/components/Threads/ThreadContext.d.ts +1 -1
- package/dist/components/Threads/ThreadContext.js +1 -1
- package/dist/components/Threads/ThreadList/ThreadList.js +1 -1
- package/dist/components/Threads/ThreadList/ThreadListItem.d.ts +1 -1
- package/dist/components/Threads/ThreadList/ThreadListItem.js +1 -1
- package/dist/components/Threads/ThreadList/ThreadListItemUI.js +5 -3
- package/dist/components/Threads/icons.js +0 -1
- package/dist/components/Tooltip/Tooltip.d.ts +1 -1
- package/dist/components/Tooltip/Tooltip.js +1 -1
- package/dist/context/ComponentContext.d.ts +3 -1
- package/dist/context/ComponentContext.js +1 -1
- package/dist/context/DialogManagerContext.d.ts +1 -1
- package/dist/context/DialogManagerContext.js +1 -1
- package/dist/context/MessageBounceContext.js +2 -2
- package/dist/context/MessageContext.js +1 -1
- package/dist/context/WithComponents.js +1 -1
- package/dist/css/v2/index.css +2 -2
- package/dist/css/v2/index.layout.css +2 -2
- package/dist/experimental/MessageActions/MessageActions.js +0 -1
- package/dist/experimental/MessageActions/defaults.js +31 -7
- package/dist/experimental/index.browser.cjs +103 -37
- package/dist/experimental/index.browser.cjs.map +2 -2
- package/dist/experimental/index.node.cjs +103 -37
- package/dist/experimental/index.node.cjs.map +2 -2
- package/dist/i18n/Streami18n.js +11 -2
- package/dist/i18n/utils.js +14 -1
- package/dist/index.browser.cjs +1774 -982
- package/dist/index.browser.cjs.map +4 -4
- package/dist/index.node.cjs +1775 -982
- package/dist/index.node.cjs.map +4 -4
- package/dist/plugins/Emojis/EmojiPicker.js +0 -1
- package/dist/plugins/Emojis/index.browser.cjs +3 -1
- package/dist/plugins/Emojis/index.browser.cjs.map +2 -2
- package/dist/plugins/Emojis/index.node.cjs +3 -1
- package/dist/plugins/Emojis/index.node.cjs.map +2 -2
- package/dist/plugins/encoders/mp3.browser.cjs +7 -4
- package/dist/plugins/encoders/mp3.browser.cjs.map +2 -2
- package/dist/plugins/encoders/mp3.node.cjs +7 -4
- package/dist/plugins/encoders/mp3.node.cjs.map +2 -2
- package/dist/scss/v2/ChannelSearch/ChannelSearch-layout.scss +1 -0
- package/dist/scss/v2/Message/Message-layout.scss +12 -5
- package/dist/scss/v2/Poll/Poll-layout.scss +1 -1
- package/dist/scss/v2/Search/Search-layout.scss +148 -0
- package/dist/scss/v2/Search/Search-theme.scss +222 -0
- package/dist/scss/v2/_icons.scss +2 -0
- package/dist/scss/v2/index.layout.scss +1 -0
- package/dist/scss/v2/index.scss +1 -0
- package/dist/store/hooks/useStateStore.js +35 -11
- package/package.json +21 -33
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// const defaults = useChannelListShapeDefaults();
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
3
|
-
import uniqBy from 'lodash.uniqby';
|
|
4
3
|
import { extractSortValue, findLastPinnedChannelIndex, isChannelArchived, isChannelPinned, moveChannelUpwards, shouldConsiderArchivedChannels, shouldConsiderPinnedChannels, } from '../utils';
|
|
5
4
|
import { useChatContext } from '../../../context';
|
|
6
5
|
import { getChannel } from '../../../utils';
|
|
@@ -77,7 +76,6 @@ export const useChannelListShapeDefaults = () => {
|
|
|
77
76
|
setChannels((channels) => moveChannelUpwards({
|
|
78
77
|
channels,
|
|
79
78
|
channelToMove: channel,
|
|
80
|
-
channelToMoveIndexWithinChannels: -1,
|
|
81
79
|
sort,
|
|
82
80
|
}));
|
|
83
81
|
}, [client]);
|
|
@@ -103,7 +101,6 @@ export const useChannelListShapeDefaults = () => {
|
|
|
103
101
|
setChannels((channels) => moveChannelUpwards({
|
|
104
102
|
channels,
|
|
105
103
|
channelToMove: channel,
|
|
106
|
-
channelToMoveIndexWithinChannels: -1,
|
|
107
104
|
sort,
|
|
108
105
|
}));
|
|
109
106
|
}, [client]);
|
|
@@ -114,13 +111,19 @@ export const useChannelListShapeDefaults = () => {
|
|
|
114
111
|
setChannels((channels) => channels.filter((channel) => channel.cid !== event.channel?.cid));
|
|
115
112
|
}, []);
|
|
116
113
|
const handleMemberUpdated = useCallback(({ event, filters, lockChannelOrder, setChannels, sort, }) => {
|
|
117
|
-
if (!event.member?.user ||
|
|
114
|
+
if (!event.member?.user ||
|
|
115
|
+
event.member.user.id !== client.userID ||
|
|
116
|
+
!event.channel_type) {
|
|
118
117
|
return;
|
|
119
118
|
}
|
|
120
119
|
const channelType = event.channel_type;
|
|
121
120
|
const channelId = event.channel_id;
|
|
122
121
|
const considerPinnedChannels = shouldConsiderPinnedChannels(sort);
|
|
123
122
|
const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
|
|
123
|
+
// `pinned_at` nor `archived` properties are set or channel list order is locked, return early
|
|
124
|
+
if ((!considerPinnedChannels && !considerArchivedChannels) || lockChannelOrder) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
124
127
|
const pinnedAtSort = extractSortValue({ atIndex: 0, sort, targetKey: 'pinned_at' });
|
|
125
128
|
setChannels((currentChannels) => {
|
|
126
129
|
const targetChannel = client.channel(channelType, channelId);
|
|
@@ -129,9 +132,6 @@ export const useChannelListShapeDefaults = () => {
|
|
|
129
132
|
const targetChannelExistsWithinList = targetChannelIndex >= 0;
|
|
130
133
|
const isTargetChannelArchived = isChannelArchived(targetChannel);
|
|
131
134
|
const isTargetChannelPinned = isChannelPinned(targetChannel);
|
|
132
|
-
// handle pinning
|
|
133
|
-
if (!considerPinnedChannels || lockChannelOrder)
|
|
134
|
-
return currentChannels;
|
|
135
135
|
const newChannels = [...currentChannels];
|
|
136
136
|
if (targetChannelExistsWithinList) {
|
|
137
137
|
newChannels.splice(targetChannelIndex, 1);
|
|
@@ -159,18 +159,27 @@ export const useChannelListShapeDefaults = () => {
|
|
|
159
159
|
}, [client]);
|
|
160
160
|
const handleChannelDeleted = useCallback((p) => shared(p), []);
|
|
161
161
|
const handleChannelHidden = useCallback((p) => shared(p), []);
|
|
162
|
-
const handleChannelVisible = useCallback(async ({ customHandler, event, setChannels }) => {
|
|
162
|
+
const handleChannelVisible = useCallback(async ({ customHandler, event, filters, setChannels, sort, }) => {
|
|
163
163
|
if (typeof customHandler === 'function') {
|
|
164
164
|
return customHandler(setChannels, event);
|
|
165
165
|
}
|
|
166
|
-
if (event.
|
|
167
|
-
|
|
168
|
-
client,
|
|
169
|
-
id: event.channel_id,
|
|
170
|
-
type: event.channel_type,
|
|
171
|
-
});
|
|
172
|
-
setChannels((channels) => uniqBy([channel, ...channels], 'cid'));
|
|
166
|
+
if (!event.channel) {
|
|
167
|
+
return;
|
|
173
168
|
}
|
|
169
|
+
const channel = await getChannel({
|
|
170
|
+
client,
|
|
171
|
+
id: event.channel.id,
|
|
172
|
+
type: event.channel.type,
|
|
173
|
+
});
|
|
174
|
+
const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
|
|
175
|
+
if (isChannelArchived(channel) && considerArchivedChannels && !filters.archived) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
setChannels((channels) => moveChannelUpwards({
|
|
179
|
+
channels,
|
|
180
|
+
channelToMove: channel,
|
|
181
|
+
sort,
|
|
182
|
+
}));
|
|
174
183
|
}, [client]);
|
|
175
184
|
const handleChannelTruncated = useCallback(({ customHandler, event, setChannels }) => {
|
|
176
185
|
if (typeof customHandler === 'function') {
|
|
@@ -193,7 +202,8 @@ export const useChannelListShapeDefaults = () => {
|
|
|
193
202
|
newChannels[channelIndex].data = {
|
|
194
203
|
...event.channel,
|
|
195
204
|
hidden: event.channel?.hidden ?? newChannels[channelIndex].data?.hidden,
|
|
196
|
-
own_capabilities: event.channel?.own_capabilities ??
|
|
205
|
+
own_capabilities: event.channel?.own_capabilities ??
|
|
206
|
+
newChannels[channelIndex].data?.own_capabilities,
|
|
197
207
|
};
|
|
198
208
|
return [...newChannels];
|
|
199
209
|
}
|
|
@@ -300,16 +310,34 @@ export const usePrepareShapeHandlers = ({ allowNewMessagesFromUnfilteredChannels
|
|
|
300
310
|
});
|
|
301
311
|
break;
|
|
302
312
|
case 'channel.hidden':
|
|
303
|
-
defaults.handleChannelHidden({
|
|
313
|
+
defaults.handleChannelHidden({
|
|
314
|
+
customHandler: onChannelHidden,
|
|
315
|
+
event,
|
|
316
|
+
setChannels,
|
|
317
|
+
});
|
|
304
318
|
break;
|
|
305
319
|
case 'channel.visible':
|
|
306
|
-
defaults.handleChannelVisible({
|
|
320
|
+
defaults.handleChannelVisible({
|
|
321
|
+
customHandler: onChannelVisible,
|
|
322
|
+
event,
|
|
323
|
+
filters,
|
|
324
|
+
setChannels,
|
|
325
|
+
sort,
|
|
326
|
+
});
|
|
307
327
|
break;
|
|
308
328
|
case 'channel.truncated':
|
|
309
|
-
defaults.handleChannelTruncated({
|
|
329
|
+
defaults.handleChannelTruncated({
|
|
330
|
+
customHandler: onChannelTruncated,
|
|
331
|
+
event,
|
|
332
|
+
setChannels,
|
|
333
|
+
});
|
|
310
334
|
break;
|
|
311
335
|
case 'channel.updated':
|
|
312
|
-
defaults.handleChannelUpdated({
|
|
336
|
+
defaults.handleChannelUpdated({
|
|
337
|
+
customHandler: onChannelUpdated,
|
|
338
|
+
event,
|
|
339
|
+
setChannels,
|
|
340
|
+
});
|
|
313
341
|
break;
|
|
314
342
|
case 'user.presence.changed':
|
|
315
343
|
defaults.handleUserPresenceChanged({ event, setChannels });
|
|
@@ -11,7 +11,8 @@ export const useChannelUpdatedListener = (setChannels, customHandler, forceUpdat
|
|
|
11
11
|
newChannels[channelIndex].data = {
|
|
12
12
|
...event.channel,
|
|
13
13
|
hidden: event.channel?.hidden ?? newChannels[channelIndex].data?.hidden,
|
|
14
|
-
own_capabilities: event.channel?.own_capabilities ??
|
|
14
|
+
own_capabilities: event.channel?.own_capabilities ??
|
|
15
|
+
newChannels[channelIndex].data?.own_capabilities,
|
|
15
16
|
};
|
|
16
17
|
return [...newChannels];
|
|
17
18
|
}
|
|
@@ -12,7 +12,9 @@ export const useMessageNewListener = (setChannels, customHandler, lockChannelOrd
|
|
|
12
12
|
else {
|
|
13
13
|
setChannels((channels) => {
|
|
14
14
|
const channelInList = channels.filter((channel) => channel.cid === event.cid).length > 0;
|
|
15
|
-
if (!channelInList &&
|
|
15
|
+
if (!channelInList &&
|
|
16
|
+
allowNewMessagesFromUnfilteredChannels &&
|
|
17
|
+
event.channel_type) {
|
|
16
18
|
const channel = client.channel(event.channel_type, event.channel_id);
|
|
17
19
|
return uniqBy([channel, ...channels], 'cid');
|
|
18
20
|
}
|
|
@@ -12,7 +12,7 @@ export const usePaginatedChannels = (client, filters, sort, options, activeChann
|
|
|
12
12
|
const lastRecoveryTimestamp = useRef(undefined);
|
|
13
13
|
const recoveryThrottleInterval = recoveryThrottleIntervalMs < MIN_RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS
|
|
14
14
|
? MIN_RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS
|
|
15
|
-
: recoveryThrottleIntervalMs ?? RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS;
|
|
15
|
+
: (recoveryThrottleIntervalMs ?? RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS);
|
|
16
16
|
// memoize props
|
|
17
17
|
const filterString = useMemo(() => JSON.stringify(filters), [filters]);
|
|
18
18
|
const sortString = useMemo(() => JSON.stringify(sort), [sort]);
|
|
@@ -64,7 +64,9 @@ export const usePaginatedChannels = (client, filters, sort, options, activeChann
|
|
|
64
64
|
const timeElapsedSinceLastRecoveryMs = lastRecoveryTimestamp.current
|
|
65
65
|
? now - lastRecoveryTimestamp.current
|
|
66
66
|
: 0;
|
|
67
|
-
if (!isFirstRecovery &&
|
|
67
|
+
if (!isFirstRecovery &&
|
|
68
|
+
timeElapsedSinceLastRecoveryMs < recoveryThrottleInterval &&
|
|
69
|
+
!error) {
|
|
68
70
|
return;
|
|
69
71
|
}
|
|
70
72
|
lastRecoveryTimestamp.current = now;
|
|
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
|
|
|
2
2
|
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
3
3
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
4
4
|
const noop = () => { };
|
|
5
|
-
export function useSelectedChannelState({ channel, stateChangeEventKeys = ['all'],
|
|
5
|
+
export function useSelectedChannelState({ channel, selector, stateChangeEventKeys = ['all'], }) {
|
|
6
6
|
const subscribe = useCallback((onStoreChange) => {
|
|
7
7
|
if (!channel)
|
|
8
8
|
return noop;
|
|
@@ -6,9 +6,9 @@ import { useChannelPreviewInfo } from './hooks/useChannelPreviewInfo';
|
|
|
6
6
|
import { getLatestMessagePreview as defaultGetLatestMessagePreview } from './utils';
|
|
7
7
|
import { useChatContext } from '../../context/ChatContext';
|
|
8
8
|
import { useTranslationContext } from '../../context/TranslationContext';
|
|
9
|
-
import { useMessageDeliveryStatus } from './hooks/useMessageDeliveryStatus';
|
|
9
|
+
import { useMessageDeliveryStatus, } from './hooks/useMessageDeliveryStatus';
|
|
10
10
|
export const ChannelPreview = (props) => {
|
|
11
|
-
const { channel,
|
|
11
|
+
const { channel, channelUpdateCount, getLatestMessagePreview = defaultGetLatestMessagePreview, Preview = ChannelPreviewMessenger, } = props;
|
|
12
12
|
const { channel: activeChannel, client, isMessageAIGenerated, setActiveChannel, } = useChatContext('ChannelPreview');
|
|
13
13
|
const { t, userLanguage } = useTranslationContext('ChannelPreview');
|
|
14
14
|
const { displayImage, displayTitle, groupChannelDisplayInfo } = useChannelPreviewInfo({
|
|
@@ -5,7 +5,7 @@ import { Avatar as DefaultAvatar } from '../Avatar';
|
|
|
5
5
|
import { useComponentContext } from '../../context';
|
|
6
6
|
const UnMemoizedChannelPreviewMessenger = (props) => {
|
|
7
7
|
const { active, Avatar = DefaultAvatar, channel, className: customClassName = '', displayImage, displayTitle, groupChannelDisplayInfo, latestMessagePreview, onSelect: customOnSelectChannel, setActiveChannel, unread, watchers, } = props;
|
|
8
|
-
const { ChannelPreviewActionButtons = DefaultChannelPreviewActionButtons
|
|
8
|
+
const { ChannelPreviewActionButtons = DefaultChannelPreviewActionButtons } = useComponentContext();
|
|
9
9
|
const channelPreviewButton = useRef(null);
|
|
10
10
|
const avatarName = displayTitle || channel.state.messages[channel.state.messages.length - 1]?.user?.id;
|
|
11
11
|
const onSelectChannel = (e) => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable react/display-name */
|
|
2
1
|
import React from 'react';
|
|
3
2
|
export const Icon = {
|
|
4
3
|
ArchiveBox: (props) => (React.createElement("svg", { className: 'str-chat__icon str-chat__icon--archive-box', fill: 'currentColor', viewBox: '0 0 512 512', xmlns: 'http://www.w3.org/2000/svg', ...props },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import ReactMarkdown from 'react-markdown';
|
|
3
|
-
export const renderPreviewText = (text) => React.createElement(ReactMarkdown, { skipHtml: true }, text);
|
|
3
|
+
export const renderPreviewText = (text) => (React.createElement(ReactMarkdown, { skipHtml: true }, text));
|
|
4
4
|
const getLatestPollVote = (latestVotesByOption) => {
|
|
5
5
|
let latestVote;
|
|
6
6
|
for (const optionVotes of Object.values(latestVotesByOption)) {
|
|
@@ -27,7 +27,7 @@ export const getLatestMessagePreview = (channel, t, userLanguage = 'en', isMessa
|
|
|
27
27
|
if (!poll.vote_count) {
|
|
28
28
|
const createdBy = poll.created_by?.id === channel.getClient().userID
|
|
29
29
|
? t('You')
|
|
30
|
-
: poll.created_by?.name ?? t('Poll');
|
|
30
|
+
: (poll.created_by?.name ?? t('Poll'));
|
|
31
31
|
return t('📊 {{createdBy}} created: {{ pollName}}', {
|
|
32
32
|
createdBy,
|
|
33
33
|
pollName: poll.name,
|
|
@@ -41,7 +41,7 @@ export const getLatestMessagePreview = (channel, t, userLanguage = 'en', isMessa
|
|
|
41
41
|
pollOptionText: option.text,
|
|
42
42
|
votedBy: latestVote?.user?.id === channel.getClient().userID
|
|
43
43
|
? t('You')
|
|
44
|
-
: latestVote.user?.name ?? t('Poll'),
|
|
44
|
+
: (latestVote.user?.name ?? t('Poll')),
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { useChannelSearch } from './hooks/useChannelSearch';
|
|
3
|
+
import { useChannelSearch, } from './hooks/useChannelSearch';
|
|
4
4
|
import { SearchBar as DefaultSearchBar } from './SearchBar';
|
|
5
5
|
import { SearchInput as DefaultSearchInput, } from './SearchInput';
|
|
6
6
|
import { SearchResults } from './SearchResults';
|
|
7
7
|
const UnMemoizedChannelSearch = (props) => {
|
|
8
|
-
const { AppMenu, ClearInputIcon, ExitSearchIcon, MenuIcon, placeholder, popupResults = false, SearchBar = DefaultSearchBar, SearchEmpty, SearchInput = DefaultSearchInput,
|
|
8
|
+
const { AppMenu, ClearInputIcon, ExitSearchIcon, MenuIcon, placeholder, popupResults = false, SearchBar = DefaultSearchBar, SearchEmpty, SearchInput = DefaultSearchInput, SearchInputIcon, SearchLoading, SearchResultItem, SearchResultsHeader, SearchResultsList, ...channelSearchParams } = props;
|
|
9
9
|
const { activateSearch, clearState, exitSearch, inputIsFocused, inputRef, onSearch, query, results, searchBarRef, searching, selectResult, } = useChannelSearch(channelSearchParams);
|
|
10
|
-
return (React.createElement("div", { className: clsx('str-chat__channel-search', popupResults
|
|
10
|
+
return (React.createElement("div", { className: clsx('str-chat__channel-search', popupResults
|
|
11
|
+
? 'str-chat__channel-search--popup'
|
|
12
|
+
: 'str-chat__channel-search--inline', {
|
|
11
13
|
'str-chat__channel-search--with-results': results.length > 0,
|
|
12
14
|
}), "data-testid": 'channel-search' },
|
|
13
15
|
React.createElement(SearchBar, { activateSearch: activateSearch, AppMenu: AppMenu, ClearInputIcon: ClearInputIcon, clearState: clearState, disabled: channelSearchParams.disabled, exitSearch: exitSearch, ExitSearchIcon: ExitSearchIcon, inputIsFocused: inputIsFocused, inputRef: inputRef, MenuIcon: MenuIcon, onSearch: onSearch, placeholder: placeholder, query: query, searchBarRef: searchBarRef, SearchInput: SearchInput, SearchInputIcon: SearchInputIcon }),
|
|
@@ -40,7 +40,7 @@ const ResultsContainer = ({ children, popupResults, }) => {
|
|
|
40
40
|
return (React.createElement("div", { "aria-label": t('aria/Channel search results'), className: clsx(`str-chat__channel-search-result-list`, popupResults ? 'popup' : 'inline') }, children));
|
|
41
41
|
};
|
|
42
42
|
export const SearchResults = (props) => {
|
|
43
|
-
const { popupResults, results,
|
|
43
|
+
const { popupResults, results, SearchEmpty = DefaultSearchEmpty, searching, SearchLoading, SearchResultItem = DefaultSearchResultItem, SearchResultsHeader = DefaultSearchResultsHeader, SearchResultsList = DefaultSearchResultsList, selectResult, } = props;
|
|
44
44
|
const { t } = useTranslationContext('SearchResults');
|
|
45
45
|
const [focusedResult, setFocusedResult] = useState();
|
|
46
46
|
const handleKeyDown = useCallback((event) => {
|
|
@@ -38,8 +38,10 @@ export type ChannelSearchParams<StreamChatGenerics extends DefaultStreamChatGene
|
|
|
38
38
|
onSelectResult?: (params: ChannelSearchFunctionParams<StreamChatGenerics>, result: ChannelOrUserResponse<StreamChatGenerics>) => Promise<void> | void;
|
|
39
39
|
/** The number of milliseconds to debounce the search query. The default interval is 200ms. */
|
|
40
40
|
searchDebounceIntervalMs?: number;
|
|
41
|
-
/** Boolean to search for channels
|
|
41
|
+
/** Boolean to search for channels in the server query, default is false and just searches for users */
|
|
42
42
|
searchForChannels?: boolean;
|
|
43
|
+
/** Boolean to search for users in the server query, default is true and just searches for users */
|
|
44
|
+
searchForUsers?: boolean;
|
|
43
45
|
/** Custom search function to override the default implementation */
|
|
44
46
|
searchFunction?: (params: ChannelSearchFunctionParams<StreamChatGenerics>, event: React.BaseSyntheticEvent) => Promise<void> | void;
|
|
45
47
|
/** Object containing filters/sort/options overrides for user / channel search */
|
|
@@ -49,4 +51,4 @@ export type ChannelSearchControllerParams<StreamChatGenerics extends DefaultStre
|
|
|
49
51
|
/** Set the array of channels displayed in the ChannelList */
|
|
50
52
|
setChannels?: React.Dispatch<React.SetStateAction<Array<Channel<StreamChatGenerics>>>>;
|
|
51
53
|
};
|
|
52
|
-
export declare const useChannelSearch: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ channelType, clearSearchOnClickOutside, disabled, onSearch: onSearchCallback, onSearchExit, onSelectResult, searchDebounceIntervalMs, searchForChannels, searchFunction, searchQueryParams, setChannels, }: ChannelSearchControllerParams<StreamChatGenerics>) => SearchController<StreamChatGenerics>;
|
|
54
|
+
export declare const useChannelSearch: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ channelType, clearSearchOnClickOutside, disabled, onSearch: onSearchCallback, onSearchExit, onSelectResult, searchDebounceIntervalMs, searchForChannels, searchForUsers, searchFunction, searchQueryParams, setChannels, }: ChannelSearchControllerParams<StreamChatGenerics>) => SearchController<StreamChatGenerics>;
|
|
@@ -3,13 +3,13 @@ import debounce from 'lodash.debounce';
|
|
|
3
3
|
import uniqBy from 'lodash.uniqby';
|
|
4
4
|
import { isChannel } from '../utils';
|
|
5
5
|
import { useChatContext } from '../../../context/ChatContext';
|
|
6
|
-
export const useChannelSearch = ({ channelType = 'messaging', clearSearchOnClickOutside = true, disabled = false, onSearch: onSearchCallback, onSearchExit, onSelectResult, searchDebounceIntervalMs = 300, searchForChannels = false, searchFunction, searchQueryParams, setChannels, }) => {
|
|
6
|
+
export const useChannelSearch = ({ channelType = 'messaging', clearSearchOnClickOutside = true, disabled = false, onSearch: onSearchCallback, onSearchExit, onSelectResult, searchDebounceIntervalMs = 300, searchForChannels = false, searchForUsers = true, searchFunction, searchQueryParams, setChannels, }) => {
|
|
7
7
|
const { client, setActiveChannel } = useChatContext('useChannelSearch');
|
|
8
8
|
const [inputIsFocused, setInputIsFocused] = useState(false);
|
|
9
9
|
const [query, setQuery] = useState('');
|
|
10
10
|
const [results, setResults] = useState([]);
|
|
11
11
|
const [searching, setSearching] = useState(false);
|
|
12
|
-
const searchQueryPromiseInProgress = useRef(
|
|
12
|
+
const searchQueryPromiseInProgress = useRef(false);
|
|
13
13
|
const shouldIgnoreQueryResults = useRef(false);
|
|
14
14
|
const inputRef = useRef(null);
|
|
15
15
|
const searchBarRef = useRef(null);
|
|
@@ -17,9 +17,7 @@ export const useChannelSearch = ({ channelType = 'messaging', clearSearchOnClick
|
|
|
17
17
|
setQuery('');
|
|
18
18
|
setResults([]);
|
|
19
19
|
setSearching(false);
|
|
20
|
-
|
|
21
|
-
shouldIgnoreQueryResults.current = true;
|
|
22
|
-
}
|
|
20
|
+
shouldIgnoreQueryResults.current = searchQueryPromiseInProgress.current;
|
|
23
21
|
}, []);
|
|
24
22
|
const activateSearch = useCallback(() => {
|
|
25
23
|
setInputIsFocused(true);
|
|
@@ -45,7 +43,6 @@ export const useChannelSearch = ({ channelType = 'messaging', clearSearchOnClick
|
|
|
45
43
|
};
|
|
46
44
|
document.addEventListener('click', clickListener);
|
|
47
45
|
return () => document.removeEventListener('click', clickListener);
|
|
48
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
46
|
}, [disabled, inputIsFocused, query, exitSearch, clearSearchOnClickOutside]);
|
|
50
47
|
useEffect(() => {
|
|
51
48
|
if (!inputRef.current || disabled)
|
|
@@ -78,7 +75,9 @@ export const useChannelSearch = ({ channelType = 'messaging', clearSearchOnClick
|
|
|
78
75
|
selectedChannel = result;
|
|
79
76
|
}
|
|
80
77
|
else {
|
|
81
|
-
const newChannel = client.channel(channelType, {
|
|
78
|
+
const newChannel = client.channel(channelType, {
|
|
79
|
+
members: [client.userID, result.id],
|
|
80
|
+
});
|
|
82
81
|
await newChannel.watch();
|
|
83
82
|
setActiveChannel(newChannel);
|
|
84
83
|
selectedChannel = newChannel;
|
|
@@ -89,34 +88,52 @@ export const useChannelSearch = ({ channelType = 'messaging', clearSearchOnClick
|
|
|
89
88
|
}
|
|
90
89
|
},
|
|
91
90
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
|
-
[
|
|
91
|
+
[
|
|
92
|
+
clearSearchOnClickOutside,
|
|
93
|
+
client,
|
|
94
|
+
exitSearch,
|
|
95
|
+
onSelectResult,
|
|
96
|
+
setActiveChannel,
|
|
97
|
+
setChannels,
|
|
98
|
+
]);
|
|
93
99
|
const getChannels = useCallback(async (text) => {
|
|
100
|
+
if (!searchForChannels && !searchForUsers)
|
|
101
|
+
return;
|
|
94
102
|
let results = [];
|
|
103
|
+
const promises = [];
|
|
95
104
|
try {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
$or: [{ id: { $autocomplete: text } }, { name: { $autocomplete: text } }],
|
|
100
|
-
...searchQueryParams?.userFilters?.filters,
|
|
101
|
-
}, { id: 1, ...searchQueryParams?.userFilters?.sort }, { limit: 8, ...searchQueryParams?.userFilters?.options });
|
|
102
|
-
if (!searchForChannels) {
|
|
103
|
-
searchQueryPromiseInProgress.current = userQueryPromise;
|
|
104
|
-
const { users } = await searchQueryPromiseInProgress.current;
|
|
105
|
-
results = users.filter((u) => u.id !== client.user?.id);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
const channelQueryPromise = client.queryChannels(
|
|
109
|
-
// @ts-expect-error
|
|
105
|
+
if (searchForChannels) {
|
|
106
|
+
promises.push(client.queryChannels(
|
|
107
|
+
// @ts-expect-error valid query
|
|
110
108
|
{
|
|
109
|
+
members: { $in: [client.userID] },
|
|
111
110
|
name: { $autocomplete: text },
|
|
112
111
|
...searchQueryParams?.channelFilters?.filters,
|
|
113
|
-
}, searchQueryParams?.channelFilters?.sort || {}, { limit: 5, ...searchQueryParams?.channelFilters?.options });
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
}, searchQueryParams?.channelFilters?.sort || {}, { limit: 5, ...searchQueryParams?.channelFilters?.options }));
|
|
113
|
+
}
|
|
114
|
+
if (searchForUsers) {
|
|
115
|
+
promises.push(client.queryUsers(
|
|
116
|
+
// @ts-expect-error valid query
|
|
117
|
+
{
|
|
118
|
+
$or: [{ id: { $autocomplete: text } }, { name: { $autocomplete: text } }],
|
|
119
|
+
...searchQueryParams?.userFilters?.filters,
|
|
120
|
+
}, { id: 1, ...searchQueryParams?.userFilters?.sort }, { limit: 8, ...searchQueryParams?.userFilters?.options }));
|
|
121
|
+
}
|
|
122
|
+
if (promises.length) {
|
|
123
|
+
searchQueryPromiseInProgress.current = true;
|
|
124
|
+
const resolved = await Promise.all(promises);
|
|
125
|
+
if (searchForChannels && searchForUsers) {
|
|
126
|
+
const [channels, { users }] = resolved;
|
|
127
|
+
results = [...channels, ...users.filter((u) => u.id !== client.user?.id)];
|
|
128
|
+
}
|
|
129
|
+
else if (searchForChannels) {
|
|
130
|
+
const [channels] = resolved;
|
|
131
|
+
results = [...channels];
|
|
132
|
+
}
|
|
133
|
+
else if (searchForUsers) {
|
|
134
|
+
const [{ users }] = resolved;
|
|
135
|
+
results = [...users.filter((u) => u.id !== client.user?.id)];
|
|
136
|
+
}
|
|
120
137
|
}
|
|
121
138
|
}
|
|
122
139
|
catch (error) {
|
|
@@ -129,13 +146,10 @@ export const useChannelSearch = ({ channelType = 'messaging', clearSearchOnClick
|
|
|
129
146
|
else {
|
|
130
147
|
shouldIgnoreQueryResults.current = false;
|
|
131
148
|
}
|
|
132
|
-
searchQueryPromiseInProgress.current =
|
|
133
|
-
}, [client, searchForChannels, searchQueryParams]);
|
|
149
|
+
searchQueryPromiseInProgress.current = false;
|
|
150
|
+
}, [client, searchForChannels, searchForUsers, searchQueryParams]);
|
|
134
151
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
135
|
-
const scheduleGetChannels = useCallback(debounce(getChannels, searchDebounceIntervalMs), [
|
|
136
|
-
getChannels,
|
|
137
|
-
searchDebounceIntervalMs,
|
|
138
|
-
]);
|
|
152
|
+
const scheduleGetChannels = useCallback(debounce(getChannels, searchDebounceIntervalMs), [getChannels, searchDebounceIntervalMs]);
|
|
139
153
|
const onSearch = useCallback((event) => {
|
|
140
154
|
event.preventDefault();
|
|
141
155
|
if (disabled)
|
|
@@ -147,6 +161,9 @@ export const useChannelSearch = ({ channelType = 'messaging', clearSearchOnClick
|
|
|
147
161
|
setSearching,
|
|
148
162
|
}, event);
|
|
149
163
|
}
|
|
164
|
+
else if (!searchForChannels && !searchForUsers) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
150
167
|
else if (event.target.value) {
|
|
151
168
|
setSearching(true);
|
|
152
169
|
setQuery(event.target.value);
|
|
@@ -157,7 +174,15 @@ export const useChannelSearch = ({ channelType = 'messaging', clearSearchOnClick
|
|
|
157
174
|
scheduleGetChannels.cancel();
|
|
158
175
|
}
|
|
159
176
|
onSearchCallback?.(event);
|
|
160
|
-
}, [
|
|
177
|
+
}, [
|
|
178
|
+
clearState,
|
|
179
|
+
disabled,
|
|
180
|
+
scheduleGetChannels,
|
|
181
|
+
onSearchCallback,
|
|
182
|
+
searchForChannels,
|
|
183
|
+
searchForUsers,
|
|
184
|
+
searchFunction,
|
|
185
|
+
]);
|
|
161
186
|
return {
|
|
162
187
|
activateSearch,
|
|
163
188
|
clearState,
|
|
@@ -3,4 +3,4 @@ export * from './SearchBar';
|
|
|
3
3
|
export * from './SearchInput';
|
|
4
4
|
export * from './SearchResults';
|
|
5
5
|
export * from './utils';
|
|
6
|
-
export type { ChannelSearchFunctionParams, ChannelSearchParams } from './hooks/useChannelSearch';
|
|
6
|
+
export type { ChannelSearchFunctionParams, ChannelSearchParams, } from './hooks/useChannelSearch';
|
|
@@ -28,7 +28,7 @@ export const useChat = ({ client, defaultLanguage = 'en', i18nInstance, initialN
|
|
|
28
28
|
if (!userAgent.includes('stream-chat-react')) {
|
|
29
29
|
// result looks like: 'stream-chat-react-2.3.2-stream-chat-javascript-client-browser-2.2.2'
|
|
30
30
|
// the upper-case text between double underscores is replaced with the actual semantic version of the library
|
|
31
|
-
client.setUserAgent(`stream-chat-react-12.
|
|
31
|
+
client.setUserAgent(`stream-chat-react-12.11.1-${userAgent}`);
|
|
32
32
|
}
|
|
33
33
|
client.threads.registerSubscriptions();
|
|
34
34
|
client.polls.registerSubscriptions();
|
|
@@ -50,7 +50,9 @@ export const useChat = ({ client, defaultLanguage = 'en', i18nInstance, initialN
|
|
|
50
50
|
let userLanguage = client.user?.language;
|
|
51
51
|
if (!userLanguage) {
|
|
52
52
|
const browserLanguage = window.navigator.language.slice(0, 2); // just get language code, not country-specific version
|
|
53
|
-
userLanguage = isLanguageSupported(browserLanguage)
|
|
53
|
+
userLanguage = isLanguageSupported(browserLanguage)
|
|
54
|
+
? browserLanguage
|
|
55
|
+
: defaultLanguage;
|
|
54
56
|
}
|
|
55
57
|
const streami18n = i18nInstance || new Streami18n({ language: userLanguage });
|
|
56
58
|
streami18n.registerSetLanguageCallback((t) => setTranslators((prevTranslator) => ({ ...prevTranslator, t })));
|
|
@@ -13,7 +13,9 @@ export const useCreateChatClient = ({ apiKey, options, tokenOrProvider, userData
|
|
|
13
13
|
useEffect(() => {
|
|
14
14
|
const client = new StreamChat(apiKey, undefined, cachedOptions);
|
|
15
15
|
let didUserConnectInterrupt = false;
|
|
16
|
-
const connectionPromise = client
|
|
16
|
+
const connectionPromise = client
|
|
17
|
+
.connectUser(cachedUserData, tokenOrProvider)
|
|
18
|
+
.then(() => {
|
|
17
19
|
if (!didUserConnectInterrupt)
|
|
18
20
|
setChatClient(client);
|
|
19
21
|
});
|
|
@@ -8,7 +8,7 @@ const UnMemoizedChatAutoComplete = (props) => {
|
|
|
8
8
|
const { AutocompleteSuggestionItem: SuggestionItem, AutocompleteSuggestionList: SuggestionList, } = useComponentContext('ChatAutoComplete');
|
|
9
9
|
const { t } = useTranslationContext('ChatAutoComplete');
|
|
10
10
|
const messageInput = useMessageInputContext('ChatAutoComplete');
|
|
11
|
-
const { cooldownRemaining, disabled, emojiSearchIndex, textareaRef: innerRef } = messageInput;
|
|
11
|
+
const { cooldownRemaining, disabled, emojiSearchIndex, textareaRef: innerRef, } = messageInput;
|
|
12
12
|
const placeholder = props.placeholder || t('Type your message');
|
|
13
13
|
const emojiReplace = props.wordReplace
|
|
14
14
|
? (word) => props.wordReplace?.(word, emojiSearchIndex)
|
|
@@ -5,7 +5,6 @@ import { UnreadCountBadge } from '../Threads/UnreadCountBadge';
|
|
|
5
5
|
import { useChatContext } from '../../context';
|
|
6
6
|
import { useStateStore } from '../../store';
|
|
7
7
|
import clsx from 'clsx';
|
|
8
|
-
const availableChatViews = ['channels', 'threads'];
|
|
9
8
|
const ChatViewContext = createContext({
|
|
10
9
|
activeChatView: 'channels',
|
|
11
10
|
setActiveChatView: () => undefined,
|
|
@@ -5,4 +5,4 @@ export type ConfirmationDialogProps = {
|
|
|
5
5
|
className?: string;
|
|
6
6
|
title?: string;
|
|
7
7
|
};
|
|
8
|
-
export declare const PromptDialog: ({ actions, className, prompt, title }: ConfirmationDialogProps) => React.JSX.Element;
|
|
8
|
+
export declare const PromptDialog: ({ actions, className, prompt, title, }: ConfirmationDialogProps) => React.JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
export const PromptDialog = ({ actions, className, prompt, title }) => (React.createElement("div", { className: clsx('str-chat__dialog str-chat__dialog--prompt', className) },
|
|
3
|
+
export const PromptDialog = ({ actions, className, prompt, title, }) => (React.createElement("div", { className: clsx('str-chat__dialog str-chat__dialog--prompt', className) },
|
|
4
4
|
React.createElement("div", { className: 'str-chat__dialog__body' },
|
|
5
5
|
title && React.createElement("div", { className: 'str-chat__dialog__title' }, title),
|
|
6
6
|
React.createElement("div", { className: 'str-chat__dialog__prompt' }, prompt)),
|
|
@@ -6,7 +6,7 @@ import { getDateString } from '../../i18n/utils';
|
|
|
6
6
|
* Component to display system and channel event messages
|
|
7
7
|
*/
|
|
8
8
|
const UnMemoizedEventComponent = (props) => {
|
|
9
|
-
const { calendar, calendarFormats, format,
|
|
9
|
+
const { Avatar = DefaultAvatar, calendar, calendarFormats, format, message } = props;
|
|
10
10
|
const { t, tDateTimeParser } = useTranslationContext('EventComponent');
|
|
11
11
|
const { created_at = '', event, text, type } = message;
|
|
12
12
|
const getDateOptions = { messageCreatedAt: created_at.toString(), tDateTimeParser };
|
|
@@ -8,7 +8,7 @@ import { useComponentContext } from '../../context';
|
|
|
8
8
|
* A simple component that displays an image.
|
|
9
9
|
*/
|
|
10
10
|
export const ImageComponent = (props) => {
|
|
11
|
-
const { dimensions = {}, fallback, image_url,
|
|
11
|
+
const { dimensions = {}, fallback, image_url, innerRef, previewUrl, style, thumb_url, } = props;
|
|
12
12
|
const [modalIsOpen, setModalIsOpen] = useState(false);
|
|
13
13
|
const { BaseImage = DefaultBaseImage, ModalGallery = DefaultModalGallery } = useComponentContext('ImageComponent');
|
|
14
14
|
const imageSrc = sanitizeUrl(previewUrl || image_url || thumb_url);
|
|
@@ -20,7 +20,6 @@ export const ModalGallery = (props) => {
|
|
|
20
20
|
};
|
|
21
21
|
}), [images, t]);
|
|
22
22
|
return (
|
|
23
|
-
// ignore the TS error as react-image-gallery was on @types/react@18 while stream-chat-react being upgraded to React 19 (https://github.com/xiaolin/react-image-gallery/issues/809)
|
|
24
|
-
// @ts-expect-error
|
|
23
|
+
// @ts-expect-error ignore the TS error as react-image-gallery was on @types/react@18 while stream-chat-react being upgraded to React 19 (https://github.com/xiaolin/react-image-gallery/issues/809)
|
|
25
24
|
React.createElement(ImageGallery, { items: formattedArray, renderItem: renderItem, showIndex: true, showPlayButton: false, showThumbnails: false, startIndex: index }));
|
|
26
25
|
};
|
|
@@ -44,7 +44,8 @@ export const InfiniteScroll = (props) => {
|
|
|
44
44
|
}
|
|
45
45
|
if (isLoading)
|
|
46
46
|
return;
|
|
47
|
-
if (previousOffset.current === offset &&
|
|
47
|
+
if (previousOffset.current === offset &&
|
|
48
|
+
previousReverseOffset.current === reverseOffset)
|
|
48
49
|
return;
|
|
49
50
|
previousOffset.current = offset;
|
|
50
51
|
previousReverseOffset.current = reverseOffset;
|
|
@@ -54,7 +55,9 @@ export const InfiniteScroll = (props) => {
|
|
|
54
55
|
hasPreviousPageFlag) {
|
|
55
56
|
loadPreviousPageFn();
|
|
56
57
|
}
|
|
57
|
-
if (offset < Number(threshold) &&
|
|
58
|
+
if (offset < Number(threshold) &&
|
|
59
|
+
typeof loadNextPageFn === 'function' &&
|
|
60
|
+
hasNextPageFlag) {
|
|
58
61
|
loadNextPageFn();
|
|
59
62
|
}
|
|
60
63
|
};
|
|
@@ -12,7 +12,7 @@ const mousewheelListener = (event) => {
|
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
export const InfiniteScrollPaginator = (props) => {
|
|
15
|
-
const { children, listenToScroll, loadNextOnScrollToBottom, loadNextOnScrollToTop, threshold = DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, useCapture = false,
|
|
15
|
+
const { children, className, listenToScroll, loadNextOnScrollToBottom, loadNextOnScrollToTop, threshold = DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, useCapture = false, ...componentProps } = props;
|
|
16
16
|
const rootRef = useRef(null);
|
|
17
17
|
const childRef = useRef(null);
|
|
18
18
|
const scrollListener = useMemo(() => debounce(() => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect } from 'react';
|
|
2
|
-
import { LoadMoreButton as DefaultLoadMoreButton } from './LoadMoreButton';
|
|
2
|
+
import { LoadMoreButton as DefaultLoadMoreButton, } from './LoadMoreButton';
|
|
3
3
|
import { deprecationAndReplacementWarning } from '../../utils/deprecationWarning';
|
|
4
4
|
export const UnMemoizedLoadMorePaginator = (props) => {
|
|
5
5
|
const { children, hasNextPage, isLoading, LoadMoreButton = DefaultLoadMoreButton, loadNextPage, refreshing, reverse, } = props;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { Suspense } from 'react';
|
|
2
2
|
import { useChatContext } from '../../context/ChatContext';
|
|
3
3
|
const MMLReact = React.lazy(async () => {
|
|
4
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
4
5
|
const mml = await import('mml-react');
|
|
5
6
|
return { default: mml.MML };
|
|
6
7
|
});
|