stream-chat-react 14.2.0 → 14.3.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/README.md +7 -9
- package/dist/cjs/index.js +218 -33
- package/dist/cjs/index.js.map +1 -1
- package/dist/css/index.css +4 -0
- package/dist/css/index.css.map +1 -1
- package/dist/es/index.mjs +218 -33
- package/dist/es/index.mjs.map +1 -1
- package/dist/types/components/ChannelList/ChannelList.d.ts.map +1 -1
- package/dist/types/components/ChannelList/hooks/usePaginatedChannels.d.ts +12 -1
- package/dist/types/components/ChannelList/hooks/usePaginatedChannels.d.ts.map +1 -1
- package/dist/types/components/Notifications/NotificationList.d.ts +58 -1
- package/dist/types/components/Notifications/NotificationList.d.ts.map +1 -1
- package/dist/types/components/Reactions/MessageReactionsDetail.d.ts.map +1 -1
- package/dist/types/components/Reactions/ReactionSelector.d.ts.map +1 -1
- package/dist/types/components/Reactions/reactionOptions.d.ts +1 -0
- package/dist/types/components/Reactions/reactionOptions.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -54,26 +54,26 @@ For complete pricing and details visit our [Chat Pricing Page](https://getstream
|
|
|
54
54
|
|
|
55
55
|
## Example Applications
|
|
56
56
|
|
|
57
|
-
We have built
|
|
57
|
+
We have built demo applications showcasing a variety of chat use cases, including social messaging, team collaboration, customer support, livestream gaming, and virtual events. You can preview these [demos](https://getstream.io/chat/demos/) on our website.
|
|
58
58
|
|
|
59
59
|
## Documentation
|
|
60
60
|
|
|
61
61
|
We use a doc generator to build our [component documentation](https://getstream.io/chat/docs/sdk/react/). We provide a brief description of each chat component and define all of the props it accepts.
|
|
62
62
|
|
|
63
|
-
The React components are created using the [stream-chat](https://github.com/getstream/stream-chat-js) library. If you're customizing the components,
|
|
63
|
+
The React components are created using the [stream-chat](https://github.com/getstream/stream-chat-js) library. If you're customizing the components, you'll likely need to make additional calls to our Chat API using our JavaScript client, which has [documentation](https://getstream.io/chat/docs/javascript/) on our website.
|
|
64
64
|
|
|
65
65
|
## Component Reusability
|
|
66
66
|
|
|
67
|
-
For components that implement significant logic, it's helpful to split the component into two parts: a top-level component
|
|
67
|
+
For components that implement significant logic, it's helpful to split the component into two parts: a top-level component that handles functionality and a lower-level component that renders the UI. This way, you can swap UI without altering the logic that gives the component its functionality. We use this provider/consumer pattern frequently in the library, and the below example shows how to swap out the `Message` UI component with `CustomMessageUI` (using `WithComponents`), without affecting any logic in the application.
|
|
68
68
|
|
|
69
69
|
```jsx
|
|
70
70
|
<Channel>
|
|
71
71
|
<Window>
|
|
72
72
|
<ChannelHeader />
|
|
73
|
-
<WithComponents overrides={{
|
|
73
|
+
<WithComponents overrides={{ MessageUI: CustomMessageUI }}>
|
|
74
74
|
<MessageList />
|
|
75
75
|
</WithComponents>
|
|
76
|
-
<
|
|
76
|
+
<MessageComposer />
|
|
77
77
|
</Window>
|
|
78
78
|
<Thread />
|
|
79
79
|
</Channel>
|
|
@@ -81,14 +81,12 @@ For components that implement significant logic, it's helpful to split the compo
|
|
|
81
81
|
|
|
82
82
|
### Customizing Styles
|
|
83
83
|
|
|
84
|
-
The preferred method for overriding the pre-defined styles in the library is
|
|
84
|
+
The preferred method for overriding the pre-defined styles in the library is a two-step process. First, import our bundled CSS into your main CSS file (or CSS file loaded with your chat application). Second, locate any Stream styles you want to override using either the browser inspector or by viewing the library code. You can then add selectors to your local CSS file to override our defaults (ideally within the stream-overrides layer). Layers (when ordered correctly, see example) ensure that your overrides take precedence even if your overriding selectors are less specific. For example:
|
|
85
85
|
|
|
86
86
|
```css title="index.css"
|
|
87
87
|
@layer stream, stream-overrides;
|
|
88
88
|
|
|
89
|
-
@import 'stream-chat-react/css/
|
|
90
|
-
/* or */
|
|
91
|
-
@import 'stream-chat-react/dist/css/v2/index.css' layer(stream);
|
|
89
|
+
@import 'stream-chat-react/css/index.css' layer(stream);
|
|
92
90
|
|
|
93
91
|
@layer stream-overrides {
|
|
94
92
|
/* your overrides */
|
package/dist/cjs/index.js
CHANGED
|
@@ -22380,6 +22380,7 @@ const defaultReactionOptions = {
|
|
|
22380
22380
|
}
|
|
22381
22381
|
}
|
|
22382
22382
|
};
|
|
22383
|
+
const getHasExtendedReactions = (reactionOptions) => !Array.isArray(reactionOptions) && typeof reactionOptions.extended !== "undefined" && Object.keys(reactionOptions.extended).length > 0;
|
|
22383
22384
|
const stableOwnReactions = [];
|
|
22384
22385
|
const ReactionSelector = (props) => {
|
|
22385
22386
|
const {
|
|
@@ -22425,7 +22426,7 @@ const ReactionSelector = (props) => {
|
|
|
22425
22426
|
})
|
|
22426
22427
|
);
|
|
22427
22428
|
}, [reactionOptions]);
|
|
22428
|
-
const hasExtendedReactions =
|
|
22429
|
+
const hasExtendedReactions = getHasExtendedReactions(reactionOptions);
|
|
22429
22430
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
22430
22431
|
"div",
|
|
22431
22432
|
{
|
|
@@ -22656,6 +22657,7 @@ const MessageReactionsDetail = ({
|
|
|
22656
22657
|
reactionDetailsSort: contextReactionDetailsSort
|
|
22657
22658
|
} = useMessageContext(MessageReactionsDetail.name);
|
|
22658
22659
|
const reactionDetailsSort = propReactionDetailsSort ?? contextReactionDetailsSort ?? defaultReactionDetailsSort;
|
|
22660
|
+
const hasExtendedReactions = getHasExtendedReactions(reactionOptions);
|
|
22659
22661
|
const {
|
|
22660
22662
|
isLoading: areReactionsLoading,
|
|
22661
22663
|
reactions: reactionDetails,
|
|
@@ -22702,7 +22704,7 @@ const MessageReactionsDetail = ({
|
|
|
22702
22704
|
className: "str-chat__message-reactions-detail__reaction-type-list",
|
|
22703
22705
|
"data-testid": "reaction-type-list",
|
|
22704
22706
|
children: [
|
|
22705
|
-
/* @__PURE__ */ jsxRuntime.jsx("li", { className: "str-chat__message-reactions-detail__reaction-type-list-item", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
22707
|
+
hasExtendedReactions && /* @__PURE__ */ jsxRuntime.jsx("li", { className: "str-chat__message-reactions-detail__reaction-type-list-item", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
22706
22708
|
"button",
|
|
22707
22709
|
{
|
|
22708
22710
|
"aria-label": t("Add reaction"),
|
|
@@ -27292,6 +27294,9 @@ const useConnectionRecoveredListener = (forceUpdate) => {
|
|
|
27292
27294
|
};
|
|
27293
27295
|
const RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS = 5e3;
|
|
27294
27296
|
const MIN_RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS = 2e3;
|
|
27297
|
+
const mapPredefinedFilterSortToChannelSort = (sort) => sort.map(({ direction = 1, field }) => ({
|
|
27298
|
+
[field]: direction
|
|
27299
|
+
}));
|
|
27295
27300
|
const usePaginatedChannels = (client, filters, sort, options, activeChannelHandler, recoveryThrottleIntervalMs = RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS, customQueryChannels) => {
|
|
27296
27301
|
const { addNotification } = useNotificationApi.useNotificationApi();
|
|
27297
27302
|
const {
|
|
@@ -27300,6 +27305,10 @@ const usePaginatedChannels = (client, filters, sort, options, activeChannelHandl
|
|
|
27300
27305
|
const { t } = useNotificationApi.useTranslationContext();
|
|
27301
27306
|
const [channels, setChannels] = React.useState([]);
|
|
27302
27307
|
const [hasNextPage, setHasNextPage] = React.useState(true);
|
|
27308
|
+
const [responseFilters, setResponseFilters] = React.useState(
|
|
27309
|
+
void 0
|
|
27310
|
+
);
|
|
27311
|
+
const [responseSort, setResponseSort] = React.useState(void 0);
|
|
27303
27312
|
const lastRecoveryTimestamp = React.useRef(void 0);
|
|
27304
27313
|
const recoveryThrottleInterval = recoveryThrottleIntervalMs < MIN_RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS ? MIN_RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS : recoveryThrottleIntervalMs ?? RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS;
|
|
27305
27314
|
const filterString = React.useMemo(() => JSON.stringify(filters), [filters]);
|
|
@@ -27320,6 +27329,8 @@ const usePaginatedChannels = (client, filters, sort, options, activeChannelHandl
|
|
|
27320
27329
|
setChannels,
|
|
27321
27330
|
setHasNextPage
|
|
27322
27331
|
});
|
|
27332
|
+
setResponseFilters(void 0);
|
|
27333
|
+
setResponseSort(void 0);
|
|
27323
27334
|
} else {
|
|
27324
27335
|
const newOptions = {
|
|
27325
27336
|
offset,
|
|
@@ -27328,13 +27339,22 @@ const usePaginatedChannels = (client, filters, sort, options, activeChannelHandl
|
|
|
27328
27339
|
const channelQueryResponse = await client.queryChannels(
|
|
27329
27340
|
filters,
|
|
27330
27341
|
sort || {},
|
|
27331
|
-
newOptions
|
|
27342
|
+
newOptions,
|
|
27343
|
+
{ withResponse: true }
|
|
27332
27344
|
);
|
|
27333
|
-
const newChannels = queryType === "reload" ? channelQueryResponse : uniqBy([...channels, ...channelQueryResponse], "cid");
|
|
27345
|
+
const newChannels = queryType === "reload" ? channelQueryResponse.channels : uniqBy([...channels, ...channelQueryResponse.channels], "cid");
|
|
27334
27346
|
setChannels(newChannels);
|
|
27335
|
-
setHasNextPage(channelQueryResponse.length >= (newOptions.limit ?? 1));
|
|
27347
|
+
setHasNextPage(channelQueryResponse.channels.length >= (newOptions.limit ?? 1));
|
|
27348
|
+
const predefinedFilter = channelQueryResponse.predefined_filter;
|
|
27349
|
+
const nextResponseFilters = predefinedFilter ? predefinedFilter.filter : void 0;
|
|
27350
|
+
const nextResponseSort = predefinedFilter?.sort ? mapPredefinedFilterSortToChannelSort(predefinedFilter.sort) : void 0;
|
|
27351
|
+
setResponseFilters(nextResponseFilters);
|
|
27352
|
+
setResponseSort(nextResponseSort);
|
|
27336
27353
|
if (!offset && activeChannelHandler) {
|
|
27337
|
-
activeChannelHandler(newChannels, setChannels
|
|
27354
|
+
activeChannelHandler(newChannels, setChannels, {
|
|
27355
|
+
filters: nextResponseFilters ?? filters,
|
|
27356
|
+
sort: nextResponseSort ?? sort
|
|
27357
|
+
});
|
|
27338
27358
|
}
|
|
27339
27359
|
}
|
|
27340
27360
|
} catch (error2) {
|
|
@@ -27374,8 +27394,12 @@ const usePaginatedChannels = (client, filters, sort, options, activeChannelHandl
|
|
|
27374
27394
|
React.useEffect(() => {
|
|
27375
27395
|
queryChannels("reload");
|
|
27376
27396
|
}, [filterString, sortString]);
|
|
27397
|
+
const effectiveFilters = responseFilters ?? filters;
|
|
27398
|
+
const effectiveSort = responseSort ?? sort;
|
|
27377
27399
|
return {
|
|
27378
27400
|
channels,
|
|
27401
|
+
effectiveFilters,
|
|
27402
|
+
effectiveSort,
|
|
27379
27403
|
hasNextPage,
|
|
27380
27404
|
loadNextPage,
|
|
27381
27405
|
setChannels
|
|
@@ -28521,7 +28545,7 @@ const UnMemoizedChannelList = (props) => {
|
|
|
28521
28545
|
searchController.state,
|
|
28522
28546
|
searchControllerStateSelector
|
|
28523
28547
|
);
|
|
28524
|
-
const activeChannelHandler = async (channels2, setChannels2) => {
|
|
28548
|
+
const activeChannelHandler = async (channels2, setChannels2, effectiveQueryParams) => {
|
|
28525
28549
|
if (!channels2.length) {
|
|
28526
28550
|
return;
|
|
28527
28551
|
}
|
|
@@ -28539,7 +28563,7 @@ const UnMemoizedChannelList = (props) => {
|
|
|
28539
28563
|
const newChannels = moveChannelUpwards({
|
|
28540
28564
|
channels: channels2,
|
|
28541
28565
|
channelToMove: customActiveChannelObject,
|
|
28542
|
-
sort
|
|
28566
|
+
sort: effectiveQueryParams.sort
|
|
28543
28567
|
});
|
|
28544
28568
|
setChannels2(newChannels);
|
|
28545
28569
|
return;
|
|
@@ -28550,7 +28574,14 @@ const UnMemoizedChannelList = (props) => {
|
|
|
28550
28574
|
}
|
|
28551
28575
|
};
|
|
28552
28576
|
const forceUpdate = React.useCallback(() => setChannelUpdateCount((count) => count + 1), []);
|
|
28553
|
-
const {
|
|
28577
|
+
const {
|
|
28578
|
+
channels,
|
|
28579
|
+
effectiveFilters,
|
|
28580
|
+
effectiveSort,
|
|
28581
|
+
hasNextPage,
|
|
28582
|
+
loadNextPage,
|
|
28583
|
+
setChannels
|
|
28584
|
+
} = usePaginatedChannels(
|
|
28554
28585
|
client,
|
|
28555
28586
|
filters || DEFAULT_FILTERS,
|
|
28556
28587
|
sort || DEFAULT_SORT,
|
|
@@ -28562,7 +28593,11 @@ const UnMemoizedChannelList = (props) => {
|
|
|
28562
28593
|
const loadedChannels = channelRenderFilterFn ? channelRenderFilterFn(channels) : channels;
|
|
28563
28594
|
const { customHandler, defaultHandler } = usePrepareShapeHandlers({
|
|
28564
28595
|
allowNewMessagesFromUnfilteredChannels,
|
|
28565
|
-
|
|
28596
|
+
// `effectiveFilters`/`effectiveSort` reflect the backend-resolved
|
|
28597
|
+
// `predefined_filter` metadata when `options.predefined_filter` is in use.
|
|
28598
|
+
// For non-predefined queries they fall back to the caller-supplied
|
|
28599
|
+
// `filters`/`sort` props so behavior is unchanged.
|
|
28600
|
+
filters: effectiveFilters,
|
|
28566
28601
|
lockChannelOrder,
|
|
28567
28602
|
onAddedToChannel,
|
|
28568
28603
|
onChannelDeleted,
|
|
@@ -28574,7 +28609,7 @@ const UnMemoizedChannelList = (props) => {
|
|
|
28574
28609
|
onMessageNewHandler,
|
|
28575
28610
|
onRemovedFromChannel,
|
|
28576
28611
|
setChannels,
|
|
28577
|
-
sort
|
|
28612
|
+
sort: effectiveSort
|
|
28578
28613
|
// TODO: implement
|
|
28579
28614
|
// customHandleChannelListShape
|
|
28580
28615
|
});
|
|
@@ -30006,7 +30041,7 @@ const Notification = React.forwardRef(
|
|
|
30006
30041
|
}
|
|
30007
30042
|
removeNotification(notification.id);
|
|
30008
30043
|
};
|
|
30009
|
-
const
|
|
30044
|
+
const isPersistent2 = !notification.duration;
|
|
30010
30045
|
const severity = notification.severity;
|
|
30011
30046
|
const livePriority = severity === "error" ? "assertive" : "polite";
|
|
30012
30047
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -30052,7 +30087,7 @@ const Notification = React.forwardRef(
|
|
|
30052
30087
|
},
|
|
30053
30088
|
index
|
|
30054
30089
|
)) }),
|
|
30055
|
-
(showClose ||
|
|
30090
|
+
(showClose || isPersistent2) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
30056
30091
|
useNotificationApi.Button,
|
|
30057
30092
|
{
|
|
30058
30093
|
appearance: "ghost",
|
|
@@ -30079,6 +30114,7 @@ const ENTER_TRANSLATION = {
|
|
|
30079
30114
|
top: { x: "0%", y: "-100%" }
|
|
30080
30115
|
};
|
|
30081
30116
|
const EXIT_ANIMATION_MS = 340;
|
|
30117
|
+
const DEFAULT_MIN_DISPLAY_MS = 1e3;
|
|
30082
30118
|
const isEnterFrom = (value) => value === "bottom" || value === "left" || value === "right" || value === "top";
|
|
30083
30119
|
const getNotificationEnterFrom = (notification, fallbackEnterFrom) => {
|
|
30084
30120
|
if (!notification) return fallbackEnterFrom;
|
|
@@ -30088,19 +30124,93 @@ const getNotificationEnterFrom = (notification, fallbackEnterFrom) => {
|
|
|
30088
30124
|
if (isEnterFrom(originEnterFrom)) return originEnterFrom;
|
|
30089
30125
|
return fallbackEnterFrom;
|
|
30090
30126
|
};
|
|
30127
|
+
const isPersistent = (notification) => !notification.duration;
|
|
30128
|
+
const haveSameType = (a, b) => !!a?.type && !!b?.type && a.type === b.type;
|
|
30129
|
+
const pickOldest = (notifications, displayed) => {
|
|
30130
|
+
const excludeId = displayed?.id ?? null;
|
|
30131
|
+
let oldest = null;
|
|
30132
|
+
for (const notification of notifications) {
|
|
30133
|
+
if (notification.id === excludeId) continue;
|
|
30134
|
+
if (!oldest || notification.createdAt < oldest.createdAt) {
|
|
30135
|
+
oldest = notification;
|
|
30136
|
+
}
|
|
30137
|
+
}
|
|
30138
|
+
return oldest;
|
|
30139
|
+
};
|
|
30140
|
+
const pickNewest = (notifications, displayed) => {
|
|
30141
|
+
const excludeId = displayed?.id ?? null;
|
|
30142
|
+
let newest = null;
|
|
30143
|
+
for (const notification of notifications) {
|
|
30144
|
+
if (notification.id === excludeId) continue;
|
|
30145
|
+
if (!newest || notification.createdAt > newest.createdAt) {
|
|
30146
|
+
newest = notification;
|
|
30147
|
+
}
|
|
30148
|
+
}
|
|
30149
|
+
return newest;
|
|
30150
|
+
};
|
|
30151
|
+
const pickNewestPersistent = (notifications, excludeId) => {
|
|
30152
|
+
let newest = null;
|
|
30153
|
+
for (const notification of notifications) {
|
|
30154
|
+
if (notification.id === excludeId) continue;
|
|
30155
|
+
if (!isPersistent(notification)) continue;
|
|
30156
|
+
if (!newest || notification.createdAt > newest.createdAt) {
|
|
30157
|
+
newest = notification;
|
|
30158
|
+
}
|
|
30159
|
+
}
|
|
30160
|
+
return newest;
|
|
30161
|
+
};
|
|
30162
|
+
const pickNewestOfType = (notifications, type, excludeId) => {
|
|
30163
|
+
if (!type) return null;
|
|
30164
|
+
let newest = null;
|
|
30165
|
+
for (const notification of notifications) {
|
|
30166
|
+
if (notification.id === excludeId) continue;
|
|
30167
|
+
if (notification.type !== type) continue;
|
|
30168
|
+
if (!newest || notification.createdAt > newest.createdAt) {
|
|
30169
|
+
newest = notification;
|
|
30170
|
+
}
|
|
30171
|
+
}
|
|
30172
|
+
return newest;
|
|
30173
|
+
};
|
|
30174
|
+
const createDefaultPickNext = (pickFromQueue = pickOldest) => (notifications, displayed) => {
|
|
30175
|
+
if (notifications.length === 0) return null;
|
|
30176
|
+
const newestPersistent = pickNewestPersistent(notifications, null);
|
|
30177
|
+
if (!displayed) {
|
|
30178
|
+
return newestPersistent ?? pickFromQueue(notifications, null);
|
|
30179
|
+
}
|
|
30180
|
+
const displayedInStore = notifications.some(({ id }) => id === displayed.id);
|
|
30181
|
+
if (!displayedInStore) {
|
|
30182
|
+
return newestPersistent ?? pickFromQueue(notifications, null);
|
|
30183
|
+
}
|
|
30184
|
+
if (isPersistent(displayed)) {
|
|
30185
|
+
const newerPersistent = newestPersistent && newestPersistent.id !== displayed.id ? newestPersistent : pickNewestPersistent(notifications, displayed.id);
|
|
30186
|
+
if (newerPersistent && newerPersistent.createdAt > displayed.createdAt) {
|
|
30187
|
+
return newerPersistent;
|
|
30188
|
+
}
|
|
30189
|
+
return displayed;
|
|
30190
|
+
}
|
|
30191
|
+
const sameTypeNewest = pickNewestOfType(notifications, displayed.type, displayed.id);
|
|
30192
|
+
if (sameTypeNewest) return sameTypeNewest;
|
|
30193
|
+
if (newestPersistent) return newestPersistent;
|
|
30194
|
+
return pickFromQueue(notifications, displayed) ?? displayed;
|
|
30195
|
+
};
|
|
30196
|
+
const defaultPickNext = createDefaultPickNext(pickOldest);
|
|
30091
30197
|
const NotificationList = ({
|
|
30092
30198
|
className,
|
|
30093
30199
|
enterFrom = "bottom",
|
|
30094
30200
|
fallbackPanel,
|
|
30095
30201
|
filter,
|
|
30202
|
+
minDisplayMs = DEFAULT_MIN_DISPLAY_MS,
|
|
30096
30203
|
panel,
|
|
30204
|
+
pickNext = defaultPickNext,
|
|
30097
30205
|
verticalAlignment = "bottom"
|
|
30098
30206
|
}) => {
|
|
30099
30207
|
const { Notification: NotificationComponent = Notification } = useNotificationApi.useComponentContext();
|
|
30100
30208
|
const { t } = useNotificationApi.useTranslationContext();
|
|
30101
30209
|
const { removeNotification, startNotificationTimeout } = useNotificationApi.useNotificationApi();
|
|
30102
30210
|
const exitTimeoutRef = React.useRef(null);
|
|
30103
|
-
const
|
|
30211
|
+
const replacementTimeoutRef = React.useRef(null);
|
|
30212
|
+
const candidateRef = React.useRef(null);
|
|
30213
|
+
const displayedAtRef = React.useRef(null);
|
|
30104
30214
|
const listRef = React.useRef(null);
|
|
30105
30215
|
const observedElementRef = React.useRef(null);
|
|
30106
30216
|
const startedTimeoutIdsRef = React.useRef(null);
|
|
@@ -30123,7 +30233,6 @@ const NotificationList = ({
|
|
|
30123
30233
|
filter: combinedFilter,
|
|
30124
30234
|
panel
|
|
30125
30235
|
});
|
|
30126
|
-
const nextNotification = notifications[0] ?? null;
|
|
30127
30236
|
const dismiss = React.useCallback(
|
|
30128
30237
|
(id) => {
|
|
30129
30238
|
startedTimeoutIdsRef.current?.delete(id);
|
|
@@ -30139,33 +30248,105 @@ const NotificationList = ({
|
|
|
30139
30248
|
}
|
|
30140
30249
|
});
|
|
30141
30250
|
}, [notifications]);
|
|
30142
|
-
React.
|
|
30143
|
-
|
|
30144
|
-
|
|
30251
|
+
const clearReplacementTimeout = React.useCallback(() => {
|
|
30252
|
+
if (replacementTimeoutRef.current !== null) {
|
|
30253
|
+
window.clearTimeout(replacementTimeoutRef.current);
|
|
30254
|
+
replacementTimeoutRef.current = null;
|
|
30255
|
+
}
|
|
30256
|
+
}, []);
|
|
30145
30257
|
React.useEffect(
|
|
30146
30258
|
() => () => {
|
|
30147
|
-
|
|
30259
|
+
clearReplacementTimeout();
|
|
30260
|
+
if (exitTimeoutRef.current !== null) {
|
|
30148
30261
|
window.clearTimeout(exitTimeoutRef.current);
|
|
30262
|
+
exitTimeoutRef.current = null;
|
|
30149
30263
|
}
|
|
30150
30264
|
},
|
|
30151
|
-
[]
|
|
30265
|
+
[clearReplacementTimeout]
|
|
30152
30266
|
);
|
|
30153
30267
|
React.useEffect(() => {
|
|
30268
|
+
candidateRef.current = pickNext(notifications, displayedNotification);
|
|
30269
|
+
}, [displayedNotification, notifications, pickNext]);
|
|
30270
|
+
React.useEffect(() => {
|
|
30271
|
+
if (transitionState === "exit") return;
|
|
30154
30272
|
if (!displayedNotification) {
|
|
30155
|
-
|
|
30156
|
-
|
|
30157
|
-
|
|
30273
|
+
const candidate2 = pickNext(notifications, null);
|
|
30274
|
+
if (candidate2) {
|
|
30275
|
+
displayedAtRef.current = Date.now();
|
|
30276
|
+
setDisplayedNotification(candidate2);
|
|
30277
|
+
setTransitionState("enter");
|
|
30278
|
+
}
|
|
30158
30279
|
return;
|
|
30159
30280
|
}
|
|
30160
|
-
|
|
30161
|
-
if (
|
|
30162
|
-
|
|
30163
|
-
|
|
30164
|
-
|
|
30165
|
-
|
|
30166
|
-
|
|
30167
|
-
|
|
30168
|
-
|
|
30281
|
+
const candidate = pickNext(notifications, displayedNotification);
|
|
30282
|
+
if (!candidate) {
|
|
30283
|
+
clearReplacementTimeout();
|
|
30284
|
+
setTransitionState("exit");
|
|
30285
|
+
exitTimeoutRef.current = window.setTimeout(() => {
|
|
30286
|
+
exitTimeoutRef.current = null;
|
|
30287
|
+
displayedAtRef.current = null;
|
|
30288
|
+
setDisplayedNotification(null);
|
|
30289
|
+
setTransitionState("enter");
|
|
30290
|
+
}, EXIT_ANIMATION_MS);
|
|
30291
|
+
return;
|
|
30292
|
+
}
|
|
30293
|
+
if (candidate.id === displayedNotification.id) {
|
|
30294
|
+
clearReplacementTimeout();
|
|
30295
|
+
return;
|
|
30296
|
+
}
|
|
30297
|
+
const displayedInStore = notifications.some(
|
|
30298
|
+
({ id }) => id === displayedNotification.id
|
|
30299
|
+
);
|
|
30300
|
+
const startSwap = () => {
|
|
30301
|
+
replacementTimeoutRef.current = null;
|
|
30302
|
+
setTransitionState("exit");
|
|
30303
|
+
const previousId = displayedNotification.id;
|
|
30304
|
+
const wasInStore = displayedInStore;
|
|
30305
|
+
exitTimeoutRef.current = window.setTimeout(() => {
|
|
30306
|
+
exitTimeoutRef.current = null;
|
|
30307
|
+
if (wasInStore) {
|
|
30308
|
+
startedTimeoutIdsRef.current?.delete(previousId);
|
|
30309
|
+
removeNotification(previousId);
|
|
30310
|
+
}
|
|
30311
|
+
const next = candidateRef.current;
|
|
30312
|
+
if (next && next.id !== previousId) {
|
|
30313
|
+
displayedAtRef.current = Date.now();
|
|
30314
|
+
setDisplayedNotification(next);
|
|
30315
|
+
setTransitionState("enter");
|
|
30316
|
+
} else {
|
|
30317
|
+
displayedAtRef.current = null;
|
|
30318
|
+
setDisplayedNotification(null);
|
|
30319
|
+
setTransitionState("enter");
|
|
30320
|
+
}
|
|
30321
|
+
}, EXIT_ANIMATION_MS);
|
|
30322
|
+
};
|
|
30323
|
+
if (!displayedInStore) {
|
|
30324
|
+
clearReplacementTimeout();
|
|
30325
|
+
startSwap();
|
|
30326
|
+
return;
|
|
30327
|
+
}
|
|
30328
|
+
if (haveSameType(displayedNotification, candidate)) {
|
|
30329
|
+
clearReplacementTimeout();
|
|
30330
|
+
startSwap();
|
|
30331
|
+
return;
|
|
30332
|
+
}
|
|
30333
|
+
const elapsed = displayedAtRef.current ? Date.now() - displayedAtRef.current : 0;
|
|
30334
|
+
const remaining = Math.max(0, minDisplayMs - elapsed);
|
|
30335
|
+
if (remaining === 0) {
|
|
30336
|
+
clearReplacementTimeout();
|
|
30337
|
+
startSwap();
|
|
30338
|
+
} else if (replacementTimeoutRef.current === null) {
|
|
30339
|
+
replacementTimeoutRef.current = window.setTimeout(startSwap, remaining);
|
|
30340
|
+
}
|
|
30341
|
+
}, [
|
|
30342
|
+
clearReplacementTimeout,
|
|
30343
|
+
displayedNotification,
|
|
30344
|
+
minDisplayMs,
|
|
30345
|
+
notifications,
|
|
30346
|
+
pickNext,
|
|
30347
|
+
removeNotification,
|
|
30348
|
+
transitionState
|
|
30349
|
+
]);
|
|
30169
30350
|
const notification = displayedNotification;
|
|
30170
30351
|
const notificationEnterFrom = getNotificationEnterFrom(notification, enterFrom);
|
|
30171
30352
|
React.useEffect(() => {
|
|
@@ -30647,7 +30828,7 @@ const useChat = ({
|
|
|
30647
30828
|
};
|
|
30648
30829
|
React.useEffect(() => {
|
|
30649
30830
|
if (!client) return;
|
|
30650
|
-
const version = "14.
|
|
30831
|
+
const version = "14.3.0";
|
|
30651
30832
|
const userAgent = client.getUserAgent();
|
|
30652
30833
|
if (!userAgent.includes("stream-chat-react")) {
|
|
30653
30834
|
client.setUserAgent(`stream-chat-react-${version}-${userAgent}`);
|
|
@@ -31336,6 +31517,7 @@ exports.WaveProgressBar = WaveProgressBar;
|
|
|
31336
31517
|
exports.Window = Window;
|
|
31337
31518
|
exports.WithComponents = WithComponents;
|
|
31338
31519
|
exports.WithDragAndDropUpload = WithDragAndDropUpload;
|
|
31520
|
+
exports.createDefaultPickNext = createDefaultPickNext;
|
|
31339
31521
|
exports.deTranslations = deTranslations;
|
|
31340
31522
|
exports.defaultAllowedTagNames = defaultAllowedTagNames;
|
|
31341
31523
|
exports.defaultAttachmentActionsDefaultFocus = defaultAttachmentActionsDefaultFocus;
|
|
@@ -31358,6 +31540,7 @@ exports.frTranslations = frTranslations;
|
|
|
31358
31540
|
exports.getChannelDisplayImage = getChannelDisplayImage;
|
|
31359
31541
|
exports.getCssDimensionsVariables = getCssDimensionsVariables;
|
|
31360
31542
|
exports.getGroupChannelDisplayInfo = getGroupChannelDisplayInfo;
|
|
31543
|
+
exports.getHasExtendedReactions = getHasExtendedReactions;
|
|
31361
31544
|
exports.getLatestMessagePreview = getLatestMessagePreview;
|
|
31362
31545
|
exports.getTextareaCaretRect = getTextareaCaretRect;
|
|
31363
31546
|
exports.getTranslatedMessageText = getTranslatedMessageText;
|
|
@@ -31388,6 +31571,8 @@ exports.modalDialogId = modalDialogId;
|
|
|
31388
31571
|
exports.modalDialogManagerId = modalDialogManagerId;
|
|
31389
31572
|
exports.moveChannelUpwards = moveChannelUpwards;
|
|
31390
31573
|
exports.nlTranslations = nlTranslations;
|
|
31574
|
+
exports.pickNewest = pickNewest;
|
|
31575
|
+
exports.pickOldest = pickOldest;
|
|
31391
31576
|
exports.plusPlusToEmphasis = plusPlusToEmphasis;
|
|
31392
31577
|
exports.ptTranslations = ptTranslations;
|
|
31393
31578
|
exports.reactionHandlerWarning = reactionHandlerWarning;
|