stream-chat-react 12.15.1 → 12.15.2
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/Chat/hooks/useChat.js +1 -1
- package/dist/components/Dialog/DialogManager.js +2 -1
- package/dist/components/MessageInput/AttachmentSelector.js +3 -3
- package/dist/components/MessageInput/MessageInput.js +4 -2
- package/dist/components/MessageList/MessageList.js +4 -2
- package/dist/components/MessageList/VirtualizedMessageList.js +4 -2
- package/dist/components/Poll/PollCreationDialog/PollCreationDialog.js +3 -2
- package/dist/components/UtilityComponents/useStableId.d.ts +5 -0
- package/dist/components/UtilityComponents/useStableId.js +11 -0
- package/dist/experimental/index.browser.cjs.map +1 -1
- package/dist/experimental/index.node.cjs.map +1 -1
- package/dist/index.browser.cjs +687 -676
- package/dist/index.browser.cjs.map +4 -4
- package/dist/index.node.cjs +576 -565
- package/dist/index.node.cjs.map +4 -4
- package/package.json +1 -1
|
@@ -24,7 +24,7 @@ export const useChat = ({ client, defaultLanguage = 'en', i18nInstance, initialN
|
|
|
24
24
|
useEffect(() => {
|
|
25
25
|
if (!client)
|
|
26
26
|
return;
|
|
27
|
-
const version = "12.15.
|
|
27
|
+
const version = "12.15.2";
|
|
28
28
|
const userAgent = client.getUserAgent();
|
|
29
29
|
if (!userAgent.includes('stream-chat-react')) {
|
|
30
30
|
// result looks like: 'stream-chat-react-2.3.2-stream-chat-javascript-client-browser-2.2.2'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid';
|
|
1
2
|
import { StateStore } from 'stream-chat';
|
|
2
3
|
/**
|
|
3
4
|
* Keeps a map of Dialog objects.
|
|
@@ -14,7 +15,7 @@ export class DialogManager {
|
|
|
14
15
|
this.state = new StateStore({
|
|
15
16
|
dialogsById: {},
|
|
16
17
|
});
|
|
17
|
-
this.id = id ??
|
|
18
|
+
this.id = id ?? nanoid();
|
|
18
19
|
}
|
|
19
20
|
get openDialogCount() {
|
|
20
21
|
return Object.values(this.state.getLatestValue().dialogsById).reduce((count, dialog) => {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import React, { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
2
|
import { UploadIcon as DefaultUploadIcon } from './icons';
|
|
4
3
|
import { CHANNEL_CONTAINER_ID } from '../Channel/constants';
|
|
5
4
|
import { DialogAnchor, useDialog, useDialogIsOpen } from '../Dialog';
|
|
@@ -10,11 +9,12 @@ import { Portal } from '../Portal/Portal';
|
|
|
10
9
|
import { UploadFileInput } from '../ReactFileUtilities';
|
|
11
10
|
import { useChannelStateContext, useComponentContext, useMessageInputContext, useTranslationContext, } from '../../context';
|
|
12
11
|
import { AttachmentSelectorContextProvider, useAttachmentSelectorContext, } from '../../context/AttachmentSelectorContext';
|
|
12
|
+
import { useStableId } from '../UtilityComponents/useStableId';
|
|
13
13
|
export const SimpleAttachmentSelector = () => {
|
|
14
14
|
const { AttachmentSelectorInitiationButtonContents, FileUploadIcon = DefaultUploadIcon, } = useComponentContext();
|
|
15
15
|
const inputRef = useRef(null);
|
|
16
16
|
const [labelElement, setLabelElement] = useState(null);
|
|
17
|
-
const id =
|
|
17
|
+
const id = useStableId();
|
|
18
18
|
useEffect(() => {
|
|
19
19
|
if (!labelElement)
|
|
20
20
|
return;
|
|
@@ -9,6 +9,7 @@ import { useComponentContext, } from '../../context/ComponentContext';
|
|
|
9
9
|
import { MessageInputContextProvider } from '../../context/MessageInputContext';
|
|
10
10
|
import { DialogManagerProvider } from '../../context';
|
|
11
11
|
import { useRegisterDropHandlers } from './WithDragAndDropUpload';
|
|
12
|
+
import { useStableId } from '../UtilityComponents/useStableId';
|
|
12
13
|
const MessageInputProvider = (props) => {
|
|
13
14
|
const cooldownTimerState = useCooldownTimer();
|
|
14
15
|
const messageInputState = useMessageInputState(props);
|
|
@@ -27,10 +28,11 @@ const UnMemoizedMessageInput = (props) => {
|
|
|
27
28
|
const { Input: PropInput } = props;
|
|
28
29
|
const { dragAndDropWindow } = useChannelStateContext();
|
|
29
30
|
const { Input: ContextInput, TriggerProvider = DefaultTriggerProvider } = useComponentContext('MessageInput');
|
|
31
|
+
const id = useStableId();
|
|
30
32
|
const Input = PropInput || ContextInput || MessageInputFlat;
|
|
31
33
|
const dialogManagerId = props.isThreadInput
|
|
32
|
-
?
|
|
33
|
-
:
|
|
34
|
+
? `message-input-dialog-manager-thread-${id}`
|
|
35
|
+
: `message-input-dialog-manager-${id}`;
|
|
34
36
|
if (dragAndDropWindow)
|
|
35
37
|
return (React.createElement(DialogManagerProvider, { id: dialogManagerId },
|
|
36
38
|
React.createElement(TriggerProvider, null,
|
|
@@ -17,6 +17,7 @@ import { LoadingIndicator as DefaultLoadingIndicator } from '../Loading';
|
|
|
17
17
|
import { defaultPinPermissions, MESSAGE_ACTIONS } from '../Message/utils';
|
|
18
18
|
import { TypingIndicator as DefaultTypingIndicator } from '../TypingIndicator';
|
|
19
19
|
import { MessageListMainPanel as DefaultMessageListMainPanel } from './MessageListMainPanel';
|
|
20
|
+
import { useStableId } from '../UtilityComponents/useStableId';
|
|
20
21
|
import { defaultRenderMessages } from './renderMessages';
|
|
21
22
|
import { DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, DEFAULT_NEXT_CHANNEL_PAGE_SIZE, } from '../../constants/limits';
|
|
22
23
|
const MessageListWithContext = (props) => {
|
|
@@ -123,10 +124,11 @@ const MessageListWithContext = (props) => {
|
|
|
123
124
|
}
|
|
124
125
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
125
126
|
}, [highlightedMessageId]);
|
|
127
|
+
const id = useStableId();
|
|
126
128
|
const showEmptyStateIndicator = elements.length === 0 && !threadList;
|
|
127
129
|
const dialogManagerId = threadList
|
|
128
|
-
?
|
|
129
|
-
:
|
|
130
|
+
? `message-list-dialog-manager-thread-${id}`
|
|
131
|
+
: `message-list-dialog-manager-${id}`;
|
|
130
132
|
return (React.createElement(MessageListContextProvider, { value: { listElement, scrollToBottom } },
|
|
131
133
|
React.createElement(MessageListMainPanel, null,
|
|
132
134
|
React.createElement(DialogManagerProvider, { id: dialogManagerId },
|
|
@@ -21,6 +21,7 @@ import { useChatContext } from '../../context/ChatContext';
|
|
|
21
21
|
import { useComponentContext, } from '../../context/ComponentContext';
|
|
22
22
|
import { VirtualizedMessageListContextProvider } from '../../context/VirtualizedMessageListContext';
|
|
23
23
|
import { DEFAULT_NEXT_CHANNEL_PAGE_SIZE } from '../../constants/limits';
|
|
24
|
+
import { useStableId } from '../UtilityComponents/useStableId';
|
|
24
25
|
function captureResizeObserverExceededError(e) {
|
|
25
26
|
if (e.message === 'ResizeObserver loop completed with undelivered notifications.' ||
|
|
26
27
|
e.message === 'ResizeObserver loop limit exceeded') {
|
|
@@ -194,11 +195,12 @@ const VirtualizedMessageListWithContext = (props) => {
|
|
|
194
195
|
clearTimeout(scrollTimeout);
|
|
195
196
|
};
|
|
196
197
|
}, [highlightedMessageId, processedMessages]);
|
|
198
|
+
const id = useStableId();
|
|
197
199
|
if (!processedMessages)
|
|
198
200
|
return null;
|
|
199
201
|
const dialogManagerId = threadList
|
|
200
|
-
?
|
|
201
|
-
:
|
|
202
|
+
? `virtualized-message-list-dialog-manager-thread-${id}`
|
|
203
|
+
: `virtualized-message-list-dialog-manager-${id}`;
|
|
202
204
|
return (React.createElement(VirtualizedMessageListContextProvider, { value: { scrollToBottom } },
|
|
203
205
|
React.createElement(MessageListMainPanel, null,
|
|
204
206
|
React.createElement(DialogManagerProvider, { id: dialogManagerId },
|
|
@@ -64,8 +64,9 @@ 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 =
|
|
68
|
-
e.target.value
|
|
67
|
+
const isValidValue = e.target.validity.valid &&
|
|
68
|
+
(!e.target.value ||
|
|
69
|
+
e.target.value.match(VALID_MAX_VOTES_VALUE_REGEX));
|
|
69
70
|
if (!isValidValue) {
|
|
70
71
|
setMultipleAnswerCountError(t('Type a number from 2 to 10'));
|
|
71
72
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* The ID is generated using the `nanoid` library and is memoized to ensure
|
|
5
|
+
* that it remains the same across renders unless the key changes.
|
|
6
|
+
*/
|
|
7
|
+
export const useStableId = (key) => {
|
|
8
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
9
|
+
const id = useMemo(() => nanoid(), [key]);
|
|
10
|
+
return id;
|
|
11
|
+
};
|