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
|
@@ -6,7 +6,7 @@ import { FieldError } from '../../Form/FieldError';
|
|
|
6
6
|
import { DragAndDropContainer } from '../../DragAndDrop/DragAndDropContainer';
|
|
7
7
|
import { useTranslationContext } from '../../../context';
|
|
8
8
|
const VALIDATION_ERRORS = { 'Option already exists': true };
|
|
9
|
-
export const OptionFieldSet = ({ errors, options, setErrors, setState }) => {
|
|
9
|
+
export const OptionFieldSet = ({ errors, options, setErrors, setState, }) => {
|
|
10
10
|
const { t } = useTranslationContext('OptionFieldSet');
|
|
11
11
|
const findOptionDuplicate = (sourceOption) => {
|
|
12
12
|
const isDuplicateFilter = (option) => !!sourceOption.text.trim() && // do not include empty options into consideration
|
|
@@ -15,7 +15,10 @@ export const OptionFieldSet = ({ errors, options, setErrors, setState }) => {
|
|
|
15
15
|
return options.find(isDuplicateFilter);
|
|
16
16
|
};
|
|
17
17
|
const onSetNewOrder = useCallback((newOrder) => {
|
|
18
|
-
setState((prev) => ({
|
|
18
|
+
setState((prev) => ({
|
|
19
|
+
...prev,
|
|
20
|
+
options: newOrder.map((index) => prev.options[index]),
|
|
21
|
+
}));
|
|
19
22
|
}, [setState]);
|
|
20
23
|
const draggable = options.length > 1;
|
|
21
24
|
return (React.createElement("fieldset", { className: 'str-chat__form__field str-chat__form__input-fieldset' },
|
|
@@ -38,7 +41,9 @@ export const OptionFieldSet = ({ errors, options, setErrors, setState }) => {
|
|
|
38
41
|
const shouldAddEmptyOption = prev.options.length < MAX_POLL_OPTIONS &&
|
|
39
42
|
(!prev.options ||
|
|
40
43
|
(prev.options.slice(i + 1).length === 0 && !!e.target.value));
|
|
41
|
-
const shouldRemoveOption = prev.options &&
|
|
44
|
+
const shouldRemoveOption = prev.options &&
|
|
45
|
+
prev.options.slice(i + 1).length > 0 &&
|
|
46
|
+
!e.target.value;
|
|
42
47
|
const optionListHead = prev.options ? prev.options.slice(0, i) : [];
|
|
43
48
|
const optionListTail = shouldAddEmptyOption
|
|
44
49
|
? [{ id: nanoid(), text: '' }]
|
|
@@ -55,7 +60,9 @@ export const OptionFieldSet = ({ errors, options, setErrors, setState }) => {
|
|
|
55
60
|
...prev,
|
|
56
61
|
options: [
|
|
57
62
|
...optionListHead,
|
|
58
|
-
...(shouldRemoveOption
|
|
63
|
+
...(shouldRemoveOption
|
|
64
|
+
? []
|
|
65
|
+
: [{ ...option, text: e.target.value }]),
|
|
59
66
|
...optionListTail,
|
|
60
67
|
],
|
|
61
68
|
};
|
|
@@ -64,20 +64,29 @@ export const PollCreationDialog = ({ close }) => {
|
|
|
64
64
|
React.createElement("div", { className: clsx('str-chat__form__input-field__value') },
|
|
65
65
|
React.createElement(FieldError, { className: 'str-chat__form__input-field__error', "data-testid": 'poll-max-votes-allowed-input-field-error', text: multipleAnswerCountError }),
|
|
66
66
|
React.createElement("input", { id: 'max_votes_allowed', onChange: (e) => {
|
|
67
|
-
const isValidValue = !e.target.value ||
|
|
67
|
+
const isValidValue = !e.target.value ||
|
|
68
|
+
e.target.value.match(VALID_MAX_VOTES_VALUE_REGEX);
|
|
68
69
|
if (!isValidValue) {
|
|
69
70
|
setMultipleAnswerCountError(t('Type a number from 2 to 10'));
|
|
70
71
|
}
|
|
71
72
|
else if (multipleAnswerCountError) {
|
|
72
73
|
setMultipleAnswerCountError(undefined);
|
|
73
74
|
}
|
|
74
|
-
setState((prev) => ({
|
|
75
|
+
setState((prev) => ({
|
|
76
|
+
...prev,
|
|
77
|
+
max_votes_allowed: e.target.value,
|
|
78
|
+
}));
|
|
75
79
|
}, placeholder: t('Maximum number of votes (from 2 to 10)'), type: 'number', value: state.max_votes_allowed }))))),
|
|
76
80
|
React.createElement(SimpleSwitchField, { checked: state.voting_visibility === 'anonymous', id: 'voting_visibility', labelText: t('Anonymous poll'), onChange: (e) => setState((prev) => ({
|
|
77
81
|
...prev,
|
|
78
|
-
voting_visibility: (e.target.checked
|
|
82
|
+
voting_visibility: (e.target.checked
|
|
83
|
+
? 'anonymous'
|
|
84
|
+
: 'public'),
|
|
85
|
+
})) }),
|
|
86
|
+
React.createElement(SimpleSwitchField, { checked: state.allow_user_suggested_options, id: 'allow_user_suggested_options', labelText: t('Allow option suggestion'), onChange: (e) => setState((prev) => ({
|
|
87
|
+
...prev,
|
|
88
|
+
allow_user_suggested_options: e.target.checked,
|
|
79
89
|
})) }),
|
|
80
|
-
React.createElement(SimpleSwitchField, { checked: state.allow_user_suggested_options, id: 'allow_user_suggested_options', labelText: t('Allow option suggestion'), onChange: (e) => setState((prev) => ({ ...prev, allow_user_suggested_options: e.target.checked })) }),
|
|
81
90
|
React.createElement(SimpleSwitchField, { checked: state.allow_answers, id: 'allow_answers', labelText: t('Allow comments'), onChange: (e) => setState((prev) => ({ ...prev, allow_answers: e.target.checked })) }))),
|
|
82
91
|
React.createElement(PollCreationDialogControls, { close: close, errors: [
|
|
83
92
|
...(nameError ?? []),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { VALID_MAX_VOTES_VALUE_REGEX } from '../constants';
|
|
3
|
-
import { useChatContext, useMessageInputContext, useTranslationContext } from '../../../context';
|
|
3
|
+
import { useChatContext, useMessageInputContext, useTranslationContext, } from '../../../context';
|
|
4
4
|
export const PollCreationDialogControls = ({ close, errors, state, }) => {
|
|
5
5
|
const { client } = useChatContext();
|
|
6
6
|
const { t } = useTranslationContext('PollCreationDialogControls');
|
|
@@ -10,7 +10,8 @@ export const PollCreationDialogControls = ({ close, errors, state, }) => {
|
|
|
10
10
|
const hasName = !!state.name;
|
|
11
11
|
const maxVotesAllowedNumber = parseInt(state.max_votes_allowed?.match(VALID_MAX_VOTES_VALUE_REGEX)?.[0] || '');
|
|
12
12
|
const validMaxVotesAllowed = state.max_votes_allowed === '' ||
|
|
13
|
-
(!!maxVotesAllowedNumber &&
|
|
13
|
+
(!!maxVotesAllowedNumber &&
|
|
14
|
+
(2 <= maxVotesAllowedNumber || maxVotesAllowedNumber <= 10));
|
|
14
15
|
const noErrors = errors.length === 0;
|
|
15
16
|
return hasAtLeastOneOption && hasName && validMaxVotesAllowed && noErrors;
|
|
16
17
|
};
|
|
@@ -24,7 +25,9 @@ export const PollCreationDialogControls = ({ close, errors, state, }) => {
|
|
|
24
25
|
max_votes_allowed: state.max_votes_allowed
|
|
25
26
|
? parseInt(state.max_votes_allowed)
|
|
26
27
|
: undefined,
|
|
27
|
-
options: state.options
|
|
28
|
+
options: state.options
|
|
29
|
+
?.filter((o) => o.text)
|
|
30
|
+
.map((o) => ({ text: o.text })),
|
|
28
31
|
});
|
|
29
32
|
pollId = poll.id;
|
|
30
33
|
}
|
|
@@ -5,7 +5,7 @@ import { useStateStore } from '../../store';
|
|
|
5
5
|
import { useComponentContext, usePollContext } from '../../context';
|
|
6
6
|
const pollStateSelector = (nextValue) => ({ options: nextValue.options });
|
|
7
7
|
export const PollOptionList = ({ optionsDisplayCount, }) => {
|
|
8
|
-
const { PollOptionSelector = DefaultPollOptionSelector
|
|
8
|
+
const { PollOptionSelector = DefaultPollOptionSelector } = useComponentContext();
|
|
9
9
|
const { poll } = usePollContext();
|
|
10
10
|
const { options } = useStateStore(poll.state, pollStateSelector);
|
|
11
11
|
return (React.createElement("div", { className: clsx('str-chat__poll-option-list', {
|
|
@@ -24,7 +24,9 @@ export const PollOptionSelector = ({ displayAvatarCount, option, voteCountVerbos
|
|
|
24
24
|
const { poll } = usePollContext();
|
|
25
25
|
const { is_closed, latest_votes_by_option, maxVotedOptionIds, ownVotesByOptionId, vote_counts_by_option, voting_visibility, } = useStateStore(poll.state, pollStateSelector);
|
|
26
26
|
const canCastVote = channelCapabilities['cast-poll-vote'] && !is_closed;
|
|
27
|
-
const winningOptionCount = maxVotedOptionIds[0]
|
|
27
|
+
const winningOptionCount = maxVotedOptionIds[0]
|
|
28
|
+
? vote_counts_by_option[maxVotedOptionIds[0]]
|
|
29
|
+
: 0;
|
|
28
30
|
const toggleVote = useMemo(() => debounce(() => {
|
|
29
31
|
if (!canCastVote)
|
|
30
32
|
return;
|
|
@@ -45,9 +47,14 @@ export const PollOptionSelector = ({ displayAvatarCount, option, voteCountVerbos
|
|
|
45
47
|
.slice(0, displayAvatarCount)
|
|
46
48
|
.map(({ user }) => (React.createElement(Avatar, { image: user?.image, key: `poll-option-${option.id}-avatar-${user?.id}`, name: user?.name }))))),
|
|
47
49
|
React.createElement("div", { className: 'str-chat__poll-option-vote-count' }, voteCountVerbose
|
|
48
|
-
? t('{{count}} votes', {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
? t('{{count}} votes', {
|
|
51
|
+
count: vote_counts_by_option[option.id] ?? 0,
|
|
52
|
+
})
|
|
53
|
+
: (vote_counts_by_option[option.id] ?? 0))),
|
|
54
|
+
React.createElement(AmountBar, { amount: (winningOptionCount &&
|
|
55
|
+
(vote_counts_by_option[option.id] ?? 0) / winningOptionCount) * 100, className: clsx('str-chat__poll-option__votes-bar', {
|
|
56
|
+
'str-chat__poll-option__votes-bar--winner': is_closed &&
|
|
57
|
+
maxVotedOptionIds.length === 1 &&
|
|
58
|
+
maxVotedOptionIds[0] === option.id,
|
|
52
59
|
}) })));
|
|
53
60
|
};
|
|
@@ -11,16 +11,21 @@ export function useManagePollVotesRealtime(managedVoteType, cursorPaginatorState
|
|
|
11
11
|
return;
|
|
12
12
|
const isAnswer = isVoteAnswer(event.poll_vote);
|
|
13
13
|
if ((managedVoteType === 'answer' && !isAnswer) ||
|
|
14
|
-
(managedVoteType === 'vote' &&
|
|
14
|
+
(managedVoteType === 'vote' &&
|
|
15
|
+
(isAnswer || event.poll_vote.option_id !== optionId)))
|
|
15
16
|
return;
|
|
16
17
|
if (event.type === 'poll.vote_removed') {
|
|
17
|
-
setVotesInRealtime((prev) => event.poll_vote
|
|
18
|
+
setVotesInRealtime((prev) => event.poll_vote
|
|
19
|
+
? prev.filter((vote) => vote.id !== event.poll_vote.id)
|
|
20
|
+
: prev);
|
|
18
21
|
}
|
|
19
22
|
if (event.type === 'poll.vote_changed') {
|
|
20
|
-
setVotesInRealtime((prev) => event.poll_vote
|
|
23
|
+
setVotesInRealtime((prev) => event.poll_vote
|
|
24
|
+
? prev.filter((vote) => vote.id !== event.poll_vote.id)
|
|
25
|
+
: prev);
|
|
21
26
|
}
|
|
22
27
|
if (['poll.vote_casted', 'poll.vote_changed'].includes(event.type)) {
|
|
23
|
-
setVotesInRealtime((prev) =>
|
|
28
|
+
setVotesInRealtime((prev) => event.poll_vote ? [event.poll_vote, ...prev] : prev);
|
|
24
29
|
}
|
|
25
30
|
};
|
|
26
31
|
const voteCastedSubscription = client.on('poll.vote_casted', handleVoteEvent);
|
|
@@ -3,13 +3,19 @@ import { useManagePollVotesRealtime } from './useManagePollVotesRealtime';
|
|
|
3
3
|
import { useCursorPaginator, } from '../../InfiniteScrollPaginator/hooks/useCursorPaginator';
|
|
4
4
|
import { usePollContext } from '../../../context';
|
|
5
5
|
import { useStateStore } from '../../../store';
|
|
6
|
-
const paginationStateSelector = (state) => [
|
|
6
|
+
const paginationStateSelector = (state) => [
|
|
7
|
+
state.error,
|
|
8
|
+
state.hasNextPage,
|
|
9
|
+
state.loading,
|
|
10
|
+
];
|
|
7
11
|
export const usePollAnswerPagination = ({ paginationParams } = {}) => {
|
|
8
12
|
const { poll } = usePollContext();
|
|
9
13
|
const paginationFn = useCallback(async (next) => {
|
|
10
14
|
const { next: newNext, votes } = await poll.queryAnswers({
|
|
11
15
|
filter: paginationParams?.filter,
|
|
12
|
-
options: !next
|
|
16
|
+
options: !next
|
|
17
|
+
? paginationParams?.options
|
|
18
|
+
: { ...paginationParams?.options, next },
|
|
13
19
|
sort: { created_at: -1, ...paginationParams?.sort },
|
|
14
20
|
});
|
|
15
21
|
return { items: votes, next: newNext };
|
|
@@ -3,13 +3,19 @@ import { useManagePollVotesRealtime } from './useManagePollVotesRealtime';
|
|
|
3
3
|
import { useCursorPaginator, } from '../../InfiniteScrollPaginator/hooks/useCursorPaginator';
|
|
4
4
|
import { useStateStore } from '../../../store';
|
|
5
5
|
import { usePollContext } from '../../../context';
|
|
6
|
-
const paginationStateSelector = (state) => [
|
|
6
|
+
const paginationStateSelector = (state) => [
|
|
7
|
+
state.error,
|
|
8
|
+
state.hasNextPage,
|
|
9
|
+
state.loading,
|
|
10
|
+
];
|
|
7
11
|
export const usePollOptionVotesPagination = ({ paginationParams, }) => {
|
|
8
12
|
const { poll } = usePollContext();
|
|
9
13
|
const paginationFn = useCallback(async (next) => {
|
|
10
14
|
const { next: newNext, votes } = await poll.queryOptionVotes({
|
|
11
15
|
filter: paginationParams.filter,
|
|
12
|
-
options: !next
|
|
16
|
+
options: !next
|
|
17
|
+
? paginationParams?.options
|
|
18
|
+
: { ...paginationParams?.options, next },
|
|
13
19
|
sort: { created_at: -1, ...paginationParams?.sort },
|
|
14
20
|
});
|
|
15
21
|
return { items: votes, next: newNext };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type GeneralType = 'audio/' | 'video/' | 'image/' | 'text/';
|
|
2
|
-
export type SupportedMimeType = typeof wordMimeTypes[number] | typeof excelMimeTypes[number] | typeof powerpointMimeTypes[number] | typeof archiveFileTypes[number] | typeof codeFileTypes[number];
|
|
2
|
+
export type SupportedMimeType = (typeof wordMimeTypes)[number] | (typeof excelMimeTypes)[number] | (typeof powerpointMimeTypes)[number] | (typeof archiveFileTypes)[number] | (typeof codeFileTypes)[number];
|
|
3
3
|
export declare const wordMimeTypes: string[];
|
|
4
4
|
export declare const excelMimeTypes: string[];
|
|
5
5
|
export declare const powerpointMimeTypes: string[];
|
|
@@ -12,7 +12,9 @@ export const ImageDropzone = ({ accept: acceptedFiles = [], children, disabled,
|
|
|
12
12
|
handleFiles(accepted);
|
|
13
13
|
}
|
|
14
14
|
}, [handleFiles]);
|
|
15
|
-
const accept = useMemo(() => (typeof acceptedFiles === 'string'
|
|
15
|
+
const accept = useMemo(() => (typeof acceptedFiles === 'string'
|
|
16
|
+
? acceptedFiles.split(',')
|
|
17
|
+
: acceptedFiles).reduce((mediaTypeMap, mediaType) => {
|
|
16
18
|
mediaTypeMap[mediaType] ?? (mediaTypeMap[mediaType] = []);
|
|
17
19
|
return mediaTypeMap;
|
|
18
20
|
}, {}), [acceptedFiles]);
|
|
@@ -14,7 +14,7 @@ export const FileInput = UploadButton;
|
|
|
14
14
|
export const UploadFileInput = forwardRef(function UploadFileInput({ className, onFileChange: onFileChangeCustom, ...props }, ref) {
|
|
15
15
|
const { t } = useTranslationContext('UploadFileInput');
|
|
16
16
|
const { acceptedFiles = [], multipleUploads } = useChannelStateContext('UploadFileInput');
|
|
17
|
-
const { isUploadEnabled, maxFilesLeft, uploadNewFiles
|
|
17
|
+
const { isUploadEnabled, maxFilesLeft, uploadNewFiles } = useMessageInputContext('UploadFileInput');
|
|
18
18
|
const id = useMemo(() => nanoid(), []);
|
|
19
19
|
const onFileChange = useCallback((files) => {
|
|
20
20
|
uploadNewFiles(files);
|
|
@@ -74,7 +74,9 @@ async function getImageSource(fileLikes, src) {
|
|
|
74
74
|
fileLikes.push(blob);
|
|
75
75
|
}
|
|
76
76
|
const extractImageSources = (s) => {
|
|
77
|
-
const imageTags = new DOMParser()
|
|
77
|
+
const imageTags = new DOMParser()
|
|
78
|
+
.parseFromString(s, 'text/html')
|
|
79
|
+
.getElementsByTagName('img');
|
|
78
80
|
return Array.from(imageTags, (tag) => tag.src).filter((tag) => tag);
|
|
79
81
|
};
|
|
80
82
|
export const isBlobButNotFile = (obj) => obj instanceof Blob && !(obj instanceof File);
|
|
@@ -36,7 +36,9 @@ const UnMemoizedReactionSelector = (props) => {
|
|
|
36
36
|
return;
|
|
37
37
|
const tooltip = tooltipRef.current?.getBoundingClientRect();
|
|
38
38
|
const target = targetRef.current?.getBoundingClientRect();
|
|
39
|
-
const container = isMutableRef(rootRef)
|
|
39
|
+
const container = isMutableRef(rootRef)
|
|
40
|
+
? rootRef.current?.getBoundingClientRect()
|
|
41
|
+
: null;
|
|
40
42
|
if (!tooltip || !target || !container)
|
|
41
43
|
return;
|
|
42
44
|
const tooltipPosition = tooltip.width === container.width || tooltip.x < container.x
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useRef } from 'react';
|
|
2
2
|
import { ReactionSelector as DefaultReactionSelector } from './ReactionSelector';
|
|
3
3
|
import { DialogAnchor, useDialog, useDialogIsOpen } from '../Dialog';
|
|
4
|
-
import { useComponentContext, useMessageContext, useTranslationContext } from '../../context';
|
|
4
|
+
import { useComponentContext, useMessageContext, useTranslationContext, } from '../../context';
|
|
5
5
|
/**
|
|
6
6
|
* Internal convenience component - not to be exported. It just groups the button and the dialog anchor and thus prevents
|
|
7
7
|
* cluttering the parent component.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { MessageContextValue } from '../../context';
|
|
2
3
|
import type { ReactionGroupResponse, ReactionResponse } from 'stream-chat';
|
|
3
4
|
import type { DefaultStreamChatGenerics } from '../../types/types';
|
|
4
5
|
import type { ReactionOptions } from './reactionOptions';
|
|
5
6
|
import type { ReactionDetailsComparator, ReactionsComparator } from './types';
|
|
6
|
-
import { MessageContextValue } from '../../context';
|
|
7
7
|
export type ReactionsListProps<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = Partial<Pick<MessageContextValue<StreamChatGenerics>, 'handleFetchReactions' | 'reactionDetailsSort'>> & {
|
|
8
8
|
/** An array of the own reaction objects to distinguish own reactions visually */
|
|
9
9
|
own_reactions?: ReactionResponse<StreamChatGenerics>[];
|
|
@@ -26,7 +26,7 @@ export type ReactionsListProps<StreamChatGenerics extends DefaultStreamChatGener
|
|
|
26
26
|
/** Comparator function to sort the list of reacted users
|
|
27
27
|
* @deprecated use `reactionDetailsSort` instead
|
|
28
28
|
*/
|
|
29
|
-
sortReactionDetails?: ReactionDetailsComparator
|
|
29
|
+
sortReactionDetails?: ReactionDetailsComparator<StreamChatGenerics>;
|
|
30
30
|
/** Comparator function to sort reactions, defaults to chronological order */
|
|
31
31
|
sortReactions?: ReactionsComparator;
|
|
32
32
|
};
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
+
import { ReactionsListModal as DefaultReactionsListModal, } from './ReactionsListModal';
|
|
3
4
|
import { useProcessReactions } from './hooks/useProcessReactions';
|
|
4
|
-
import {
|
|
5
|
-
import { useTranslationContext } from '../../context';
|
|
5
|
+
import { useComponentContext, useTranslationContext, } from '../../context';
|
|
6
6
|
import { MAX_MESSAGE_REACTIONS_TO_FETCH } from '../Message/hooks';
|
|
7
7
|
const UnMemoizedReactionsList = (props) => {
|
|
8
|
-
const { handleFetchReactions,
|
|
8
|
+
const { handleFetchReactions,
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10
|
+
reactionDetailsSort, reverse = false, sortReactionDetails, ...rest } = props;
|
|
9
11
|
const { existingReactions, hasReactions, totalReactionCount } = useProcessReactions(rest);
|
|
10
|
-
const [selectedReactionType, setSelectedReactionType
|
|
12
|
+
const [selectedReactionType, setSelectedReactionType] = useState(null);
|
|
11
13
|
const { t } = useTranslationContext('ReactionsList');
|
|
14
|
+
const { ReactionsListModal = DefaultReactionsListModal } = useComponentContext();
|
|
12
15
|
const handleReactionButtonClick = (reactionType) => {
|
|
13
16
|
if (totalReactionCount > MAX_MESSAGE_REACTIONS_TO_FETCH) {
|
|
14
17
|
return;
|
|
@@ -4,7 +4,7 @@ import { ModalProps } from '../Modal';
|
|
|
4
4
|
import { MessageContextValue } from '../../context';
|
|
5
5
|
import { DefaultStreamChatGenerics } from '../../types/types';
|
|
6
6
|
import { ReactionSort } from 'stream-chat';
|
|
7
|
-
type ReactionsListModalProps<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = ModalProps & Partial<Pick<MessageContextValue<StreamChatGenerics>, 'handleFetchReactions' | 'reactionDetailsSort'>> & {
|
|
7
|
+
export type ReactionsListModalProps<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = ModalProps & Partial<Pick<MessageContextValue<StreamChatGenerics>, 'handleFetchReactions' | 'reactionDetailsSort'>> & {
|
|
8
8
|
reactions: ReactionSummary[];
|
|
9
9
|
selectedReactionType: ReactionType<StreamChatGenerics>;
|
|
10
10
|
onSelectedReactionTypeChange?: (reactionType: ReactionType<StreamChatGenerics>) => void;
|
|
@@ -13,4 +13,3 @@ type ReactionsListModalProps<StreamChatGenerics extends DefaultStreamChatGeneric
|
|
|
13
13
|
sortReactionDetails?: ReactionDetailsComparator<StreamChatGenerics>;
|
|
14
14
|
};
|
|
15
15
|
export declare function ReactionsListModal<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ handleFetchReactions, onSelectedReactionTypeChange, reactionDetailsSort: propReactionDetailsSort, reactions, selectedReactionType, sortReactionDetails: propSortReactionDetails, ...modalProps }: ReactionsListModalProps<StreamChatGenerics>): React.JSX.Element;
|
|
16
|
-
export {};
|
|
@@ -12,7 +12,7 @@ export function ReactionsListModal({ handleFetchReactions, onSelectedReactionTyp
|
|
|
12
12
|
const { reactionDetailsSort: contextReactionDetailsSort, sortReactionDetails: contextSortReactionDetails, } = useMessageContext('ReactionsListModal');
|
|
13
13
|
const legacySortReactionDetails = propSortReactionDetails ?? contextSortReactionDetails;
|
|
14
14
|
const reactionDetailsSort = propReactionDetailsSort ?? contextReactionDetailsSort ?? defaultReactionDetailsSort;
|
|
15
|
-
const { isLoading: areReactionsLoading, reactions: reactionDetails
|
|
15
|
+
const { isLoading: areReactionsLoading, reactions: reactionDetails } = useFetchReactions({
|
|
16
16
|
handleFetchReactions,
|
|
17
17
|
reactionType: selectedReactionType,
|
|
18
18
|
shouldFetch: modalProps.open,
|
|
@@ -15,8 +15,12 @@ export const SpriteImage = ({ columns, fallback, height, position, rows, spriteU
|
|
|
15
15
|
'--str-chat__sprite-image-resize-ratio-y': 'calc(var(--str-chat__sprite-image-height) / var(--str-chat__sprite-item-height))',
|
|
16
16
|
'--str-chat__sprite-item-height': `${spriteHeight / rows}`,
|
|
17
17
|
'--str-chat__sprite-item-width': `${spriteWidth / columns}`,
|
|
18
|
-
...(Number.isFinite(height)
|
|
19
|
-
|
|
18
|
+
...(Number.isFinite(height)
|
|
19
|
+
? { '--str-chat__sprite-image-height': `${height}px` }
|
|
20
|
+
: {}),
|
|
21
|
+
...(Number.isFinite(width)
|
|
22
|
+
? { '--str-chat__sprite-image-width': `${width}px` }
|
|
23
|
+
: {}),
|
|
20
24
|
backgroundImage: `url('${spriteUrl}')`,
|
|
21
25
|
backgroundPosition: `${x * (100 / (columns - 1))}% ${y * (100 / (rows - 1))}%`,
|
|
22
26
|
backgroundSize: `${columns * 100}% ${rows * 100}%`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
import { useMessageContext } from '../../../context';
|
|
3
3
|
export function useFetchReactions(options) {
|
|
4
|
-
const { handleFetchReactions: contextHandleFetchReactions
|
|
4
|
+
const { handleFetchReactions: contextHandleFetchReactions } = useMessageContext('useFetchReactions');
|
|
5
5
|
const [reactions, setReactions] = useState([]);
|
|
6
6
|
const { handleFetchReactions: propHandleFetchReactions, reactionType, shouldFetch, sort, } = options;
|
|
7
7
|
const [isLoading, setIsLoading] = useState(shouldFetch);
|
|
@@ -10,7 +10,7 @@ export const defaultReactionsSort = (a, b) => {
|
|
|
10
10
|
export const useProcessReactions = (params) => {
|
|
11
11
|
const { own_reactions: propOwnReactions, reaction_groups: propReactionGroups, reactionOptions: propReactionOptions, reactions: propReactions, sortReactions: propSortReactions, } = params;
|
|
12
12
|
const { message, sortReactions: contextSortReactions } = useMessageContext('useProcessReactions');
|
|
13
|
-
const { reactionOptions: contextReactionOptions = defaultReactionOptions
|
|
13
|
+
const { reactionOptions: contextReactionOptions = defaultReactionOptions } = useComponentContext('useProcessReactions');
|
|
14
14
|
const reactionOptions = propReactionOptions ?? contextReactionOptions;
|
|
15
15
|
const sortReactions = propSortReactions ?? contextSortReactions ?? defaultReactionsSort;
|
|
16
16
|
const latestReactions = propReactions || message.latest_reactions;
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
/* eslint-disable sort-keys */
|
|
2
|
-
/* eslint-disable react/display-name */
|
|
3
2
|
import React from 'react';
|
|
4
3
|
import { StreamEmoji } from './StreamEmoji';
|
|
5
4
|
export const defaultReactionOptions = [
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
{
|
|
6
|
+
type: 'haha',
|
|
7
|
+
Component: () => React.createElement(StreamEmoji, { fallback: '\uD83D\uDE02', type: 'haha' }),
|
|
8
|
+
name: 'Joy',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
type: 'like',
|
|
12
|
+
Component: () => React.createElement(StreamEmoji, { fallback: '\uD83D\uDC4D', type: 'like' }),
|
|
13
|
+
name: 'Thumbs up',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
type: 'love',
|
|
17
|
+
Component: () => React.createElement(StreamEmoji, { fallback: '\u2764\uFE0F', type: 'love' }),
|
|
18
|
+
name: 'Heart',
|
|
19
|
+
},
|
|
9
20
|
{ type: 'sad', Component: () => React.createElement(StreamEmoji, { fallback: '\uD83D\uDE14', type: 'sad' }), name: 'Sad' },
|
|
10
|
-
{
|
|
21
|
+
{
|
|
22
|
+
type: 'wow',
|
|
23
|
+
Component: () => React.createElement(StreamEmoji, { fallback: '\uD83D\uDE32', type: 'wow' }),
|
|
24
|
+
name: 'Astonished',
|
|
25
|
+
},
|
|
11
26
|
];
|
|
@@ -34,7 +34,7 @@ const ThreadInner = (props) => {
|
|
|
34
34
|
const { thread, threadHasMore, threadLoadingMore, threadMessages = [], threadSuppressAutoscroll, } = useChannelStateContext('Thread');
|
|
35
35
|
const { closeThread, loadMoreThread } = useChannelActionContext('Thread');
|
|
36
36
|
const { customClasses } = useChatContext('Thread');
|
|
37
|
-
const {
|
|
37
|
+
const { Message: ContextMessage, ThreadHead = DefaultThreadHead, ThreadHeader = DefaultThreadHeader, ThreadInput: ContextInput, VirtualMessage, } = useComponentContext('Thread');
|
|
38
38
|
const ThreadInput = PropInput ?? additionalMessageInputProps?.Input ?? ContextInput ?? MessageInputFlat;
|
|
39
39
|
const ThreadMessage = PropMessage || additionalMessageListProps?.Message;
|
|
40
40
|
const FallbackMessage = virtualized && VirtualMessage ? VirtualMessage : ContextMessage;
|
|
@@ -45,7 +45,6 @@ const ThreadInner = (props) => {
|
|
|
45
45
|
// FIXME: integrators can customize channel query options but cannot customize channel.getReplies() options
|
|
46
46
|
loadMoreThread();
|
|
47
47
|
}
|
|
48
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
48
|
}, [thread, loadMoreThread]);
|
|
50
49
|
const threadProps = threadInstance
|
|
51
50
|
? {
|
|
@@ -71,6 +70,8 @@ const ThreadInner = (props) => {
|
|
|
71
70
|
const head = (React.createElement(ThreadHead, { key: messageAsThread.id, message: messageAsThread, Message: MessageUIComponent, ...additionalParentMessageProps }));
|
|
72
71
|
return (React.createElement("div", { className: threadClass },
|
|
73
72
|
React.createElement(ThreadHeader, { closeThread: closeThread, thread: messageAsThread }),
|
|
74
|
-
React.createElement(ThreadMessageList, { disableDateSeparator: !enableDateSeparator, head: head, Message: MessageUIComponent, messageActions: messageActions, suppressAutoscroll: threadSuppressAutoscroll, threadList: true, ...threadProps, ...(virtualized
|
|
73
|
+
React.createElement(ThreadMessageList, { disableDateSeparator: !enableDateSeparator, head: head, Message: MessageUIComponent, messageActions: messageActions, suppressAutoscroll: threadSuppressAutoscroll, threadList: true, ...threadProps, ...(virtualized
|
|
74
|
+
? additionalVirtualizedMessageListProps
|
|
75
|
+
: additionalMessageListProps) }),
|
|
75
76
|
React.createElement(MessageInput, { focus: autoFocus, Input: ThreadInput, isThreadInput: true, parent: thread ?? parentMessage, publishTypingEvent: false, ...additionalMessageInputProps })));
|
|
76
77
|
};
|
|
@@ -4,6 +4,6 @@ import { Thread } from 'stream-chat';
|
|
|
4
4
|
export type ThreadContextValue = Thread | undefined;
|
|
5
5
|
export declare const ThreadContext: React.Context<ThreadContextValue>;
|
|
6
6
|
export declare const useThreadContext: () => Thread<import("stream-chat").DefaultGenerics> | undefined;
|
|
7
|
-
export declare const ThreadProvider: ({ children, thread }: PropsWithChildren<{
|
|
7
|
+
export declare const ThreadProvider: ({ children, thread, }: PropsWithChildren<{
|
|
8
8
|
thread?: Thread;
|
|
9
9
|
}>) => React.JSX.Element;
|
|
@@ -5,5 +5,5 @@ export const useThreadContext = () => {
|
|
|
5
5
|
const thread = useContext(ThreadContext);
|
|
6
6
|
return thread ?? undefined;
|
|
7
7
|
};
|
|
8
|
-
export const ThreadProvider = ({ children, thread }) => (React.createElement(ThreadContext.Provider, { value: thread },
|
|
8
|
+
export const ThreadProvider = ({ children, thread, }) => (React.createElement(ThreadContext.Provider, { value: thread },
|
|
9
9
|
React.createElement(Channel, { channel: thread?.channel }, children)));
|
|
@@ -29,7 +29,7 @@ export const useThreadList = () => {
|
|
|
29
29
|
};
|
|
30
30
|
export const ThreadList = ({ virtuosoProps }) => {
|
|
31
31
|
const { client } = useChatContext();
|
|
32
|
-
const {
|
|
32
|
+
const { ThreadListEmptyPlaceholder = DefaultThreadListEmptyPlaceholder, ThreadListItem = DefaultThreadListItem, ThreadListLoadingIndicator = DefaultThreadListLoadingIndicator, ThreadListUnseenThreadsBanner = DefaultThreadListUnseenThreadsBanner, } = useComponentContext();
|
|
33
33
|
const { threads } = useStateStore(client.threads.state, selector);
|
|
34
34
|
useThreadList();
|
|
35
35
|
return (React.createElement("div", { className: 'str-chat__thread-list-container' },
|
|
@@ -6,4 +6,4 @@ export type ThreadListItemProps = {
|
|
|
6
6
|
threadListItemUIProps?: ThreadListItemUIProps;
|
|
7
7
|
};
|
|
8
8
|
export declare const useThreadListItemContext: () => Thread<import("stream-chat").DefaultGenerics> | undefined;
|
|
9
|
-
export declare const ThreadListItem: ({ thread, threadListItemUIProps }: ThreadListItemProps) => React.JSX.Element;
|
|
9
|
+
export declare const ThreadListItem: ({ thread, threadListItemUIProps, }: ThreadListItemProps) => React.JSX.Element;
|
|
@@ -3,7 +3,7 @@ import { useComponentContext } from '../../../context';
|
|
|
3
3
|
import { ThreadListItemUI as DefaultThreadListItemUI } from './ThreadListItemUI';
|
|
4
4
|
const ThreadListItemContext = createContext(undefined);
|
|
5
5
|
export const useThreadListItemContext = () => useContext(ThreadListItemContext);
|
|
6
|
-
export const ThreadListItem = ({ thread, threadListItemUIProps }) => {
|
|
6
|
+
export const ThreadListItem = ({ thread, threadListItemUIProps, }) => {
|
|
7
7
|
const { ThreadListItemUI = DefaultThreadListItemUI } = useComponentContext();
|
|
8
8
|
return (React.createElement(ThreadListItemContext.Provider, { value: thread },
|
|
9
9
|
React.createElement(ThreadListItemUI, { ...threadListItemUIProps })));
|
|
@@ -26,8 +26,7 @@ const getTitleFromMessage = ({ currentUserId, message, }) => {
|
|
|
26
26
|
let attachmentIcon = '';
|
|
27
27
|
if (attachment) {
|
|
28
28
|
attachmentIcon +=
|
|
29
|
-
attachmentTypeIconMap[attachment.type ?? 'file'] ??
|
|
30
|
-
attachmentTypeIconMap.file;
|
|
29
|
+
attachmentTypeIconMap[attachment.type ?? 'file'] ?? attachmentTypeIconMap.file;
|
|
31
30
|
}
|
|
32
31
|
const messageBelongsToCurrentUser = message?.user?.id === currentUserId;
|
|
33
32
|
if (message?.deleted_at && message.parent_id)
|
|
@@ -69,7 +68,10 @@ export const ThreadListItemUI = (props) => {
|
|
|
69
68
|
React.createElement("div", { className: 'str-chat__thread-list-item__latest-reply-text-and-timestamp' },
|
|
70
69
|
React.createElement("div", { className: 'str-chat__thread-list-item__latest-reply-text' }, deletedAt
|
|
71
70
|
? 'This thread was deleted'
|
|
72
|
-
: getTitleFromMessage({
|
|
71
|
+
: getTitleFromMessage({
|
|
72
|
+
currentUserId: client.user?.id,
|
|
73
|
+
message: latestReply,
|
|
74
|
+
})),
|
|
73
75
|
React.createElement("div", { className: 'str-chat__thread-list-item__latest-reply-timestamp' },
|
|
74
76
|
React.createElement(Timestamp, { timestamp: deletedAt ?? latestReply?.created_at })))))));
|
|
75
77
|
};
|
|
@@ -11,4 +11,4 @@ export type PopperTooltipProps<T extends HTMLElement> = React.PropsWithChildren<
|
|
|
11
11
|
/** Tells component whether to render its contents */
|
|
12
12
|
visible?: boolean;
|
|
13
13
|
}>;
|
|
14
|
-
export declare const PopperTooltip: <T extends HTMLElement>({ children, offset,
|
|
14
|
+
export declare const PopperTooltip: <T extends HTMLElement>({ children, offset, placement, referenceElement, visible, }: PopperTooltipProps<T>) => React.JSX.Element | null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { usePopper } from 'react-popper';
|
|
3
3
|
export const Tooltip = ({ children, ...rest }) => (React.createElement("div", { className: 'str-chat__tooltip', ...rest }, children));
|
|
4
|
-
export const PopperTooltip = ({ children, offset = [0, 10],
|
|
4
|
+
export const PopperTooltip = ({ children, offset = [0, 10], placement = 'top', referenceElement, visible = false, }) => {
|
|
5
5
|
const [popperElement, setPopperElement] = useState(null);
|
|
6
6
|
const { attributes, styles } = usePopper(referenceElement, popperElement, {
|
|
7
7
|
modifiers: [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from 'react';
|
|
2
|
-
import { AttachmentPreviewListProps, AttachmentProps, AvatarProps, BaseImageProps, ChannelPreviewActionButtonsProps, CooldownTimerProps, CustomMessageActionsListProps, DateSeparatorProps, EmojiSearchIndex, EmptyStateIndicatorProps, EventComponentProps, FixedHeightMessageProps, GiphyPreviewMessageProps, LinkPreviewListProps, LoadingIndicatorProps, MessageBouncePromptProps, MessageDeletedProps, MessageInputProps, MessageListNotificationsProps, MessageNotificationProps, MessageOptionsProps, MessageProps, MessageRepliesCountButtonProps, MessageStatusProps, MessageTimestampProps, MessageUIComponentProps, ModalGalleryProps, PinIndicatorProps, PollCreationDialogProps, PollOptionSelectorProps, QuotedMessagePreviewProps, ReactionOptions, ReactionSelectorProps, ReactionsListProps, RecordingPermissionDeniedNotificationProps, SendButtonProps, StartRecordingAudioButtonProps, StreamedMessageTextProps, SuggestionItemProps, SuggestionListProps, ThreadHeaderProps, ThreadListItemProps, ThreadListItemUIProps, TimestampProps, TypingIndicatorProps, UnreadMessagesNotificationProps, UnreadMessagesSeparatorProps } from '../components';
|
|
2
|
+
import { AttachmentPreviewListProps, AttachmentProps, AvatarProps, BaseImageProps, ChannelPreviewActionButtonsProps, CooldownTimerProps, CustomMessageActionsListProps, DateSeparatorProps, EmojiSearchIndex, EmptyStateIndicatorProps, EventComponentProps, FixedHeightMessageProps, GiphyPreviewMessageProps, LinkPreviewListProps, LoadingIndicatorProps, MessageBouncePromptProps, MessageDeletedProps, MessageInputProps, MessageListNotificationsProps, MessageNotificationProps, MessageOptionsProps, MessageProps, MessageRepliesCountButtonProps, MessageStatusProps, MessageTimestampProps, MessageUIComponentProps, ModalGalleryProps, PinIndicatorProps, PollCreationDialogProps, PollOptionSelectorProps, QuotedMessagePreviewProps, ReactionOptions, ReactionSelectorProps, ReactionsListModalProps, ReactionsListProps, RecordingPermissionDeniedNotificationProps, SendButtonProps, StartRecordingAudioButtonProps, StreamedMessageTextProps, SuggestionItemProps, SuggestionListProps, ThreadHeaderProps, ThreadListItemProps, ThreadListItemUIProps, TimestampProps, TypingIndicatorProps, UnreadMessagesNotificationProps, UnreadMessagesSeparatorProps } from '../components';
|
|
3
3
|
import type { CustomTrigger, DefaultStreamChatGenerics, PropsWithChildrenOnly, UnknownType } from '../types/types';
|
|
4
4
|
import type { StopAIGenerationButtonProps } from '../components/MessageInput/StopAIGenerationButton';
|
|
5
5
|
export type ComponentContextValue<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, V extends CustomTrigger = CustomTrigger> = {
|
|
@@ -105,6 +105,8 @@ export type ComponentContextValue<StreamChatGenerics extends DefaultStreamChatGe
|
|
|
105
105
|
ReactionSelector?: React.ForwardRefExoticComponent<ReactionSelectorProps<StreamChatGenerics>>;
|
|
106
106
|
/** Custom UI component to display the list of reactions on a message, defaults to and accepts same props as: [ReactionsList](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Reactions/ReactionsList.tsx) */
|
|
107
107
|
ReactionsList?: React.ComponentType<ReactionsListProps<StreamChatGenerics>>;
|
|
108
|
+
/** Custom UI component to display the reactions modal, defaults to and accepts same props as: [ReactionsListModal](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Reactions/ReactionsListModal.tsx) */
|
|
109
|
+
ReactionsListModal?: React.ComponentType<ReactionsListModalProps<StreamChatGenerics>>;
|
|
108
110
|
RecordingPermissionDeniedNotification?: React.ComponentType<RecordingPermissionDeniedNotificationProps>;
|
|
109
111
|
/** Custom UI component for send button, defaults to and accepts same props as: [SendButton](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/icons.tsx) */
|
|
110
112
|
SendButton?: React.ComponentType<SendButtonProps<StreamChatGenerics>>;
|
|
@@ -5,7 +5,7 @@ export const useComponentContext = (
|
|
|
5
5
|
/**
|
|
6
6
|
* @deprecated
|
|
7
7
|
*/
|
|
8
|
-
// eslint-disable-next-line
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9
9
|
_componentName) => useContext(ComponentContext);
|
|
10
10
|
/**
|
|
11
11
|
* Typescript currently does not support partial inference, so if ComponentContext
|
|
@@ -3,7 +3,7 @@ import { DialogManager } from '../components/Dialog/DialogManager';
|
|
|
3
3
|
type DialogManagerProviderContextValue = {
|
|
4
4
|
dialogManager: DialogManager;
|
|
5
5
|
};
|
|
6
|
-
export declare const DialogManagerProvider: ({ children, id }: PropsWithChildren<{
|
|
6
|
+
export declare const DialogManagerProvider: ({ children, id, }: PropsWithChildren<{
|
|
7
7
|
id?: string;
|
|
8
8
|
}>) => React.JSX.Element;
|
|
9
9
|
export declare const useDialogManager: () => DialogManagerProviderContextValue;
|