@messenger-box/platform-mobile 10.0.3-alpha.16 → 10.0.3-alpha.162
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/CHANGELOG.md +248 -0
- package/lib/compute.js +2 -3
- package/lib/compute.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/module.js.map +1 -1
- package/lib/queries/inboxQueries.js +65 -0
- package/lib/queries/inboxQueries.js.map +1 -0
- package/lib/routes.json +13 -1
- package/lib/screens/inbox/DialogMessages.js +5 -3
- package/lib/screens/inbox/DialogMessages.js.map +1 -1
- package/lib/screens/inbox/DialogThreadMessages.js +3 -7
- package/lib/screens/inbox/DialogThreadMessages.js.map +1 -1
- package/lib/screens/inbox/DialogThreads.js +57 -18
- package/lib/screens/inbox/DialogThreads.js.map +1 -1
- package/lib/screens/inbox/Inbox.js.map +1 -1
- package/lib/screens/inbox/components/CachedImage/consts.js +1 -1
- package/lib/screens/inbox/components/CachedImage/consts.js.map +1 -1
- package/lib/screens/inbox/components/CachedImage/index.js +168 -46
- package/lib/screens/inbox/components/CachedImage/index.js.map +1 -1
- package/lib/screens/inbox/components/DialogItem.js +169 -0
- package/lib/screens/inbox/components/DialogItem.js.map +1 -0
- package/lib/screens/inbox/components/GiftedChatInboxComponent.js +313 -0
- package/lib/screens/inbox/components/GiftedChatInboxComponent.js.map +1 -0
- package/lib/screens/inbox/components/SlackMessageContainer/ImageViewerModal.js.map +1 -1
- package/lib/screens/inbox/components/SlackMessageContainer/PaymentMessage.js +197 -0
- package/lib/screens/inbox/components/SlackMessageContainer/PaymentMessage.js.map +1 -0
- package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js +141 -31
- package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js.map +1 -1
- package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js.map +1 -1
- package/lib/screens/inbox/components/SubscriptionHandler.js +24 -0
- package/lib/screens/inbox/components/SubscriptionHandler.js.map +1 -0
- package/lib/screens/inbox/components/ThreadsViewItem.js +66 -44
- package/lib/screens/inbox/components/ThreadsViewItem.js.map +1 -1
- package/lib/screens/inbox/config/config.js +2 -2
- package/lib/screens/inbox/config/config.js.map +1 -1
- package/lib/screens/inbox/containers/ConversationView.js +1205 -432
- package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
- package/lib/screens/inbox/containers/Dialogs.js +193 -80
- package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
- package/lib/screens/inbox/containers/ThreadConversationView.js +724 -207
- package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
- package/lib/screens/inbox/containers/ThreadsView.js +83 -50
- package/lib/screens/inbox/containers/ThreadsView.js.map +1 -1
- package/lib/screens/inbox/hooks/useInboxMessages.js +31 -0
- package/lib/screens/inbox/hooks/useInboxMessages.js.map +1 -0
- package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js +108 -0
- package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js.map +1 -0
- package/lib/screens/inbox/workflow/dialog-threads-xstate.js +151 -0
- package/lib/screens/inbox/workflow/dialog-threads-xstate.js.map +1 -0
- package/package.json +5 -5
- package/src/index.ts +2 -0
- package/src/queries/inboxQueries.ts +299 -0
- package/src/queries/index.d.ts +2 -0
- package/src/queries/index.ts +1 -0
- package/src/screens/inbox/DialogMessages.tsx +2 -1
- package/src/screens/inbox/DialogThreadMessages.tsx +3 -11
- package/src/screens/inbox/DialogThreads.tsx +53 -60
- package/src/screens/inbox/components/Actionsheet.tsx +30 -0
- package/src/screens/inbox/components/CachedImage/consts.ts +4 -3
- package/src/screens/inbox/components/CachedImage/index.tsx +232 -61
- package/src/screens/inbox/components/DialogItem.tsx +306 -0
- package/src/screens/inbox/components/DialogsListItem.tsx +230 -170
- package/src/screens/inbox/components/ExpandableInput.tsx +460 -0
- package/src/screens/inbox/components/ExpandableInputActionSheet.tsx +518 -0
- package/src/screens/inbox/components/GiftedChatInboxComponent.tsx +411 -0
- package/src/screens/inbox/components/ServiceDialogsListItem.tsx +330 -171
- package/src/screens/inbox/components/SlackInput.tsx +23 -0
- package/src/screens/inbox/components/SlackMessageContainer/PaymentMessage.tsx +199 -0
- package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +233 -23
- package/src/screens/inbox/components/SmartLoader.tsx +61 -0
- package/src/screens/inbox/components/SubscriptionHandler.tsx +41 -0
- package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +41 -24
- package/src/screens/inbox/components/ThreadsViewItem.tsx +177 -265
- package/src/screens/inbox/components/workflow/dialogs-list-item-xstate.ts +145 -0
- package/src/screens/inbox/components/workflow/service-dialogs-list-item-xstate.ts +159 -0
- package/src/screens/inbox/config/config.ts +2 -2
- package/src/screens/inbox/containers/ConversationView.tsx +2004 -698
- package/src/screens/inbox/containers/ConversationView.tsx.bk +1467 -0
- package/src/screens/inbox/containers/Dialogs.tsx +402 -196
- package/src/screens/inbox/containers/SupportServiceDialogs.tsx +2 -2
- package/src/screens/inbox/containers/ThreadConversationView.tsx +1337 -301
- package/src/screens/inbox/containers/ThreadsView.tsx +105 -186
- package/src/screens/inbox/containers/workflow/apollo/handleResult.ts +20 -0
- package/src/screens/inbox/containers/workflow/conversation-xstate.ts +313 -0
- package/src/screens/inbox/containers/workflow/dialogs-xstate.ts +196 -0
- package/src/screens/inbox/containers/workflow/thread-conversation-xstate.ts +401 -0
- package/src/screens/inbox/hooks/useInboxMessages.ts +34 -0
- package/src/screens/inbox/hooks/useSafeDialogThreadsMachine.ts +136 -0
- package/src/screens/inbox/index.ts +37 -0
- package/src/screens/inbox/machines/threadsMachine.ts +147 -0
- package/src/screens/inbox/workflow/dialog-threads-xstate.ts +163 -0
- package/lib/screens/inbox/components/DialogsListItem.js +0 -175
- package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
- package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -165
- package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo, useState } from 'react';
|
|
1
|
+
import React, { useMemo, useState, useCallback, useRef, useEffect } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Text,
|
|
4
4
|
Image,
|
|
@@ -15,14 +15,10 @@ import {
|
|
|
15
15
|
import { format, isToday, isYesterday } from 'date-fns';
|
|
16
16
|
import { useFocusEffect } from '@react-navigation/native';
|
|
17
17
|
import { IChannel, SortEnum, IUserAccount } from 'common';
|
|
18
|
-
import {
|
|
19
|
-
useMessagesQuery,
|
|
20
|
-
useOnChatMessageAddedSubscription,
|
|
21
|
-
OnChatMessageAddedDocument as CHAT_MESSAGE_ADDED,
|
|
22
|
-
useUserAccountQuery,
|
|
23
|
-
} from 'common/graphql';
|
|
18
|
+
import { CHAT_MESSAGE_ADDED, useMessagesQuery as useMessagesQueryFromInbox } from '../../../queries/inboxQueries';
|
|
24
19
|
import { startCase } from 'lodash-es';
|
|
25
20
|
import colors from 'tailwindcss/colors';
|
|
21
|
+
import { SubscriptionHandler } from './SubscriptionHandler';
|
|
26
22
|
|
|
27
23
|
const createdAtText = (value: string) => {
|
|
28
24
|
if (!value) return '';
|
|
@@ -42,8 +38,56 @@ export interface IDialogListItemProps {
|
|
|
42
38
|
selectedChannelId?: any;
|
|
43
39
|
channel?: any;
|
|
44
40
|
onOpen: (id: any, title: any) => void;
|
|
41
|
+
forceRefresh?: boolean;
|
|
42
|
+
visible?: boolean;
|
|
45
43
|
}
|
|
46
44
|
|
|
45
|
+
// LastMessage component definition
|
|
46
|
+
const LastMessageComponent = ({ title, lastMessage }) => {
|
|
47
|
+
const count = 30;
|
|
48
|
+
const channelTitle = title?.slice(0, count) + (title?.length > count ? '...' : '') || '';
|
|
49
|
+
|
|
50
|
+
// Define message display text
|
|
51
|
+
let displayMessage = 'No messages yet';
|
|
52
|
+
|
|
53
|
+
if (lastMessage) {
|
|
54
|
+
if (lastMessage.message && lastMessage.message.trim() !== '') {
|
|
55
|
+
// Show text message
|
|
56
|
+
displayMessage = lastMessage.message;
|
|
57
|
+
} else if (lastMessage.files?.data?.length > 0) {
|
|
58
|
+
// Show message with files
|
|
59
|
+
displayMessage = '📎 File attachment';
|
|
60
|
+
} else {
|
|
61
|
+
// Default for empty message
|
|
62
|
+
displayMessage = '(Empty message)';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Determine the date/time to display
|
|
67
|
+
const displayDate = lastMessage?.createdAt
|
|
68
|
+
? createdAtText(lastMessage.createdAt)
|
|
69
|
+
: lastMessage?.updatedAt
|
|
70
|
+
? createdAtText(lastMessage.updatedAt)
|
|
71
|
+
: '';
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<HStack space={'sm'} className="flex-1 justify-between">
|
|
75
|
+
<Box className="flex-[0.8]">
|
|
76
|
+
<Text color={colors.gray[600]} className="text-base text-wrap flex-wrap font-semibold">
|
|
77
|
+
{channelTitle}
|
|
78
|
+
</Text>
|
|
79
|
+
<Text color={colors.gray[600]} numberOfLines={1}>
|
|
80
|
+
{displayMessage}
|
|
81
|
+
</Text>
|
|
82
|
+
</Box>
|
|
83
|
+
|
|
84
|
+
<Box className="flex-[0.2]">
|
|
85
|
+
<Text color={colors.gray[500]}>{displayDate}</Text>
|
|
86
|
+
</Box>
|
|
87
|
+
</HStack>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
47
91
|
/**
|
|
48
92
|
* TODO:
|
|
49
93
|
* - Get Reservation info: reservation date, status
|
|
@@ -51,117 +95,214 @@ export interface IDialogListItemProps {
|
|
|
51
95
|
*/
|
|
52
96
|
export const DialogsListItemComponent: React.FC<IDialogListItemProps> = function DialogsListItem({
|
|
53
97
|
currentUser,
|
|
54
|
-
// users,
|
|
55
98
|
selectedChannelId,
|
|
56
99
|
channel,
|
|
57
100
|
onOpen,
|
|
101
|
+
forceRefresh,
|
|
102
|
+
visible = true,
|
|
58
103
|
}) {
|
|
104
|
+
// Create a ref to track if component is mounted
|
|
105
|
+
const isMountedRef = useRef(true);
|
|
106
|
+
|
|
107
|
+
// Define parentId early to avoid linter errors
|
|
59
108
|
const parentId: any = null;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
109
|
+
|
|
110
|
+
// Simplified state - only keep loading state, rely on Apollo cache for data
|
|
111
|
+
const [loading, setLoading] = useState(false);
|
|
112
|
+
const [title, setTitle] = useState('');
|
|
113
|
+
|
|
114
|
+
// Only run queries/subscriptions if visible
|
|
115
|
+
const shouldQuery = !!channel?.id && visible;
|
|
116
|
+
|
|
117
|
+
// Memoize query variables to prevent unnecessary re-renders
|
|
118
|
+
const queryVariables = useMemo(
|
|
119
|
+
() => ({
|
|
68
120
|
channelId: channel?.id?.toString(),
|
|
69
121
|
parentId: parentId,
|
|
70
122
|
limit: 10,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
123
|
+
}),
|
|
124
|
+
[channel?.id, parentId],
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Optimized message processing function
|
|
128
|
+
const processMessagesData = useCallback((messagesData: any[]) => {
|
|
129
|
+
if (!messagesData?.length) return null;
|
|
130
|
+
|
|
131
|
+
// Sort messages and return the latest one
|
|
132
|
+
const sortedMessages = [...messagesData].sort(
|
|
133
|
+
(a, b) =>
|
|
134
|
+
new Date(b?.updatedAt || b?.createdAt).getTime() - new Date(a?.updatedAt || a?.createdAt).getTime(),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
return sortedMessages[0];
|
|
138
|
+
}, []);
|
|
139
|
+
|
|
140
|
+
// Optimized refetch function - consolidated all refetch logic
|
|
141
|
+
const optimizedRefetch = useCallback(
|
|
142
|
+
async (reason: string = 'manual') => {
|
|
143
|
+
if (!shouldQuery || !channel?.id || !isMountedRef.current) return null;
|
|
144
|
+
|
|
145
|
+
console.log(`Optimized refetch triggered: ${reason} for channel ${channel?.id}`);
|
|
146
|
+
setLoading(true);
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
const result = await refetchMessages(queryVariables);
|
|
150
|
+
console.log(
|
|
151
|
+
`Refetch completed: ${reason}, messages count: ${result?.data?.messages?.data?.length || 0}`,
|
|
152
|
+
);
|
|
153
|
+
return result;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
console.error(`Refetch error (${reason}):`, error);
|
|
156
|
+
return null;
|
|
157
|
+
} finally {
|
|
158
|
+
if (isMountedRef.current) {
|
|
159
|
+
setLoading(false);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
76
162
|
},
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
});
|
|
163
|
+
[shouldQuery, channel?.id, queryVariables],
|
|
164
|
+
);
|
|
80
165
|
|
|
166
|
+
// Query hooks for fetching messages - optimized configuration
|
|
81
167
|
const {
|
|
82
|
-
data:
|
|
83
|
-
loading:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
168
|
+
data: messagesQuery,
|
|
169
|
+
loading: messageLoading,
|
|
170
|
+
refetch: refetchMessages,
|
|
171
|
+
subscribeToMore,
|
|
172
|
+
error,
|
|
173
|
+
} = useMessagesQueryFromInbox({
|
|
174
|
+
variables: queryVariables,
|
|
175
|
+
skip: !shouldQuery,
|
|
176
|
+
fetchPolicy: 'cache-first', // Changed from cache-and-network for better performance
|
|
177
|
+
nextFetchPolicy: 'cache-first',
|
|
178
|
+
notifyOnNetworkStatusChange: true,
|
|
179
|
+
errorPolicy: 'all', // Handle partial errors gracefully
|
|
180
|
+
onCompleted: (data) => {
|
|
181
|
+
// Simplified onCompleted - minimal processing
|
|
182
|
+
if (!shouldQuery || !data?.messages?.data) return;
|
|
183
|
+
|
|
184
|
+
console.log(`Query completed for channel ${channel?.id}, messages: ${data.messages.data.length}`);
|
|
185
|
+
},
|
|
186
|
+
onError: (error) => {
|
|
187
|
+
if (!shouldQuery) return;
|
|
188
|
+
console.error(`Query error for channel ${channel?.id}:`, error);
|
|
88
189
|
},
|
|
89
190
|
});
|
|
90
191
|
|
|
192
|
+
// Derived state from query data - use Apollo cache as single source of truth
|
|
193
|
+
const messages = useMemo(() => messagesQuery?.messages?.data || [], [messagesQuery]);
|
|
194
|
+
const lastMessage = useMemo(() => processMessagesData(messages), [messages, processMessagesData]);
|
|
195
|
+
|
|
196
|
+
// Set mounted state on mount/unmount
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
isMountedRef.current = true;
|
|
199
|
+
return () => {
|
|
200
|
+
isMountedRef.current = false;
|
|
201
|
+
};
|
|
202
|
+
}, []);
|
|
203
|
+
|
|
204
|
+
// Optimized focus effect - single refetch with debouncing
|
|
205
|
+
const firstRenderRef = useRef(true);
|
|
91
206
|
useFocusEffect(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
parentId: parentId,
|
|
97
|
-
limit: 10,
|
|
98
|
-
// sort: {
|
|
99
|
-
// key: 'updatedAt',
|
|
100
|
-
// value: SortEnum.Desc,
|
|
101
|
-
// },
|
|
102
|
-
//limit: 25
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
return () => {
|
|
106
|
-
// Do something when the screen is unfocused
|
|
107
|
-
// Useful for cleanup functions
|
|
108
|
-
};
|
|
109
|
-
}, []),
|
|
110
|
-
);
|
|
207
|
+
useCallback(() => {
|
|
208
|
+
if (!channel?.id) return;
|
|
209
|
+
|
|
210
|
+
console.log('DialogsListItem focused for channel:', channel?.id);
|
|
111
211
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
setMessages((pre: any[]) => [...pre, ...msg]);
|
|
212
|
+
// Skip refresh on first render
|
|
213
|
+
if (firstRenderRef.current) {
|
|
214
|
+
firstRenderRef.current = false;
|
|
215
|
+
return;
|
|
117
216
|
}
|
|
118
|
-
}
|
|
119
|
-
}, [messagesQuery]);
|
|
120
217
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
218
|
+
// Debounced refetch on focus
|
|
219
|
+
const timeoutId = setTimeout(() => {
|
|
220
|
+
optimizedRefetch('focus');
|
|
221
|
+
}, 100);
|
|
222
|
+
|
|
223
|
+
return () => clearTimeout(timeoutId);
|
|
224
|
+
}, [channel?.id, optimizedRefetch]),
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
// Simplified effect for force refresh
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
if (forceRefresh && shouldQuery) {
|
|
230
|
+
const timeoutId = setTimeout(() => {
|
|
231
|
+
optimizedRefetch('force');
|
|
232
|
+
}, 50);
|
|
233
|
+
return () => clearTimeout(timeoutId);
|
|
124
234
|
}
|
|
125
|
-
|
|
126
|
-
const data = messages;
|
|
127
|
-
const filteredData: any = data?.filter((p: any) => p?.message !== '');
|
|
128
|
-
// return filteredData[0];
|
|
129
|
-
let filteredLastMessage =
|
|
130
|
-
filteredData && filteredData?.length
|
|
131
|
-
? filteredData?.reduce((a, b) => {
|
|
132
|
-
return new Date(a?.updatedAt) > new Date(b?.updatedAt) ? a : b;
|
|
133
|
-
}, []) ?? null
|
|
134
|
-
: null;
|
|
135
|
-
return filteredLastMessage;
|
|
136
|
-
//return data[data.length - 1];
|
|
137
|
-
}, [messages]);
|
|
235
|
+
}, [forceRefresh, shouldQuery, optimizedRefetch]);
|
|
138
236
|
|
|
237
|
+
// Channel members computation - optimized with better memoization
|
|
139
238
|
const channelMembers = useMemo(
|
|
140
239
|
() =>
|
|
141
240
|
channel?.members
|
|
142
|
-
?.filter((ch: any) => ch?.user?.id
|
|
143
|
-
?.map((m: any) => m?.user) ??
|
|
144
|
-
[currentUser, channel],
|
|
241
|
+
?.filter((ch: any) => ch?.user?.id !== currentUser?.id && ch?.user?.__typename === 'UserAccount')
|
|
242
|
+
?.map((m: any) => m?.user) ?? [],
|
|
243
|
+
[currentUser?.id, channel?.members],
|
|
145
244
|
);
|
|
146
245
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
246
|
+
// Set title when channel members change
|
|
247
|
+
useEffect(() => {
|
|
248
|
+
if (channelMembers.length > 0 && isMountedRef.current) {
|
|
249
|
+
const titleString =
|
|
250
|
+
channelMembers
|
|
251
|
+
?.map((u: any) => `${u?.givenName || ''} ${u?.familyName || ''}`.trim())
|
|
252
|
+
?.filter(Boolean)
|
|
253
|
+
?.join(', ') || '';
|
|
254
|
+
setTitle(titleString);
|
|
255
|
+
}
|
|
256
|
+
}, [channelMembers]);
|
|
153
257
|
|
|
258
|
+
// Compute title with proper truncation
|
|
259
|
+
const displayTitle = useMemo(() => {
|
|
154
260
|
const length = 30;
|
|
155
|
-
return
|
|
156
|
-
}, [
|
|
261
|
+
return title.length > length ? title.substring(0, length - 3) + '...' : title;
|
|
262
|
+
}, [title]);
|
|
263
|
+
|
|
264
|
+
// Combined loading state
|
|
265
|
+
const isLoading = loading || messageLoading;
|
|
157
266
|
|
|
158
267
|
return (
|
|
159
268
|
<Pressable
|
|
160
|
-
onPress={() =>
|
|
161
|
-
className="flex-1 border-gray-200 rounded-md
|
|
269
|
+
onPress={() => onOpen(channel?.id, displayTitle)}
|
|
270
|
+
className="flex-1 border-gray-200 rounded-md dark:border-gray-600 dark:bg-gray-700"
|
|
162
271
|
style={{ borderBottomWidth: 1, borderColor: '#e5e7eb', marginVertical: 0, paddingHorizontal: 10 }}
|
|
163
272
|
>
|
|
164
|
-
|
|
273
|
+
{/* Optimized subscription handler */}
|
|
274
|
+
<SubscriptionHandler
|
|
275
|
+
subscribeToMore={subscribeToMore}
|
|
276
|
+
document={CHAT_MESSAGE_ADDED}
|
|
277
|
+
variables={{ channelId: channel?.id?.toString() }}
|
|
278
|
+
enabled={shouldQuery}
|
|
279
|
+
updateQuery={(prev, { subscriptionData }) => {
|
|
280
|
+
if (!subscriptionData?.data?.chatMessageAdded || !isMountedRef.current) return prev;
|
|
281
|
+
|
|
282
|
+
const newMessage = subscriptionData.data.chatMessageAdded;
|
|
283
|
+
|
|
284
|
+
// Optimized cache update - check for duplicates more efficiently
|
|
285
|
+
const existingMessages = prev?.messages;
|
|
286
|
+
const messageExists = existingMessages?.data?.some((msg: any) => msg.id === newMessage.id);
|
|
287
|
+
|
|
288
|
+
if (!messageExists) {
|
|
289
|
+
return {
|
|
290
|
+
...prev,
|
|
291
|
+
messages: {
|
|
292
|
+
...existingMessages,
|
|
293
|
+
data: [...(existingMessages?.data || []), newMessage],
|
|
294
|
+
totalCount: (existingMessages?.totalCount || 0) + 1,
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
return prev;
|
|
299
|
+
}}
|
|
300
|
+
onError={(error) => {
|
|
301
|
+
console.error(`Subscription error for channel ${channel?.id}:`, error);
|
|
302
|
+
}}
|
|
303
|
+
/>
|
|
304
|
+
|
|
305
|
+
<HStack space={'md'} className="flex-1 w-[100%] py-3 items-center">
|
|
165
306
|
<Box className="flex-[0.1] items-start pl-3">
|
|
166
307
|
<AvatarGroup>
|
|
167
308
|
{channelMembers &&
|
|
@@ -175,7 +316,6 @@ export const DialogsListItemComponent: React.FC<IDialogListItemProps> = function
|
|
|
175
316
|
}] z-[${i == 1 ? 5 : 1}]`}
|
|
176
317
|
>
|
|
177
318
|
<AvatarFallbackText>{startCase(ch?.username?.charAt(0))}</AvatarFallbackText>
|
|
178
|
-
|
|
179
319
|
{channelMembers?.length > 1 && (
|
|
180
320
|
<AvatarBadge
|
|
181
321
|
style={{
|
|
@@ -207,96 +347,16 @@ export const DialogsListItemComponent: React.FC<IDialogListItemProps> = function
|
|
|
207
347
|
))}
|
|
208
348
|
</AvatarGroup>
|
|
209
349
|
</Box>
|
|
210
|
-
<Box className="flex-1
|
|
211
|
-
{/* <HStack space={1} flex={1} direction={'row'} justifyContent={'center'} alignItems={'center'}>
|
|
212
|
-
<Box flex={0.8}>
|
|
213
|
-
<Text color="gray.600" fontSize="lg" flexWrap={'wrap'} fontWeight="semibold">
|
|
214
|
-
{title}
|
|
215
|
-
</Text>
|
|
216
|
-
<Text color="gray.600" noOfLines={1}>
|
|
217
|
-
{lastMessage?.message ?? ''}
|
|
218
|
-
</Text>
|
|
219
|
-
</Box>
|
|
220
|
-
|
|
221
|
-
<Box flex={0.2}>
|
|
222
|
-
<Text color="gray.500">{lastMessage ? createdAtText(lastMessage?.createdAt) : ''}</Text>
|
|
223
|
-
</Box>
|
|
224
|
-
</HStack> */}
|
|
350
|
+
<Box className="flex-1">
|
|
225
351
|
<LastMessageComponent
|
|
226
|
-
|
|
352
|
+
key={`last-msg-${lastMessage?.id || 'none'}-${messages.length}`}
|
|
353
|
+
title={displayTitle}
|
|
227
354
|
lastMessage={lastMessage}
|
|
228
|
-
channelId={channel?.id}
|
|
229
|
-
subscribeToNewMessages={() =>
|
|
230
|
-
subscribeToMore({
|
|
231
|
-
document: CHAT_MESSAGE_ADDED,
|
|
232
|
-
variables: {
|
|
233
|
-
channelId: channel.id?.toString(),
|
|
234
|
-
},
|
|
235
|
-
updateQuery: (prev, { subscriptionData }: any) => {
|
|
236
|
-
if (!subscriptionData.data) return prev;
|
|
237
|
-
const newMessage: any = subscriptionData?.data?.chatMessageAdded;
|
|
238
|
-
const existingMessages: any = prev?.messages;
|
|
239
|
-
const previousData = existingMessages?.data
|
|
240
|
-
? [...existingMessages.data, newMessage]
|
|
241
|
-
: [];
|
|
242
|
-
const totalMsgCount = existingMessages?.totalCount + 1;
|
|
243
|
-
const merged = {
|
|
244
|
-
...prev,
|
|
245
|
-
messages: {
|
|
246
|
-
...existingMessages,
|
|
247
|
-
data: previousData,
|
|
248
|
-
totalCount: totalMsgCount,
|
|
249
|
-
},
|
|
250
|
-
};
|
|
251
|
-
return merged;
|
|
252
|
-
},
|
|
253
|
-
})
|
|
254
|
-
}
|
|
255
355
|
/>
|
|
256
|
-
{/* <Text
|
|
257
|
-
flex={1}
|
|
258
|
-
color="gray.600"
|
|
259
|
-
p={0}
|
|
260
|
-
m={0}
|
|
261
|
-
w={'100%'}
|
|
262
|
-
justifyContent={''}
|
|
263
|
-
fontSize="lg"
|
|
264
|
-
fontWeight="semibold"
|
|
265
|
-
>
|
|
266
|
-
{title}
|
|
267
|
-
</Text> */}
|
|
268
|
-
{/* <Text flex={0.1} color="gray.600">
|
|
269
|
-
{lastMessage?.message ?? ''}
|
|
270
|
-
</Text> */}
|
|
271
356
|
</Box>
|
|
272
|
-
{/* <Text flex={0.2} color="gray.500">
|
|
273
|
-
{lastMessage ? createdAtText(lastMessage?.createdAt) : ''}
|
|
274
|
-
</Text> */}
|
|
275
357
|
</HStack>
|
|
276
358
|
</Pressable>
|
|
277
359
|
);
|
|
278
360
|
};
|
|
279
361
|
|
|
280
|
-
const LastMessageComponent = ({ subscribeToNewMessages, title, lastMessage, channelId }) => {
|
|
281
|
-
React.useEffect(() => subscribeToNewMessages(), [channelId]);
|
|
282
|
-
const count = 30;
|
|
283
|
-
const channelTitle = title.slice(0, count) + (title.length > count ? '...' : '');
|
|
284
|
-
return (
|
|
285
|
-
<HStack space={'sm'} className="flex-1 justify-between">
|
|
286
|
-
<Box className="flex-[0.8]">
|
|
287
|
-
<Text color={colors.gray[600]} className="text-base text-wrap flex-wrap font-semibold">
|
|
288
|
-
{channelTitle}
|
|
289
|
-
</Text>
|
|
290
|
-
<Text color={colors.gray[600]} numberOfLines={1}>
|
|
291
|
-
{lastMessage?.message ?? ''}
|
|
292
|
-
</Text>
|
|
293
|
-
</Box>
|
|
294
|
-
|
|
295
|
-
<Box className="flex-[0.2]">
|
|
296
|
-
<Text color={colors.gray[500]}>{lastMessage ? createdAtText(lastMessage?.createdAt) : ''}</Text>
|
|
297
|
-
</Box>
|
|
298
|
-
</HStack>
|
|
299
|
-
);
|
|
300
|
-
};
|
|
301
|
-
|
|
302
362
|
export const DialogsListItem = React.memo(DialogsListItemComponent);
|