stream-chat-react 12.9.0 → 12.11.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/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/components/WaveProgressBar.js +1 -1
- package/dist/components/Attachment/hooks/useAudioController.d.ts +1 -1
- package/dist/components/Attachment/hooks/useAudioController.js +4 -2
- 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 -7
- package/dist/components/AutoCompleteTextarea/utils.js +3 -7
- package/dist/components/Avatar/ChannelAvatar.js +1 -1
- package/dist/components/Channel/Channel.d.ts +1 -1
- package/dist/components/Channel/Channel.js +30 -14
- package/dist/components/Channel/channelState.d.ts +1 -3
- package/dist/components/Channel/channelState.js +10 -4
- package/dist/components/Channel/hooks/useCreateChannelStateContext.js +5 -3
- package/dist/components/Channel/hooks/useIsMounted.d.ts +1 -1
- 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 +46 -19
- package/dist/components/ChannelList/hooks/useChannelUpdatedListener.js +2 -1
- package/dist/components/ChannelList/hooks/useMessageNewListener.js +3 -1
- package/dist/components/ChannelList/hooks/useMobileNavigation.d.ts +1 -1
- package/dist/components/ChannelList/hooks/usePaginatedChannels.js +5 -3
- 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/SearchBar.d.ts +1 -1
- package/dist/components/ChannelSearch/SearchInput.d.ts +1 -1
- 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/BaseImage.d.ts +1 -3
- package/dist/components/Gallery/Gallery.js +10 -2
- package/dist/components/Gallery/Image.js +1 -1
- package/dist/components/Gallery/ModalGallery.js +4 -4
- package/dist/components/InfiniteScrollPaginator/InfiniteScroll.js +9 -6
- 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/MessageActions/hooks/useMessageActionsBoxPopper.d.ts +1 -1
- 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.d.ts +1 -1
- package/dist/components/MessageInput/hooks/useMessageInputText.js +5 -3
- package/dist/components/MessageInput/hooks/useSubmitHandler.js +5 -3
- package/dist/components/MessageInput/hooks/useTimeElapsed.js +1 -1
- 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 -6
- package/dist/components/MessageList/MessageListNotifications.js +3 -1
- package/dist/components/MessageList/VirtualizedMessageList.d.ts +1 -1
- package/dist/components/MessageList/VirtualizedMessageList.js +19 -12
- 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 +3 -2
- 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/useMessageSetKey.js +1 -1
- package/dist/components/MessageList/hooks/VirtualizedMessageList/useNewMessageNotification.d.ts +1 -1
- package/dist/components/MessageList/hooks/VirtualizedMessageList/usePrependMessagesCount.js +4 -3
- package/dist/components/MessageList/hooks/VirtualizedMessageList/useScrollToBottomOnNewMessage.js +1 -1
- package/dist/components/MessageList/hooks/VirtualizedMessageList/useUnreadMessagesNotificationVirtualized.js +7 -3
- package/dist/components/MessageList/hooks/useMarkRead.d.ts +2 -4
- package/dist/components/MessageList/hooks/useMarkRead.js +14 -16
- 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/VirtualizedMessageListContext.d.ts +13 -0
- package/dist/context/VirtualizedMessageListContext.js +7 -0
- 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 +2329 -1145
- package/dist/index.browser.cjs.map +4 -4
- package/dist/index.node.cjs +2594 -1164
- 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 +32 -47
|
@@ -3,10 +3,10 @@ import clsx from 'clsx';
|
|
|
3
3
|
import { ChannelListMessenger } from './ChannelListMessenger';
|
|
4
4
|
import { useConnectionRecoveredListener } from './hooks/useConnectionRecoveredListener';
|
|
5
5
|
import { useMobileNavigation } from './hooks/useMobileNavigation';
|
|
6
|
-
import { usePaginatedChannels } from './hooks/usePaginatedChannels';
|
|
6
|
+
import { usePaginatedChannels, } from './hooks/usePaginatedChannels';
|
|
7
7
|
import { MAX_QUERY_CHANNELS_LIMIT, moveChannelUpwards } from './utils';
|
|
8
8
|
import { Avatar as DefaultAvatar } from '../Avatar';
|
|
9
|
-
import { ChannelPreview } from '../ChannelPreview/ChannelPreview';
|
|
9
|
+
import { ChannelPreview, } from '../ChannelPreview/ChannelPreview';
|
|
10
10
|
import { ChannelSearch as DefaultChannelSearch, } from '../ChannelSearch/ChannelSearch';
|
|
11
11
|
import { EmptyStateIndicator as DefaultEmptyStateIndicator, } from '../EmptyStateIndicator';
|
|
12
12
|
import { LoadingChannels } from '../Loading/LoadingChannels';
|
|
@@ -14,12 +14,12 @@ import { LoadMorePaginator } from '../LoadMore/LoadMorePaginator';
|
|
|
14
14
|
import { NullComponent } from '../UtilityComponents';
|
|
15
15
|
import { ChannelListContextProvider } from '../../context';
|
|
16
16
|
import { useChatContext } from '../../context/ChatContext';
|
|
17
|
-
import { useChannelListShape, usePrepareShapeHandlers } from './hooks/useChannelListShape';
|
|
17
|
+
import { useChannelListShape, usePrepareShapeHandlers, } from './hooks/useChannelListShape';
|
|
18
18
|
const DEFAULT_FILTERS = {};
|
|
19
19
|
const DEFAULT_OPTIONS = {};
|
|
20
20
|
const DEFAULT_SORT = {};
|
|
21
21
|
const UnMemoizedChannelList = (props) => {
|
|
22
|
-
const { additionalChannelSearchProps,
|
|
22
|
+
const { additionalChannelSearchProps, allowNewMessagesFromUnfilteredChannels = true, Avatar = DefaultAvatar, channelRenderFilterFn, ChannelSearch = DefaultChannelSearch, customActiveChannel, customQueryChannels, EmptyStateIndicator = DefaultEmptyStateIndicator, filters = {}, getLatestMessagePreview, List = ChannelListMessenger, LoadingErrorIndicator = NullComponent, LoadingIndicator = LoadingChannels, lockChannelOrder = false, onAddedToChannel, onChannelDeleted, onChannelHidden, onChannelTruncated, onChannelUpdated, onChannelVisible, onMessageNew, onMessageNewHandler, onRemovedFromChannel, options, Paginator = LoadMorePaginator, Preview, recoveryThrottleIntervalMs, renderChannels, sendChannelsToList = false, setActiveChannelOnMount = true, showChannelSearch = false, sort = DEFAULT_SORT, watchers = {}, } = props;
|
|
23
23
|
const { channel, channelsQueryState, client, closeMobileNav, customClasses, navOpen = false, setActiveChannel, theme, useImageFlagEmojisOnWindows, } = useChatContext('ChannelList');
|
|
24
24
|
const channelListRef = useRef(null);
|
|
25
25
|
const [channelUpdateCount, setChannelUpdateCount] = useState(0);
|
|
@@ -29,15 +29,18 @@ const UnMemoizedChannelList = (props) => {
|
|
|
29
29
|
* If customActiveChannel prop is absent, then set the first channel in list as active channel.
|
|
30
30
|
*/
|
|
31
31
|
const activeChannelHandler = async (channels, setChannels) => {
|
|
32
|
-
if (!channels.length ||
|
|
32
|
+
if (!channels.length ||
|
|
33
|
+
channels.length > (options?.limit || MAX_QUERY_CHANNELS_LIMIT)) {
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
if (customActiveChannel) {
|
|
36
37
|
// FIXME: this is wrong...
|
|
37
38
|
let customActiveChannelObject = channels.find((chan) => chan.id === customActiveChannel);
|
|
38
39
|
if (!customActiveChannelObject) {
|
|
39
|
-
//@ts-expect-error
|
|
40
|
-
[customActiveChannelObject] = await client.queryChannels({
|
|
40
|
+
//@ts-expect-error valid query
|
|
41
|
+
[customActiveChannelObject] = await client.queryChannels({
|
|
42
|
+
id: customActiveChannel,
|
|
43
|
+
});
|
|
41
44
|
}
|
|
42
45
|
if (customActiveChannelObject) {
|
|
43
46
|
setActiveChannel(customActiveChannelObject, watchers);
|
|
@@ -70,7 +73,9 @@ const UnMemoizedChannelList = (props) => {
|
|
|
70
73
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
71
74
|
}, []);
|
|
72
75
|
const { channels, hasNextPage, loadNextPage, setChannels } = usePaginatedChannels(client, filters || DEFAULT_FILTERS, sort || DEFAULT_SORT, options || DEFAULT_OPTIONS, activeChannelHandler, recoveryThrottleIntervalMs, customQueryChannels);
|
|
73
|
-
const loadedChannels = channelRenderFilterFn
|
|
76
|
+
const loadedChannels = channelRenderFilterFn
|
|
77
|
+
? channelRenderFilterFn(channels)
|
|
78
|
+
: channels;
|
|
74
79
|
useMobileNavigation(channelListRef, navOpen, closeMobileNav);
|
|
75
80
|
const { customHandler, defaultHandler } = usePrepareShapeHandlers({
|
|
76
81
|
allowNewMessagesFromUnfilteredChannels,
|
|
@@ -27,7 +27,7 @@ type HandleMemberUpdatedParameters<SCG extends ExtendableGenerics> = BaseParamet
|
|
|
27
27
|
} & Required<Pick<ChannelListProps<SCG>, 'sort' | 'filters'>>;
|
|
28
28
|
type HandleChannelDeletedParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> & RepeatedParameters<SCG>;
|
|
29
29
|
type HandleChannelHiddenParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> & RepeatedParameters<SCG>;
|
|
30
|
-
type HandleChannelVisibleParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> & RepeatedParameters<SCG
|
|
30
|
+
type HandleChannelVisibleParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> & RepeatedParameters<SCG> & Required<Pick<ChannelListProps<SCG>, 'sort' | 'filters'>>;
|
|
31
31
|
type HandleChannelTruncatedParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> & RepeatedParameters<SCG>;
|
|
32
32
|
type HandleChannelUpdatedParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG> & RepeatedParameters<SCG>;
|
|
33
33
|
type HandleUserPresenceChangedParameters<SCG extends ExtendableGenerics> = BaseParameters<SCG>;
|
|
@@ -36,7 +36,7 @@ export declare const useChannelListShapeDefaults: <SCG extends ExtendableGeneric
|
|
|
36
36
|
handleChannelHidden: (p: HandleChannelHiddenParameters<SCG>) => void;
|
|
37
37
|
handleChannelTruncated: ({ customHandler, event, setChannels }: HandleChannelTruncatedParameters<SCG>) => void;
|
|
38
38
|
handleChannelUpdated: ({ customHandler, event, setChannels }: HandleChannelUpdatedParameters<SCG>) => void;
|
|
39
|
-
handleChannelVisible: ({ customHandler, event, setChannels }: HandleChannelVisibleParameters<SCG>) => Promise<void>;
|
|
39
|
+
handleChannelVisible: ({ customHandler, event, filters, setChannels, sort, }: HandleChannelVisibleParameters<SCG>) => Promise<void>;
|
|
40
40
|
handleMemberUpdated: ({ event, filters, lockChannelOrder, setChannels, sort, }: HandleMemberUpdatedParameters<SCG>) => void;
|
|
41
41
|
handleMessageNew: ({ allowNewMessagesFromUnfilteredChannels, customHandler, event, filters, lockChannelOrder, setChannels, sort, }: HandleMessageNewParameters<SCG>) => void;
|
|
42
42
|
handleNotificationAddedToChannel: ({ allowNewMessagesFromUnfilteredChannels, customHandler, event, setChannels, sort, }: HandleNotificationAddedToChannelParameters<SCG>) => Promise<void>;
|
|
@@ -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,7 +111,9 @@ 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;
|
|
@@ -159,18 +158,27 @@ export const useChannelListShapeDefaults = () => {
|
|
|
159
158
|
}, [client]);
|
|
160
159
|
const handleChannelDeleted = useCallback((p) => shared(p), []);
|
|
161
160
|
const handleChannelHidden = useCallback((p) => shared(p), []);
|
|
162
|
-
const handleChannelVisible = useCallback(async ({ customHandler, event, setChannels }) => {
|
|
161
|
+
const handleChannelVisible = useCallback(async ({ customHandler, event, filters, setChannels, sort, }) => {
|
|
163
162
|
if (typeof customHandler === 'function') {
|
|
164
163
|
return customHandler(setChannels, event);
|
|
165
164
|
}
|
|
166
|
-
if (event.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
165
|
+
if (!event.channel) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const channel = await getChannel({
|
|
169
|
+
client,
|
|
170
|
+
id: event.channel.id,
|
|
171
|
+
type: event.channel.type,
|
|
172
|
+
});
|
|
173
|
+
const considerArchivedChannels = shouldConsiderArchivedChannels(filters);
|
|
174
|
+
if (isChannelArchived(channel) && considerArchivedChannels && !filters.archived) {
|
|
175
|
+
return;
|
|
173
176
|
}
|
|
177
|
+
setChannels((channels) => moveChannelUpwards({
|
|
178
|
+
channels,
|
|
179
|
+
channelToMove: channel,
|
|
180
|
+
sort,
|
|
181
|
+
}));
|
|
174
182
|
}, [client]);
|
|
175
183
|
const handleChannelTruncated = useCallback(({ customHandler, event, setChannels }) => {
|
|
176
184
|
if (typeof customHandler === 'function') {
|
|
@@ -193,7 +201,8 @@ export const useChannelListShapeDefaults = () => {
|
|
|
193
201
|
newChannels[channelIndex].data = {
|
|
194
202
|
...event.channel,
|
|
195
203
|
hidden: event.channel?.hidden ?? newChannels[channelIndex].data?.hidden,
|
|
196
|
-
own_capabilities: event.channel?.own_capabilities ??
|
|
204
|
+
own_capabilities: event.channel?.own_capabilities ??
|
|
205
|
+
newChannels[channelIndex].data?.own_capabilities,
|
|
197
206
|
};
|
|
198
207
|
return [...newChannels];
|
|
199
208
|
}
|
|
@@ -245,8 +254,8 @@ export const useChannelListShapeDefaults = () => {
|
|
|
245
254
|
};
|
|
246
255
|
export const usePrepareShapeHandlers = ({ allowNewMessagesFromUnfilteredChannels, customHandleChannelListShape, filters, lockChannelOrder, onAddedToChannel, onChannelDeleted, onChannelHidden, onChannelTruncated, onChannelUpdated, onChannelVisible, onMessageNew, onMessageNewHandler, onRemovedFromChannel, setChannels, sort, }) => {
|
|
247
256
|
const defaults = useChannelListShapeDefaults();
|
|
248
|
-
const defaultHandleChannelListShapeRef = useRef();
|
|
249
|
-
const customHandleChannelListShapeRef = useRef();
|
|
257
|
+
const defaultHandleChannelListShapeRef = useRef(undefined);
|
|
258
|
+
const customHandleChannelListShapeRef = useRef(undefined);
|
|
250
259
|
customHandleChannelListShapeRef.current = (event) => {
|
|
251
260
|
// @ts-expect-error can't use ReturnType<typeof useChannelListShapeDefaults<SCG>> until we upgrade prettier to at least v2.7.0
|
|
252
261
|
customHandleChannelListShape?.({ defaults, event, setChannels });
|
|
@@ -300,16 +309,34 @@ export const usePrepareShapeHandlers = ({ allowNewMessagesFromUnfilteredChannels
|
|
|
300
309
|
});
|
|
301
310
|
break;
|
|
302
311
|
case 'channel.hidden':
|
|
303
|
-
defaults.handleChannelHidden({
|
|
312
|
+
defaults.handleChannelHidden({
|
|
313
|
+
customHandler: onChannelHidden,
|
|
314
|
+
event,
|
|
315
|
+
setChannels,
|
|
316
|
+
});
|
|
304
317
|
break;
|
|
305
318
|
case 'channel.visible':
|
|
306
|
-
defaults.handleChannelVisible({
|
|
319
|
+
defaults.handleChannelVisible({
|
|
320
|
+
customHandler: onChannelVisible,
|
|
321
|
+
event,
|
|
322
|
+
filters,
|
|
323
|
+
setChannels,
|
|
324
|
+
sort,
|
|
325
|
+
});
|
|
307
326
|
break;
|
|
308
327
|
case 'channel.truncated':
|
|
309
|
-
defaults.handleChannelTruncated({
|
|
328
|
+
defaults.handleChannelTruncated({
|
|
329
|
+
customHandler: onChannelTruncated,
|
|
330
|
+
event,
|
|
331
|
+
setChannels,
|
|
332
|
+
});
|
|
310
333
|
break;
|
|
311
334
|
case 'channel.updated':
|
|
312
|
-
defaults.handleChannelUpdated({
|
|
335
|
+
defaults.handleChannelUpdated({
|
|
336
|
+
customHandler: onChannelUpdated,
|
|
337
|
+
event,
|
|
338
|
+
setChannels,
|
|
339
|
+
});
|
|
313
340
|
break;
|
|
314
341
|
case 'user.presence.changed':
|
|
315
342
|
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
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const useMobileNavigation: (channelListRef: React.RefObject<HTMLDivElement>, navOpen: boolean, closeMobileNav?: () => void) => void;
|
|
1
|
+
export declare const useMobileNavigation: (channelListRef: React.RefObject<HTMLDivElement | null>, navOpen: boolean, closeMobileNav?: () => void) => void;
|
|
@@ -9,10 +9,10 @@ export const usePaginatedChannels = (client, filters, sort, options, activeChann
|
|
|
9
9
|
const { channelsQueryState: { error, setError, setQueryInProgress }, } = useChatContext('usePaginatedChannels');
|
|
10
10
|
const [channels, setChannels] = useState([]);
|
|
11
11
|
const [hasNextPage, setHasNextPage] = useState(true);
|
|
12
|
-
const lastRecoveryTimestamp = useRef();
|
|
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 }),
|
|
@@ -11,7 +11,7 @@ export type SearchBarController = {
|
|
|
11
11
|
/** Flag determining whether the search input is focused */
|
|
12
12
|
inputIsFocused: boolean;
|
|
13
13
|
/** Ref object for the input wrapper in the SearchBar */
|
|
14
|
-
searchBarRef: React.RefObject<HTMLDivElement>;
|
|
14
|
+
searchBarRef: React.RefObject<HTMLDivElement | null>;
|
|
15
15
|
};
|
|
16
16
|
export type AdditionalSearchBarProps = {
|
|
17
17
|
/** Application menu to be displayed when clicked on MenuIcon */
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
export type SearchInputController = {
|
|
3
3
|
/** Clears the channel search state */
|
|
4
4
|
clearState: () => void;
|
|
5
|
-
inputRef: React.RefObject<HTMLInputElement>;
|
|
5
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
6
6
|
/** Search input change handler */
|
|
7
7
|
onSearch: React.ChangeEventHandler<HTMLInputElement>;
|
|
8
8
|
/** Current search string */
|
|
@@ -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.0-${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,
|