@messenger-box/platform-mobile 10.0.3-alpha.46 → 10.0.3-alpha.48
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 +8 -0
- package/lib/queries/inboxQueries.js +2 -14
- package/lib/queries/inboxQueries.js.map +1 -1
- package/lib/screens/inbox/DialogThreads.js +5 -2
- package/lib/screens/inbox/DialogThreads.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/config/config.js +2 -2
- package/lib/screens/inbox/config/config.js.map +1 -1
- package/lib/screens/inbox/containers/ConversationView.js +26 -8
- package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
- package/lib/screens/inbox/containers/Dialogs.js +17 -36
- package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
- package/package.json +4 -4
- package/src/queries/inboxQueries.ts +7 -6
- package/src/screens/inbox/DialogThreads.tsx +2 -1
- package/src/screens/inbox/components/DialogItem.tsx +306 -0
- package/src/screens/inbox/components/DialogsListItem.tsx +140 -305
- package/src/screens/inbox/components/ServiceDialogsListItem.tsx +171 -264
- package/src/screens/inbox/config/config.ts +2 -2
- package/src/screens/inbox/containers/ConversationView.tsx +25 -7
- package/src/screens/inbox/containers/Dialogs.tsx +128 -65
- package/lib/screens/inbox/components/DialogsListItem.js +0 -355
- package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
- package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -402
- package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState, useMemo } from 'react';
|
|
2
2
|
import { FlatList, Box, Heading, Input, InputField, Text, Center, Spinner } from '@admin-layout/gluestack-ui-mobile';
|
|
3
3
|
import { Ionicons } from '@expo/vector-icons';
|
|
4
|
-
import { useSelector } from 'react-redux';
|
|
4
|
+
import { useSelector, shallowEqual } from 'react-redux';
|
|
5
5
|
import { useNavigation, useRoute, useFocusEffect } from '@react-navigation/native';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { DialogItem } from '../components/DialogItem';
|
|
7
|
+
// import { useChannelsQuery, CHAT_MESSAGE_ADDED } from '../../../queries/inboxQueries';
|
|
8
|
+
import {
|
|
9
|
+
useGetChannelsByUserQuery,
|
|
10
|
+
useGetChannelsByUserWithLastMessageQuery,
|
|
11
|
+
OnChatMessageAddedDocument,
|
|
12
|
+
} from 'common/graphql';
|
|
9
13
|
import { RoomType } from 'common';
|
|
10
14
|
import { userSelector } from '@adminide-stack/user-auth0-client';
|
|
11
15
|
import { config } from '../config';
|
|
@@ -21,16 +25,13 @@ export interface InboxProps {
|
|
|
21
25
|
const DialogsComponent = (props: InboxProps) => {
|
|
22
26
|
const { channelFilters: channelFilterProp, channelRole, supportServices } = props;
|
|
23
27
|
const channelFilters = { ...channelFilterProp };
|
|
24
|
-
channelFilters.type = channelFilters?.type ?? RoomType.Direct;
|
|
28
|
+
// channelFilters.type = channelFilters?.type ?? RoomType.Direct;
|
|
29
|
+
channelFilters.type = [RoomType.Direct, RoomType.Service];
|
|
25
30
|
const { params } = useRoute<any>();
|
|
26
|
-
const auth = useSelector(userSelector);
|
|
31
|
+
const auth = useSelector(userSelector, shallowEqual);
|
|
27
32
|
const navigation = useNavigation<any>();
|
|
28
|
-
|
|
29
|
-
// Local state for UI control
|
|
33
|
+
// Local state for UI control - only keeping searchQuery as it's needed for local filtering
|
|
30
34
|
const [searchQuery, setSearchQuery] = useState('');
|
|
31
|
-
const [selectedChannelId, setSelectedChannelId] = useState<string | null>(params?.channelId || null);
|
|
32
|
-
const [page, setPage] = useState(1);
|
|
33
|
-
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
|
34
35
|
|
|
35
36
|
// Create a ref to track if component is mounted
|
|
36
37
|
const isMountedRef = useRef(true);
|
|
@@ -46,20 +47,105 @@ const DialogsComponent = (props: InboxProps) => {
|
|
|
46
47
|
const resetActiveChannelTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
47
48
|
|
|
48
49
|
// Apollo query with pagination and optimistic updates
|
|
49
|
-
const { data, loading, refetch, fetchMore, subscribeToMore } =
|
|
50
|
+
const { data, loading, refetch, fetchMore, subscribeToMore } = useGetChannelsByUserWithLastMessageQuery({
|
|
50
51
|
variables: {
|
|
51
52
|
role: channelRole,
|
|
52
53
|
criteria: channelFilters,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
// supportServices: false,
|
|
55
|
+
// supportServices: supportServices ? true : false,
|
|
56
|
+
// supportServiceCriteria: {
|
|
57
|
+
// type: RoomType.Service,
|
|
58
|
+
// },
|
|
57
59
|
limit: 15,
|
|
58
60
|
skip: 0,
|
|
59
61
|
},
|
|
60
62
|
notifyOnNetworkStatusChange: true,
|
|
63
|
+
fetchPolicy: 'cache-and-network',
|
|
61
64
|
});
|
|
62
65
|
|
|
66
|
+
// Subscribe to new messages to update lastMessage in channels
|
|
67
|
+
// useEffect(() => {
|
|
68
|
+
// if (!data?.channelsByUser?.length || !subscribeToMore) return;
|
|
69
|
+
|
|
70
|
+
// const subscriptions: (() => void)[] = [];
|
|
71
|
+
|
|
72
|
+
// // Subscribe to each channel for real-time lastMessage updates
|
|
73
|
+
// data.channelsByUser.forEach(channel => {
|
|
74
|
+
// if (!channel?.id) return;
|
|
75
|
+
|
|
76
|
+
// const unsubscribe = subscribeToMore({
|
|
77
|
+
// document: OnChatMessageAddedDocument,
|
|
78
|
+
// variables: {
|
|
79
|
+
// channelId: channel.id.toString(),
|
|
80
|
+
// },
|
|
81
|
+
// updateQuery: (prev, { subscriptionData }: any) => {
|
|
82
|
+
// if (!subscriptionData?.data?.chatMessageAdded || !isMountedRef.current) {
|
|
83
|
+
// return prev;
|
|
84
|
+
// }
|
|
85
|
+
|
|
86
|
+
// const newMessage = subscriptionData.data.chatMessageAdded;
|
|
87
|
+
// const channelId = newMessage.channel?.id;
|
|
88
|
+
|
|
89
|
+
// if (!channelId) return prev;
|
|
90
|
+
|
|
91
|
+
// // Update the specific channel's lastMessage
|
|
92
|
+
// const updatedChannels = (prev.channelsByUser || []).map(ch => {
|
|
93
|
+
// if (ch?.id === channelId) {
|
|
94
|
+
// return {
|
|
95
|
+
// ...ch,
|
|
96
|
+
// lastMessage: {
|
|
97
|
+
// id: newMessage.id,
|
|
98
|
+
// message: newMessage.message || '',
|
|
99
|
+
// createdAt: newMessage.createdAt,
|
|
100
|
+
// updatedAt: newMessage.updatedAt,
|
|
101
|
+
// author: newMessage.author ? {
|
|
102
|
+
// id: newMessage.author.id,
|
|
103
|
+
// givenName: newMessage.author.givenName,
|
|
104
|
+
// familyName: newMessage.author.familyName,
|
|
105
|
+
// username: newMessage.author.username,
|
|
106
|
+
// } : null,
|
|
107
|
+
// files: newMessage.files ? {
|
|
108
|
+
// totalCount: newMessage.files.totalCount || 0,
|
|
109
|
+
// data: (newMessage.files.data || []).map(file => ({
|
|
110
|
+
// id: file.id,
|
|
111
|
+
// name: file.name,
|
|
112
|
+
// extension: file.extension,
|
|
113
|
+
// mimeType: file.mimeType,
|
|
114
|
+
// }))
|
|
115
|
+
// } : null,
|
|
116
|
+
// },
|
|
117
|
+
// updatedAt: newMessage.createdAt,
|
|
118
|
+
// lastPostAt: newMessage.createdAt,
|
|
119
|
+
// };
|
|
120
|
+
// }
|
|
121
|
+
// return ch;
|
|
122
|
+
// });
|
|
123
|
+
|
|
124
|
+
// return {
|
|
125
|
+
// ...prev,
|
|
126
|
+
// channelsByUser: updatedChannels,
|
|
127
|
+
// };
|
|
128
|
+
// },
|
|
129
|
+
// onError: (error) => {
|
|
130
|
+
// console.error(`LastMessage subscription error for channel ${channel.id}:`, error);
|
|
131
|
+
// },
|
|
132
|
+
// });
|
|
133
|
+
|
|
134
|
+
// subscriptions.push(unsubscribe);
|
|
135
|
+
// });
|
|
136
|
+
|
|
137
|
+
// // Cleanup subscriptions
|
|
138
|
+
// return () => {
|
|
139
|
+
// subscriptions.forEach(unsub => {
|
|
140
|
+
// try {
|
|
141
|
+
// unsub?.();
|
|
142
|
+
// } catch (error) {
|
|
143
|
+
// console.error('Error unsubscribing from lastMessage updates:', error);
|
|
144
|
+
// }
|
|
145
|
+
// });
|
|
146
|
+
// };
|
|
147
|
+
// }, [data?.channelsByUser, subscribeToMore]);
|
|
148
|
+
|
|
63
149
|
// Memoize processChannels and sortChannels to avoid unnecessary recalculations
|
|
64
150
|
const processChannels = useCallback(
|
|
65
151
|
(rawChannels = []) => {
|
|
@@ -76,11 +162,12 @@ const DialogsComponent = (props: InboxProps) => {
|
|
|
76
162
|
|
|
77
163
|
const sortChannels = useCallback((channels) => {
|
|
78
164
|
if (!channels?.length) return [];
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
165
|
+
return channels;
|
|
166
|
+
// return [...channels].sort((a, b) => {
|
|
167
|
+
// const dateA = new Date(a?.updatedAt || a?.createdAt).getTime();
|
|
168
|
+
// const dateB = new Date(b?.updatedAt || b?.createdAt).getTime();
|
|
169
|
+
// return dateB - dateA;
|
|
170
|
+
// });
|
|
84
171
|
}, []);
|
|
85
172
|
|
|
86
173
|
// Navigation handlers with debounce to prevent double taps
|
|
@@ -97,7 +184,6 @@ const DialogsComponent = (props: InboxProps) => {
|
|
|
97
184
|
resetActiveChannelTimeoutRef.current = setTimeout(() => {
|
|
98
185
|
activeChannelRef.current = null;
|
|
99
186
|
}, 2000);
|
|
100
|
-
setSelectedChannelId(id);
|
|
101
187
|
console.log('📱 Navigating to channel:', id);
|
|
102
188
|
navigation.navigate(config.INBOX_MESSEGE_PATH, {
|
|
103
189
|
channelId: id,
|
|
@@ -124,7 +210,6 @@ const DialogsComponent = (props: InboxProps) => {
|
|
|
124
210
|
resetActiveChannelTimeoutRef.current = setTimeout(() => {
|
|
125
211
|
activeChannelRef.current = null;
|
|
126
212
|
}, 2000);
|
|
127
|
-
setSelectedChannelId(id);
|
|
128
213
|
console.log('📱 Navigating to service channel:', id);
|
|
129
214
|
navigation.navigate(postParentId || postParentId === 0 ? config.THREAD_MESSEGE_PATH : config.THREADS_PATH, {
|
|
130
215
|
channelId: id,
|
|
@@ -144,10 +229,11 @@ const DialogsComponent = (props: InboxProps) => {
|
|
|
144
229
|
}, []);
|
|
145
230
|
|
|
146
231
|
// Memoize allChannels and channels
|
|
147
|
-
const allChannels = useMemo(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
);
|
|
232
|
+
// const allChannels = useMemo(
|
|
233
|
+
// () => [...(data?.supportServiceChannels || []), ...(data?.channelsByUser || [])],
|
|
234
|
+
// [data],
|
|
235
|
+
// );
|
|
236
|
+
const allChannels = useMemo(() => [...(data?.channelsByUser || [])], [data]);
|
|
151
237
|
const channels = useMemo(
|
|
152
238
|
() => sortChannels(processChannels(allChannels)),
|
|
153
239
|
[allChannels, processChannels, sortChannels],
|
|
@@ -175,39 +261,27 @@ const DialogsComponent = (props: InboxProps) => {
|
|
|
175
261
|
const renderItem = useCallback(
|
|
176
262
|
({ item: channel }) => {
|
|
177
263
|
const key = `${channel.type === RoomType.Service ? 'service' : 'direct'}-${channel.id}`;
|
|
178
|
-
return
|
|
179
|
-
<
|
|
180
|
-
key={key}
|
|
181
|
-
onOpen={handleSelectServiceChannel}
|
|
182
|
-
currentUser={auth}
|
|
183
|
-
channel={channel}
|
|
184
|
-
refreshing={loading}
|
|
185
|
-
selectedChannelId={selectedChannelId}
|
|
186
|
-
role={channelRole}
|
|
187
|
-
/>
|
|
188
|
-
) : (
|
|
189
|
-
<DialogsListItem
|
|
264
|
+
return (
|
|
265
|
+
<DialogItem
|
|
190
266
|
key={key}
|
|
191
|
-
onOpen={handleSelectChannel}
|
|
267
|
+
onOpen={channel?.type === RoomType.Service ? handleSelectServiceChannel : handleSelectChannel}
|
|
192
268
|
currentUser={auth}
|
|
193
269
|
channel={channel}
|
|
194
|
-
selectedChannelId={selectedChannelId}
|
|
195
|
-
forceRefresh={true}
|
|
196
270
|
/>
|
|
197
271
|
);
|
|
198
272
|
},
|
|
199
|
-
[auth,
|
|
273
|
+
[auth, handleSelectChannel, handleSelectServiceChannel],
|
|
200
274
|
);
|
|
201
275
|
|
|
202
276
|
// Memoize ListFooterComponent and ListEmptyComponent
|
|
203
277
|
const ListFooterComponent = useMemo(
|
|
204
278
|
() =>
|
|
205
|
-
|
|
279
|
+
loading ? (
|
|
206
280
|
<Center className="py-4">
|
|
207
281
|
<Spinner color={colors.blue[500]} size="small" />
|
|
208
282
|
</Center>
|
|
209
283
|
) : null,
|
|
210
|
-
[
|
|
284
|
+
[loading],
|
|
211
285
|
);
|
|
212
286
|
|
|
213
287
|
const ListEmptyComponent = useMemo(() => {
|
|
@@ -321,52 +395,41 @@ const DialogsComponent = (props: InboxProps) => {
|
|
|
321
395
|
|
|
322
396
|
// Load more channels
|
|
323
397
|
const handleLoadMore = useCallback(() => {
|
|
324
|
-
if (
|
|
398
|
+
if (loading || !data || channels.length < 10) {
|
|
325
399
|
console.log('Skip loading more: already loading or all data loaded');
|
|
326
400
|
return;
|
|
327
401
|
}
|
|
328
402
|
|
|
329
|
-
console.log('Loading more channels
|
|
330
|
-
setIsLoadingMore(true);
|
|
403
|
+
console.log('Loading more channels');
|
|
331
404
|
|
|
332
405
|
fetchMore({
|
|
333
406
|
variables: {
|
|
334
|
-
skip:
|
|
407
|
+
skip: channels.length,
|
|
335
408
|
},
|
|
336
409
|
updateQuery: (prev, { fetchMoreResult }) => {
|
|
337
|
-
setIsLoadingMore(false);
|
|
338
|
-
setPage((prevPage) => prevPage + 1);
|
|
339
|
-
|
|
340
410
|
if (!fetchMoreResult) return prev;
|
|
341
411
|
|
|
342
412
|
// Combine previous and new results
|
|
343
413
|
return {
|
|
344
414
|
...fetchMoreResult,
|
|
345
415
|
channelsByUser: [...(prev.channelsByUser || []), ...(fetchMoreResult.channelsByUser || [])],
|
|
346
|
-
supportServiceChannels: [
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
],
|
|
416
|
+
// supportServiceChannels: [
|
|
417
|
+
// ...(prev.supportServiceChannels || []),
|
|
418
|
+
// ...(fetchMoreResult.supportServiceChannels || []),
|
|
419
|
+
// ],
|
|
350
420
|
};
|
|
351
421
|
},
|
|
352
422
|
}).catch((error) => {
|
|
353
423
|
console.error('Error loading more channels:', error);
|
|
354
|
-
setIsLoadingMore(false);
|
|
355
424
|
});
|
|
356
|
-
}, [fetchMore,
|
|
425
|
+
}, [fetchMore, loading, data, channels.length]);
|
|
357
426
|
|
|
358
427
|
return (
|
|
359
428
|
<Box className="p-2">
|
|
360
|
-
<SubscriptionHandler
|
|
361
|
-
subscribeToMore={subscribeToMore}
|
|
362
|
-
document={CHAT_MESSAGE_ADDED}
|
|
363
|
-
variables={{}}
|
|
364
|
-
updateQuery={undefined}
|
|
365
|
-
/>
|
|
366
429
|
<FlatList
|
|
367
430
|
data={displayChannels}
|
|
368
431
|
onRefresh={handlePullToRefresh}
|
|
369
|
-
refreshing={loading
|
|
432
|
+
refreshing={loading}
|
|
370
433
|
contentContainerStyle={{ minHeight: '100%' }}
|
|
371
434
|
ItemSeparatorComponent={React.useCallback(
|
|
372
435
|
() => (
|
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
import React__default,{useRef,useState,useEffect,useCallback,useMemo}from'react';import {Pressable,HStack,Box,AvatarGroup,Avatar,AvatarFallbackText,AvatarBadge,Text,AvatarImage}from'@admin-layout/gluestack-ui-mobile';import {isToday,isYesterday,format}from'date-fns';import {useFocusEffect}from'@react-navigation/native';import {useChatMessageAddedSubscription,CHAT_MESSAGE_ADDED}from'../../../queries/inboxQueries.js';import {startCase}from'lodash-es';import colors from'tailwindcss/colors';import {SubscriptionHandler}from'./SubscriptionHandler.js';import {useMessagesQuery}from'common/graphql';var __defProp = Object.defineProperty;
|
|
2
|
-
var __defProps = Object.defineProperties;
|
|
3
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
-
var __spreadValues = (a, b) => {
|
|
9
|
-
for (var prop in b || (b = {}))
|
|
10
|
-
if (__hasOwnProp.call(b, prop))
|
|
11
|
-
__defNormalProp(a, prop, b[prop]);
|
|
12
|
-
if (__getOwnPropSymbols)
|
|
13
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
-
if (__propIsEnum.call(b, prop))
|
|
15
|
-
__defNormalProp(a, prop, b[prop]);
|
|
16
|
-
}
|
|
17
|
-
return a;
|
|
18
|
-
};
|
|
19
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
-
const createdAtText = (value) => {
|
|
21
|
-
if (!value)
|
|
22
|
-
return "";
|
|
23
|
-
let date = new Date(value);
|
|
24
|
-
if (isToday(date))
|
|
25
|
-
return "Today";
|
|
26
|
-
if (isYesterday(date))
|
|
27
|
-
return "Yesterday";
|
|
28
|
-
return format(new Date(value), "MMM dd, yyyy");
|
|
29
|
-
};
|
|
30
|
-
const LastMessageComponent = ({
|
|
31
|
-
subscribeToNewMessages,
|
|
32
|
-
title,
|
|
33
|
-
lastMessage,
|
|
34
|
-
channelId,
|
|
35
|
-
subscribeToMore
|
|
36
|
-
}) => {
|
|
37
|
-
var _a, _b;
|
|
38
|
-
React__default.useEffect(() => {
|
|
39
|
-
const unsubscribe = subscribeToNewMessages();
|
|
40
|
-
return () => {
|
|
41
|
-
if (unsubscribe && typeof unsubscribe === "function") {
|
|
42
|
-
unsubscribe();
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
}, [channelId, subscribeToNewMessages]);
|
|
46
|
-
const count = 30;
|
|
47
|
-
const channelTitle = (title == null ? void 0 : title.slice(0, count)) + ((title == null ? void 0 : title.length) > count ? "..." : "") || "";
|
|
48
|
-
let displayMessage = "No messages yet";
|
|
49
|
-
if (lastMessage) {
|
|
50
|
-
if (lastMessage.message && lastMessage.message.trim() !== "") {
|
|
51
|
-
displayMessage = lastMessage.message;
|
|
52
|
-
} else if (((_b = (_a = lastMessage.files) == null ? void 0 : _a.data) == null ? void 0 : _b.length) > 0) {
|
|
53
|
-
displayMessage = "\u{1F4CE} File attachment";
|
|
54
|
-
} else {
|
|
55
|
-
displayMessage = "(Empty message)";
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
const displayDate = (lastMessage == null ? void 0 : lastMessage.createdAt) ? createdAtText(lastMessage.createdAt) : (lastMessage == null ? void 0 : lastMessage.updatedAt) ? createdAtText(lastMessage.updatedAt) : "";
|
|
59
|
-
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
|
|
60
|
-
SubscriptionHandler,
|
|
61
|
-
{
|
|
62
|
-
subscribeToMore,
|
|
63
|
-
document: CHAT_MESSAGE_ADDED,
|
|
64
|
-
variables: {
|
|
65
|
-
channelId: channelId == null ? void 0 : channelId.toString()
|
|
66
|
-
},
|
|
67
|
-
updateQuery: void 0
|
|
68
|
-
}
|
|
69
|
-
), /* @__PURE__ */ React__default.createElement(HStack, { space: "sm", className: "flex-1 justify-between" }, /* @__PURE__ */ React__default.createElement(Box, { className: "flex-[0.8]" }, /* @__PURE__ */ React__default.createElement(Text, { color: colors.gray[600], className: "text-base text-wrap flex-wrap font-semibold" }, channelTitle), /* @__PURE__ */ React__default.createElement(Text, { color: colors.gray[600], numberOfLines: 1 }, displayMessage)), /* @__PURE__ */ React__default.createElement(Box, { className: "flex-[0.2]" }, /* @__PURE__ */ React__default.createElement(Text, { color: colors.gray[500] }, displayDate))));
|
|
70
|
-
};
|
|
71
|
-
const DialogsListItemComponent = function DialogsListItem2({
|
|
72
|
-
currentUser,
|
|
73
|
-
selectedChannelId,
|
|
74
|
-
channel,
|
|
75
|
-
onOpen,
|
|
76
|
-
forceRefresh,
|
|
77
|
-
visible = true
|
|
78
|
-
}) {
|
|
79
|
-
var _a, _b, _c, _d;
|
|
80
|
-
const isMountedRef = useRef(true);
|
|
81
|
-
const parentId = null;
|
|
82
|
-
const [loading, setLoading] = useState(false);
|
|
83
|
-
const [title, setTitle] = useState("");
|
|
84
|
-
const [messages, setMessages] = useState([]);
|
|
85
|
-
const [lastMessage, setLastMessage] = useState(null);
|
|
86
|
-
const shouldQuery = !!(channel == null ? void 0 : channel.id) && visible;
|
|
87
|
-
const {
|
|
88
|
-
data: messagesQuery,
|
|
89
|
-
loading: messageLoading,
|
|
90
|
-
refetch: refetchMessages,
|
|
91
|
-
subscribeToMore
|
|
92
|
-
} = useMessagesQuery({
|
|
93
|
-
variables: {
|
|
94
|
-
channelId: (_a = channel == null ? void 0 : channel.id) == null ? void 0 : _a.toString(),
|
|
95
|
-
parentId,
|
|
96
|
-
limit: 10
|
|
97
|
-
},
|
|
98
|
-
skip: !shouldQuery,
|
|
99
|
-
fetchPolicy: "cache-and-network",
|
|
100
|
-
refetchWritePolicy: "overwrite",
|
|
101
|
-
nextFetchPolicy: "network-only",
|
|
102
|
-
onCompleted: (data) => {
|
|
103
|
-
var _a2;
|
|
104
|
-
if (!shouldQuery)
|
|
105
|
-
return;
|
|
106
|
-
if ((_a2 = data == null ? void 0 : data.messages) == null ? void 0 : _a2.data) {
|
|
107
|
-
setMessages(data.messages.data);
|
|
108
|
-
const sortedMessages = [...data.messages.data].sort((a, b) => new Date((b == null ? void 0 : b.updatedAt) || (b == null ? void 0 : b.createdAt)).getTime() - new Date((a == null ? void 0 : a.updatedAt) || (a == null ? void 0 : a.createdAt)).getTime());
|
|
109
|
-
if (sortedMessages.length > 0) {
|
|
110
|
-
setLastMessage(sortedMessages[0]);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
onError: (error) => {
|
|
115
|
-
if (!shouldQuery)
|
|
116
|
-
return;
|
|
117
|
-
console.error(`Error fetching messages for channel ${channel == null ? void 0 : channel.id}:`, error);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
const {
|
|
121
|
-
data: newMessage
|
|
122
|
-
} = useChatMessageAddedSubscription({
|
|
123
|
-
variables: {
|
|
124
|
-
channelId: (_b = channel == null ? void 0 : channel.id) == null ? void 0 : _b.toString()
|
|
125
|
-
},
|
|
126
|
-
skip: !shouldQuery
|
|
127
|
-
});
|
|
128
|
-
useEffect(() => {
|
|
129
|
-
isMountedRef.current = true;
|
|
130
|
-
return () => {
|
|
131
|
-
isMountedRef.current = false;
|
|
132
|
-
};
|
|
133
|
-
}, []);
|
|
134
|
-
const refreshDialogState = useCallback(() => {
|
|
135
|
-
var _a2;
|
|
136
|
-
if (shouldQuery && isMountedRef.current) {
|
|
137
|
-
setLoading(true);
|
|
138
|
-
const options = {
|
|
139
|
-
channelId: (_a2 = channel == null ? void 0 : channel.id) == null ? void 0 : _a2.toString(),
|
|
140
|
-
parentId,
|
|
141
|
-
limit: 10
|
|
142
|
-
};
|
|
143
|
-
refetchMessages(options).then((result) => {
|
|
144
|
-
var _a3, _b2;
|
|
145
|
-
if (((_b2 = (_a3 = result.data) == null ? void 0 : _a3.messages) == null ? void 0 : _b2.data) && isMountedRef.current) {
|
|
146
|
-
const sortedMessages = [...result.data.messages.data].sort((a, b) => new Date((b == null ? void 0 : b.updatedAt) || (b == null ? void 0 : b.createdAt)).getTime() - new Date((a == null ? void 0 : a.updatedAt) || (a == null ? void 0 : a.createdAt)).getTime());
|
|
147
|
-
const latestMessage = sortedMessages.length > 0 ? sortedMessages[0] : null;
|
|
148
|
-
setMessages(result.data.messages.data);
|
|
149
|
-
setLastMessage(latestMessage);
|
|
150
|
-
}
|
|
151
|
-
setLoading(false);
|
|
152
|
-
}).catch((err) => {
|
|
153
|
-
console.error("Error refreshing dialog state:", err);
|
|
154
|
-
setLoading(false);
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
}, [shouldQuery, channel == null ? void 0 : channel.id, refetchMessages, parentId]);
|
|
158
|
-
const firstRenderRef = useRef(true);
|
|
159
|
-
useFocusEffect(React__default.useCallback(() => {
|
|
160
|
-
if (!(channel == null ? void 0 : channel.id))
|
|
161
|
-
return;
|
|
162
|
-
console.log("DialogsListItem focused for channel:", channel == null ? void 0 : channel.id);
|
|
163
|
-
if (firstRenderRef.current) {
|
|
164
|
-
console.log("Skipping initial focus refresh for channel:", channel == null ? void 0 : channel.id);
|
|
165
|
-
firstRenderRef.current = false;
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
console.log("FOCUS EFFECT: Force refetching messages on navigation back for channel:", channel == null ? void 0 : channel.id);
|
|
169
|
-
setLoading(true);
|
|
170
|
-
const fetchFreshData = async () => {
|
|
171
|
-
var _a2, _b2, _c2, _d2, _e, _f;
|
|
172
|
-
try {
|
|
173
|
-
const options = {
|
|
174
|
-
channelId: (_a2 = channel == null ? void 0 : channel.id) == null ? void 0 : _a2.toString(),
|
|
175
|
-
parentId,
|
|
176
|
-
limit: 10
|
|
177
|
-
};
|
|
178
|
-
const result = await refetchMessages(options);
|
|
179
|
-
console.log(`FOCUS EFFECT: Refetched ${((_d2 = (_c2 = (_b2 = result == null ? void 0 : result.data) == null ? void 0 : _b2.messages) == null ? void 0 : _c2.data) == null ? void 0 : _d2.length) || 0} messages for channel ${channel == null ? void 0 : channel.id}`);
|
|
180
|
-
if (((_f = (_e = result == null ? void 0 : result.data) == null ? void 0 : _e.messages) == null ? void 0 : _f.data) && isMountedRef.current) {
|
|
181
|
-
const currentMessages = messages;
|
|
182
|
-
const fetchedMessages = result.data.messages.data;
|
|
183
|
-
console.log("Data comparison:", {
|
|
184
|
-
currentCount: currentMessages.length,
|
|
185
|
-
fetchedCount: fetchedMessages.length,
|
|
186
|
-
isDifferent: JSON.stringify(currentMessages) !== JSON.stringify(fetchedMessages)
|
|
187
|
-
});
|
|
188
|
-
const sortedMessages = [...fetchedMessages].sort((a, b) => new Date((b == null ? void 0 : b.updatedAt) || (b == null ? void 0 : b.createdAt)).getTime() - new Date((a == null ? void 0 : a.updatedAt) || (a == null ? void 0 : a.createdAt)).getTime());
|
|
189
|
-
const latestMessage = sortedMessages.length > 0 ? sortedMessages[0] : null;
|
|
190
|
-
setMessages(fetchedMessages);
|
|
191
|
-
setLastMessage(latestMessage);
|
|
192
|
-
}
|
|
193
|
-
} catch (error) {
|
|
194
|
-
console.error("Error refetching messages on focus:", error);
|
|
195
|
-
} finally {
|
|
196
|
-
if (isMountedRef.current) {
|
|
197
|
-
setLoading(false);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
fetchFreshData();
|
|
202
|
-
return () => {
|
|
203
|
-
};
|
|
204
|
-
}, [channel == null ? void 0 : channel.id, refetchMessages, messages, isMountedRef, parentId]));
|
|
205
|
-
useEffect(() => {
|
|
206
|
-
if (!shouldQuery)
|
|
207
|
-
return;
|
|
208
|
-
if ((channel == null ? void 0 : channel.id) && isMountedRef.current) {
|
|
209
|
-
const timer = setTimeout(() => {
|
|
210
|
-
if (isMountedRef.current) {
|
|
211
|
-
refreshDialogState();
|
|
212
|
-
}
|
|
213
|
-
}, 100);
|
|
214
|
-
return () => {
|
|
215
|
-
clearTimeout(timer);
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
}, [shouldQuery, channel == null ? void 0 : channel.id, refreshDialogState]);
|
|
219
|
-
useEffect(() => {
|
|
220
|
-
if (forceRefresh && shouldQuery && (channel == null ? void 0 : channel.id) && isMountedRef.current) {
|
|
221
|
-
const timer = setTimeout(() => {
|
|
222
|
-
var _a2;
|
|
223
|
-
if (isMountedRef.current && refetchMessages) {
|
|
224
|
-
refetchMessages({
|
|
225
|
-
channelId: (_a2 = channel == null ? void 0 : channel.id) == null ? void 0 : _a2.toString(),
|
|
226
|
-
parentId,
|
|
227
|
-
limit: 10
|
|
228
|
-
}).then((result) => {
|
|
229
|
-
var _a3, _b2;
|
|
230
|
-
if (((_b2 = (_a3 = result == null ? void 0 : result.data) == null ? void 0 : _a3.messages) == null ? void 0 : _b2.data) && isMountedRef.current) {
|
|
231
|
-
const sortedMessages = [...result.data.messages.data].sort((a, b) => new Date((b == null ? void 0 : b.updatedAt) || (b == null ? void 0 : b.createdAt)).getTime() - new Date((a == null ? void 0 : a.updatedAt) || (a == null ? void 0 : a.createdAt)).getTime());
|
|
232
|
-
const latestMessage = sortedMessages.length > 0 ? sortedMessages[0] : null;
|
|
233
|
-
setMessages(result.data.messages.data);
|
|
234
|
-
setLastMessage(latestMessage);
|
|
235
|
-
}
|
|
236
|
-
}).catch((error) => {
|
|
237
|
-
console.error(`Error force refreshing channel ${channel == null ? void 0 : channel.id}:`, error);
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
}, 50);
|
|
241
|
-
return () => clearTimeout(timer);
|
|
242
|
-
}
|
|
243
|
-
}, [shouldQuery, channel == null ? void 0 : channel.id, forceRefresh, refetchMessages, parentId]);
|
|
244
|
-
const channelMembers = useMemo(() => {
|
|
245
|
-
var _a2, _b2, _c2;
|
|
246
|
-
return (_c2 = (_b2 = (_a2 = channel == null ? void 0 : channel.members) == null ? void 0 : _a2.filter((ch) => {
|
|
247
|
-
var _a3, _b3;
|
|
248
|
-
return ((_a3 = ch == null ? void 0 : ch.user) == null ? void 0 : _a3.id) != (currentUser == null ? void 0 : currentUser.id) && ((_b3 = ch == null ? void 0 : ch.user) == null ? void 0 : _b3.__typename) == "UserAccount";
|
|
249
|
-
})) == null ? void 0 : _b2.map((m) => m == null ? void 0 : m.user)) != null ? _c2 : null;
|
|
250
|
-
}, [currentUser, channel]);
|
|
251
|
-
useEffect(() => {
|
|
252
|
-
var _a2, _b2, _c2;
|
|
253
|
-
if (channelMembers && isMountedRef.current) {
|
|
254
|
-
const titleString = (_c2 = (_b2 = (_a2 = channelMembers == null ? void 0 : channelMembers.map((u) => {
|
|
255
|
-
var _a3;
|
|
256
|
-
return (u == null ? void 0 : u.givenName) + " " + ((_a3 = u == null ? void 0 : u.familyName) != null ? _a3 : "");
|
|
257
|
-
})) == null ? void 0 : _a2.filter((mu) => mu)) == null ? void 0 : _b2.join(", ")) != null ? _c2 : "";
|
|
258
|
-
setTitle(titleString);
|
|
259
|
-
}
|
|
260
|
-
}, [channelMembers]);
|
|
261
|
-
const displayTitle = useMemo(() => {
|
|
262
|
-
const length = 30;
|
|
263
|
-
return title.length > length ? title.substring(0, length - 3) + "..." : title;
|
|
264
|
-
}, [title]);
|
|
265
|
-
useEffect(() => {
|
|
266
|
-
var _a2, _b2;
|
|
267
|
-
console.log(`DialogsListItem for channel ${channel == null ? void 0 : channel.id}: `, {
|
|
268
|
-
hasLastMessage: !!lastMessage,
|
|
269
|
-
message: ((_a2 = lastMessage == null ? void 0 : lastMessage.message) == null ? void 0 : _a2.substring(0, 20)) + (((_b2 = lastMessage == null ? void 0 : lastMessage.message) == null ? void 0 : _b2.length) > 20 ? "..." : ""),
|
|
270
|
-
messagesCount: messages.length
|
|
271
|
-
});
|
|
272
|
-
}, [channel == null ? void 0 : channel.id, lastMessage, messages.length]);
|
|
273
|
-
useEffect(() => {
|
|
274
|
-
if (!shouldQuery)
|
|
275
|
-
return;
|
|
276
|
-
if ((newMessage == null ? void 0 : newMessage.chatMessageAdded) && (channel == null ? void 0 : channel.id)) {
|
|
277
|
-
const incomingMessage = newMessage.chatMessageAdded;
|
|
278
|
-
if (messages.some((msg) => msg.id === incomingMessage.id)) {
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
setMessages((prevMessages) => [...prevMessages, incomingMessage]);
|
|
282
|
-
setLastMessage(incomingMessage);
|
|
283
|
-
}
|
|
284
|
-
}, [shouldQuery, newMessage, channel == null ? void 0 : channel.id, messages]);
|
|
285
|
-
useEffect(() => {
|
|
286
|
-
if (!shouldQuery)
|
|
287
|
-
return;
|
|
288
|
-
if ((channel == null ? void 0 : channel.lastMessage) && channel.lastMessage.id) {
|
|
289
|
-
if (!messages.some((msg) => msg.id === channel.lastMessage.id)) {
|
|
290
|
-
setMessages((prevMessages) => [...prevMessages, channel.lastMessage]);
|
|
291
|
-
setLastMessage(channel.lastMessage);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}, [shouldQuery, (_c = channel == null ? void 0 : channel.lastMessage) == null ? void 0 : _c.id, messages]);
|
|
295
|
-
return /* @__PURE__ */ React__default.createElement(Pressable, { onPress: () => onOpen(channel == null ? void 0 : channel.id, displayTitle), className: "flex-1 border-gray-200 rounded-md dark:border-gray-600 dark:bg-gray-700", style: {
|
|
296
|
-
borderBottomWidth: 1,
|
|
297
|
-
borderColor: "#e5e7eb",
|
|
298
|
-
marginVertical: 0,
|
|
299
|
-
paddingHorizontal: 10
|
|
300
|
-
} }, /* @__PURE__ */ React__default.createElement(HStack, { space: "md", className: "flex-1 w-[100%] py-3 items-center" }, /* @__PURE__ */ React__default.createElement(Box, { className: "flex-[0.1] items-start pl-3" }, /* @__PURE__ */ React__default.createElement(AvatarGroup, null, channelMembers && (channelMembers == null ? void 0 : channelMembers.length) > 0 && ((_d = channelMembers == null ? void 0 : channelMembers.slice(0, 1)) == null ? void 0 : _d.map((ch, i) => {
|
|
301
|
-
var _a2;
|
|
302
|
-
return /* @__PURE__ */ React__default.createElement(Avatar, { key: "dialogs-list-" + i, size: "sm", className: `bg-transparent top-[${i == 1 ? "4" : "0"}] right-[${i == 1 ? "-2" : "0"}] z-[${i == 1 ? 5 : 1}]` }, /* @__PURE__ */ React__default.createElement(AvatarFallbackText, null, startCase((_a2 = ch == null ? void 0 : ch.username) == null ? void 0 : _a2.charAt(0))), (channelMembers == null ? void 0 : channelMembers.length) > 1 && /* @__PURE__ */ React__default.createElement(AvatarBadge, { style: {
|
|
303
|
-
width: "100%",
|
|
304
|
-
height: "100%",
|
|
305
|
-
backgroundColor: "#e5e7eb",
|
|
306
|
-
borderRadius: 5
|
|
307
|
-
}, className: "items-center justify-center bg-gray-200 rounded-md" }, /* @__PURE__ */ React__default.createElement(Text, { style: {
|
|
308
|
-
fontSize: 12,
|
|
309
|
-
fontWeight: "bold",
|
|
310
|
-
color: "#000"
|
|
311
|
-
} }, channelMembers == null ? void 0 : channelMembers.length)), (channelMembers == null ? void 0 : channelMembers.length) == 1 && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(AvatarImage, { alt: "user image", style: {
|
|
312
|
-
borderRadius: 6,
|
|
313
|
-
borderWidth: 2,
|
|
314
|
-
borderColor: "#fff"
|
|
315
|
-
}, source: {
|
|
316
|
-
uri: ch == null ? void 0 : ch.picture
|
|
317
|
-
} }), /* @__PURE__ */ React__default.createElement(AvatarBadge, { style: {
|
|
318
|
-
width: 10,
|
|
319
|
-
height: 10
|
|
320
|
-
} })));
|
|
321
|
-
})))), /* @__PURE__ */ React__default.createElement(Box, { className: "flex-1" }, /* @__PURE__ */ React__default.createElement(LastMessageComponent, { key: `last-msg-${(lastMessage == null ? void 0 : lastMessage.id) || "none"}-${messages.length}`, title: displayTitle, lastMessage, channelId: channel == null ? void 0 : channel.id, subscribeToNewMessages: () => {
|
|
322
|
-
var _a2;
|
|
323
|
-
return shouldQuery ? subscribeToMore({
|
|
324
|
-
document: CHAT_MESSAGE_ADDED,
|
|
325
|
-
variables: {
|
|
326
|
-
channelId: (_a2 = channel.id) == null ? void 0 : _a2.toString()
|
|
327
|
-
},
|
|
328
|
-
updateQuery: (prev, {
|
|
329
|
-
subscriptionData
|
|
330
|
-
}) => {
|
|
331
|
-
var _a3;
|
|
332
|
-
if (!subscriptionData.data)
|
|
333
|
-
return prev;
|
|
334
|
-
const newMessage2 = (_a3 = subscriptionData == null ? void 0 : subscriptionData.data) == null ? void 0 : _a3.chatMessageAdded;
|
|
335
|
-
if (isMountedRef.current) {
|
|
336
|
-
if (!messages.some((msg) => msg.id === newMessage2.id)) {
|
|
337
|
-
setMessages((prevMessages) => [...prevMessages, newMessage2]);
|
|
338
|
-
setLastMessage(newMessage2);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
const existingMessages = prev == null ? void 0 : prev.messages;
|
|
342
|
-
const previousData = (existingMessages == null ? void 0 : existingMessages.data) ? [...existingMessages.data, newMessage2] : [];
|
|
343
|
-
const totalMsgCount = (existingMessages == null ? void 0 : existingMessages.totalCount) + 1;
|
|
344
|
-
const merged = __spreadProps(__spreadValues({}, prev), {
|
|
345
|
-
messages: __spreadProps(__spreadValues({}, existingMessages), {
|
|
346
|
-
data: previousData,
|
|
347
|
-
totalCount: totalMsgCount
|
|
348
|
-
})
|
|
349
|
-
});
|
|
350
|
-
return merged;
|
|
351
|
-
}
|
|
352
|
-
}) : void 0;
|
|
353
|
-
}, subscribeToMore }))));
|
|
354
|
-
};
|
|
355
|
-
const DialogsListItem = React__default.memo(DialogsListItemComponent);export{DialogsListItem,DialogsListItemComponent};//# sourceMappingURL=DialogsListItem.js.map
|