stream-chat-react-native-core 5.38.1 → 5.39.0-beta.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/lib/commonjs/components/Channel/Channel.js +58 -25
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Channel/hooks/useCreateThreadContext.js +33 -21
- package/lib/commonjs/components/Channel/hooks/useCreateThreadContext.js.map +1 -1
- package/lib/commonjs/components/Chat/Chat.js +7 -0
- package/lib/commonjs/components/Chat/Chat.js.map +1 -1
- package/lib/commonjs/components/Indicators/EmptyStateIndicator.js +14 -0
- package/lib/commonjs/components/Indicators/EmptyStateIndicator.js.map +1 -1
- package/lib/commonjs/components/Indicators/LoadingIndicator.js +4 -0
- package/lib/commonjs/components/Indicators/LoadingIndicator.js.map +1 -1
- package/lib/commonjs/components/Message/hooks/useProcessReactions.js +13 -7
- package/lib/commonjs/components/Message/hooks/useProcessReactions.js.map +1 -1
- package/lib/commonjs/components/MessageList/InlineLoadingMoreRecentThreadIndicator.js +52 -0
- package/lib/commonjs/components/MessageList/InlineLoadingMoreRecentThreadIndicator.js.map +1 -0
- package/lib/commonjs/components/MessageList/MessageList.js +14 -6
- package/lib/commonjs/components/MessageList/MessageList.js.map +1 -1
- package/lib/commonjs/components/Thread/Thread.js +12 -5
- package/lib/commonjs/components/Thread/Thread.js.map +1 -1
- package/lib/commonjs/components/Thread/components/ThreadFooterComponent.js +41 -18
- package/lib/commonjs/components/Thread/components/ThreadFooterComponent.js.map +1 -1
- package/lib/commonjs/components/ThreadList/ThreadList.js +132 -0
- package/lib/commonjs/components/ThreadList/ThreadList.js.map +1 -0
- package/lib/commonjs/components/ThreadList/ThreadListItem.js +246 -0
- package/lib/commonjs/components/ThreadList/ThreadListItem.js.map +1 -0
- package/lib/commonjs/components/ThreadList/ThreadListUnreadBanner.js +66 -0
- package/lib/commonjs/components/ThreadList/ThreadListUnreadBanner.js.map +1 -0
- package/lib/commonjs/components/index.js +11 -11
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js +19 -0
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/contexts/threadContext/ThreadContext.js.map +1 -1
- package/lib/commonjs/contexts/threadsContext/ThreadListItemContext.js +28 -0
- package/lib/commonjs/contexts/threadsContext/ThreadListItemContext.js.map +1 -0
- package/lib/commonjs/contexts/threadsContext/ThreadsContext.js +33 -0
- package/lib/commonjs/contexts/threadsContext/ThreadsContext.js.map +1 -0
- package/lib/commonjs/hooks/index.js +11 -0
- package/lib/commonjs/hooks/index.js.map +1 -1
- package/lib/commonjs/hooks/useStateStore.js +23 -0
- package/lib/commonjs/hooks/useStateStore.js.map +1 -0
- package/lib/commonjs/i18n/en.json +7 -0
- package/lib/commonjs/i18n/es.json +7 -0
- package/lib/commonjs/i18n/fr.json +7 -0
- package/lib/commonjs/i18n/he.json +7 -0
- package/lib/commonjs/i18n/hi.json +7 -0
- package/lib/commonjs/i18n/it.json +7 -0
- package/lib/commonjs/i18n/ja.json +7 -0
- package/lib/commonjs/i18n/ko.json +7 -0
- package/lib/commonjs/i18n/nl.json +7 -0
- package/lib/commonjs/i18n/pt-br.json +7 -0
- package/lib/commonjs/i18n/ru.json +7 -0
- package/lib/commonjs/i18n/tr.json +7 -0
- package/lib/commonjs/icons/MessageBubble.js +19 -0
- package/lib/commonjs/icons/MessageBubble.js.map +1 -0
- package/lib/commonjs/icons/MessageBubbleEmpty.js +19 -0
- package/lib/commonjs/icons/MessageBubbleEmpty.js.map +1 -0
- package/lib/commonjs/icons/Reload.js +19 -0
- package/lib/commonjs/icons/Reload.js.map +1 -0
- package/lib/commonjs/icons/index.js +33 -0
- package/lib/commonjs/icons/index.js.map +1 -1
- package/lib/commonjs/store/mappers/mapDateTimeToStorable.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Channel/Channel.js +58 -25
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Channel/hooks/useCreateThreadContext.js +33 -21
- package/lib/module/components/Channel/hooks/useCreateThreadContext.js.map +1 -1
- package/lib/module/components/Chat/Chat.js +7 -0
- package/lib/module/components/Chat/Chat.js.map +1 -1
- package/lib/module/components/Indicators/EmptyStateIndicator.js +14 -0
- package/lib/module/components/Indicators/EmptyStateIndicator.js.map +1 -1
- package/lib/module/components/Indicators/LoadingIndicator.js +4 -0
- package/lib/module/components/Indicators/LoadingIndicator.js.map +1 -1
- package/lib/module/components/Message/hooks/useProcessReactions.js +13 -7
- package/lib/module/components/Message/hooks/useProcessReactions.js.map +1 -1
- package/lib/module/components/MessageList/InlineLoadingMoreRecentThreadIndicator.js +52 -0
- package/lib/module/components/MessageList/InlineLoadingMoreRecentThreadIndicator.js.map +1 -0
- package/lib/module/components/MessageList/MessageList.js +14 -6
- package/lib/module/components/MessageList/MessageList.js.map +1 -1
- package/lib/module/components/Thread/Thread.js +12 -5
- package/lib/module/components/Thread/Thread.js.map +1 -1
- package/lib/module/components/Thread/components/ThreadFooterComponent.js +41 -18
- package/lib/module/components/Thread/components/ThreadFooterComponent.js.map +1 -1
- package/lib/module/components/ThreadList/ThreadList.js +132 -0
- package/lib/module/components/ThreadList/ThreadList.js.map +1 -0
- package/lib/module/components/ThreadList/ThreadListItem.js +246 -0
- package/lib/module/components/ThreadList/ThreadListItem.js.map +1 -0
- package/lib/module/components/ThreadList/ThreadListUnreadBanner.js +66 -0
- package/lib/module/components/ThreadList/ThreadListUnreadBanner.js.map +1 -0
- package/lib/module/components/index.js +11 -11
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/contexts/themeContext/utils/theme.js +19 -0
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/contexts/threadContext/ThreadContext.js.map +1 -1
- package/lib/module/contexts/threadsContext/ThreadListItemContext.js +28 -0
- package/lib/module/contexts/threadsContext/ThreadListItemContext.js.map +1 -0
- package/lib/module/contexts/threadsContext/ThreadsContext.js +33 -0
- package/lib/module/contexts/threadsContext/ThreadsContext.js.map +1 -0
- package/lib/module/hooks/index.js +11 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/useStateStore.js +23 -0
- package/lib/module/hooks/useStateStore.js.map +1 -0
- package/lib/module/i18n/en.json +7 -0
- package/lib/module/i18n/es.json +7 -0
- package/lib/module/i18n/fr.json +7 -0
- package/lib/module/i18n/he.json +7 -0
- package/lib/module/i18n/hi.json +7 -0
- package/lib/module/i18n/it.json +7 -0
- package/lib/module/i18n/ja.json +7 -0
- package/lib/module/i18n/ko.json +7 -0
- package/lib/module/i18n/nl.json +7 -0
- package/lib/module/i18n/pt-br.json +7 -0
- package/lib/module/i18n/ru.json +7 -0
- package/lib/module/i18n/tr.json +7 -0
- package/lib/module/icons/MessageBubble.js +19 -0
- package/lib/module/icons/MessageBubble.js.map +1 -0
- package/lib/module/icons/MessageBubbleEmpty.js +19 -0
- package/lib/module/icons/MessageBubbleEmpty.js.map +1 -0
- package/lib/module/icons/Reload.js +19 -0
- package/lib/module/icons/Reload.js.map +1 -0
- package/lib/module/icons/index.js +33 -0
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/store/mappers/mapDateTimeToStorable.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/AttachmentPicker/AttachmentPicker.d.ts +1 -1
- package/lib/typescript/components/Channel/Channel.d.ts +3 -2
- package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateThreadContext.d.ts +34 -1
- package/lib/typescript/components/Channel/hooks/useCreateThreadContext.d.ts.map +1 -1
- package/lib/typescript/components/Chat/Chat.d.ts.map +1 -1
- package/lib/typescript/components/Indicators/EmptyStateIndicator.d.ts +1 -1
- package/lib/typescript/components/Indicators/EmptyStateIndicator.d.ts.map +1 -1
- package/lib/typescript/components/Indicators/LoadingIndicator.d.ts +1 -1
- package/lib/typescript/components/Indicators/LoadingIndicator.d.ts.map +1 -1
- package/lib/typescript/components/Message/hooks/useProcessReactions.d.ts.map +1 -1
- package/lib/typescript/components/MessageList/InlineLoadingMoreRecentThreadIndicator.d.ts +8 -0
- package/lib/typescript/components/MessageList/InlineLoadingMoreRecentThreadIndicator.d.ts.map +1 -0
- package/lib/typescript/components/MessageList/MessageList.d.ts +1 -1
- package/lib/typescript/components/MessageList/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/Thread/Thread.d.ts +1 -1
- package/lib/typescript/components/Thread/Thread.d.ts.map +1 -1
- package/lib/typescript/components/Thread/components/ThreadFooterComponent.d.ts +1 -0
- package/lib/typescript/components/Thread/components/ThreadFooterComponent.d.ts.map +1 -1
- package/lib/typescript/components/ThreadList/ThreadList.d.ts +11 -0
- package/lib/typescript/components/ThreadList/ThreadList.d.ts.map +1 -0
- package/lib/typescript/components/ThreadList/ThreadListItem.d.ts +16 -0
- package/lib/typescript/components/ThreadList/ThreadListItem.d.ts.map +1 -0
- package/lib/typescript/components/ThreadList/ThreadListUnreadBanner.d.ts +3 -0
- package/lib/typescript/components/ThreadList/ThreadListUnreadBanner.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +1 -1
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/contexts/attachmentPickerContext/AttachmentPickerContext.d.ts +1 -1
- package/lib/typescript/contexts/messageContext/MessageContext.d.ts +1 -1
- package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +1 -1
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +19 -0
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
- package/lib/typescript/contexts/threadContext/ThreadContext.d.ts +11 -2
- package/lib/typescript/contexts/threadContext/ThreadContext.d.ts.map +1 -1
- package/lib/typescript/contexts/threadsContext/ThreadListItemContext.d.ts +19 -0
- package/lib/typescript/contexts/threadsContext/ThreadListItemContext.d.ts.map +1 -0
- package/lib/typescript/contexts/threadsContext/ThreadsContext.d.ts +25 -0
- package/lib/typescript/contexts/threadsContext/ThreadsContext.d.ts.map +1 -0
- package/lib/typescript/hooks/index.d.ts +1 -0
- package/lib/typescript/hooks/index.d.ts.map +1 -1
- package/lib/typescript/hooks/useStateStore.d.ts +4 -0
- package/lib/typescript/hooks/useStateStore.d.ts.map +1 -0
- package/lib/typescript/i18n/en.json +7 -0
- package/lib/typescript/i18n/es.json +7 -0
- package/lib/typescript/i18n/fr.json +7 -0
- package/lib/typescript/i18n/he.json +7 -0
- package/lib/typescript/i18n/hi.json +7 -0
- package/lib/typescript/i18n/it.json +7 -0
- package/lib/typescript/i18n/ja.json +7 -0
- package/lib/typescript/i18n/ko.json +7 -0
- package/lib/typescript/i18n/nl.json +7 -0
- package/lib/typescript/i18n/pt-br.json +7 -0
- package/lib/typescript/i18n/ru.json +7 -0
- package/lib/typescript/i18n/tr.json +7 -0
- package/lib/typescript/icons/MessageBubble.d.ts +4 -0
- package/lib/typescript/icons/MessageBubble.d.ts.map +1 -0
- package/lib/typescript/icons/MessageBubbleEmpty.d.ts +4 -0
- package/lib/typescript/icons/MessageBubbleEmpty.d.ts.map +1 -0
- package/lib/typescript/icons/Reload.d.ts +4 -0
- package/lib/typescript/icons/Reload.d.ts.map +1 -0
- package/lib/typescript/icons/index.d.ts +3 -0
- package/lib/typescript/icons/index.d.ts.map +1 -1
- package/lib/typescript/store/mappers/mapDateTimeToStorable.d.ts +1 -1
- package/lib/typescript/store/mappers/mapDateTimeToStorable.d.ts.map +1 -1
- package/lib/typescript/utils/i18n/Streami18n.d.ts +7 -0
- package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/Channel/Channel.tsx +54 -20
- package/src/components/Channel/hooks/useCreateThreadContext.ts +36 -31
- package/src/components/Chat/Chat.tsx +10 -0
- package/src/components/Indicators/EmptyStateIndicator.tsx +9 -2
- package/src/components/Indicators/LoadingIndicator.tsx +3 -1
- package/src/components/Message/hooks/useProcessReactions.ts +25 -4
- package/src/components/MessageList/InlineLoadingMoreRecentThreadIndicator.tsx +64 -0
- package/src/components/MessageList/MessageList.tsx +23 -9
- package/src/components/Thread/Thread.tsx +18 -9
- package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +6 -0
- package/src/components/Thread/components/ThreadFooterComponent.tsx +28 -2
- package/src/components/ThreadList/ThreadList.tsx +118 -0
- package/src/components/ThreadList/ThreadListItem.tsx +268 -0
- package/src/components/ThreadList/ThreadListUnreadBanner.tsx +52 -0
- package/src/components/index.ts +1 -1
- package/src/contexts/themeContext/utils/theme.ts +36 -0
- package/src/contexts/threadContext/ThreadContext.tsx +9 -2
- package/src/contexts/threadsContext/ThreadListItemContext.tsx +41 -0
- package/src/contexts/threadsContext/ThreadsContext.tsx +62 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useStateStore.ts +31 -0
- package/src/i18n/en.json +7 -0
- package/src/i18n/es.json +7 -0
- package/src/i18n/fr.json +7 -0
- package/src/i18n/he.json +7 -0
- package/src/i18n/hi.json +7 -0
- package/src/i18n/it.json +7 -0
- package/src/i18n/ja.json +7 -0
- package/src/i18n/ko.json +7 -0
- package/src/i18n/nl.json +7 -0
- package/src/i18n/pt-br.json +7 -0
- package/src/i18n/ru.json +7 -0
- package/src/i18n/tr.json +7 -0
- package/src/icons/MessageBubble.tsx +12 -0
- package/src/icons/MessageBubbleEmpty.tsx +12 -0
- package/src/icons/Reload.tsx +12 -0
- package/src/icons/index.ts +3 -0
- package/src/store/mappers/mapDateTimeToStorable.ts +1 -1
- package/src/version.json +1 -1
- package/lib/commonjs/components/MessageList/InlineLoadingMoreThreadIndicator.js +0 -52
- package/lib/commonjs/components/MessageList/InlineLoadingMoreThreadIndicator.js.map +0 -1
- package/lib/module/components/MessageList/InlineLoadingMoreThreadIndicator.js +0 -52
- package/lib/module/components/MessageList/InlineLoadingMoreThreadIndicator.js.map +0 -1
- package/lib/typescript/components/MessageList/InlineLoadingMoreThreadIndicator.d.ts +0 -8
- package/lib/typescript/components/MessageList/InlineLoadingMoreThreadIndicator.d.ts.map +0 -1
- package/src/components/MessageList/InlineLoadingMoreThreadIndicator.tsx +0 -64
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ThreadState } from 'stream-chat';
|
|
2
2
|
|
|
3
3
|
import type { ThreadContextValue } from '../../../contexts/threadContext/ThreadContext';
|
|
4
|
+
import { useStateStore } from '../../../hooks';
|
|
4
5
|
import type { DefaultStreamChatGenerics } from '../../../types/types';
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
const selector = (nextValue: ThreadState) =>
|
|
8
|
+
[
|
|
9
|
+
nextValue.replies,
|
|
10
|
+
nextValue.pagination.isLoadingPrev,
|
|
11
|
+
nextValue.pagination.isLoadingNext,
|
|
12
|
+
nextValue.parentMessage,
|
|
13
|
+
] as const;
|
|
6
14
|
|
|
7
15
|
export const useCreateThreadContext = <
|
|
8
16
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
@@ -15,38 +23,35 @@ export const useCreateThreadContext = <
|
|
|
15
23
|
setThreadLoadingMore,
|
|
16
24
|
thread,
|
|
17
25
|
threadHasMore,
|
|
26
|
+
threadInstance,
|
|
18
27
|
threadLoadingMore,
|
|
19
28
|
threadMessages,
|
|
20
29
|
}: ThreadContextValue<StreamChatGenerics>) => {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
const threadLatestReactions = thread?.latest_reactions;
|
|
24
|
-
const threadMessagesStr = reduceMessagesToString(threadMessages);
|
|
30
|
+
const [latestReplies, isLoadingPrev, isLoadingNext] =
|
|
31
|
+
useStateStore(threadInstance?.state, selector) ?? [];
|
|
25
32
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
threadLoadingMore,
|
|
37
|
-
threadMessages,
|
|
38
|
-
}),
|
|
39
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
40
|
-
[
|
|
41
|
-
allowThreadMessagesInChannel,
|
|
42
|
-
threadHasMore,
|
|
43
|
-
threadId,
|
|
44
|
-
threadLoadingMore,
|
|
45
|
-
threadMessagesStr,
|
|
46
|
-
threadReplyCount,
|
|
47
|
-
threadLatestReactions,
|
|
48
|
-
],
|
|
49
|
-
);
|
|
33
|
+
const contextAdapter = threadInstance
|
|
34
|
+
? {
|
|
35
|
+
loadMoreRecentThread: threadInstance.loadNextPage,
|
|
36
|
+
loadMoreThread: threadInstance.loadPrevPage,
|
|
37
|
+
threadInstance,
|
|
38
|
+
threadLoadingMore: isLoadingPrev,
|
|
39
|
+
threadLoadingMoreRecent: isLoadingNext,
|
|
40
|
+
threadMessages: latestReplies ?? [],
|
|
41
|
+
}
|
|
42
|
+
: {};
|
|
50
43
|
|
|
51
|
-
return
|
|
44
|
+
return {
|
|
45
|
+
allowThreadMessagesInChannel,
|
|
46
|
+
closeThread,
|
|
47
|
+
loadMoreThread,
|
|
48
|
+
openThread,
|
|
49
|
+
reloadThread,
|
|
50
|
+
setThreadLoadingMore,
|
|
51
|
+
thread,
|
|
52
|
+
threadHasMore,
|
|
53
|
+
threadLoadingMore,
|
|
54
|
+
threadMessages,
|
|
55
|
+
...contextAdapter,
|
|
56
|
+
};
|
|
52
57
|
};
|
|
@@ -215,6 +215,16 @@ const ChatWithContext = <
|
|
|
215
215
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
216
216
|
}, [userID, enableOfflineSupport]);
|
|
217
217
|
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
if (!client) return;
|
|
220
|
+
|
|
221
|
+
client.threads.registerSubscriptions();
|
|
222
|
+
|
|
223
|
+
return () => {
|
|
224
|
+
client.threads.unregisterSubscriptions();
|
|
225
|
+
};
|
|
226
|
+
}, [client]);
|
|
227
|
+
|
|
218
228
|
// In case something went wrong, make sure to also unsubscribe the listener
|
|
219
229
|
// on unmount if it exists to prevent a memory leak.
|
|
220
230
|
useEffect(() => () => DBSyncManager.connectionChangedListener?.unsubscribe(), []);
|
|
@@ -4,10 +4,10 @@ import { StyleSheet, Text, View } from 'react-native';
|
|
|
4
4
|
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
5
5
|
import { useTranslationContext } from '../../contexts/translationContext/TranslationContext';
|
|
6
6
|
import { useViewport } from '../../hooks/useViewport';
|
|
7
|
-
import { ChatIcon, MessageIcon } from '../../icons';
|
|
7
|
+
import { ChatIcon, MessageBubbleEmpty, MessageIcon } from '../../icons';
|
|
8
8
|
|
|
9
9
|
export type EmptyStateProps = {
|
|
10
|
-
listType?: 'channel' | 'message' | 'default';
|
|
10
|
+
listType?: 'channel' | 'message' | 'threads' | 'default';
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export const EmptyStateIndicator = ({ listType }: EmptyStateProps) => {
|
|
@@ -55,6 +55,13 @@ export const EmptyStateIndicator = ({ listType }: EmptyStateProps) => {
|
|
|
55
55
|
</Text>
|
|
56
56
|
</View>
|
|
57
57
|
);
|
|
58
|
+
case 'threads':
|
|
59
|
+
return (
|
|
60
|
+
<View style={[styles.container]}>
|
|
61
|
+
<MessageBubbleEmpty height={width} pathFill={'#B4BBBA'} width={width} />
|
|
62
|
+
<Text style={{ color: '#7E828B' }}>{t<string>('No threads here yet')}...</Text>
|
|
63
|
+
</View>
|
|
64
|
+
);
|
|
58
65
|
default:
|
|
59
66
|
return <Text style={[{ color: black }, messageContainer]}>No items exist</Text>;
|
|
60
67
|
}
|
|
@@ -26,7 +26,7 @@ const LoadingIndicatorWrapper = ({ text }: LoadingIndicatorWrapperProps) => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export type LoadingProps = {
|
|
29
|
-
listType?: 'channel' | 'message' | 'default';
|
|
29
|
+
listType?: 'channel' | 'message' | 'threads' | 'default';
|
|
30
30
|
loadingText?: string;
|
|
31
31
|
};
|
|
32
32
|
|
|
@@ -47,6 +47,8 @@ export const LoadingIndicator = (props: LoadingProps) => {
|
|
|
47
47
|
return <LoadingIndicatorWrapper text={t('Loading channels...')} />;
|
|
48
48
|
case 'message':
|
|
49
49
|
return <LoadingIndicatorWrapper text={t('Loading messages...')} />;
|
|
50
|
+
case 'threads':
|
|
51
|
+
return <LoadingIndicatorWrapper text={t('Loading threads...')} />;
|
|
50
52
|
default:
|
|
51
53
|
return <LoadingIndicatorWrapper text={t('Loading...')} />;
|
|
52
54
|
}
|
|
@@ -2,6 +2,7 @@ import { ComponentType, useMemo } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { ReactionResponse } from 'stream-chat';
|
|
4
4
|
|
|
5
|
+
import { useChatContext } from '../../../contexts';
|
|
5
6
|
import {
|
|
6
7
|
MessagesContextValue,
|
|
7
8
|
useMessagesContext,
|
|
@@ -46,7 +47,15 @@ const isOwnReaction = <
|
|
|
46
47
|
>(
|
|
47
48
|
reactionType: string,
|
|
48
49
|
ownReactions?: ReactionResponse<StreamChatGenerics>[] | null,
|
|
49
|
-
|
|
50
|
+
latestReactions?: ReactionResponse<StreamChatGenerics>[] | null,
|
|
51
|
+
userID?: string,
|
|
52
|
+
) =>
|
|
53
|
+
(ownReactions ? ownReactions.some((reaction) => reaction.type === reactionType) : false) ||
|
|
54
|
+
(latestReactions
|
|
55
|
+
? latestReactions.some(
|
|
56
|
+
(reaction) => reaction?.user?.id === userID && reaction.type === reactionType,
|
|
57
|
+
)
|
|
58
|
+
: false);
|
|
50
59
|
|
|
51
60
|
const isSupportedReaction = (reactionType: string, supportedReactions: ReactionData[]) =>
|
|
52
61
|
supportedReactions
|
|
@@ -76,6 +85,7 @@ export const useProcessReactions = <
|
|
|
76
85
|
props: UseProcessReactionsParams<StreamChatGenerics>,
|
|
77
86
|
) => {
|
|
78
87
|
const { supportedReactions: contextSupportedReactions } = useMessagesContext();
|
|
88
|
+
const { client } = useChatContext<StreamChatGenerics>();
|
|
79
89
|
|
|
80
90
|
const {
|
|
81
91
|
latest_reactions,
|
|
@@ -100,7 +110,12 @@ export const useProcessReactions = <
|
|
|
100
110
|
Icon: getEmojiByReactionType(reactionType, supportedReactions),
|
|
101
111
|
lastReactionAt: last_reaction_at ? new Date(last_reaction_at) : null,
|
|
102
112
|
latestReactedUserNames,
|
|
103
|
-
own: isOwnReaction<StreamChatGenerics>(
|
|
113
|
+
own: isOwnReaction<StreamChatGenerics>(
|
|
114
|
+
reactionType,
|
|
115
|
+
own_reactions,
|
|
116
|
+
latest_reactions,
|
|
117
|
+
client.userID,
|
|
118
|
+
),
|
|
104
119
|
type: reactionType,
|
|
105
120
|
unlistedReactedUserCount: count - latestReactedUserNames.length,
|
|
106
121
|
};
|
|
@@ -112,6 +127,12 @@ export const useProcessReactions = <
|
|
|
112
127
|
hasReactions: unsortedReactions.length > 0,
|
|
113
128
|
totalReactionCount: unsortedReactions.reduce((total, { count }) => total + count, 0),
|
|
114
129
|
};
|
|
115
|
-
|
|
116
|
-
|
|
130
|
+
}, [
|
|
131
|
+
client.userID,
|
|
132
|
+
reaction_groups,
|
|
133
|
+
own_reactions,
|
|
134
|
+
latest_reactions,
|
|
135
|
+
supportedReactions,
|
|
136
|
+
sortReactions,
|
|
137
|
+
]);
|
|
117
138
|
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { useThreadContext } from '../../contexts';
|
|
5
|
+
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
6
|
+
|
|
7
|
+
import type { DefaultStreamChatGenerics } from '../../types/types';
|
|
8
|
+
|
|
9
|
+
const styles = StyleSheet.create({
|
|
10
|
+
activityIndicatorContainer: {
|
|
11
|
+
padding: 10,
|
|
12
|
+
width: '100%',
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export type InlineLoadingMoreRecentThreadIndicatorPropsWithContext = {
|
|
17
|
+
loadingMoreRecent?: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const InlineLoadingMoreRecentIndicatorWithContext = ({
|
|
21
|
+
loadingMoreRecent,
|
|
22
|
+
}: InlineLoadingMoreRecentThreadIndicatorPropsWithContext) => {
|
|
23
|
+
const { theme } = useTheme();
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
colors: { accent_blue },
|
|
27
|
+
} = theme;
|
|
28
|
+
|
|
29
|
+
if (!loadingMoreRecent) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<View style={styles.activityIndicatorContainer}>
|
|
35
|
+
<ActivityIndicator color={accent_blue} size='small' />
|
|
36
|
+
</View>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const areEqual = (
|
|
41
|
+
prevProps: InlineLoadingMoreRecentThreadIndicatorPropsWithContext,
|
|
42
|
+
nextProps: InlineLoadingMoreRecentThreadIndicatorPropsWithContext,
|
|
43
|
+
) => {
|
|
44
|
+
const { loadingMoreRecent: prevLoadingMoreRecent } = prevProps;
|
|
45
|
+
const { loadingMoreRecent: nextLoadingMoreRecent } = nextProps;
|
|
46
|
+
|
|
47
|
+
const loadingMoreRecentEqual = prevLoadingMoreRecent === nextLoadingMoreRecent;
|
|
48
|
+
if (!loadingMoreRecentEqual) return false;
|
|
49
|
+
|
|
50
|
+
return true;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const MemoizedInlineLoadingMoreRecentIndicator = React.memo(
|
|
54
|
+
InlineLoadingMoreRecentIndicatorWithContext,
|
|
55
|
+
areEqual,
|
|
56
|
+
) as typeof InlineLoadingMoreRecentIndicatorWithContext;
|
|
57
|
+
|
|
58
|
+
export const InlineLoadingMoreRecentThreadIndicator = <
|
|
59
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
60
|
+
>() => {
|
|
61
|
+
const { threadLoadingMoreRecent } = useThreadContext<StreamChatGenerics>();
|
|
62
|
+
|
|
63
|
+
return <MemoizedInlineLoadingMoreRecentIndicator loadingMoreRecent={threadLoadingMoreRecent} />;
|
|
64
|
+
};
|
|
@@ -20,7 +20,7 @@ import { useShouldScrollToRecentOnNewOwnMessage } from './hooks/useShouldScrollT
|
|
|
20
20
|
|
|
21
21
|
import { InlineLoadingMoreIndicator } from './InlineLoadingMoreIndicator';
|
|
22
22
|
import { InlineLoadingMoreRecentIndicator } from './InlineLoadingMoreRecentIndicator';
|
|
23
|
-
import {
|
|
23
|
+
import { InlineLoadingMoreRecentThreadIndicator } from './InlineLoadingMoreRecentThreadIndicator';
|
|
24
24
|
import { getLastReceivedMessage } from './utils/getLastReceivedMessage';
|
|
25
25
|
|
|
26
26
|
import {
|
|
@@ -147,7 +147,10 @@ type MessageListPropsWithContext<
|
|
|
147
147
|
| 'TypingIndicator'
|
|
148
148
|
| 'TypingIndicatorContainer'
|
|
149
149
|
> &
|
|
150
|
-
Pick<
|
|
150
|
+
Pick<
|
|
151
|
+
ThreadContextValue<StreamChatGenerics>,
|
|
152
|
+
'loadMoreRecentThread' | 'loadMoreThread' | 'thread' | 'threadInstance'
|
|
153
|
+
> & {
|
|
151
154
|
/**
|
|
152
155
|
* Besides existing (default) UX behavior of underlying FlatList of MessageList component, if you want
|
|
153
156
|
* to attach some additional props to underlying FlatList, you can add it to following prop.
|
|
@@ -221,9 +224,9 @@ const MessageListWithContext = <
|
|
|
221
224
|
>(
|
|
222
225
|
props: MessageListPropsWithContext<StreamChatGenerics>,
|
|
223
226
|
) => {
|
|
224
|
-
const
|
|
225
|
-
?
|
|
226
|
-
:
|
|
227
|
+
const LoadingMoreRecentIndicator = props.threadList
|
|
228
|
+
? InlineLoadingMoreRecentThreadIndicator
|
|
229
|
+
: InlineLoadingMoreRecentIndicator;
|
|
227
230
|
const {
|
|
228
231
|
additionalFlatListProps,
|
|
229
232
|
channel,
|
|
@@ -234,9 +237,9 @@ const MessageListWithContext = <
|
|
|
234
237
|
disableTypingIndicator,
|
|
235
238
|
EmptyStateIndicator,
|
|
236
239
|
FlatList,
|
|
237
|
-
FooterComponent =
|
|
240
|
+
FooterComponent = InlineLoadingMoreIndicator,
|
|
238
241
|
hasNoMoreRecentMessagesToLoad,
|
|
239
|
-
HeaderComponent =
|
|
242
|
+
HeaderComponent = LoadingMoreRecentIndicator,
|
|
240
243
|
hideStickyDateHeader,
|
|
241
244
|
initialScrollToFirstUnreadMessage,
|
|
242
245
|
InlineDateSeparator,
|
|
@@ -249,6 +252,7 @@ const MessageListWithContext = <
|
|
|
249
252
|
LoadingIndicator,
|
|
250
253
|
loadMore,
|
|
251
254
|
loadMoreRecent,
|
|
255
|
+
loadMoreRecentThread,
|
|
252
256
|
loadMoreThread,
|
|
253
257
|
markRead,
|
|
254
258
|
Message,
|
|
@@ -269,6 +273,7 @@ const MessageListWithContext = <
|
|
|
269
273
|
StickyHeader,
|
|
270
274
|
targetedMessage,
|
|
271
275
|
thread,
|
|
276
|
+
threadInstance,
|
|
272
277
|
threadList = false,
|
|
273
278
|
TypingIndicator,
|
|
274
279
|
TypingIndicatorContainer,
|
|
@@ -744,7 +749,13 @@ const MessageListWithContext = <
|
|
|
744
749
|
if (onEndReachedInPromise.current) {
|
|
745
750
|
await onEndReachedInPromise.current;
|
|
746
751
|
}
|
|
747
|
-
onStartReachedInPromise.current =
|
|
752
|
+
onStartReachedInPromise.current = (
|
|
753
|
+
threadList && !!threadInstance && loadMoreRecentThread
|
|
754
|
+
? loadMoreRecentThread({ limit })
|
|
755
|
+
: loadMoreRecent(limit)
|
|
756
|
+
)
|
|
757
|
+
.then(callback)
|
|
758
|
+
.catch(onError);
|
|
748
759
|
};
|
|
749
760
|
|
|
750
761
|
/**
|
|
@@ -1253,7 +1264,8 @@ export const MessageList = <
|
|
|
1253
1264
|
const { hasNoMoreRecentMessagesToLoad, loadMore, loadMoreRecent } =
|
|
1254
1265
|
usePaginatedMessageListContext<StreamChatGenerics>();
|
|
1255
1266
|
const { overlay } = useOverlayContext();
|
|
1256
|
-
const { loadMoreThread, thread } =
|
|
1267
|
+
const { loadMoreRecentThread, loadMoreThread, thread, threadInstance } =
|
|
1268
|
+
useThreadContext<StreamChatGenerics>();
|
|
1257
1269
|
|
|
1258
1270
|
return (
|
|
1259
1271
|
<MessageListWithContext
|
|
@@ -1280,6 +1292,7 @@ export const MessageList = <
|
|
|
1280
1292
|
LoadingIndicator,
|
|
1281
1293
|
loadMore,
|
|
1282
1294
|
loadMoreRecent,
|
|
1295
|
+
loadMoreRecentThread,
|
|
1283
1296
|
loadMoreThread,
|
|
1284
1297
|
markRead,
|
|
1285
1298
|
Message,
|
|
@@ -1297,6 +1310,7 @@ export const MessageList = <
|
|
|
1297
1310
|
StickyHeader,
|
|
1298
1311
|
targetedMessage,
|
|
1299
1312
|
thread,
|
|
1313
|
+
threadInstance,
|
|
1300
1314
|
threadList,
|
|
1301
1315
|
TypingIndicator,
|
|
1302
1316
|
TypingIndicatorContainer,
|
|
@@ -23,7 +23,12 @@ type ThreadPropsWithContext<
|
|
|
23
23
|
Pick<MessagesContextValue<StreamChatGenerics>, 'MessageList'> &
|
|
24
24
|
Pick<
|
|
25
25
|
ThreadContextValue<StreamChatGenerics>,
|
|
26
|
-
|
|
26
|
+
| 'closeThread'
|
|
27
|
+
| 'loadMoreThread'
|
|
28
|
+
| 'parentMessagePreventPress'
|
|
29
|
+
| 'reloadThread'
|
|
30
|
+
| 'thread'
|
|
31
|
+
| 'threadInstance'
|
|
27
32
|
> & {
|
|
28
33
|
/**
|
|
29
34
|
* Additional props for underlying MessageInput component.
|
|
@@ -70,9 +75,13 @@ const ThreadWithContext = <
|
|
|
70
75
|
onThreadDismount,
|
|
71
76
|
parentMessagePreventPress = true,
|
|
72
77
|
thread,
|
|
78
|
+
threadInstance,
|
|
73
79
|
} = props;
|
|
74
80
|
|
|
75
81
|
useEffect(() => {
|
|
82
|
+
if (threadInstance?.activate) {
|
|
83
|
+
threadInstance.activate();
|
|
84
|
+
}
|
|
76
85
|
const loadMoreThreadAsync = async () => {
|
|
77
86
|
await loadMoreThread();
|
|
78
87
|
};
|
|
@@ -80,21 +89,20 @@ const ThreadWithContext = <
|
|
|
80
89
|
if (thread?.id && thread.reply_count) {
|
|
81
90
|
loadMoreThreadAsync();
|
|
82
91
|
}
|
|
83
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
84
|
-
}, []);
|
|
85
92
|
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
return () => {
|
|
94
|
+
if (threadInstance?.deactivate) {
|
|
95
|
+
threadInstance.deactivate();
|
|
96
|
+
}
|
|
88
97
|
if (closeThreadOnDismount) {
|
|
89
98
|
closeThread();
|
|
90
99
|
}
|
|
91
100
|
if (onThreadDismount) {
|
|
92
101
|
onThreadDismount();
|
|
93
102
|
}
|
|
94
|
-
}
|
|
103
|
+
};
|
|
95
104
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
96
|
-
|
|
97
|
-
);
|
|
105
|
+
}, []);
|
|
98
106
|
|
|
99
107
|
if (!thread) return null;
|
|
100
108
|
|
|
@@ -137,7 +145,7 @@ export const Thread = <
|
|
|
137
145
|
const { client } = useChatContext<StreamChatGenerics>();
|
|
138
146
|
const { threadList } = useChannelContext<StreamChatGenerics>();
|
|
139
147
|
const { MessageList } = useMessagesContext<StreamChatGenerics>();
|
|
140
|
-
const { closeThread, loadMoreThread, reloadThread, thread } =
|
|
148
|
+
const { closeThread, loadMoreThread, reloadThread, thread, threadInstance } =
|
|
141
149
|
useThreadContext<StreamChatGenerics>();
|
|
142
150
|
|
|
143
151
|
if (thread?.id && !threadList) {
|
|
@@ -155,6 +163,7 @@ export const Thread = <
|
|
|
155
163
|
MessageList,
|
|
156
164
|
reloadThread,
|
|
157
165
|
thread,
|
|
166
|
+
threadInstance,
|
|
158
167
|
}}
|
|
159
168
|
{...props}
|
|
160
169
|
/>
|
|
@@ -54,6 +54,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
54
54
|
"attachments": [],
|
|
55
55
|
"created_at": 2020-05-05T14:50:00.000Z,
|
|
56
56
|
"dateSeparator": undefined,
|
|
57
|
+
"deleted_at": null,
|
|
57
58
|
"groupStyles": [
|
|
58
59
|
"single",
|
|
59
60
|
],
|
|
@@ -62,6 +63,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
62
63
|
"message_text_updated_at": "2020-05-05T14:50:00.000Z",
|
|
63
64
|
"parent_id": "b4612a73-fa2b-5787-bf71-1adc8f291a04",
|
|
64
65
|
"pinned_at": null,
|
|
66
|
+
"reaction_groups": null,
|
|
65
67
|
"readBy": false,
|
|
66
68
|
"status": "received",
|
|
67
69
|
"text": "Message6",
|
|
@@ -83,6 +85,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
83
85
|
"attachments": [],
|
|
84
86
|
"created_at": 2020-05-05T14:50:00.000Z,
|
|
85
87
|
"dateSeparator": undefined,
|
|
88
|
+
"deleted_at": null,
|
|
86
89
|
"groupStyles": [
|
|
87
90
|
"single",
|
|
88
91
|
],
|
|
@@ -91,6 +94,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
91
94
|
"message_text_updated_at": "2020-05-05T14:50:00.000Z",
|
|
92
95
|
"parent_id": "b4612a73-fa2b-5787-bf71-1adc8f291a04",
|
|
93
96
|
"pinned_at": null,
|
|
97
|
+
"reaction_groups": null,
|
|
94
98
|
"readBy": false,
|
|
95
99
|
"status": "received",
|
|
96
100
|
"text": "Message5",
|
|
@@ -112,6 +116,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
112
116
|
"attachments": [],
|
|
113
117
|
"created_at": 2020-05-05T14:50:00.000Z,
|
|
114
118
|
"dateSeparator": 2020-05-05T14:50:00.000Z,
|
|
119
|
+
"deleted_at": null,
|
|
115
120
|
"groupStyles": [
|
|
116
121
|
"single",
|
|
117
122
|
],
|
|
@@ -120,6 +125,7 @@ exports[`Thread should match thread snapshot 1`] = `
|
|
|
120
125
|
"message_text_updated_at": "2020-05-05T14:50:00.000Z",
|
|
121
126
|
"parent_id": "b4612a73-fa2b-5787-bf71-1adc8f291a04",
|
|
122
127
|
"pinned_at": null,
|
|
128
|
+
"reaction_groups": null,
|
|
123
129
|
"readBy": false,
|
|
124
130
|
"status": "received",
|
|
125
131
|
"text": "Message4",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { StyleSheet, Text, View } from 'react-native';
|
|
2
|
+
import { ActivityIndicator, StyleSheet, Text, View } from 'react-native';
|
|
3
3
|
import Svg, { Defs, LinearGradient, Rect, Stop } from 'react-native-svg';
|
|
4
4
|
|
|
5
5
|
import {
|
|
@@ -17,6 +17,10 @@ import type { DefaultStreamChatGenerics } from '../../../types/types';
|
|
|
17
17
|
|
|
18
18
|
const styles = StyleSheet.create({
|
|
19
19
|
absolute: { position: 'absolute' },
|
|
20
|
+
activityIndicatorContainer: {
|
|
21
|
+
padding: 10,
|
|
22
|
+
width: '100%',
|
|
23
|
+
},
|
|
20
24
|
messagePadding: {
|
|
21
25
|
paddingHorizontal: 8,
|
|
22
26
|
},
|
|
@@ -40,6 +44,25 @@ type ThreadFooterComponentPropsWithContext<
|
|
|
40
44
|
> = Pick<MessagesContextValue<StreamChatGenerics>, 'Message'> &
|
|
41
45
|
Pick<ThreadContextValue<StreamChatGenerics>, 'parentMessagePreventPress' | 'thread'>;
|
|
42
46
|
|
|
47
|
+
export const InlineLoadingMoreThreadIndicator = () => {
|
|
48
|
+
const { threadLoadingMore } = useThreadContext();
|
|
49
|
+
const {
|
|
50
|
+
theme: {
|
|
51
|
+
colors: { accent_blue },
|
|
52
|
+
},
|
|
53
|
+
} = useTheme();
|
|
54
|
+
|
|
55
|
+
if (!threadLoadingMore) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<View style={styles.activityIndicatorContainer}>
|
|
61
|
+
<ActivityIndicator color={accent_blue} size='small' />
|
|
62
|
+
</View>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
43
66
|
const ThreadFooterComponentWithContext = <
|
|
44
67
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
45
68
|
>(
|
|
@@ -111,6 +134,7 @@ const ThreadFooterComponentWithContext = <
|
|
|
111
134
|
})}
|
|
112
135
|
</Text>
|
|
113
136
|
</View>
|
|
137
|
+
<InlineLoadingMoreThreadIndicator />
|
|
114
138
|
</View>
|
|
115
139
|
);
|
|
116
140
|
};
|
|
@@ -163,7 +187,8 @@ export const ThreadFooterComponent = <
|
|
|
163
187
|
props: ThreadFooterComponentProps<StreamChatGenerics>,
|
|
164
188
|
) => {
|
|
165
189
|
const { Message } = useMessagesContext<StreamChatGenerics>();
|
|
166
|
-
const { parentMessagePreventPress, thread } =
|
|
190
|
+
const { parentMessagePreventPress, thread, threadLoadingMore } =
|
|
191
|
+
useThreadContext<StreamChatGenerics>();
|
|
167
192
|
|
|
168
193
|
return (
|
|
169
194
|
<MemoizedThreadFooter
|
|
@@ -171,6 +196,7 @@ export const ThreadFooterComponent = <
|
|
|
171
196
|
Message,
|
|
172
197
|
parentMessagePreventPress,
|
|
173
198
|
thread,
|
|
199
|
+
threadLoadingMore,
|
|
174
200
|
}}
|
|
175
201
|
{...props}
|
|
176
202
|
/>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { FlatList, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { Thread, ThreadManagerState } from 'stream-chat';
|
|
5
|
+
|
|
6
|
+
import { ThreadListItem } from './ThreadListItem';
|
|
7
|
+
import { ThreadListUnreadBanner as DefaultThreadListBanner } from './ThreadListUnreadBanner';
|
|
8
|
+
|
|
9
|
+
import { useChatContext } from '../../contexts';
|
|
10
|
+
import {
|
|
11
|
+
ThreadsContextValue,
|
|
12
|
+
ThreadsProvider,
|
|
13
|
+
useThreadsContext,
|
|
14
|
+
} from '../../contexts/threadsContext/ThreadsContext';
|
|
15
|
+
import { useStateStore } from '../../hooks';
|
|
16
|
+
import type { DefaultStreamChatGenerics } from '../../types/types';
|
|
17
|
+
import { EmptyStateIndicator } from '../Indicators/EmptyStateIndicator';
|
|
18
|
+
import { LoadingIndicator } from '../Indicators/LoadingIndicator';
|
|
19
|
+
|
|
20
|
+
const selector = (nextValue: ThreadManagerState) =>
|
|
21
|
+
[nextValue.threads, nextValue.pagination.isLoading, nextValue.pagination.isLoadingNext] as const;
|
|
22
|
+
|
|
23
|
+
export type ThreadListProps<
|
|
24
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
25
|
+
> = Pick<
|
|
26
|
+
ThreadsContextValue<StreamChatGenerics>,
|
|
27
|
+
| 'additionalFlatListProps'
|
|
28
|
+
| 'isFocused'
|
|
29
|
+
| 'onThreadSelect'
|
|
30
|
+
| 'ThreadListEmptyPlaceholder'
|
|
31
|
+
| 'ThreadListLoadingIndicator'
|
|
32
|
+
| 'ThreadListUnreadBanner'
|
|
33
|
+
> & { ThreadList?: React.ComponentType };
|
|
34
|
+
|
|
35
|
+
export const DefaultThreadListEmptyPlaceholder = () => <EmptyStateIndicator listType='threads' />;
|
|
36
|
+
|
|
37
|
+
export const DefaultThreadListLoadingIndicator = () => <LoadingIndicator listType='threads' />;
|
|
38
|
+
export const DefaultThreadListLoadingNextIndicator = () => <LoadingIndicator />;
|
|
39
|
+
|
|
40
|
+
const DefaultThreadListItem = (props: { item: Thread }) => <ThreadListItem thread={props.item} />;
|
|
41
|
+
|
|
42
|
+
const ThreadListComponent = () => {
|
|
43
|
+
const {
|
|
44
|
+
additionalFlatListProps,
|
|
45
|
+
isLoading,
|
|
46
|
+
isLoadingNext,
|
|
47
|
+
loadMore,
|
|
48
|
+
ThreadListEmptyPlaceholder = DefaultThreadListEmptyPlaceholder,
|
|
49
|
+
ThreadListLoadingIndicator = DefaultThreadListLoadingIndicator,
|
|
50
|
+
ThreadListLoadingMoreIndicator = DefaultThreadListLoadingNextIndicator,
|
|
51
|
+
ThreadListUnreadBanner = DefaultThreadListBanner,
|
|
52
|
+
threads,
|
|
53
|
+
} = useThreadsContext();
|
|
54
|
+
|
|
55
|
+
if (isLoading) {
|
|
56
|
+
return (
|
|
57
|
+
<View style={{ flex: 1 }}>
|
|
58
|
+
<ThreadListLoadingIndicator />
|
|
59
|
+
</View>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<>
|
|
65
|
+
<ThreadListUnreadBanner />
|
|
66
|
+
<FlatList
|
|
67
|
+
contentContainerStyle={{ flexGrow: 1 }}
|
|
68
|
+
data={threads}
|
|
69
|
+
keyExtractor={(props) => props.id}
|
|
70
|
+
ListEmptyComponent={ThreadListEmptyPlaceholder}
|
|
71
|
+
ListFooterComponent={isLoadingNext ? ThreadListLoadingMoreIndicator : null}
|
|
72
|
+
onEndReached={loadMore}
|
|
73
|
+
renderItem={DefaultThreadListItem}
|
|
74
|
+
testID='thread-flatlist'
|
|
75
|
+
{...additionalFlatListProps}
|
|
76
|
+
/>
|
|
77
|
+
</>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const ThreadList = (props: ThreadListProps) => {
|
|
82
|
+
const { isFocused = true, ThreadList = ThreadListComponent } = props;
|
|
83
|
+
const { client } = useChatContext();
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (!client) return;
|
|
87
|
+
if (isFocused) {
|
|
88
|
+
client.threads.activate();
|
|
89
|
+
} else {
|
|
90
|
+
client.threads.deactivate();
|
|
91
|
+
}
|
|
92
|
+
}, [client, isFocused]);
|
|
93
|
+
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (!client) return;
|
|
96
|
+
|
|
97
|
+
const listener = client.on('connection.recovered', () => {
|
|
98
|
+
client.threads.reload({ force: true });
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
client.threads.reload({ force: true });
|
|
102
|
+
|
|
103
|
+
return () => {
|
|
104
|
+
client.threads.deactivate();
|
|
105
|
+
listener.unsubscribe();
|
|
106
|
+
};
|
|
107
|
+
}, [client]);
|
|
108
|
+
|
|
109
|
+
const [threads, isLoading, isLoadingNext] = useStateStore(client.threads.state, selector);
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<ThreadsProvider
|
|
113
|
+
value={{ isLoading, isLoadingNext, loadMore: client.threads.loadNextPage, threads, ...props }}
|
|
114
|
+
>
|
|
115
|
+
<ThreadList />
|
|
116
|
+
</ThreadsProvider>
|
|
117
|
+
);
|
|
118
|
+
};
|