@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.
@@ -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 onClick={onClose} className="p-1 hover:bg-gray-100 rounded-full transition-colors">
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">{children}</div>
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 isMobileView = useMediaQuery('(max-width: 767px)');
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 className="h-[100vh] border-t border-gray-300 flex overflow-hidden" style={{ height: '100vh ' }}>
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' : 'w-80 lg:w-96 xl:w-[420px]'}
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' : 'block'}
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] && !isMobileView && (
332
- // <div className="w-80 xl:w-96 border-l border-gray-200 bg-white flex-shrink-0">
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 h-full">
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 className="px-4 sm:px-6 py-4 border-b border-gray-200 bg-white flex-shrink-0">
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-3">
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 lg:hidden"
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 className="text-lg font-semibold text-gray-800 truncate">{channelName}</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="mx-4 mt-4">
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-base px-4 py-2 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors"
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
- {channelId && (
438
- <>
439
- {postId ? (
440
- postId === '1' ? (
441
- <ThreadsInbox
442
- channelId={channelId}
443
- role={channelRole}
444
- pathPrefix={pathPrefix}
445
- setChannelId={() => {}}
446
- setPostId={() => {}}
447
- setGoBack={() => {}}
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
- <ThreadMessagesInbox
575
+ <MessagesComponent
451
576
  channelId={channelId}
452
- postId={postId}
453
- role={channelRole}
454
- goBack={false}
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
- <MessagesComponent
463
- channelId={channelId}
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
- // <div className="w-80 xl:w-96 border-l border-gray-200 bg-white flex-shrink-0">
504
- <RightSidebar
505
- channelMessages={sortedMessages}
506
- visibility="visible"
507
- selectedPost={selectedPost}
508
- {...detailSidebarOptions}
509
- />
510
- // </div>
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 { channelId, MessagesLoaderQuery, channelsDetail, channelLoading, onMessageClick } = props;
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="flex flex-col flex-grow flex-shrink overflow-y-auto p-4 px-4 md:px-8 lg:px-12 bg-gray-50"
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
- {messages.length > 0 ? (
876
- <>
877
- {/* Loading indicator for older messages at the top */}
878
- {isLoadingOlder && (
879
- <div className="flex justify-center py-4">
880
- <div className="flex items-center space-x-2 text-gray-500">
881
- <Spinner className="w-4 h-4" />
882
- <span className="text-sm">Loading older messages...</span>
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
- </div>
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
  });