stream-chat-react-native-core 8.13.13 → 8.13.15
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 +44 -34
- 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 +44 -34
- 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 -26
- 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,16 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
389
391
|
|
|
390
392
|
useEffect(() => {
|
|
391
393
|
if (autoscrollToRecent && flashListRef.current) {
|
|
394
|
+
if (hasPendingInitialTargetLoad?.()) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
console.log('[STREAM] scrollToEnd effect#1 (autoscrollToRecent) fired');
|
|
392
399
|
flashListRef.current.scrollToEnd({
|
|
393
400
|
animated: true,
|
|
394
401
|
});
|
|
395
402
|
}
|
|
396
|
-
}, [autoscrollToRecent]);
|
|
403
|
+
}, [autoscrollToRecent, hasPendingInitialTargetLoad]);
|
|
397
404
|
|
|
398
405
|
const maintainVisibleContentPosition = useMemo(() => {
|
|
399
406
|
return {
|
|
@@ -409,18 +416,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
409
416
|
}
|
|
410
417
|
}, [disabled]);
|
|
411
418
|
|
|
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
419
|
/**
|
|
425
420
|
* Check if a messageId needs to be scrolled to after list loads, and scroll to it
|
|
426
421
|
* Note: This effect fires on every list change with a small debounce so that scrolling isnt abrupted by an immediate rerender
|
|
@@ -438,16 +433,30 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
438
433
|
if (indexOfParentInMessageList === -1) {
|
|
439
434
|
loadChannelAroundMessage({ messageId: targetedMessage, setTargetedMessage });
|
|
440
435
|
} else {
|
|
441
|
-
scrollToDebounceTimeoutRef.current = setTimeout(() => {
|
|
436
|
+
scrollToDebounceTimeoutRef.current = setTimeout(async () => {
|
|
442
437
|
clearTimeout(scrollToDebounceTimeoutRef.current);
|
|
443
438
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
439
|
+
const scrollToIndex = async () => {
|
|
440
|
+
const list = flashListRef.current;
|
|
441
|
+
|
|
442
|
+
if (!list) {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
await list.scrollToIndex({
|
|
447
|
+
animated: true,
|
|
448
|
+
index: indexOfParentInMessageList,
|
|
449
|
+
viewPosition: 0.5,
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
return true;
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
await scrollToIndex();
|
|
456
|
+
requestAnimationFrame(async () => {
|
|
457
|
+
await scrollToIndex();
|
|
458
|
+
setTargetedMessage(undefined);
|
|
449
459
|
});
|
|
450
|
-
setTargetedMessage(undefined);
|
|
451
460
|
}, WAIT_FOR_SCROLL_TIMEOUT);
|
|
452
461
|
}
|
|
453
462
|
}, [loadChannelAroundMessage, processedMessageList, setTargetedMessage, targetedMessage]);
|
|
@@ -457,8 +466,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
457
466
|
(message) => message?.id === messageId,
|
|
458
467
|
);
|
|
459
468
|
|
|
460
|
-
indexToScrollToRef.current = indexOfParentInMessageList;
|
|
461
|
-
|
|
462
469
|
try {
|
|
463
470
|
if (indexOfParentInMessageList === -1) {
|
|
464
471
|
clearTimeout(scrollToDebounceTimeoutRef.current);
|
|
@@ -530,7 +537,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
530
537
|
setScrollToBottomButtonVisible(true);
|
|
531
538
|
return;
|
|
532
539
|
} else {
|
|
533
|
-
indexToScrollToRef.current = undefined;
|
|
534
540
|
setAutoscrollToRecent(true);
|
|
535
541
|
}
|
|
536
542
|
const latestNonCurrentMessageBeforeUpdate = latestNonCurrentMessageBeforeUpdateRef.current;
|
|
@@ -1072,9 +1078,6 @@ const MessageFlashListWithContext = (props: MessageFlashListPropsWithContext) =>
|
|
|
1072
1078
|
data={processedMessageList}
|
|
1073
1079
|
drawDistance={800}
|
|
1074
1080
|
getItemType={getItemTypeInternal}
|
|
1075
|
-
initialScrollIndex={
|
|
1076
|
-
indexToScrollToRef.current === -1 ? undefined : indexToScrollToRef.current
|
|
1077
|
-
}
|
|
1078
1081
|
keyboardShouldPersistTaps='handled'
|
|
1079
1082
|
keyExtractor={keyExtractor}
|
|
1080
1083
|
ListFooterComponent={FooterComponent}
|
|
@@ -1151,6 +1154,7 @@ export const MessageFlashList = (props: MessageFlashListProps) => {
|
|
|
1151
1154
|
scrollToFirstUnreadThreshold,
|
|
1152
1155
|
setChannelUnreadState,
|
|
1153
1156
|
setTargetedMessage,
|
|
1157
|
+
hasPendingInitialTargetLoad,
|
|
1154
1158
|
StickyHeader,
|
|
1155
1159
|
targetedMessage,
|
|
1156
1160
|
threadList,
|
|
@@ -1192,6 +1196,7 @@ export const MessageFlashList = (props: MessageFlashListProps) => {
|
|
|
1192
1196
|
enableMessageGroupingByUser,
|
|
1193
1197
|
error,
|
|
1194
1198
|
FlatList,
|
|
1199
|
+
hasPendingInitialTargetLoad,
|
|
1195
1200
|
hideStickyDateHeader,
|
|
1196
1201
|
highlightedMessageId,
|
|
1197
1202
|
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