@messenger-box/tailwind-ui-inbox 10.0.3-alpha.70 → 10.0.3-alpha.71
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 +4 -0
- package/lib/components/InboxMessage/LeftSidebar.d.ts +2 -0
- package/lib/components/InboxMessage/LeftSidebar.d.ts.map +1 -1
- package/lib/components/InboxMessage/LeftSidebar.js +16 -5
- package/lib/components/InboxMessage/LeftSidebar.js.map +1 -1
- package/lib/components/InboxMessage/Messages.d.ts +3 -1
- package/lib/components/InboxMessage/Messages.d.ts.map +1 -1
- package/lib/components/InboxMessage/Messages.js +13 -7
- package/lib/components/InboxMessage/Messages.js.map +1 -1
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts +2 -0
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts.map +1 -1
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js +25 -21
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js.map +1 -1
- package/lib/container/Inbox.d.ts.map +1 -1
- package/lib/container/Inbox.js +173 -56
- package/lib/container/Inbox.js.map +1 -1
- package/package.json +2 -2
- package/src/components/InboxMessage/LeftSidebar.tsx +14 -4
- package/src/components/InboxMessage/Messages.tsx +22 -12
- package/src/components/InboxMessage/message-widgets/SlackLikeMessageGroup.tsx +48 -16
- package/src/container/Inbox.tsx +274 -127
package/src/container/Inbox.tsx
CHANGED
|
@@ -63,6 +63,32 @@ const useMediaQuery = (query: string) => {
|
|
|
63
63
|
return matches;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
+
// Hook to get window dimensions
|
|
67
|
+
const useWindowDimensions = () => {
|
|
68
|
+
const [windowDimensions, setWindowDimensions] = React.useState({
|
|
69
|
+
width: typeof window !== 'undefined' ? window.innerWidth : 1024,
|
|
70
|
+
height: typeof window !== 'undefined' ? window.innerHeight : 768,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (typeof window === 'undefined') return;
|
|
75
|
+
|
|
76
|
+
const handleResize = () => {
|
|
77
|
+
setWindowDimensions({
|
|
78
|
+
width: window.innerWidth,
|
|
79
|
+
height: window.innerHeight,
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
window.addEventListener('resize', handleResize);
|
|
84
|
+
handleResize(); // Set initial dimensions
|
|
85
|
+
|
|
86
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
87
|
+
}, []);
|
|
88
|
+
|
|
89
|
+
return windowDimensions;
|
|
90
|
+
};
|
|
91
|
+
|
|
66
92
|
// Static components
|
|
67
93
|
const Spinner = React.memo(({ className = '' }: { className?: string }) => (
|
|
68
94
|
<div className={`animate-spin rounded-full border-4 border-gray-200 border-t-blue-500 ${className}`}>
|
|
@@ -76,10 +102,13 @@ const Drawer = React.memo(({ isOpen, onClose, children, title }: DrawerProps) =>
|
|
|
76
102
|
return (
|
|
77
103
|
<div className="fixed inset-0 z-50 overflow-hidden">
|
|
78
104
|
<div className="absolute inset-0 bg-black bg-opacity-50" onClick={onClose} />
|
|
79
|
-
<div className="absolute bottom-0 left-0 right-0 bg-white rounded-t-lg shadow-lg max-h-[80vh] overflow-hidden">
|
|
80
|
-
<div className="flex items-center justify-between p-4 border-b border-gray-200">
|
|
81
|
-
<h2 className="text-lg font-semibold">{title}</h2>
|
|
82
|
-
<button
|
|
105
|
+
<div className="absolute bottom-0 left-0 right-0 bg-white rounded-t-lg shadow-lg max-h-[80vh] flex flex-col overflow-hidden">
|
|
106
|
+
<div className="flex items-center justify-between p-4 border-b border-gray-200 flex-shrink-0">
|
|
107
|
+
<h2 className="text-lg font-semibold truncate">{title}</h2>
|
|
108
|
+
<button
|
|
109
|
+
onClick={onClose}
|
|
110
|
+
className="p-1 hover:bg-gray-100 rounded-full transition-colors flex-shrink-0 ml-2"
|
|
111
|
+
>
|
|
83
112
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
84
113
|
<path
|
|
85
114
|
strokeLinecap="round"
|
|
@@ -90,15 +119,17 @@ const Drawer = React.memo(({ isOpen, onClose, children, title }: DrawerProps) =>
|
|
|
90
119
|
</svg>
|
|
91
120
|
</button>
|
|
92
121
|
</div>
|
|
93
|
-
<div className="p-4 overflow-y-auto"
|
|
122
|
+
<div className="flex-1 p-4 overflow-y-auto" style={{ minHeight: 0 }}>
|
|
123
|
+
{children}
|
|
124
|
+
</div>
|
|
94
125
|
</div>
|
|
95
126
|
</div>
|
|
96
127
|
);
|
|
97
128
|
});
|
|
98
129
|
|
|
99
130
|
const EmptyState = React.memo(() => (
|
|
100
|
-
<div className="h-full flex items-center justify-center bg-gray-100 p-4 sm:p-6">
|
|
101
|
-
<div className="text-center max-w-sm">
|
|
131
|
+
<div className="h-full flex items-center justify-center bg-gray-100 p-4 sm:p-6 overflow-hidden">
|
|
132
|
+
<div className="text-center max-w-sm mx-auto">
|
|
102
133
|
<div className="text-3xl sm:text-4xl text-gray-400 mb-4">💬</div>
|
|
103
134
|
<h3 className="text-lg sm:text-xl font-semibold text-gray-600 mb-2">Welcome to Messenger</h3>
|
|
104
135
|
<p className="text-sm sm:text-base text-gray-500 leading-relaxed">
|
|
@@ -133,8 +164,14 @@ const Inbox = (props: InboxProps) => {
|
|
|
133
164
|
mobilePreviewCTAText: false,
|
|
134
165
|
});
|
|
135
166
|
|
|
136
|
-
// Hooks
|
|
137
|
-
const
|
|
167
|
+
// Hooks - improved responsive breakpoints with better granularity
|
|
168
|
+
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
|
|
169
|
+
const isMobileView = useMediaQuery('(max-width: 640px)');
|
|
170
|
+
const isSmallTabletView = useMediaQuery('(min-width: 641px) and (max-width: 900px)');
|
|
171
|
+
const isTabletView = useMediaQuery('(min-width: 901px) and (max-width: 1024px)');
|
|
172
|
+
const isDesktopView = useMediaQuery('(min-width: 1025px)');
|
|
173
|
+
const isLargeDesktopView = useMediaQuery('(min-width: 1440px)');
|
|
174
|
+
const isSmallScreen = useMediaQuery('(max-width: 900px)');
|
|
138
175
|
const auth = useSelector(userSelector);
|
|
139
176
|
|
|
140
177
|
// Data destructuring from Apollo queries
|
|
@@ -198,6 +235,13 @@ const Inbox = (props: InboxProps) => {
|
|
|
198
235
|
return title || 'Direct Message';
|
|
199
236
|
}
|
|
200
237
|
|
|
238
|
+
if (members.length === 1 && members[0].user.id === currentUser?.id) {
|
|
239
|
+
if (members[0].user?.givenName && members[0].user?.familyName) {
|
|
240
|
+
return `${members[0].user?.givenName} ${members[0].user?.familyName}`;
|
|
241
|
+
}
|
|
242
|
+
return members[0].user?.givenName || members[0].user?.familyName || 'Direct Message';
|
|
243
|
+
}
|
|
244
|
+
|
|
201
245
|
return title || 'Channel';
|
|
202
246
|
}, [channels, pathChannelId, currentUser]);
|
|
203
247
|
|
|
@@ -268,6 +312,11 @@ const Inbox = (props: InboxProps) => {
|
|
|
268
312
|
const detailSidebarOptions = useMemo(
|
|
269
313
|
() => ({
|
|
270
314
|
isMobileView,
|
|
315
|
+
isSmallTabletView,
|
|
316
|
+
isTabletView,
|
|
317
|
+
isDesktopView,
|
|
318
|
+
isLargeDesktopView,
|
|
319
|
+
isSmallScreen,
|
|
271
320
|
setMobilePreviewCTAText: (v: string | ReactNode) =>
|
|
272
321
|
localDispatch({ payload: { mobilePreviewCTAText: v }, type: 'update' }),
|
|
273
322
|
setMobilePreviewText: (v: string | ReactNode) =>
|
|
@@ -275,17 +324,39 @@ const Inbox = (props: InboxProps) => {
|
|
|
275
324
|
setMobilePreviewVisibility: (v: boolean) =>
|
|
276
325
|
localDispatch({ payload: { mobilePreviewVisibility: v }, type: 'update' }),
|
|
277
326
|
}),
|
|
278
|
-
[isMobileView],
|
|
327
|
+
[isMobileView, isSmallTabletView, isTabletView, isDesktopView, isLargeDesktopView, isSmallScreen],
|
|
279
328
|
);
|
|
280
329
|
|
|
281
330
|
return (
|
|
282
|
-
<div
|
|
331
|
+
<div
|
|
332
|
+
className="border-t border-gray-300 flex overflow-hidden"
|
|
333
|
+
style={{
|
|
334
|
+
height: `${windowHeight}px`,
|
|
335
|
+
maxHeight: '100vh',
|
|
336
|
+
}}
|
|
337
|
+
>
|
|
283
338
|
{/* Left Sidebar - Responsive Design */}
|
|
284
339
|
<div
|
|
285
340
|
className={`
|
|
286
341
|
flex-shrink-0 bg-gray-50 border-r border-gray-300 overflow-hidden transition-all duration-300 ease-in-out
|
|
287
|
-
${isMobileView && pathChannelId ? 'hidden' : '
|
|
342
|
+
${isMobileView && pathChannelId ? 'hidden' : ''}
|
|
288
343
|
`}
|
|
344
|
+
style={{
|
|
345
|
+
width:
|
|
346
|
+
isMobileView && !pathChannelId
|
|
347
|
+
? '100%'
|
|
348
|
+
: isMobileView && pathChannelId
|
|
349
|
+
? '0px'
|
|
350
|
+
: isSmallTabletView
|
|
351
|
+
? `${Math.min(288, windowWidth * 0.35)}px` // w-72 or 35% of window
|
|
352
|
+
: isTabletView
|
|
353
|
+
? `${Math.min(320, windowWidth * 0.3)}px` // w-80 or 30% of window
|
|
354
|
+
: isLargeDesktopView
|
|
355
|
+
? `${Math.min(384, windowWidth * 0.25)}px` // w-96 or 25% of window
|
|
356
|
+
: `${Math.min(320, windowWidth * 0.28)}px`, // w-80 or 28% of window
|
|
357
|
+
height: `${windowHeight}px`,
|
|
358
|
+
maxHeight: '100vh',
|
|
359
|
+
}}
|
|
289
360
|
>
|
|
290
361
|
<LeftSidebar
|
|
291
362
|
currentUser={currentUser}
|
|
@@ -298,15 +369,23 @@ const Inbox = (props: InboxProps) => {
|
|
|
298
369
|
getChannelsRefetch={getChannelsRefetch}
|
|
299
370
|
role={channelRole}
|
|
300
371
|
messagesQuery={data?.[1]}
|
|
372
|
+
windowHeight={windowHeight}
|
|
373
|
+
windowWidth={windowWidth}
|
|
301
374
|
/>
|
|
302
375
|
</div>
|
|
303
376
|
|
|
304
377
|
{/* Main Content Area - Responsive */}
|
|
305
378
|
<div
|
|
306
379
|
className={`
|
|
307
|
-
flex-1 min-w-0 overflow-hidden transition-all duration-300 ease-in-out
|
|
308
|
-
${isMobileView && !pathChannelId ? 'hidden' : '
|
|
380
|
+
flex-1 min-w-0 flex flex-col overflow-hidden transition-all duration-300 ease-in-out
|
|
381
|
+
${isMobileView && !pathChannelId ? 'hidden' : 'flex'}
|
|
309
382
|
`}
|
|
383
|
+
style={{
|
|
384
|
+
minWidth: isSmallScreen ? '300px' : isDesktopView ? '500px' : '400px',
|
|
385
|
+
width: 'auto',
|
|
386
|
+
height: `${windowHeight}px`,
|
|
387
|
+
maxHeight: '100vh',
|
|
388
|
+
}}
|
|
310
389
|
>
|
|
311
390
|
{pathChannelId ? (
|
|
312
391
|
<ContentComponent
|
|
@@ -315,6 +394,13 @@ const Inbox = (props: InboxProps) => {
|
|
|
315
394
|
channelRole={channelRole}
|
|
316
395
|
pathPrefix={props.pathPrefix}
|
|
317
396
|
isMobileView={isMobileView}
|
|
397
|
+
isSmallTabletView={isSmallTabletView}
|
|
398
|
+
isTabletView={isTabletView}
|
|
399
|
+
isDesktopView={isDesktopView}
|
|
400
|
+
isLargeDesktopView={isLargeDesktopView}
|
|
401
|
+
isSmallScreen={isSmallScreen}
|
|
402
|
+
windowWidth={windowWidth}
|
|
403
|
+
windowHeight={windowHeight}
|
|
318
404
|
mobilePreviewState={mobilePreviewState}
|
|
319
405
|
detailSidebarOptions={detailSidebarOptions}
|
|
320
406
|
isBottomDrawerOpen={isBottomDrawerOpen}
|
|
@@ -328,8 +414,17 @@ const Inbox = (props: InboxProps) => {
|
|
|
328
414
|
</div>
|
|
329
415
|
|
|
330
416
|
{/* Right Sidebar - Desktop Only */}
|
|
331
|
-
{pathChannelId && data?.[1] &&
|
|
332
|
-
// <div
|
|
417
|
+
{pathChannelId && data?.[1] && isDesktopView && (
|
|
418
|
+
// <div
|
|
419
|
+
// className="border-l border-gray-200 bg-white flex-shrink-0 overflow-hidden"
|
|
420
|
+
// style={{
|
|
421
|
+
// width: isLargeDesktopView
|
|
422
|
+
// ? `${Math.min(384, windowWidth * 0.25)}px` // w-96 or 25% of window
|
|
423
|
+
// : `${Math.min(320, windowWidth * 0.22)}px`, // w-80 or 22% of window
|
|
424
|
+
// height: `${windowHeight}px`,
|
|
425
|
+
// maxHeight: '100vh'
|
|
426
|
+
// }}
|
|
427
|
+
// >
|
|
333
428
|
<RightSidebarWrapper
|
|
334
429
|
MessagesLoaderQuery={data?.[1]}
|
|
335
430
|
selectedPost={null}
|
|
@@ -348,6 +443,13 @@ const ContentComponent = React.memo((props: any) => {
|
|
|
348
443
|
pathPrefix,
|
|
349
444
|
postId,
|
|
350
445
|
isMobileView,
|
|
446
|
+
isSmallTabletView,
|
|
447
|
+
isTabletView,
|
|
448
|
+
isDesktopView,
|
|
449
|
+
isLargeDesktopView,
|
|
450
|
+
isSmallScreen,
|
|
451
|
+
windowWidth,
|
|
452
|
+
windowHeight,
|
|
351
453
|
mobilePreviewState,
|
|
352
454
|
detailSidebarOptions,
|
|
353
455
|
isBottomDrawerOpen,
|
|
@@ -371,18 +473,22 @@ const ContentComponent = React.memo((props: any) => {
|
|
|
371
473
|
}, [channelData]);
|
|
372
474
|
|
|
373
475
|
return (
|
|
374
|
-
<div className="flex
|
|
476
|
+
<div className="flex overflow-hidden" style={{ height: `${windowHeight}px`, maxHeight: '100vh' }}>
|
|
375
477
|
{/* Main Chat Content */}
|
|
376
|
-
<div className="flex-1 flex flex-col">
|
|
478
|
+
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
|
377
479
|
{/* Channel Header */}
|
|
378
480
|
{channelId && (
|
|
379
|
-
<div
|
|
481
|
+
<div
|
|
482
|
+
className={`border-b border-gray-200 bg-white flex-shrink-0 z-10 ${
|
|
483
|
+
isSmallScreen ? 'px-3 py-3' : 'px-4 sm:px-6 py-4'
|
|
484
|
+
}`}
|
|
485
|
+
>
|
|
380
486
|
<div className="flex items-center justify-between">
|
|
381
|
-
<div className="flex items-center space-x-
|
|
382
|
-
{/* Mobile Back Button */}
|
|
383
|
-
{isMobileView && (
|
|
487
|
+
<div className="flex items-center space-x-2 min-w-0 flex-1">
|
|
488
|
+
{/* Mobile/Small Screen Back Button */}
|
|
489
|
+
{(isMobileView || isSmallTabletView) && (
|
|
384
490
|
<button
|
|
385
|
-
className="p-2 hover:bg-gray-100 rounded-full transition-colors
|
|
491
|
+
className="p-2 hover:bg-gray-100 rounded-full transition-colors flex-shrink-0"
|
|
386
492
|
onClick={() => window.history.back()}
|
|
387
493
|
aria-label="Go back"
|
|
388
494
|
>
|
|
@@ -401,11 +507,17 @@ const ContentComponent = React.memo((props: any) => {
|
|
|
401
507
|
</svg>
|
|
402
508
|
</button>
|
|
403
509
|
)}
|
|
404
|
-
<h2
|
|
510
|
+
<h2
|
|
511
|
+
className={`font-semibold text-gray-800 truncate ${
|
|
512
|
+
isSmallScreen ? 'text-base' : 'text-lg'
|
|
513
|
+
}`}
|
|
514
|
+
>
|
|
515
|
+
{channelName}
|
|
516
|
+
</h2>
|
|
405
517
|
</div>
|
|
406
|
-
{isMobileView && mobilePreviewState?.mobilePreviewVisibility && (
|
|
518
|
+
{(isMobileView || isSmallTabletView) && mobilePreviewState?.mobilePreviewVisibility && (
|
|
407
519
|
<button
|
|
408
|
-
className="text-sm px-3 py-1 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors"
|
|
520
|
+
className="text-sm px-3 py-1 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors flex-shrink-0"
|
|
409
521
|
onClick={() => setBottomDrawer(true)}
|
|
410
522
|
>
|
|
411
523
|
{mobilePreviewState?.mobilePreviewCTAText}
|
|
@@ -416,13 +528,13 @@ const ContentComponent = React.memo((props: any) => {
|
|
|
416
528
|
)}
|
|
417
529
|
|
|
418
530
|
{/* Mobile Preview */}
|
|
419
|
-
{isMobileView && channelId && mobilePreviewState?.mobilePreviewVisibility && (
|
|
420
|
-
<div className=
|
|
531
|
+
{(isMobileView || isSmallTabletView) && channelId && mobilePreviewState?.mobilePreviewVisibility && (
|
|
532
|
+
<div className={`mt-4 ${isSmallScreen ? 'mx-3' : 'mx-4'}`}>
|
|
421
533
|
<div className="mb-2">
|
|
422
|
-
<div className="w-full flex justify-between mb-[5px]">
|
|
423
|
-
<span>{mobilePreviewState?.mobilePreviewText}</span>
|
|
534
|
+
<div className="w-full flex justify-between items-center gap-2 mb-[5px]">
|
|
535
|
+
<span className="truncate flex-1 text-sm">{mobilePreviewState?.mobilePreviewText}</span>
|
|
424
536
|
<button
|
|
425
|
-
className="text-
|
|
537
|
+
className="text-sm px-3 py-2 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors flex-shrink-0"
|
|
426
538
|
onClick={() => setBottomDrawer(true)}
|
|
427
539
|
>
|
|
428
540
|
{mobilePreviewState?.mobilePreviewCTAText}
|
|
@@ -434,45 +546,51 @@ const ContentComponent = React.memo((props: any) => {
|
|
|
434
546
|
)}
|
|
435
547
|
|
|
436
548
|
{/* Content based on postId */}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
postId
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
549
|
+
<div className="flex-1 flex flex-col min-h-0 overflow-hidden">
|
|
550
|
+
{channelId && (
|
|
551
|
+
<>
|
|
552
|
+
{postId ? (
|
|
553
|
+
postId === '1' ? (
|
|
554
|
+
<ThreadsInbox
|
|
555
|
+
channelId={channelId}
|
|
556
|
+
role={channelRole}
|
|
557
|
+
pathPrefix={pathPrefix}
|
|
558
|
+
setChannelId={() => {}}
|
|
559
|
+
setPostId={() => {}}
|
|
560
|
+
setGoBack={() => {}}
|
|
561
|
+
/>
|
|
562
|
+
) : (
|
|
563
|
+
<ThreadMessagesInbox
|
|
564
|
+
channelId={channelId}
|
|
565
|
+
postId={postId}
|
|
566
|
+
role={channelRole}
|
|
567
|
+
goBack={false}
|
|
568
|
+
pathPrefix={pathPrefix}
|
|
569
|
+
setPostId={() => {}}
|
|
570
|
+
setChannelId={() => {}}
|
|
571
|
+
onMessageClick={onMessageClick}
|
|
572
|
+
/>
|
|
573
|
+
)
|
|
449
574
|
) : (
|
|
450
|
-
<
|
|
575
|
+
<MessagesComponent
|
|
451
576
|
channelId={channelId}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
pathPrefix={pathPrefix}
|
|
456
|
-
setPostId={() => {}}
|
|
457
|
-
setChannelId={() => {}}
|
|
577
|
+
MessagesLoaderQuery={MessagesLoaderQuery}
|
|
578
|
+
channelsDetail={channelsDetail}
|
|
579
|
+
channelLoading={channelLoading}
|
|
458
580
|
onMessageClick={onMessageClick}
|
|
581
|
+
isSmallScreen={isSmallScreen}
|
|
582
|
+
isDesktopView={isDesktopView}
|
|
583
|
+
windowHeight={windowHeight}
|
|
584
|
+
windowWidth={windowWidth}
|
|
459
585
|
/>
|
|
460
|
-
)
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
MessagesLoaderQuery={MessagesLoaderQuery}
|
|
465
|
-
channelsDetail={channelsDetail}
|
|
466
|
-
channelLoading={channelLoading}
|
|
467
|
-
onMessageClick={onMessageClick}
|
|
468
|
-
/>
|
|
469
|
-
)}
|
|
470
|
-
</>
|
|
471
|
-
)}
|
|
586
|
+
)}
|
|
587
|
+
</>
|
|
588
|
+
)}
|
|
589
|
+
</div>
|
|
472
590
|
</div>
|
|
473
591
|
|
|
474
|
-
{/* Mobile Drawer */}
|
|
475
|
-
{isMobileView && (
|
|
592
|
+
{/* Mobile/Small Screen Drawer */}
|
|
593
|
+
{(isMobileView || isSmallTabletView) && (
|
|
476
594
|
<Drawer
|
|
477
595
|
isOpen={isBottomDrawerOpen}
|
|
478
596
|
onClose={() => setBottomDrawer(false)}
|
|
@@ -500,19 +618,29 @@ const RightSidebarWrapper = React.memo(({ MessagesLoaderQuery, selectedPost, det
|
|
|
500
618
|
if (!sortedMessages.length) return null;
|
|
501
619
|
|
|
502
620
|
return (
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
621
|
+
<div className="h-full flex flex-col overflow-hidden">
|
|
622
|
+
<RightSidebar
|
|
623
|
+
channelMessages={sortedMessages}
|
|
624
|
+
visibility="visible"
|
|
625
|
+
selectedPost={selectedPost}
|
|
626
|
+
{...detailSidebarOptions}
|
|
627
|
+
/>
|
|
628
|
+
</div>
|
|
511
629
|
);
|
|
512
630
|
});
|
|
513
631
|
|
|
514
632
|
const MessagesComponent = React.memo((props: any) => {
|
|
515
|
-
const {
|
|
633
|
+
const {
|
|
634
|
+
channelId,
|
|
635
|
+
MessagesLoaderQuery,
|
|
636
|
+
channelsDetail,
|
|
637
|
+
channelLoading,
|
|
638
|
+
onMessageClick,
|
|
639
|
+
isSmallScreen,
|
|
640
|
+
isDesktopView,
|
|
641
|
+
windowHeight = 768,
|
|
642
|
+
windowWidth = 1024,
|
|
643
|
+
} = props;
|
|
516
644
|
|
|
517
645
|
const messageRootListRef = useRef(null);
|
|
518
646
|
const messageListRef = useRef(null);
|
|
@@ -869,66 +997,85 @@ const MessagesComponent = React.memo((props: any) => {
|
|
|
869
997
|
<>
|
|
870
998
|
<div
|
|
871
999
|
ref={messageRootListRef}
|
|
872
|
-
className=
|
|
1000
|
+
className={`overflow-y-scroll bg-gray-50 ${
|
|
1001
|
+
isSmallScreen ? 'p-2 px-3' : isDesktopView ? 'p-6 px-8' : 'p-4 px-6'
|
|
1002
|
+
}`}
|
|
873
1003
|
onScroll={onMessagesScroll}
|
|
1004
|
+
style={{
|
|
1005
|
+
height: `${windowHeight - 140}px`, // Subtract header + input height
|
|
1006
|
+
maxHeight: '100vh',
|
|
1007
|
+
scrollbarWidth: 'thin',
|
|
1008
|
+
scrollbarColor: '#cbd5e0 #f7fafc',
|
|
1009
|
+
overflowY: 'scroll',
|
|
1010
|
+
WebkitOverflowScrolling: 'touch',
|
|
1011
|
+
}}
|
|
874
1012
|
>
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
<div className="flex
|
|
881
|
-
<
|
|
882
|
-
|
|
1013
|
+
<div className="min-h-full">
|
|
1014
|
+
{messages.length > 0 ? (
|
|
1015
|
+
<>
|
|
1016
|
+
{/* Loading indicator for older messages at the top */}
|
|
1017
|
+
{isLoadingOlder && (
|
|
1018
|
+
<div className="flex justify-center py-4">
|
|
1019
|
+
<div className="flex items-center space-x-2 text-gray-500">
|
|
1020
|
+
<Spinner className="w-4 h-4" />
|
|
1021
|
+
<span className="text-sm">Loading older messages...</span>
|
|
1022
|
+
</div>
|
|
883
1023
|
</div>
|
|
1024
|
+
)}
|
|
1025
|
+
<Messages
|
|
1026
|
+
innerRef={messageListRef}
|
|
1027
|
+
channelId={channelId}
|
|
1028
|
+
currentUser={auth}
|
|
1029
|
+
channelMessages={messages}
|
|
1030
|
+
totalCount={totalCount}
|
|
1031
|
+
onMessageClick={onMessageClick}
|
|
1032
|
+
isDesktopView={isDesktopView || false}
|
|
1033
|
+
isSmallScreen={isSmallScreen || false}
|
|
1034
|
+
/>
|
|
1035
|
+
<SubscriptionHandler
|
|
1036
|
+
subscribeToMore={subscribeToMore}
|
|
1037
|
+
document={CHAT_MESSAGE_ADDED}
|
|
1038
|
+
variables={{ channelId: channelId.toString() }}
|
|
1039
|
+
enabled={!!channelId && !!subscribeToMore}
|
|
1040
|
+
updateQuery={(prev: any, { subscriptionData }: any) => {
|
|
1041
|
+
console.log('Subscription updateQuery called:', { prev, subscriptionData });
|
|
1042
|
+
if (!subscriptionData.data) {
|
|
1043
|
+
console.log('No subscription data, returning prev');
|
|
1044
|
+
return prev;
|
|
1045
|
+
}
|
|
1046
|
+
const newMessage = subscriptionData.data.chatMessageAdded;
|
|
1047
|
+
console.log('New message received via subscription:', newMessage);
|
|
1048
|
+
|
|
1049
|
+
return {
|
|
1050
|
+
...prev,
|
|
1051
|
+
messages: {
|
|
1052
|
+
...prev?.messages,
|
|
1053
|
+
data: uniqBy([...(prev?.messages?.data || []), newMessage], 'id'),
|
|
1054
|
+
totalCount: (prev?.messages?.totalCount || 0) + 1,
|
|
1055
|
+
},
|
|
1056
|
+
};
|
|
1057
|
+
}}
|
|
1058
|
+
onError={(error) => {
|
|
1059
|
+
console.error('Subscription error:', error);
|
|
1060
|
+
}}
|
|
1061
|
+
/>
|
|
1062
|
+
</>
|
|
1063
|
+
) : (
|
|
1064
|
+
<div className="flex items-center justify-center text-gray-500 min-h-96">
|
|
1065
|
+
<div className="text-center max-w-sm mx-auto px-4">
|
|
1066
|
+
<div className="text-6xl mb-4 opacity-50">💬</div>
|
|
1067
|
+
<h3 className="text-lg font-semibold text-gray-600 mb-2">No messages yet</h3>
|
|
1068
|
+
<p className="text-sm text-gray-500">
|
|
1069
|
+
Start the conversation by sending a message below!
|
|
1070
|
+
</p>
|
|
884
1071
|
</div>
|
|
885
|
-
)}
|
|
886
|
-
<Messages
|
|
887
|
-
innerRef={messageListRef}
|
|
888
|
-
channelId={channelId}
|
|
889
|
-
currentUser={auth}
|
|
890
|
-
channelMessages={messages}
|
|
891
|
-
totalCount={totalCount}
|
|
892
|
-
onMessageClick={onMessageClick}
|
|
893
|
-
/>
|
|
894
|
-
<SubscriptionHandler
|
|
895
|
-
subscribeToMore={subscribeToMore}
|
|
896
|
-
document={CHAT_MESSAGE_ADDED}
|
|
897
|
-
variables={{ channelId: channelId.toString() }}
|
|
898
|
-
enabled={!!channelId && !!subscribeToMore}
|
|
899
|
-
updateQuery={(prev: any, { subscriptionData }: any) => {
|
|
900
|
-
console.log('Subscription updateQuery called:', { prev, subscriptionData });
|
|
901
|
-
if (!subscriptionData.data) {
|
|
902
|
-
console.log('No subscription data, returning prev');
|
|
903
|
-
return prev;
|
|
904
|
-
}
|
|
905
|
-
const newMessage = subscriptionData.data.chatMessageAdded;
|
|
906
|
-
console.log('New message received via subscription:', newMessage);
|
|
907
|
-
|
|
908
|
-
return {
|
|
909
|
-
...prev,
|
|
910
|
-
messages: {
|
|
911
|
-
...prev?.messages,
|
|
912
|
-
data: uniqBy([...(prev?.messages?.data || []), newMessage], 'id'),
|
|
913
|
-
totalCount: (prev?.messages?.totalCount || 0) + 1,
|
|
914
|
-
},
|
|
915
|
-
};
|
|
916
|
-
}}
|
|
917
|
-
onError={(error) => {
|
|
918
|
-
console.error('Subscription error:', error);
|
|
919
|
-
}}
|
|
920
|
-
/>
|
|
921
|
-
</>
|
|
922
|
-
) : (
|
|
923
|
-
<div className="flex-1 flex items-center justify-center text-gray-500">
|
|
924
|
-
<div className="text-center">
|
|
925
|
-
<div className="text-4xl mb-4">💬</div>
|
|
926
|
-
<p>No messages yet. Start the conversation!</p>
|
|
927
1072
|
</div>
|
|
928
|
-
|
|
929
|
-
|
|
1073
|
+
)}
|
|
1074
|
+
</div>
|
|
1075
|
+
</div>
|
|
1076
|
+
<div className="flex-shrink-0 border-t border-gray-200 bg-white">
|
|
1077
|
+
<MessageInput channelId={channelId} handleSend={handleSend} placeholder="Message" />
|
|
930
1078
|
</div>
|
|
931
|
-
<MessageInput channelId={channelId} handleSend={handleSend} placeholder="Message" />
|
|
932
1079
|
</>
|
|
933
1080
|
);
|
|
934
1081
|
});
|