@messenger-box/tailwind-ui-inbox 10.0.3-alpha.65 → 10.0.3-alpha.69
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/components/InboxMessage/ConversationItem.d.ts +10 -7
- package/lib/components/InboxMessage/ConversationItem.d.ts.map +1 -1
- package/lib/components/InboxMessage/ConversationItem.js +58 -77
- package/lib/components/InboxMessage/ConversationItem.js.map +1 -1
- package/lib/components/InboxMessage/LeftSidebar.d.ts +2 -1
- package/lib/components/InboxMessage/LeftSidebar.d.ts.map +1 -1
- package/lib/components/InboxMessage/LeftSidebar.js +15 -8
- package/lib/components/InboxMessage/LeftSidebar.js.map +1 -1
- package/lib/components/InboxMessage/MessageInput.d.ts.map +1 -1
- package/lib/components/InboxMessage/MessageInput.js +15 -1
- package/lib/components/InboxMessage/MessageInput.js.map +1 -1
- package/lib/components/InboxMessage/SubscriptionHandler.d.ts +19 -0
- package/lib/components/InboxMessage/SubscriptionHandler.d.ts.map +1 -0
- package/lib/components/InboxMessage/SubscriptionHandler.js +41 -0
- package/lib/components/InboxMessage/SubscriptionHandler.js.map +1 -0
- package/lib/container/Inbox.d.ts.map +1 -1
- package/lib/container/Inbox.js +49 -28
- package/lib/container/Inbox.js.map +1 -1
- package/lib/container/InboxWithLoader.d.ts +10 -3
- package/lib/container/InboxWithLoader.d.ts.map +1 -1
- package/lib/container/InboxWithLoader.js +81 -30
- package/lib/container/InboxWithLoader.js.map +1 -1
- package/lib/container/ServiceInbox.js +1 -1
- package/lib/container/ServiceInbox.js.map +1 -1
- package/lib/container/ThreadMessages.js +1 -1
- package/lib/container/ThreadMessages.js.map +1 -1
- package/lib/container/ThreadMessagesInbox.js +1 -1
- package/lib/container/ThreadMessagesInbox.js.map +1 -1
- package/lib/container/Threads.js +1 -1
- package/lib/container/Threads.js.map +1 -1
- package/package.json +4 -4
- package/src/components/InboxMessage/ConversationItem.tsx +188 -186
- package/src/components/InboxMessage/LeftSidebar.tsx +20 -11
- package/src/components/InboxMessage/MessageInput.tsx +16 -1
- package/src/components/InboxMessage/SubscriptionHandler.tsx +55 -0
- package/src/container/Inbox.tsx +53 -35
- package/src/container/InboxWithLoader.tsx +104 -38
package/src/container/Inbox.tsx
CHANGED
|
@@ -18,6 +18,7 @@ import { objectId } from '@messenger-box/core';
|
|
|
18
18
|
import { ThreadsInbox } from './ThreadsInbox';
|
|
19
19
|
import { ThreadMessagesInbox } from './ThreadMessagesInbox';
|
|
20
20
|
import { useApolloClient } from '@apollo/client';
|
|
21
|
+
import { SubscriptionHandler } from '../components/InboxMessage/SubscriptionHandler';
|
|
21
22
|
|
|
22
23
|
const { MESSAGES_PER_PAGE } = config;
|
|
23
24
|
|
|
@@ -151,11 +152,16 @@ const Inbox = (props: InboxProps) => {
|
|
|
151
152
|
return uniqBy([...(userChannels?.supportServiceChannels ?? []), ...(userChannels?.channelsByUser ?? [])], 'id');
|
|
152
153
|
}, [userChannels]);
|
|
153
154
|
|
|
155
|
+
// Memoize stable channel array to prevent unnecessary re-renders
|
|
156
|
+
const stableChannels = useMemo(() => {
|
|
157
|
+
return channels || [];
|
|
158
|
+
}, [channels]);
|
|
159
|
+
|
|
154
160
|
// Memoized values derived from Apollo cache data
|
|
155
161
|
const channelFilters = useMemo(() => {
|
|
156
162
|
const filters = { ...channelFilterProp };
|
|
157
163
|
const channelType = filters?.type ?? RoomType.Direct;
|
|
158
|
-
filters.type = supportServices ? [channelType, RoomType.Service] :
|
|
164
|
+
filters.type = supportServices ? [channelType, RoomType.Service] : channelType;
|
|
159
165
|
return filters;
|
|
160
166
|
}, [channelFilterProp, supportServices]);
|
|
161
167
|
|
|
@@ -168,10 +174,11 @@ const Inbox = (props: InboxProps) => {
|
|
|
168
174
|
);
|
|
169
175
|
}, [channels]);
|
|
170
176
|
|
|
171
|
-
const currentUser = useMemo(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
);
|
|
177
|
+
// const currentUser = useMemo(
|
|
178
|
+
// () => users?.find((user) => user && user.alias?.includes(auth?.authUserId)),
|
|
179
|
+
// [users, auth?.authUserId],
|
|
180
|
+
// );
|
|
181
|
+
const currentUser = auth;
|
|
175
182
|
|
|
176
183
|
const channelName = useMemo(() => {
|
|
177
184
|
if (!channels || !pathChannelId) return '';
|
|
@@ -226,8 +233,8 @@ const Inbox = (props: InboxProps) => {
|
|
|
226
233
|
const basePath = pathPrefix ? `${pathPrefix}${mainPath}` : mainPath;
|
|
227
234
|
|
|
228
235
|
const searchParams = new URLSearchParams();
|
|
229
|
-
if (channelRole) searchParams.set('channelRole', channelRole);
|
|
230
|
-
if (orgName) searchParams.set('orgName', orgName);
|
|
236
|
+
// if (channelRole) searchParams.set('channelRole', channelRole);
|
|
237
|
+
// if (orgName) searchParams.set('orgName', orgName);
|
|
231
238
|
|
|
232
239
|
const newPath = searchParams.toString() ? `${basePath}?${searchParams.toString()}` : basePath;
|
|
233
240
|
navigate(newPath, { replace: true });
|
|
@@ -282,7 +289,7 @@ const Inbox = (props: InboxProps) => {
|
|
|
282
289
|
>
|
|
283
290
|
<LeftSidebar
|
|
284
291
|
currentUser={currentUser}
|
|
285
|
-
userChannels={
|
|
292
|
+
userChannels={stableChannels}
|
|
286
293
|
userChannelsLoading={userChannelsLoading}
|
|
287
294
|
users={users}
|
|
288
295
|
handleSelectChannel={handleSelectChannel}
|
|
@@ -290,6 +297,7 @@ const Inbox = (props: InboxProps) => {
|
|
|
290
297
|
channelToTop={0}
|
|
291
298
|
getChannelsRefetch={getChannelsRefetch}
|
|
292
299
|
role={channelRole}
|
|
300
|
+
messagesQuery={data?.[1]}
|
|
293
301
|
/>
|
|
294
302
|
</div>
|
|
295
303
|
|
|
@@ -764,33 +772,43 @@ const MessagesComponent = React.memo((props: any) => {
|
|
|
764
772
|
onScroll={onMessagesScroll}
|
|
765
773
|
>
|
|
766
774
|
{messages.length > 0 ? (
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
775
|
+
<>
|
|
776
|
+
<Messages
|
|
777
|
+
innerRef={messageListRef}
|
|
778
|
+
channelId={channelId}
|
|
779
|
+
currentUser={auth}
|
|
780
|
+
channelMessages={messages}
|
|
781
|
+
totalCount={totalCount}
|
|
782
|
+
onMessageClick={onMessageClick}
|
|
783
|
+
/>
|
|
784
|
+
<SubscriptionHandler
|
|
785
|
+
subscribeToMore={subscribeToMore}
|
|
786
|
+
document={CHAT_MESSAGE_ADDED}
|
|
787
|
+
variables={{ channelId: channelId.toString() }}
|
|
788
|
+
enabled={!!channelId && !!subscribeToMore}
|
|
789
|
+
updateQuery={(prev: any, { subscriptionData }: any) => {
|
|
790
|
+
console.log('Subscription updateQuery called:', { prev, subscriptionData });
|
|
791
|
+
if (!subscriptionData.data) {
|
|
792
|
+
console.log('No subscription data, returning prev');
|
|
793
|
+
return prev;
|
|
794
|
+
}
|
|
795
|
+
const newMessage = subscriptionData.data.chatMessageAdded;
|
|
796
|
+
console.log('New message received via subscription:', newMessage);
|
|
797
|
+
|
|
798
|
+
return {
|
|
799
|
+
...prev,
|
|
800
|
+
messages: {
|
|
801
|
+
...prev?.messages,
|
|
802
|
+
data: uniqBy([...(prev?.messages?.data || []), newMessage], 'id'),
|
|
803
|
+
totalCount: (prev?.messages?.totalCount || 0) + 1,
|
|
804
|
+
},
|
|
805
|
+
};
|
|
806
|
+
}}
|
|
807
|
+
onError={(error) => {
|
|
808
|
+
console.error('Subscription error:', error);
|
|
809
|
+
}}
|
|
810
|
+
/>
|
|
811
|
+
</>
|
|
794
812
|
) : (
|
|
795
813
|
<div className="flex-1 flex items-center justify-center text-gray-500">
|
|
796
814
|
<div className="text-center">
|
|
@@ -1,23 +1,38 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { useMemo, useCallback } from 'react';
|
|
2
2
|
import { useParams, useLocation } from '@remix-run/react';
|
|
3
3
|
|
|
4
4
|
// import AddGovernmentId from './AddGovernmentId';
|
|
5
5
|
import Inbox from './Inbox';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
useGetChannelsByUserQuery,
|
|
8
|
+
useGetChannelsByUserWithLastMessageQuery,
|
|
9
|
+
useMessagesQuery,
|
|
10
|
+
useViewChannelDetailQuery,
|
|
11
|
+
} from 'common/graphql';
|
|
7
12
|
import { RoomType } from 'common';
|
|
8
13
|
import { config } from '../config';
|
|
9
14
|
|
|
10
15
|
const { MESSAGES_PER_PAGE } = config;
|
|
11
16
|
|
|
12
|
-
//
|
|
13
|
-
export const queryParamsGenerator = (params
|
|
17
|
+
// Enhanced query parameters generator with better typing and flexibility
|
|
18
|
+
export const queryParamsGenerator = (params: {
|
|
19
|
+
role?: string;
|
|
20
|
+
criteria?: Record<string, any>;
|
|
21
|
+
supportServices?: boolean;
|
|
22
|
+
orgName?: string;
|
|
23
|
+
}) => ({
|
|
14
24
|
variable1: {
|
|
15
25
|
role: params.role,
|
|
16
|
-
criteria:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
type: RoomType.Service,
|
|
26
|
+
criteria: {
|
|
27
|
+
...params.criteria,
|
|
28
|
+
...(params.orgName && { orgName: params.orgName }),
|
|
20
29
|
},
|
|
30
|
+
supportServices: params.supportServices ? true : false,
|
|
31
|
+
supportServiceCriteria: params.supportServices
|
|
32
|
+
? {
|
|
33
|
+
type: RoomType.Service,
|
|
34
|
+
}
|
|
35
|
+
: undefined,
|
|
21
36
|
orderBy: {
|
|
22
37
|
lastPostAt: 'desc',
|
|
23
38
|
},
|
|
@@ -172,28 +187,35 @@ const InboxWithLoader = (props: InboxWithLoaderProps) => {
|
|
|
172
187
|
const { channelFilters: channelFilterProp, channelRole: channelRoleProp, supportServices, pathPrefix } = props;
|
|
173
188
|
const { orgName, channelRole: channelRoleParam } = useParams();
|
|
174
189
|
const channelRole = channelRoleParam || channelRoleProp;
|
|
175
|
-
|
|
190
|
+
|
|
176
191
|
// Create new props object with orgName instead of mutating original props
|
|
177
|
-
const inboxProps =
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
192
|
+
const inboxProps = useMemo(
|
|
193
|
+
() => ({
|
|
194
|
+
...props,
|
|
195
|
+
orgName: orgName || '',
|
|
196
|
+
pathPrefix: pathPrefix || '',
|
|
197
|
+
}),
|
|
198
|
+
[props, orgName, pathPrefix],
|
|
199
|
+
);
|
|
182
200
|
|
|
183
201
|
const { id: pathChannelId } = useParams();
|
|
184
202
|
|
|
185
|
-
//
|
|
186
|
-
const channelsQueryVariables = useMemo(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
203
|
+
// Enhanced query variables with better filtering and stable references
|
|
204
|
+
const channelsQueryVariables = useMemo(() => {
|
|
205
|
+
const channelFilters = { ...channelFilterProp };
|
|
206
|
+
const channelType = channelFilters?.type ?? RoomType.Direct;
|
|
207
|
+
const baseFilters = {
|
|
208
|
+
...channelFilters,
|
|
209
|
+
type: supportServices ? [channelType, RoomType.Service] : channelType,
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
return queryParamsGenerator({
|
|
213
|
+
role: channelRole,
|
|
214
|
+
criteria: baseFilters,
|
|
215
|
+
supportServices,
|
|
216
|
+
orgName: orgName || '',
|
|
217
|
+
}).variable1;
|
|
218
|
+
}, [channelRole, channelFilterProp, supportServices, orgName]);
|
|
197
219
|
|
|
198
220
|
const messagesQueryVariables = useMemo(
|
|
199
221
|
() => ({
|
|
@@ -211,43 +233,67 @@ const InboxWithLoader = (props: InboxWithLoaderProps) => {
|
|
|
211
233
|
[pathChannelId],
|
|
212
234
|
);
|
|
213
235
|
|
|
214
|
-
// Apollo queries with
|
|
236
|
+
// Enhanced Apollo queries with better cache policies and error handling
|
|
215
237
|
const channelsQuery = useGetChannelsByUserQuery({
|
|
216
238
|
variables: channelsQueryVariables,
|
|
217
|
-
fetchPolicy: 'cache-
|
|
239
|
+
fetchPolicy: 'cache-and-network', // Better for real-time updates
|
|
218
240
|
errorPolicy: 'all',
|
|
219
|
-
notifyOnNetworkStatusChange:
|
|
220
|
-
// Enable optimistic updates and real-time subscriptions
|
|
241
|
+
notifyOnNetworkStatusChange: false,
|
|
221
242
|
returnPartialData: true,
|
|
243
|
+
// Add context for better cache management
|
|
244
|
+
context: {
|
|
245
|
+
cacheKey: 'channels-list',
|
|
246
|
+
},
|
|
222
247
|
});
|
|
223
248
|
|
|
224
249
|
const messagesQuery = useMessagesQuery({
|
|
225
250
|
variables: messagesQueryVariables,
|
|
226
251
|
skip: !pathChannelId,
|
|
227
|
-
fetchPolicy: 'cache-and-network', //
|
|
252
|
+
fetchPolicy: 'cache-and-network', // Better for real-time messaging
|
|
228
253
|
errorPolicy: 'all',
|
|
229
254
|
notifyOnNetworkStatusChange: true,
|
|
230
255
|
returnPartialData: true,
|
|
231
|
-
//
|
|
232
|
-
pollInterval:
|
|
256
|
+
// Disable polling to allow subscriptions to work properly
|
|
257
|
+
pollInterval: 0,
|
|
258
|
+
// Add context for better cache management
|
|
259
|
+
context: {
|
|
260
|
+
cacheKey: 'messages-list',
|
|
261
|
+
},
|
|
233
262
|
});
|
|
234
263
|
|
|
235
264
|
const channelDetailQuery = useViewChannelDetailQuery({
|
|
236
265
|
variables: channelDetailQueryVariables,
|
|
237
266
|
skip: !pathChannelId,
|
|
238
|
-
fetchPolicy: 'cache-first',
|
|
267
|
+
fetchPolicy: 'cache-first', // Channel details don't change often
|
|
239
268
|
errorPolicy: 'all',
|
|
240
|
-
notifyOnNetworkStatusChange:
|
|
269
|
+
notifyOnNetworkStatusChange: false, // No need for real-time updates
|
|
241
270
|
returnPartialData: true,
|
|
271
|
+
// Add context for better cache management
|
|
272
|
+
context: {
|
|
273
|
+
cacheKey: 'channel-detail',
|
|
274
|
+
},
|
|
242
275
|
});
|
|
243
276
|
|
|
244
|
-
//
|
|
277
|
+
// Enhanced error handling with retry logic
|
|
278
|
+
const handleRetry = useCallback(() => {
|
|
279
|
+
if (channelsQuery.error) {
|
|
280
|
+
channelsQuery.refetch();
|
|
281
|
+
}
|
|
282
|
+
if (messagesQuery.error) {
|
|
283
|
+
messagesQuery.refetch();
|
|
284
|
+
}
|
|
285
|
+
if (channelDetailQuery.error) {
|
|
286
|
+
channelDetailQuery.refetch();
|
|
287
|
+
}
|
|
288
|
+
}, [channelsQuery, messagesQuery, channelDetailQuery]);
|
|
289
|
+
|
|
290
|
+
// Create loader data array for Inbox component with better error handling
|
|
245
291
|
const loaderData = useMemo(
|
|
246
292
|
() => [channelsQuery, messagesQuery, channelDetailQuery],
|
|
247
293
|
[channelsQuery, messagesQuery, channelDetailQuery],
|
|
248
294
|
);
|
|
249
295
|
|
|
250
|
-
// Enhanced loading states with
|
|
296
|
+
// Enhanced loading states with better UX
|
|
251
297
|
if (channelsQuery.loading && !pathChannelId && !channelsQuery.data) {
|
|
252
298
|
return <InboxSkeleton showRightSidebar={false} />;
|
|
253
299
|
}
|
|
@@ -262,8 +308,28 @@ const InboxWithLoader = (props: InboxWithLoaderProps) => {
|
|
|
262
308
|
return <InboxSkeleton showRightSidebar={true} />;
|
|
263
309
|
}
|
|
264
310
|
|
|
311
|
+
// Enhanced error handling with retry option
|
|
265
312
|
if (channelsQuery.error && !channelsQuery.data) {
|
|
266
|
-
return
|
|
313
|
+
return (
|
|
314
|
+
<div className="flex flex-col items-center justify-center min-h-screen space-y-4">
|
|
315
|
+
<TailwindAlert>Error loading channels: {channelsQuery.error.message}</TailwindAlert>
|
|
316
|
+
<button
|
|
317
|
+
onClick={handleRetry}
|
|
318
|
+
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
|
|
319
|
+
>
|
|
320
|
+
Retry
|
|
321
|
+
</button>
|
|
322
|
+
</div>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Handle individual query errors gracefully
|
|
327
|
+
if (messagesQuery.error && !messagesQuery.data && pathChannelId) {
|
|
328
|
+
console.warn('Messages query error:', messagesQuery.error);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (channelDetailQuery.error && !channelDetailQuery.data && pathChannelId) {
|
|
332
|
+
console.warn('Channel detail query error:', channelDetailQuery.error);
|
|
267
333
|
}
|
|
268
334
|
|
|
269
335
|
return <Inbox data={loaderData} {...inboxProps} />;
|