stream-chat-react-native-core 8.13.13 → 8.13.14
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/lib/commonjs/components/AutoCompleteInput/AutoCompleteSuggestionList.js +3 -2
- package/lib/commonjs/components/AutoCompleteInput/AutoCompleteSuggestionList.js.map +1 -1
- package/lib/commonjs/components/Channel/Channel.js +18 -2
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Channel/hooks/useCreateChannelContext.js +2 -0
- package/lib/commonjs/components/Channel/hooks/useCreateChannelContext.js.map +1 -1
- package/lib/commonjs/components/MessageList/MessageFlashList.js +43 -32
- package/lib/commonjs/components/MessageList/MessageFlashList.js.map +1 -1
- package/lib/commonjs/contexts/channelContext/ChannelContext.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/AutoCompleteInput/AutoCompleteSuggestionList.js +3 -2
- package/lib/module/components/AutoCompleteInput/AutoCompleteSuggestionList.js.map +1 -1
- package/lib/module/components/Channel/Channel.js +18 -2
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Channel/hooks/useCreateChannelContext.js +2 -0
- package/lib/module/components/Channel/hooks/useCreateChannelContext.js.map +1 -1
- package/lib/module/components/MessageList/MessageFlashList.js +43 -32
- package/lib/module/components/MessageList/MessageFlashList.js.map +1 -1
- package/lib/module/contexts/channelContext/ChannelContext.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateChannelContext.d.ts +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateChannelContext.d.ts.map +1 -1
- package/lib/typescript/components/MessageList/MessageFlashList.d.ts +1 -1
- package/lib/typescript/components/MessageList/MessageFlashList.d.ts.map +1 -1
- package/lib/typescript/contexts/channelContext/ChannelContext.d.ts +6 -0
- package/lib/typescript/contexts/channelContext/ChannelContext.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/offline-support/offline-feature.js +10 -2
- package/src/components/AutoCompleteInput/AutoCompleteSuggestionList.tsx +2 -1
- package/src/components/Channel/Channel.tsx +21 -6
- package/src/components/Channel/hooks/useCreateChannelContext.ts +2 -0
- package/src/components/MessageList/MessageFlashList.tsx +31 -25
- package/src/contexts/channelContext/ChannelContext.tsx +6 -0
- package/src/version.json +1 -1
|
@@ -834,6 +834,18 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
|
|
|
834
834
|
channel,
|
|
835
835
|
});
|
|
836
836
|
|
|
837
|
+
const shouldLoadInitialChannelAtFirstUnreadMessage = useStableCallback((unreadCount?: number) => {
|
|
838
|
+
if (messageId || !initialScrollToFirstUnreadMessage || !client.user) {
|
|
839
|
+
return false;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
return (unreadCount ?? channel.countUnread()) > scrollToFirstUnreadThreshold;
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
const hasPendingInitialTargetLoad = useStableCallback(() => {
|
|
846
|
+
return !!messageId || shouldLoadInitialChannelAtFirstUnreadMessage();
|
|
847
|
+
});
|
|
848
|
+
|
|
837
849
|
const { setMessages: copyMessagesStateFromChannel, viewabilityChangedCallback } =
|
|
838
850
|
usePrunableMessageList({ maximumMessageLimit, setMessages: rawCopyMessagesStateFromChannel });
|
|
839
851
|
|
|
@@ -960,6 +972,7 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
|
|
|
960
972
|
const initChannel = async () => {
|
|
961
973
|
setLastRead(new Date());
|
|
962
974
|
const unreadCount = channel.countUnread();
|
|
975
|
+
const shouldLoadAtFirstUnread = shouldLoadInitialChannelAtFirstUnreadMessage(unreadCount);
|
|
963
976
|
if (!channel || !shouldSyncChannel) {
|
|
964
977
|
return;
|
|
965
978
|
}
|
|
@@ -989,13 +1002,14 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
|
|
|
989
1002
|
|
|
990
1003
|
if (messageId) {
|
|
991
1004
|
await loadChannelAroundMessage({ messageId, setTargetedMessage });
|
|
992
|
-
} else if (
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1005
|
+
} else if (shouldLoadAtFirstUnread) {
|
|
1006
|
+
const clientUserId = client.user?.id;
|
|
1007
|
+
if (!clientUserId) {
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
997
1011
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
998
|
-
const { user, ...ownReadState } = channel.state.read[
|
|
1012
|
+
const { user, ...ownReadState } = channel.state.read[clientUserId];
|
|
999
1013
|
|
|
1000
1014
|
await loadChannelAtFirstUnreadMessage({
|
|
1001
1015
|
channelUnreadState: ownReadState,
|
|
@@ -1788,6 +1802,7 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
|
|
|
1788
1802
|
enableMessageGroupingByUser,
|
|
1789
1803
|
enforceUniqueReaction,
|
|
1790
1804
|
error,
|
|
1805
|
+
hasPendingInitialTargetLoad,
|
|
1791
1806
|
hideDateSeparators,
|
|
1792
1807
|
hideStickyDateHeader,
|
|
1793
1808
|
highlightedMessageId,
|
|
@@ -31,6 +31,7 @@ export const useCreateChannelContext = ({
|
|
|
31
31
|
setChannelUnreadState,
|
|
32
32
|
setLastRead,
|
|
33
33
|
setTargetedMessage,
|
|
34
|
+
hasPendingInitialTargetLoad,
|
|
34
35
|
StickyHeader,
|
|
35
36
|
targetedMessage,
|
|
36
37
|
threadList,
|
|
@@ -58,6 +59,7 @@ export const useCreateChannelContext = ({
|
|
|
58
59
|
enableMessageGroupingByUser,
|
|
59
60
|
enforceUniqueReaction,
|
|
60
61
|
error,
|
|
62
|
+
hasPendingInitialTargetLoad,
|
|
61
63
|
hideDateSeparators,
|
|
62
64
|
hideStickyDateHeader,
|
|
63
65
|
highlightedMessageId,
|
|
@@ -119,6 +119,7 @@ type MessageFlashListPropsWithContext = Pick<
|
|
|
119
119
|
| 'scrollToFirstUnreadThreshold'
|
|
120
120
|
| 'setChannelUnreadState'
|
|
121
121
|
| 'setTargetedMessage'
|
|
122
|
+
| 'hasPendingInitialTargetLoad'
|
|
122
123
|
| 'StickyHeader'
|
|
123
124
|
| 'targetedMessage'
|
|
124
125
|
| 'threadList'
|
|
@@ -298,6 +299,7 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
298
299
|
setMessages,
|
|
299
300
|
setSelectedPicker,
|
|
300
301
|
setTargetedMessage,
|
|
302
|
+
hasPendingInitialTargetLoad,
|
|
301
303
|
StickyHeader,
|
|
302
304
|
targetedMessage,
|
|
303
305
|
thread,
|
|
@@ -389,11 +391,15 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
389
391
|
|
|
390
392
|
useEffect(() => {
|
|
391
393
|
if (autoscrollToRecent && flashListRef.current) {
|
|
394
|
+
if (hasPendingInitialTargetLoad?.()) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
|
|
392
398
|
flashListRef.current.scrollToEnd({
|
|
393
399
|
animated: true,
|
|
394
400
|
});
|
|
395
401
|
}
|
|
396
|
-
}, [autoscrollToRecent]);
|
|
402
|
+
}, [autoscrollToRecent, hasPendingInitialTargetLoad]);
|
|
397
403
|
|
|
398
404
|
const maintainVisibleContentPosition = useMemo(() => {
|
|
399
405
|
return {
|
|
@@ -409,18 +415,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
409
415
|
}
|
|
410
416
|
}, [disabled]);
|
|
411
417
|
|
|
412
|
-
const indexToScrollToRef = useRef<number | undefined>(undefined);
|
|
413
|
-
|
|
414
|
-
const initialIndexToScrollTo = useMemo(() => {
|
|
415
|
-
return targetedMessage
|
|
416
|
-
? processedMessageList.findIndex((message) => message?.id === targetedMessage)
|
|
417
|
-
: -1;
|
|
418
|
-
}, [processedMessageList, targetedMessage]);
|
|
419
|
-
|
|
420
|
-
useEffect(() => {
|
|
421
|
-
indexToScrollToRef.current = initialIndexToScrollTo;
|
|
422
|
-
}, [initialIndexToScrollTo]);
|
|
423
|
-
|
|
424
418
|
/**
|
|
425
419
|
* Check if a messageId needs to be scrolled to after list loads, and scroll to it
|
|
426
420
|
* Note: This effect fires on every list change with a small debounce so that scrolling isnt abrupted by an immediate rerender
|
|
@@ -441,13 +435,29 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
441
435
|
scrollToDebounceTimeoutRef.current = setTimeout(() => {
|
|
442
436
|
clearTimeout(scrollToDebounceTimeoutRef.current);
|
|
443
437
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
438
|
+
const scrollToIndex = async () => {
|
|
439
|
+
const list = flashListRef.current;
|
|
440
|
+
|
|
441
|
+
if (!list) {
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
await list.scrollToIndex({
|
|
446
|
+
animated: true,
|
|
447
|
+
index: indexOfParentInMessageList,
|
|
448
|
+
viewPosition: 0.5,
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
return true;
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
requestAnimationFrame(async () => {
|
|
455
|
+
await scrollToIndex();
|
|
456
|
+
requestAnimationFrame(async () => {
|
|
457
|
+
await scrollToIndex();
|
|
458
|
+
setTargetedMessage(undefined);
|
|
459
|
+
});
|
|
449
460
|
});
|
|
450
|
-
setTargetedMessage(undefined);
|
|
451
461
|
}, WAIT_FOR_SCROLL_TIMEOUT);
|
|
452
462
|
}
|
|
453
463
|
}, [loadChannelAroundMessage, processedMessageList, setTargetedMessage, targetedMessage]);
|
|
@@ -457,8 +467,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
457
467
|
(message) => message?.id === messageId,
|
|
458
468
|
);
|
|
459
469
|
|
|
460
|
-
indexToScrollToRef.current = indexOfParentInMessageList;
|
|
461
|
-
|
|
462
470
|
try {
|
|
463
471
|
if (indexOfParentInMessageList === -1) {
|
|
464
472
|
clearTimeout(scrollToDebounceTimeoutRef.current);
|
|
@@ -530,7 +538,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
530
538
|
setScrollToBottomButtonVisible(true);
|
|
531
539
|
return;
|
|
532
540
|
} else {
|
|
533
|
-
indexToScrollToRef.current = undefined;
|
|
534
541
|
setAutoscrollToRecent(true);
|
|
535
542
|
}
|
|
536
543
|
const latestNonCurrentMessageBeforeUpdate = latestNonCurrentMessageBeforeUpdateRef.current;
|
|
@@ -1072,9 +1079,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
1072
1079
|
data={processedMessageList}
|
|
1073
1080
|
drawDistance={800}
|
|
1074
1081
|
getItemType={getItemTypeInternal}
|
|
1075
|
-
initialScrollIndex={
|
|
1076
|
-
indexToScrollToRef.current === -1 ? undefined : indexToScrollToRef.current
|
|
1077
|
-
}
|
|
1078
1082
|
keyboardShouldPersistTaps='handled'
|
|
1079
1083
|
keyExtractor={keyExtractor}
|
|
1080
1084
|
ListFooterComponent={FooterComponent}
|
|
@@ -1151,6 +1155,7 @@ export const MessageFlashList = (props: MessageFlashListProps) => {
|
|
|
1151
1155
|
scrollToFirstUnreadThreshold,
|
|
1152
1156
|
setChannelUnreadState,
|
|
1153
1157
|
setTargetedMessage,
|
|
1158
|
+
hasPendingInitialTargetLoad,
|
|
1154
1159
|
StickyHeader,
|
|
1155
1160
|
targetedMessage,
|
|
1156
1161
|
threadList,
|
|
@@ -1192,6 +1197,7 @@ export const MessageFlashList = (props: MessageFlashListProps) => {
|
|
|
1192
1197
|
enableMessageGroupingByUser,
|
|
1193
1198
|
error,
|
|
1194
1199
|
FlatList,
|
|
1200
|
+
hasPendingInitialTargetLoad,
|
|
1195
1201
|
hideStickyDateHeader,
|
|
1196
1202
|
highlightedMessageId,
|
|
1197
1203
|
InlineDateSeparator,
|
|
@@ -130,6 +130,12 @@ export type ChannelContextValue = {
|
|
|
130
130
|
setChannelUnreadState: (data: ChannelUnreadStateStoreType['channelUnreadState']) => void;
|
|
131
131
|
setLastRead: React.Dispatch<React.SetStateAction<Date | undefined>>;
|
|
132
132
|
setTargetedMessage: (messageId?: string) => void;
|
|
133
|
+
/**
|
|
134
|
+
* Returns true when Channel is about to load an initial targeted message.
|
|
135
|
+
*
|
|
136
|
+
* @internal
|
|
137
|
+
*/
|
|
138
|
+
hasPendingInitialTargetLoad?: () => boolean;
|
|
133
139
|
/**
|
|
134
140
|
* Abort controller for cancelling async requests made for uploading images/files
|
|
135
141
|
* Its a map of filename and AbortController
|
package/src/version.json
CHANGED