@messenger-box/tailwind-ui-inbox 10.0.3-alpha.71 → 10.0.3-alpha.72

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.
Files changed (148) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/lib/components/AIAgent/AIAgent.d.ts +14 -0
  3. package/lib/components/AIAgent/AIAgent.d.ts.map +1 -0
  4. package/lib/components/AIAgent/AIAgent.js +1148 -0
  5. package/lib/components/AIAgent/AIAgent.js.map +1 -0
  6. package/lib/components/AIAgent/index.d.ts +2 -0
  7. package/lib/components/AIAgent/index.d.ts.map +1 -0
  8. package/lib/components/InboxMessage/InputComponent.d.ts +9 -0
  9. package/lib/components/InboxMessage/InputComponent.d.ts.map +1 -0
  10. package/lib/components/InboxMessage/InputComponent.js +210 -0
  11. package/lib/components/InboxMessage/InputComponent.js.map +1 -0
  12. package/lib/components/InboxMessage/MessageInput.d.ts.map +1 -1
  13. package/lib/components/InboxMessage/MessageInput.js +14 -10
  14. package/lib/components/InboxMessage/MessageInput.js.map +1 -1
  15. package/lib/components/InboxMessage/MessageInputComponent.d.ts +9 -0
  16. package/lib/components/InboxMessage/MessageInputComponent.d.ts.map +1 -0
  17. package/lib/components/InboxMessage/MessageInputComponent.js +173 -0
  18. package/lib/components/InboxMessage/MessageInputComponent.js.map +1 -0
  19. package/lib/components/InboxMessage/Messages.d.ts.map +1 -1
  20. package/lib/components/InboxMessage/Messages.js +4 -54
  21. package/lib/components/InboxMessage/Messages.js.map +1 -1
  22. package/lib/components/InboxMessage/MessagesBuilderUi.d.ts +17 -0
  23. package/lib/components/InboxMessage/MessagesBuilderUi.d.ts.map +1 -0
  24. package/lib/components/InboxMessage/MessagesBuilderUi.js +162 -0
  25. package/lib/components/InboxMessage/MessagesBuilderUi.js.map +1 -0
  26. package/lib/components/InboxMessage/UploadImageButton.d.ts +1 -0
  27. package/lib/components/InboxMessage/UploadImageButton.d.ts.map +1 -1
  28. package/lib/components/InboxMessage/UploadImageButton.js +3 -3
  29. package/lib/components/InboxMessage/UploadImageButton.js.map +1 -1
  30. package/lib/components/InboxMessage/index.d.ts +3 -0
  31. package/lib/components/InboxMessage/index.d.ts.map +1 -1
  32. package/lib/components/InboxMessage/message-widgets/CommonMessage.d.ts.map +1 -1
  33. package/lib/components/InboxMessage/message-widgets/CommonMessage.js +11 -6
  34. package/lib/components/InboxMessage/message-widgets/CommonMessage.js.map +1 -1
  35. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts +14 -0
  36. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts.map +1 -0
  37. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js +1525 -0
  38. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js.map +1 -0
  39. package/lib/components/InboxMessage/message-widgets/PlainMessage.d.ts.map +1 -1
  40. package/lib/components/InboxMessage/message-widgets/PlainMessage.js +6 -3
  41. package/lib/components/InboxMessage/message-widgets/PlainMessage.js.map +1 -1
  42. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts.map +1 -1
  43. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js +207 -12
  44. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js.map +1 -1
  45. package/lib/components/InboxMessage/message-widgets/index.d.ts +1 -0
  46. package/lib/components/InboxMessage/message-widgets/index.d.ts.map +1 -1
  47. package/lib/components/index.d.ts +2 -1
  48. package/lib/components/index.d.ts.map +1 -1
  49. package/lib/compute.d.ts.map +1 -1
  50. package/lib/compute.js +79 -3
  51. package/lib/compute.js.map +1 -1
  52. package/lib/config/env-config.d.ts +6 -0
  53. package/lib/config/env-config.d.ts.map +1 -1
  54. package/lib/config/env-config.js +19 -1
  55. package/lib/config/env-config.js.map +1 -1
  56. package/lib/container/AiInbox.d.ts +15 -0
  57. package/lib/container/AiInbox.d.ts.map +1 -0
  58. package/lib/container/AiInbox.js +1520 -0
  59. package/lib/container/AiInbox.js.map +1 -0
  60. package/lib/container/AiInboxWithLoader.d.ts +36 -0
  61. package/lib/container/AiInboxWithLoader.d.ts.map +1 -0
  62. package/lib/container/AiInboxWithLoader.js +300 -0
  63. package/lib/container/AiInboxWithLoader.js.map +1 -0
  64. package/lib/container/AiLandingInput.d.ts +4 -0
  65. package/lib/container/AiLandingInput.d.ts.map +1 -0
  66. package/lib/container/AiLandingInput.js +164 -0
  67. package/lib/container/AiLandingInput.js.map +1 -0
  68. package/lib/container/Inbox.d.ts.map +1 -1
  69. package/lib/container/Inbox.js +6 -4
  70. package/lib/container/Inbox.js.map +1 -1
  71. package/lib/container/InboxAiMessagesLoader.d.ts +36 -0
  72. package/lib/container/InboxAiMessagesLoader.d.ts.map +1 -0
  73. package/lib/container/InboxAiMessagesLoader.js +47 -0
  74. package/lib/container/InboxAiMessagesLoader.js.map +1 -0
  75. package/lib/container/InboxContainer.d.ts +12 -0
  76. package/lib/container/InboxContainer.d.ts.map +1 -0
  77. package/lib/container/InboxContainer.js +31 -0
  78. package/lib/container/InboxContainer.js.map +1 -0
  79. package/lib/container/InboxTemplate1.d.ts +15 -0
  80. package/lib/container/InboxTemplate1.d.ts.map +1 -0
  81. package/lib/container/InboxTemplate1.js +1375 -0
  82. package/lib/container/InboxTemplate1.js.map +1 -0
  83. package/lib/container/InboxTemplate1WithLoader.d.ts +36 -0
  84. package/lib/container/InboxTemplate1WithLoader.d.ts.map +1 -0
  85. package/lib/container/InboxTemplate2.d.ts +15 -0
  86. package/lib/container/InboxTemplate2.d.ts.map +1 -0
  87. package/lib/container/InboxTemplate2.js +1426 -0
  88. package/lib/container/InboxTemplate2.js.map +1 -0
  89. package/lib/container/InboxWithAiLoader.d.ts +15 -0
  90. package/lib/container/InboxWithAiLoader.d.ts.map +1 -0
  91. package/lib/container/InboxWithAiLoader.js +56 -0
  92. package/lib/container/InboxWithAiLoader.js.map +1 -0
  93. package/lib/container/ServiceInbox.js +1 -1
  94. package/lib/container/ServiceInbox.js.map +1 -1
  95. package/lib/container/ThreadMessages.js +1 -1
  96. package/lib/container/ThreadMessages.js.map +1 -1
  97. package/lib/container/ThreadMessagesInbox.js +1 -1
  98. package/lib/container/ThreadMessagesInbox.js.map +1 -1
  99. package/lib/container/Threads.js +1 -1
  100. package/lib/container/Threads.js.map +1 -1
  101. package/lib/container/index.d.ts +4 -1
  102. package/lib/container/index.d.ts.map +1 -1
  103. package/lib/index.js +1 -1
  104. package/lib/machines/aiAgentMachine.d.ts +3 -0
  105. package/lib/machines/aiAgentMachine.d.ts.map +1 -0
  106. package/lib/machines/aiAgentMachine.js +1040 -0
  107. package/lib/machines/aiAgentMachine.js.map +1 -0
  108. package/lib/machines/types.d.ts +77 -0
  109. package/lib/machines/types.d.ts.map +1 -0
  110. package/lib/routes.json +40 -0
  111. package/lib/templates/InboxWithAi.d.ts +15 -0
  112. package/lib/templates/InboxWithAi.d.ts.map +1 -0
  113. package/lib/templates/InboxWithAi.js +405 -0
  114. package/lib/templates/InboxWithAi.js.map +1 -0
  115. package/lib/templates/InboxWithAi.tsx +502 -0
  116. package/package.json +7 -5
  117. package/src/components/AIAgent/AIAgent.tsx +1351 -0
  118. package/src/components/AIAgent/README.md +82 -0
  119. package/src/components/AIAgent/index.ts +1 -0
  120. package/src/components/InboxMessage/InputComponent.tsx +263 -0
  121. package/src/components/InboxMessage/MessageInput.tsx +73 -66
  122. package/src/components/InboxMessage/MessageInputComponent.tsx +245 -0
  123. package/src/components/InboxMessage/Messages.tsx +2 -56
  124. package/src/components/InboxMessage/MessagesBuilderUi.tsx +205 -0
  125. package/src/components/InboxMessage/UploadImageButton.tsx +3 -2
  126. package/src/components/InboxMessage/index.ts +3 -0
  127. package/src/components/InboxMessage/message-widgets/CommonMessage.tsx +39 -21
  128. package/src/components/InboxMessage/message-widgets/ModernMessageGroup.tsx +1968 -0
  129. package/src/components/InboxMessage/message-widgets/PlainMessage.tsx +6 -2
  130. package/src/components/InboxMessage/message-widgets/SlackLikeMessageGroup.tsx +306 -54
  131. package/src/components/InboxMessage/message-widgets/index.ts +1 -0
  132. package/src/components/index.ts +4 -0
  133. package/src/compute.ts +83 -2
  134. package/src/config/env-config.ts +6 -0
  135. package/src/container/AiInbox.tsx +1796 -0
  136. package/src/container/AiInboxWithLoader.tsx +356 -0
  137. package/src/container/AiLandingInput.tsx +168 -0
  138. package/src/container/Inbox.tsx +8 -5
  139. package/src/container/InboxAiMessagesLoader.tsx +68 -0
  140. package/src/container/InboxContainer.tsx +35 -0
  141. package/src/container/InboxTemplate1.tsx +1542 -0
  142. package/src/container/InboxTemplate1WithLoader.tsx +338 -0
  143. package/src/container/InboxTemplate2.tsx +1606 -0
  144. package/src/container/InboxWithAiLoader.tsx +76 -0
  145. package/src/container/index.ts +15 -1
  146. package/src/machines/aiAgentMachine.ts +1248 -0
  147. package/src/machines/types.ts +59 -0
  148. package/src/templates/InboxWithAi.tsx +502 -0
@@ -0,0 +1,1426 @@
1
+ import React__default,{createContext,useState,useCallback,useMemo,useContext,useRef,useEffect,useReducer}from'react';import {orderBy,uniqBy}from'lodash-es';import {useSendMessagesMutation,MessagesDocument,OnChatMessageAddedDocument}from'common/graphql';import {useUploadFiles}from'@messenger-box/platform-client';import {RoomType}from'common';import {useSelector,shallowEqual}from'react-redux';import {useParams,useNavigate}from'@remix-run/react';import'../components/inbox/FilesList.js';import'../components/inbox/MessageItem.js';import'../components/inbox/ThreadItem.js';import'date-fns';import'@react-icons/all-files/bs/BsFlag.js';import'../components/InboxMessage/ConversationItem.js';import'../components/InboxMessage/ServiceConversationItem.js';import {LeftSidebar}from'../components/InboxMessage/LeftSidebar.js';import'react-i18next';import {config}from'../config/env-config.js';import'@react-icons/all-files/bi/BiImage.js';import'@react-icons/all-files/ai/AiOutlineSecurityScan.js';import'@react-icons/all-files/fi/FiCheck.js';import'@react-icons/all-files/bs/BsFillStarFill.js';import'@common-stack/components-pro';import'../enums/messenger-slot-fill-name-enum.js';import'../components/InboxMessage/ServiceInboxItem.js';import {InputComponent}from'../components/InboxMessage/InputComponent.js';import {MessagesBuilderUi}from'../components/InboxMessage/MessagesBuilderUi.js';import {objectId}from'@messenger-box/core';import {AIAgent}from'../components/AIAgent/AIAgent.js';import {userSelector}from'@adminide-stack/user-auth0-client';import {applyFooterStyles}from'./apply-footer-styles.js';import {ThreadsInbox}from'./ThreadsInbox.js';import {ThreadMessagesInbox}from'./ThreadMessagesInbox.js';import {useApolloClient}from'@apollo/client/index.js';import {SubscriptionHandler}from'../components/InboxMessage/SubscriptionHandler.js';const {
2
+ MESSAGES_PER_PAGE
3
+ } = config;
4
+ // Context for sharing tab state between header and sidebar
5
+ const TabContext = createContext({
6
+ activeTab: 'design',
7
+ setActiveTab: () => {}
8
+ });
9
+ // Static utility hooks and components
10
+ const useMediaQuery = query => {
11
+ const [matches, setMatches] = React__default.useState(false);
12
+ useEffect(() => {
13
+ if (typeof window === 'undefined') return;
14
+ const mediaQuery = window.matchMedia(query);
15
+ const updateMatches = () => setMatches(mediaQuery.matches);
16
+ updateMatches();
17
+ mediaQuery.addEventListener('change', updateMatches);
18
+ return () => mediaQuery.removeEventListener('change', updateMatches);
19
+ }, [query]);
20
+ return matches;
21
+ };
22
+ // Hook to get window dimensions
23
+ const useWindowDimensions = () => {
24
+ const [windowDimensions, setWindowDimensions] = React__default.useState({
25
+ width: typeof window !== 'undefined' ? window.innerWidth : 1024,
26
+ height: typeof window !== 'undefined' ? window.innerHeight : 768
27
+ });
28
+ useEffect(() => {
29
+ if (typeof window === 'undefined') return;
30
+ const handleResize = () => {
31
+ setWindowDimensions({
32
+ width: window.innerWidth,
33
+ height: window.innerHeight
34
+ });
35
+ };
36
+ window.addEventListener('resize', handleResize);
37
+ handleResize(); // Set initial dimensions
38
+ return () => window.removeEventListener('resize', handleResize);
39
+ }, []);
40
+ return windowDimensions;
41
+ };
42
+ // Static components
43
+ const Spinner = React__default.memo(({
44
+ className = ''
45
+ }) => React__default.createElement("div", {
46
+ className: `animate-spin rounded-full border-4 border-gray-200 border-t-blue-500 ${className}`
47
+ }, React__default.createElement("span", {
48
+ className: "sr-only"
49
+ }, "Loading...")));
50
+ const Drawer = React__default.memo(({
51
+ isOpen,
52
+ onClose,
53
+ children,
54
+ title
55
+ }) => {
56
+ if (!isOpen) return null;
57
+ return React__default.createElement("div", {
58
+ className: "fixed inset-0 z-50 overflow-hidden"
59
+ }, React__default.createElement("div", {
60
+ className: "absolute inset-0 bg-black bg-opacity-50",
61
+ onClick: onClose
62
+ }), React__default.createElement("div", {
63
+ className: "absolute bottom-0 left-0 right-0 bg-white rounded-t-lg shadow-lg max-h-[80vh] flex flex-col overflow-hidden"
64
+ }, React__default.createElement("div", {
65
+ className: "flex items-center justify-between p-4 border-b border-gray-200 flex-shrink-0"
66
+ }, React__default.createElement("h2", {
67
+ className: "text-lg font-semibold truncate"
68
+ }, title), React__default.createElement("button", {
69
+ onClick: onClose,
70
+ className: "p-1 hover:bg-gray-100 rounded-full transition-colors flex-shrink-0 ml-2"
71
+ }, React__default.createElement("svg", {
72
+ className: "w-6 h-6",
73
+ fill: "none",
74
+ stroke: "currentColor",
75
+ viewBox: "0 0 24 24"
76
+ }, React__default.createElement("path", {
77
+ strokeLinecap: "round",
78
+ strokeLinejoin: "round",
79
+ strokeWidth: 2,
80
+ d: "M6 18L18 6M6 6l12 12"
81
+ })))), React__default.createElement("div", {
82
+ className: "flex-1 p-4 overflow-y-auto",
83
+ style: {
84
+ minHeight: 0
85
+ }
86
+ }, children)));
87
+ });
88
+ const EmptyState = React__default.memo(() => React__default.createElement("div", {
89
+ className: "h-full flex items-center justify-center bg-gray-100 p-4 sm:p-6 overflow-hidden"
90
+ }, React__default.createElement("div", {
91
+ className: "text-center max-w-sm mx-auto"
92
+ }, React__default.createElement("div", {
93
+ className: "text-3xl sm:text-4xl text-gray-400 mb-4"
94
+ }, "\uD83D\uDCAC"), React__default.createElement("h3", {
95
+ className: "text-lg sm:text-xl font-semibold text-gray-600 mb-2"
96
+ }, "Welcome to Messenger"), React__default.createElement("p", {
97
+ className: "text-sm sm:text-base text-gray-500 leading-relaxed"
98
+ }, "Select a conversation from the sidebar to start messaging"))));
99
+ // Mobile preview reducer
100
+ const mobilePreviewReducer = (state, action) => {
101
+ if (action.type === 'update') {
102
+ return {
103
+ ...state,
104
+ ...action.payload
105
+ };
106
+ }
107
+ return state;
108
+ };
109
+ const InboxTemplate1 = props => {
110
+ const [activeTab, setActiveTab] = React__default.useState('design');
111
+ return React__default.createElement(TabContext.Provider, {
112
+ value: {
113
+ activeTab,
114
+ setActiveTab
115
+ }
116
+ }, React__default.createElement(InboxTemplate1Internal, {
117
+ ...props
118
+ }));
119
+ };
120
+ const InboxTemplate1Internal = props => {
121
+ const {
122
+ channelFilters: channelFilterProp,
123
+ channelRole,
124
+ supportServices,
125
+ data,
126
+ orgName,
127
+ pathPrefix = null
128
+ } = props;
129
+ const {
130
+ id: pathChannelId,
131
+ postId: pathPostId
132
+ } = useParams();
133
+ const navigate = useNavigate();
134
+ const apolloClient = useApolloClient();
135
+ // Reduced state - only UI state remains, data comes from Apollo cache
136
+ const [isBottomDrawerOpen, setBottomDrawer] = React__default.useState(false);
137
+ const [mobilePreviewState, localDispatch] = useReducer(mobilePreviewReducer, {
138
+ mobilePreviewVisibility: false,
139
+ mobilePreviewText: false,
140
+ mobilePreviewCTAText: false
141
+ });
142
+ // Hooks - improved responsive breakpoints with better granularity
143
+ const {
144
+ width: windowWidth,
145
+ height: windowHeight
146
+ } = useWindowDimensions();
147
+ const isMobileView = useMediaQuery('(max-width: 640px)');
148
+ const isSmallTabletView = useMediaQuery('(min-width: 641px) and (max-width: 900px)');
149
+ const isTabletView = useMediaQuery('(min-width: 901px) and (max-width: 1024px)');
150
+ const isDesktopView = useMediaQuery('(min-width: 1025px)');
151
+ const isLargeDesktopView = useMediaQuery('(min-width: 1440px)');
152
+ const isSmallScreen = useMediaQuery('(max-width: 900px)');
153
+ // const auth = useSelector(userSelector);
154
+ const auth = useSelector(userSelector, shallowEqual);
155
+ // const user = useSelector((state: any) => state.user, shallowEqual);
156
+ // Data destructuring from Apollo queries
157
+ const GetChannelsByUserQuery = data?.[0];
158
+ const {
159
+ data: userChannels,
160
+ loading: userChannelsLoading,
161
+ refetch: getChannelsRefetch
162
+ } = GetChannelsByUserQuery || {};
163
+ // Get data directly from Apollo cache instead of local state
164
+ const channels = useMemo(() => {
165
+ if (!userChannels?.channelsByUser && !userChannels?.supportServiceChannels) return [];
166
+ return uniqBy([...(userChannels?.supportServiceChannels ?? []), ...(userChannels?.channelsByUser ?? [])], 'id');
167
+ }, [userChannels]);
168
+ // Memoize stable channel array to prevent unnecessary re-renders
169
+ const stableChannels = useMemo(() => {
170
+ return channels || [];
171
+ }, [channels]);
172
+ // Memoized values derived from Apollo cache data
173
+ const channelFilters = useMemo(() => {
174
+ const filters = {
175
+ ...channelFilterProp
176
+ };
177
+ const channelType = filters?.type ?? RoomType.Direct;
178
+ filters.type = supportServices ? [channelType, RoomType.Service] : channelType;
179
+ return filters;
180
+ }, [channelFilterProp, supportServices]);
181
+ const users = useMemo(() => {
182
+ return channels?.reduce((acc, curr) => {
183
+ const newMembers = curr.members?.filter(({
184
+ user
185
+ }) => !acc.find(({
186
+ id
187
+ }) => id === user.id)) || [];
188
+ return [...acc, ...newMembers.map(({
189
+ user
190
+ }) => user)];
191
+ }, []) || [];
192
+ }, [channels]);
193
+ // const currentUser = useMemo(
194
+ // () => users?.find((user) => user && user.alias?.includes(auth?.authUserId)),
195
+ // [users, auth?.authUserId],
196
+ // );
197
+ const currentUser = auth;
198
+ const channelName = useMemo(() => {
199
+ if (!channels || !pathChannelId) return '';
200
+ const currChannel = channels?.find(ch => ch.id === pathChannelId);
201
+ if (!currChannel) return '';
202
+ const {
203
+ members,
204
+ title,
205
+ type
206
+ } = currChannel;
207
+ if (type === RoomType.Direct && members?.length >= 2) {
208
+ const otherUser = members.find(member => member.user.id !== currentUser?.id);
209
+ if (otherUser?.user) {
210
+ const {
211
+ givenName,
212
+ familyName
213
+ } = otherUser.user;
214
+ if (givenName && familyName) return `${givenName} ${familyName}`;
215
+ return givenName || familyName || title || 'Direct Message';
216
+ }
217
+ return title || 'Direct Message';
218
+ }
219
+ if (type === RoomType.Direct && members?.length === 1) {
220
+ if (members[0].user?.givenName && members[0]?.user?.familyName) {
221
+ return `${members[0].user?.givenName} ${members[0].user?.familyName}`;
222
+ }
223
+ return members[0].user?.givenName || members[0].user?.familyName || 'Direct Message';
224
+ }
225
+ return title || 'Channel';
226
+ }, [channels, pathChannelId, currentUser]);
227
+ // Effects
228
+ useEffect(() => {
229
+ applyFooterStyles();
230
+ // Optimistic refetch with cache update
231
+ const timeout = setTimeout(() => {
232
+ getChannelsRefetch?.({
233
+ role: channelRole,
234
+ criteria: orgName ? {
235
+ ...channelFilters,
236
+ orgName: channelFilters?.orgName || orgName || ''
237
+ } : channelFilters,
238
+ supportServices: !!supportServices,
239
+ supportServiceCriteria: {
240
+ type: RoomType.Service
241
+ }
242
+ });
243
+ }, 0);
244
+ return () => clearTimeout(timeout);
245
+ }, [channelRole, channelFilters, supportServices, getChannelsRefetch]);
246
+ // Optimistic navigation with cache updates
247
+ const handleSelectChannel = useCallback(async (channelId, pId = null) => {
248
+ // Optimistic UI update
249
+ const mainPath = orgName ? pId ? `/o/${orgName}/ai-messenger/${channelId}/${pId}` : `/o/${orgName}/ai-messenger/${channelId}` : pId ? `/inbox/${channelId}/${pId}` : `/inbox/${channelId}`;
250
+ const basePath = pathPrefix ? `${pathPrefix}${mainPath}` : mainPath;
251
+ const searchParams = new URLSearchParams();
252
+ // if (channelRole) searchParams.set('channelRole', channelRole);
253
+ // if (orgName) searchParams.set('orgName', orgName);
254
+ const newPath = searchParams.toString() ? `${basePath}?${searchParams.toString()}` : basePath;
255
+ navigate(newPath, {
256
+ replace: true
257
+ });
258
+ // Optimistically update Apollo cache for immediate UI feedback
259
+ try {
260
+ apolloClient.writeQuery({
261
+ query: MessagesDocument,
262
+ variables: {
263
+ channelId: channelId.toString(),
264
+ parentId: null,
265
+ limit: MESSAGES_PER_PAGE
266
+ },
267
+ data: {
268
+ messages: {
269
+ __typename: 'Messages',
270
+ data: [],
271
+ totalCount: 0,
272
+ messagesRefId: channelId
273
+ }
274
+ }
275
+ });
276
+ } catch (error) {
277
+ // Cache write might fail if query hasn't been executed yet, that's OK
278
+ console.debug('Cache write failed (expected on first load):', error);
279
+ }
280
+ }, [navigate, apolloClient, orgName, channelRole, pathPrefix]);
281
+ const detailSidebarOptions = useMemo(() => ({
282
+ isMobileView,
283
+ isSmallTabletView,
284
+ isTabletView,
285
+ isDesktopView,
286
+ isLargeDesktopView,
287
+ isSmallScreen,
288
+ setMobilePreviewCTAText: v => localDispatch({
289
+ payload: {
290
+ mobilePreviewCTAText: v
291
+ },
292
+ type: 'update'
293
+ }),
294
+ setMobilePreviewText: v => localDispatch({
295
+ payload: {
296
+ mobilePreviewText: v
297
+ },
298
+ type: 'update'
299
+ }),
300
+ setMobilePreviewVisibility: v => localDispatch({
301
+ payload: {
302
+ mobilePreviewVisibility: v
303
+ },
304
+ type: 'update'
305
+ })
306
+ }), [isMobileView, isSmallTabletView, isTabletView, isDesktopView, isLargeDesktopView, isSmallScreen]);
307
+ return React__default.createElement("div", {
308
+ className: "border-t border-gray-300 flex overflow-hidden",
309
+ style: {
310
+ height: `${windowHeight}px`,
311
+ maxHeight: '100vh'
312
+ }
313
+ }, React__default.createElement("div", {
314
+ className: `
315
+ flex-shrink-0 bg-gray-50 border-r border-gray-300 overflow-hidden transition-all duration-300 ease-in-out
316
+ ${isMobileView && pathChannelId ? 'hidden' : ''}
317
+ `,
318
+ style: {
319
+ width: isMobileView && !pathChannelId ? '100%' : isMobileView && pathChannelId ? '0px' : isSmallTabletView ? `${Math.min(288, windowWidth * 0.35)}px` // w-72 or 35% of window
320
+ : isTabletView ? `${Math.min(320, windowWidth * 0.3)}px` // w-80 or 30% of window
321
+ : isLargeDesktopView ? `${Math.min(384, windowWidth * 0.25)}px` // w-96 or 25% of window
322
+ : `${Math.min(320, windowWidth * 0.28)}px`,
323
+ // w-80 or 28% of window
324
+ height: `${windowHeight}px`,
325
+ maxHeight: '100vh'
326
+ }
327
+ }, React__default.createElement(LeftSidebar, {
328
+ currentUser: currentUser,
329
+ userChannels: stableChannels,
330
+ userChannelsLoading: userChannelsLoading,
331
+ users: users,
332
+ handleSelectChannel: handleSelectChannel,
333
+ selectedChannelId: pathChannelId,
334
+ channelToTop: 0,
335
+ getChannelsRefetch: getChannelsRefetch,
336
+ role: channelRole,
337
+ messagesQuery: data?.[1],
338
+ windowHeight: windowHeight,
339
+ windowWidth: windowWidth
340
+ })), React__default.createElement("div", {
341
+ className: `
342
+ flex-1 min-w-0 flex flex-col overflow-hidden transition-all duration-300 ease-in-out
343
+ ${isMobileView && !pathChannelId ? 'hidden' : 'flex'}
344
+ `,
345
+ style: {
346
+ minWidth: isSmallScreen ? '300px' : isDesktopView ? '500px' : '400px',
347
+ width: 'auto',
348
+ height: `${windowHeight}px`,
349
+ maxHeight: '100vh'
350
+ }
351
+ }, pathChannelId ? React__default.createElement(ContentComponent, {
352
+ channelId: pathChannelId,
353
+ postId: pathPostId,
354
+ channelRole: channelRole,
355
+ pathPrefix: props.pathPrefix,
356
+ isMobileView: isMobileView,
357
+ isSmallTabletView: isSmallTabletView,
358
+ isTabletView: isTabletView,
359
+ isDesktopView: isDesktopView,
360
+ isLargeDesktopView: isLargeDesktopView,
361
+ isSmallScreen: isSmallScreen,
362
+ windowWidth: windowWidth,
363
+ windowHeight: windowHeight,
364
+ mobilePreviewState: mobilePreviewState,
365
+ detailSidebarOptions: detailSidebarOptions,
366
+ isBottomDrawerOpen: isBottomDrawerOpen,
367
+ setBottomDrawer: setBottomDrawer,
368
+ channelName: channelName,
369
+ loaderdata: data,
370
+ currentUser: currentUser
371
+ }) : React__default.createElement(EmptyState, null)), pathChannelId && data?.[1] && isDesktopView && React__default.createElement(RightSidebarContent, {
372
+ MessagesLoaderQuery: data?.[1],
373
+ selectedPost: null,
374
+ detailSidebarOptions: detailSidebarOptions,
375
+ windowWidth: windowWidth,
376
+ windowHeight: windowHeight
377
+ }));
378
+ };
379
+ const HeaderWithTabs = React__default.memo(props => {
380
+ const {
381
+ channelName,
382
+ isMobileView,
383
+ isSmallTabletView,
384
+ isSmallScreen,
385
+ mobilePreviewState,
386
+ setBottomDrawer
387
+ } = props;
388
+ return React__default.createElement("div", {
389
+ className: `border-b border-gray-200 bg-white flex-shrink-0 z-10 ${isSmallScreen ? 'px-3 py-3' : 'px-4 sm:px-6 py-4'}`
390
+ }, React__default.createElement("div", {
391
+ className: "flex items-center justify-between"
392
+ }, React__default.createElement("div", {
393
+ className: "flex items-center space-x-2 min-w-0 flex-1"
394
+ }, (isMobileView || isSmallTabletView) && React__default.createElement("button", {
395
+ className: "p-2 hover:bg-gray-100 rounded-full transition-colors flex-shrink-0",
396
+ onClick: () => window.history.back(),
397
+ "aria-label": "Go back"
398
+ }, React__default.createElement("svg", {
399
+ className: "w-5 h-5 text-gray-600",
400
+ fill: "none",
401
+ stroke: "currentColor",
402
+ viewBox: "0 0 24 24"
403
+ }, React__default.createElement("path", {
404
+ strokeLinecap: "round",
405
+ strokeLinejoin: "round",
406
+ strokeWidth: 2,
407
+ d: "M15 19l-7-7 7-7"
408
+ }))), React__default.createElement("h2", {
409
+ className: `font-semibold text-gray-800 truncate ${isSmallScreen ? 'text-base' : 'text-lg'}`
410
+ }, channelName)), (isMobileView || isSmallTabletView) && mobilePreviewState?.mobilePreviewVisibility && React__default.createElement("button", {
411
+ className: "text-sm px-3 py-1 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors flex-shrink-0",
412
+ onClick: () => setBottomDrawer(true)
413
+ }, mobilePreviewState?.mobilePreviewCTAText)));
414
+ });
415
+ const ContentComponent = React__default.memo(props => {
416
+ const {
417
+ channelId,
418
+ channelRole,
419
+ pathPrefix,
420
+ postId,
421
+ isMobileView,
422
+ isSmallTabletView,
423
+ isTabletView,
424
+ isDesktopView,
425
+ isLargeDesktopView,
426
+ isSmallScreen,
427
+ windowWidth,
428
+ windowHeight,
429
+ mobilePreviewState,
430
+ detailSidebarOptions,
431
+ isBottomDrawerOpen,
432
+ setBottomDrawer,
433
+ channelName,
434
+ loaderdata,
435
+ currentUser
436
+ } = props;
437
+ // AI Agent mode state
438
+ const [isAIAgentMode, setIsAIAgentMode] = useState(false);
439
+ const ViewChannelDetailLoaderQuery = loaderdata?.[2];
440
+ const MessagesLoaderQuery = loaderdata?.[1];
441
+ const [selectedPost, setSelectedPost] = React__default.useState(null);
442
+ const {
443
+ data: channelData,
444
+ loading: channelLoading
445
+ } = ViewChannelDetailLoaderQuery || {};
446
+ const onMessageClick = useCallback(msg => {
447
+ setSelectedPost(msg);
448
+ }, []);
449
+ const channelsDetail = useMemo(() => {
450
+ return channelData?.viewChannelDetail || null;
451
+ }, [channelData]);
452
+ return React__default.createElement("div", {
453
+ className: "flex overflow-hidden",
454
+ style: {
455
+ height: `${windowHeight}px`,
456
+ maxHeight: '100vh'
457
+ }
458
+ }, React__default.createElement("div", {
459
+ className: "flex-1 flex flex-col min-w-0 overflow-hidden"
460
+ }, channelId && React__default.createElement(HeaderWithTabs, {
461
+ channelName: channelName,
462
+ isMobileView: isMobileView,
463
+ isSmallTabletView: isSmallTabletView,
464
+ isSmallScreen: isSmallScreen,
465
+ mobilePreviewState: mobilePreviewState,
466
+ setBottomDrawer: setBottomDrawer,
467
+ loaderdata: loaderdata
468
+ }), React__default.createElement("div", {
469
+ className: `${isSmallScreen ? 'mx-3' : 'mx-4'} mt-4 mb-2`
470
+ }, React__default.createElement("div", {
471
+ className: "flex items-center justify-between"
472
+ }, React__default.createElement("div", {
473
+ className: "flex items-center space-x-2"
474
+ }, React__default.createElement("span", {
475
+ className: "text-sm font-medium text-gray-700"
476
+ }, "AI Assistant"), React__default.createElement("div", {
477
+ className: "relative inline-block w-10 mr-2 align-middle select-none"
478
+ }, React__default.createElement("input", {
479
+ type: "checkbox",
480
+ name: "toggle",
481
+ id: "ai-agent-toggle",
482
+ checked: isAIAgentMode,
483
+ onChange: e => setIsAIAgentMode(e.target.checked),
484
+ className: "sr-only"
485
+ }), React__default.createElement("label", {
486
+ htmlFor: "ai-agent-toggle",
487
+ className: `block w-10 h-6 rounded-full cursor-pointer transition-all duration-200 ease-in-out shadow-inner ${isAIAgentMode ? 'bg-blue-500' : 'bg-gray-300'}`
488
+ }, React__default.createElement("span", {
489
+ className: `block w-4 h-4 bg-white rounded-full transition-transform duration-200 ease-in-out transform shadow-md ${isAIAgentMode ? 'translate-x-5' : 'translate-x-1'}`,
490
+ style: {
491
+ marginTop: '2px'
492
+ }
493
+ })))), isAIAgentMode && React__default.createElement("div", {
494
+ className: "flex items-center space-x-2 text-xs text-blue-600"
495
+ }, React__default.createElement("span", {
496
+ className: "w-2 h-2 bg-blue-500 rounded-full animate-pulse"
497
+ }), React__default.createElement("span", null, "AI Mode Active")))), (isMobileView || isSmallTabletView) && channelId && mobilePreviewState?.mobilePreviewVisibility && React__default.createElement("div", {
498
+ className: `mt-4 ${isSmallScreen ? 'mx-3' : 'mx-4'}`
499
+ }, React__default.createElement("div", {
500
+ className: "mb-2"
501
+ }, React__default.createElement("div", {
502
+ className: "w-full flex justify-between items-center gap-2 mb-[5px]"
503
+ }, React__default.createElement("span", {
504
+ className: "truncate flex-1 text-sm"
505
+ }, mobilePreviewState?.mobilePreviewText), React__default.createElement("button", {
506
+ className: "text-sm px-3 py-2 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors flex-shrink-0",
507
+ onClick: () => setBottomDrawer(true)
508
+ }, mobilePreviewState?.mobilePreviewCTAText))), React__default.createElement("hr", {
509
+ className: "border-gray-200"
510
+ })), React__default.createElement("div", {
511
+ className: "flex-1 flex flex-col min-h-0 overflow-hidden"
512
+ }, channelId && React__default.createElement(React__default.Fragment, null, postId ? postId === '1' ? React__default.createElement(ThreadsInbox, {
513
+ channelId: channelId,
514
+ role: channelRole,
515
+ pathPrefix: pathPrefix,
516
+ setChannelId: () => {},
517
+ setPostId: () => {},
518
+ setGoBack: () => {}
519
+ }) : React__default.createElement(ThreadMessagesInbox, {
520
+ channelId: channelId,
521
+ postId: postId,
522
+ role: channelRole,
523
+ goBack: false,
524
+ pathPrefix: pathPrefix,
525
+ setPostId: () => {},
526
+ setChannelId: () => {},
527
+ onMessageClick: onMessageClick
528
+ }) : React__default.createElement(MessagesComponent, {
529
+ channelId: channelId,
530
+ MessagesLoaderQuery: MessagesLoaderQuery,
531
+ channelsDetail: channelsDetail,
532
+ channelLoading: channelLoading,
533
+ onMessageClick: onMessageClick,
534
+ isSmallScreen: isSmallScreen,
535
+ isDesktopView: isDesktopView,
536
+ windowHeight: windowHeight,
537
+ windowWidth: windowWidth,
538
+ isAIAgentMode: isAIAgentMode,
539
+ channelName: channelName,
540
+ currentUser: currentUser
541
+ })))), (isMobileView || isSmallTabletView) && React__default.createElement(Drawer, {
542
+ isOpen: isBottomDrawerOpen,
543
+ onClose: () => setBottomDrawer(false),
544
+ title: mobilePreviewState.mobilePreviewText
545
+ }, React__default.createElement(RightSidebarWrapper, {
546
+ MessagesLoaderQuery: MessagesLoaderQuery,
547
+ selectedPost: selectedPost,
548
+ detailSidebarOptions: detailSidebarOptions
549
+ })));
550
+ });
551
+ const RightSidebarWrapper = React__default.memo(({
552
+ MessagesLoaderQuery,
553
+ selectedPost,
554
+ detailSidebarOptions
555
+ }) => {
556
+ const {
557
+ data
558
+ } = MessagesLoaderQuery || {};
559
+ const {
560
+ activeTab,
561
+ setActiveTab
562
+ } = useContext(TabContext);
563
+ const sortedMessages = useMemo(() => {
564
+ const messages = data?.messages?.data || [];
565
+ return orderBy(uniqBy(messages, 'id'), ['createdAt'], ['asc']);
566
+ }, [data?.messages?.data]);
567
+ const handleRefreshSandbox = useCallback(() => {
568
+ console.log('Refreshing sandbox...');
569
+ }, []);
570
+ if (!sortedMessages.length) return null;
571
+ return React__default.createElement("div", {
572
+ className: "h-full flex flex-col overflow-hidden bg-white"
573
+ }, React__default.createElement("div", {
574
+ className: "flex-shrink-0 border-b border-gray-200"
575
+ }, React__default.createElement("div", {
576
+ className: "flex items-center justify-between px-4 py-3"
577
+ }, React__default.createElement("div", {
578
+ className: "flex items-center space-x-1"
579
+ }, React__default.createElement("button", {
580
+ onClick: () => setActiveTab('design'),
581
+ className: `flex items-center space-x-2 px-3 py-2 text-sm font-medium rounded-lg transition-colors ${activeTab === 'design' ? 'bg-blue-500 text-white' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-50'}`
582
+ }, React__default.createElement("svg", {
583
+ className: "w-4 h-4",
584
+ fill: "none",
585
+ stroke: "currentColor",
586
+ viewBox: "0 0 24 24"
587
+ }, React__default.createElement("path", {
588
+ strokeLinecap: "round",
589
+ strokeLinejoin: "round",
590
+ strokeWidth: 2,
591
+ d: "M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z"
592
+ })), React__default.createElement("span", null, "Design")), React__default.createElement("button", {
593
+ onClick: () => setActiveTab('interact'),
594
+ className: `flex items-center space-x-2 px-3 py-2 text-sm font-medium rounded-lg transition-colors ${activeTab === 'interact' ? 'bg-blue-500 text-white' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-50'}`
595
+ }, React__default.createElement("svg", {
596
+ className: "w-4 h-4",
597
+ fill: "none",
598
+ stroke: "currentColor",
599
+ viewBox: "0 0 24 24"
600
+ }, React__default.createElement("path", {
601
+ strokeLinecap: "round",
602
+ strokeLinejoin: "round",
603
+ strokeWidth: 2,
604
+ d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z"
605
+ }), React__default.createElement("path", {
606
+ strokeLinecap: "round",
607
+ strokeLinejoin: "round",
608
+ strokeWidth: 2,
609
+ d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
610
+ })), React__default.createElement("span", null, "Interact")), React__default.createElement("button", {
611
+ onClick: () => setActiveTab('code'),
612
+ className: `flex items-center space-x-2 px-3 py-2 text-sm font-medium rounded-lg transition-colors ${activeTab === 'code' ? 'bg-blue-500 text-white' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-50'}`
613
+ }, React__default.createElement("svg", {
614
+ className: "w-4 h-4",
615
+ fill: "none",
616
+ stroke: "currentColor",
617
+ viewBox: "0 0 24 24"
618
+ }, React__default.createElement("path", {
619
+ strokeLinecap: "round",
620
+ strokeLinejoin: "round",
621
+ strokeWidth: 2,
622
+ d: "M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
623
+ })), React__default.createElement("span", null, "Code"))), React__default.createElement("button", {
624
+ onClick: handleRefreshSandbox,
625
+ className: "p-2 text-gray-600 hover:text-gray-900 hover:bg-gray-50 rounded-lg transition-colors",
626
+ title: "Refresh Sandbox"
627
+ }, React__default.createElement("svg", {
628
+ className: "w-4 h-4",
629
+ fill: "none",
630
+ stroke: "currentColor",
631
+ viewBox: "0 0 24 24"
632
+ }, React__default.createElement("path", {
633
+ strokeLinecap: "round",
634
+ strokeLinejoin: "round",
635
+ strokeWidth: 2,
636
+ d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
637
+ }))))), React__default.createElement("div", {
638
+ className: "flex-1 overflow-hidden"
639
+ }, activeTab === 'design' ? React__default.createElement("div", {
640
+ className: "h-full flex items-center justify-center bg-gray-50"
641
+ }, React__default.createElement("div", {
642
+ className: "text-center"
643
+ }, React__default.createElement("div", {
644
+ className: "mb-8"
645
+ }, React__default.createElement("svg", {
646
+ className: "w-32 h-16 mx-auto text-black",
647
+ viewBox: "0 0 394 80",
648
+ fill: "currentColor"
649
+ }, React__default.createElement("path", {
650
+ d: "M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.4zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.7h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"
651
+ }), React__default.createElement("path", {
652
+ d: "M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.2 3.4 1 1.4 1.5 3 1.5 5h-5.8z"
653
+ }))), React__default.createElement("div", {
654
+ className: "space-y-4 text-gray-600"
655
+ }, React__default.createElement("h3", {
656
+ className: "text-lg font-semibold text-gray-900"
657
+ }, "Design View"), React__default.createElement("p", {
658
+ className: "font-mono text-sm bg-gray-100 px-3 py-1 rounded"
659
+ }, "Design components and UI"), React__default.createElement("p", null, "Customize and preview your design changes.")), React__default.createElement("div", {
660
+ className: "mt-8 space-y-4"
661
+ }, React__default.createElement("button", {
662
+ className: "bg-black text-white px-6 py-3 rounded-full hover:bg-gray-800 transition-colors flex items-center space-x-2 mx-auto"
663
+ }, React__default.createElement("svg", {
664
+ className: "w-4 h-4",
665
+ fill: "currentColor",
666
+ viewBox: "0 0 24 24"
667
+ }, React__default.createElement("path", {
668
+ d: "M12 2L2 7v10c0 5.55 3.84 9.739 9 11 5.16-1.261 9-5.45 9-11V7l-10-5z"
669
+ })), React__default.createElement("span", null, "Design now")), React__default.createElement("p", {
670
+ className: "text-sm text-gray-500 underline cursor-pointer hover:text-gray-700"
671
+ }, "View design docs")))) : activeTab === 'interact' ? React__default.createElement("div", {
672
+ className: "h-full flex items-center justify-center bg-blue-50"
673
+ }, React__default.createElement("div", {
674
+ className: "text-center"
675
+ }, React__default.createElement("div", {
676
+ className: "mb-8"
677
+ }, React__default.createElement("svg", {
678
+ className: "w-32 h-32 mx-auto text-blue-500",
679
+ fill: "none",
680
+ stroke: "currentColor",
681
+ viewBox: "0 0 24 24"
682
+ }, React__default.createElement("path", {
683
+ strokeLinecap: "round",
684
+ strokeLinejoin: "round",
685
+ strokeWidth: 1,
686
+ d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z"
687
+ }), React__default.createElement("path", {
688
+ strokeLinecap: "round",
689
+ strokeLinejoin: "round",
690
+ strokeWidth: 1,
691
+ d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
692
+ }))), React__default.createElement("div", {
693
+ className: "space-y-4 text-gray-600"
694
+ }, React__default.createElement("h3", {
695
+ className: "text-lg font-semibold text-gray-900"
696
+ }, "Interactive Mode"), React__default.createElement("p", {
697
+ className: "font-mono text-sm bg-blue-100 px-3 py-1 rounded"
698
+ }, "Live interaction and testing"), React__default.createElement("p", null, "Test and interact with your components in real-time.")), React__default.createElement("div", {
699
+ className: "mt-8 space-y-4"
700
+ }, React__default.createElement("button", {
701
+ className: "bg-blue-500 text-white px-6 py-3 rounded-full hover:bg-blue-600 transition-colors flex items-center space-x-2 mx-auto"
702
+ }, React__default.createElement("svg", {
703
+ className: "w-4 h-4",
704
+ fill: "currentColor",
705
+ viewBox: "0 0 24 24"
706
+ }, React__default.createElement("path", {
707
+ d: "M8 5v14l11-7z"
708
+ })), React__default.createElement("span", null, "Start Interacting")), React__default.createElement("p", {
709
+ className: "text-sm text-gray-500 underline cursor-pointer hover:text-gray-700"
710
+ }, "Learn about interactions")))) : React__default.createElement("div", {
711
+ className: "h-full bg-gray-900 text-gray-300 p-4 overflow-auto"
712
+ }, React__default.createElement("div", {
713
+ className: "font-mono text-sm"
714
+ }, React__default.createElement("div", {
715
+ className: "mb-4"
716
+ }, React__default.createElement("div", {
717
+ className: "text-green-400"
718
+ }, "// app/page.tsx")), React__default.createElement("div", {
719
+ className: "space-y-2"
720
+ }, React__default.createElement("div", null, React__default.createElement("span", {
721
+ className: "text-purple-400"
722
+ }, "export"), ' ', React__default.createElement("span", {
723
+ className: "text-purple-400"
724
+ }, "default"), ' ', React__default.createElement("span", {
725
+ className: "text-blue-400"
726
+ }, "function"), ' ', React__default.createElement("span", {
727
+ className: "text-yellow-400"
728
+ }, "Home"), "() ", '{'), React__default.createElement("div", {
729
+ className: "ml-4"
730
+ }, React__default.createElement("span", {
731
+ className: "text-purple-400"
732
+ }, "return"), " ("), React__default.createElement("div", {
733
+ className: "ml-8"
734
+ }, '<', React__default.createElement("span", {
735
+ className: "text-red-400"
736
+ }, "main"), ' ', React__default.createElement("span", {
737
+ className: "text-green-400"
738
+ }, "className"), "=", React__default.createElement("span", {
739
+ className: "text-yellow-400"
740
+ }, "\"flex min-h-screen flex-col items-center justify-between p-24\""), '>'), React__default.createElement("div", {
741
+ className: "ml-12"
742
+ }, '<', React__default.createElement("span", {
743
+ className: "text-red-400"
744
+ }, "div"), ' ', React__default.createElement("span", {
745
+ className: "text-green-400"
746
+ }, "className"), "=", React__default.createElement("span", {
747
+ className: "text-yellow-400"
748
+ }, "\"z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex\""), '>'), React__default.createElement("div", {
749
+ className: "ml-16"
750
+ }, '<', React__default.createElement("span", {
751
+ className: "text-red-400"
752
+ }, "p"), ' ', React__default.createElement("span", {
753
+ className: "text-green-400"
754
+ }, "className"), "=", React__default.createElement("span", {
755
+ className: "text-yellow-400"
756
+ }, "\"fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30\""), '>'), React__default.createElement("div", {
757
+ className: "ml-20 text-gray-400"
758
+ }, "Get started by editing\u00A0"), React__default.createElement("div", {
759
+ className: "ml-20"
760
+ }, '<', React__default.createElement("span", {
761
+ className: "text-red-400"
762
+ }, "code"), ' ', React__default.createElement("span", {
763
+ className: "text-green-400"
764
+ }, "className"), "=", React__default.createElement("span", {
765
+ className: "text-yellow-400"
766
+ }, "\"font-mono font-bold\""), '>', "app/page.tsx", '</', React__default.createElement("span", {
767
+ className: "text-red-400"
768
+ }, "code"), '>'), React__default.createElement("div", {
769
+ className: "ml-16"
770
+ }, '</', React__default.createElement("span", {
771
+ className: "text-red-400"
772
+ }, "p"), '>'), React__default.createElement("div", {
773
+ className: "ml-12"
774
+ }, '</', React__default.createElement("span", {
775
+ className: "text-red-400"
776
+ }, "div"), '>'), React__default.createElement("div", {
777
+ className: "ml-8"
778
+ }, '</', React__default.createElement("span", {
779
+ className: "text-red-400"
780
+ }, "main"), '>'), React__default.createElement("div", {
781
+ className: "ml-4"
782
+ }, ");"), React__default.createElement("div", null, '}'))))));
783
+ });
784
+ const RightSidebarContent = React__default.memo(({
785
+ MessagesLoaderQuery,
786
+ selectedPost,
787
+ detailSidebarOptions,
788
+ windowWidth,
789
+ windowHeight
790
+ }) => {
791
+ const {
792
+ data
793
+ } = MessagesLoaderQuery || {};
794
+ const sortedMessages = useMemo(() => {
795
+ const messages = data?.messages?.data || [];
796
+ return orderBy(uniqBy(messages, 'id'), ['createdAt'], ['asc']);
797
+ }, [data?.messages?.data]);
798
+ if (!sortedMessages.length) return null;
799
+ return React__default.createElement("div", {
800
+ className: "border-l border-gray-200 bg-white flex-shrink-0 overflow-hidden",
801
+ style: {
802
+ width: `${windowWidth * 0.35}px`,
803
+ // 35% of window width
804
+ height: `${windowHeight}px`,
805
+ maxHeight: '100vh'
806
+ }
807
+ }, React__default.createElement(RightSidebarWrapper, {
808
+ MessagesLoaderQuery: MessagesLoaderQuery,
809
+ selectedPost: selectedPost,
810
+ detailSidebarOptions: detailSidebarOptions
811
+ }));
812
+ });
813
+ const MessagesComponent = React__default.memo(props => {
814
+ const {
815
+ channelId,
816
+ MessagesLoaderQuery,
817
+ channelsDetail,
818
+ channelLoading,
819
+ onMessageClick,
820
+ isSmallScreen,
821
+ isDesktopView,
822
+ windowHeight = 768,
823
+ windowWidth = 1024,
824
+ isAIAgentMode,
825
+ channelName,
826
+ currentUser
827
+ } = props;
828
+ const messageRootListRef = useRef(null);
829
+ const messageListRef = useRef(null);
830
+ useApolloClient();
831
+ const [isLoadingOlder, setIsLoadingOlder] = React__default.useState(false);
832
+ const isLoadingOlderRef = useRef(false);
833
+ const scrollTimeoutRef = useRef(null);
834
+ const auth = useSelector(userSelector);
835
+ const {
836
+ startUpload
837
+ } = useUploadFiles();
838
+ const [sendMsg] = useSendMessagesMutation();
839
+ const {
840
+ data,
841
+ loading: messageLoading,
842
+ fetchMore: fetchMoreMessages,
843
+ subscribeToMore
844
+ } = MessagesLoaderQuery || {};
845
+ // Add dummy messages with modern formatting to showcase the new UI
846
+ const dummyMessages = [{
847
+ id: 'dummy-1',
848
+ message: `# Modern Next.js-Style Application
849
+
850
+ I'll help you build a modern Next.js-style application. Let me first examine the current homepage and then completely rebuild it to create a beautiful, modern "next app" experience.`,
851
+ createdAt: new Date(Date.now() + 2000).toISOString(),
852
+ author: {
853
+ id: 'ai-assistant',
854
+ username: 'AI Assistant',
855
+ givenName: 'AI',
856
+ familyName: 'Assistant',
857
+ picture: '/default-avatar.svg'
858
+ },
859
+ files: {
860
+ data: [],
861
+ totalCount: 0
862
+ }
863
+ }, {
864
+ id: 'dummy-2',
865
+ message: `## Key Features:
866
+
867
+ - **Professional Navigation** - Clean header with logo and navigation links
868
+ - **Hero Section** - Compelling headline with gradient text effects and code preview
869
+ - **Feature Cards** - Showcase of Next.js capabilities with modern icons
870
+ - **Call-to-Action** - Clear conversion paths for user engagement
871
+ - **Footer** - Comprehensive site navigation and branding
872
+
873
+ ### Design Highlights:
874
+
875
+ - Modern gradient branding (blue to purple to pink)
876
+ - Clean typography with proper hierarchy
877
+ - Responsive grid layouts for all screen sizes
878
+ - Subtle backdrop blur effects and modern cards
879
+ - Smooth scroll behavior and enhanced visual effects
880
+ - Production-ready color palette with proper light/dark mode support`,
881
+ createdAt: new Date(Date.now() + 3000).toISOString(),
882
+ author: {
883
+ id: 'ai-assistant',
884
+ username: 'AI Assistant',
885
+ givenName: 'AI',
886
+ familyName: 'Assistant',
887
+ picture: '/default-avatar.svg'
888
+ },
889
+ files: {
890
+ data: [],
891
+ totalCount: 0
892
+ }
893
+ }, {
894
+ id: 'dummy-3',
895
+ message: `### Technical Implementation:
896
+
897
+ Uses existing **shadcn/ui components** (Button, Card, Badge)
898
+ .`,
899
+ createdAt: new Date(Date.now() + 4000).toISOString(),
900
+ author: {
901
+ id: 'ai-assistant',
902
+ username: 'AI Assistant',
903
+ givenName: 'AI',
904
+ familyName: 'Assistant',
905
+ picture: '/default-avatar.svg'
906
+ },
907
+ files: {
908
+ data: [],
909
+ totalCount: 0
910
+ }
911
+ }, {
912
+ id: 'dummy-4',
913
+ message: `\`\`\`typescript
914
+ export default function Home() {
915
+ return (
916
+ <main className="flex min-h-screen flex-col items-center">
917
+ <div className="z-10 max-w-5xl w-full items-center">
918
+ <p className="fixed left-0 top-0 flex w-full justify-center">
919
+ Get started by editing app/page.tsx
920
+ </p>
921
+ </div>
922
+ </main>
923
+ );
924
+ }\`\`\`
925
+ .`,
926
+ createdAt: new Date(Date.now() + 4000).toISOString(),
927
+ author: {
928
+ id: 'ai-assistant',
929
+ username: 'AI Assistant',
930
+ givenName: 'AI',
931
+ familyName: 'Assistant',
932
+ picture: '/default-avatar.svg'
933
+ },
934
+ files: {
935
+ data: [],
936
+ totalCount: 0
937
+ }
938
+ }, {
939
+ id: 'tool-status-1',
940
+ message: `<div class="px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm text-gray-700" style="border-radius: 5px !important;">🔧 Running tool</div>`,
941
+ createdAt: new Date(Date.now() + 5000).toISOString(),
942
+ author: {
943
+ id: 'system-tool',
944
+ username: 'System Tool',
945
+ givenName: 'System',
946
+ familyName: 'Tool',
947
+ picture: '/default-avatar.svg'
948
+ },
949
+ files: {
950
+ data: [],
951
+ totalCount: 0
952
+ }
953
+ }, {
954
+ id: 'tool-status-2',
955
+ message: `<div class="px-3 py-2 bg-gray-100 border border-gray-300 rounded-lg text-sm text-gray-700" style="border-radius: 5px !important;">🔧 Running tool</div>`,
956
+ createdAt: new Date(Date.now() + 5500).toISOString(),
957
+ author: {
958
+ id: 'system-tool',
959
+ username: 'System Tool',
960
+ givenName: 'System',
961
+ familyName: 'Tool',
962
+ picture: '/default-avatar.svg'
963
+ },
964
+ files: {
965
+ data: [],
966
+ totalCount: 0
967
+ }
968
+ }, {
969
+ id: 'bullet-point-1',
970
+ message: `<div>
971
+ <h1 class="text-xl font-bold">Installation process</h1>
972
+ <ul>
973
+ <li>Install Node.js</li>
974
+ <li>Install npm</li>
975
+ <li>Install React</li>
976
+ <li>Install Tailwind CSS</li>
977
+ <li>Install shadcn/ui</li>
978
+ <li>Install Next.js</li>
979
+ <li>Install TypeScript</li>
980
+ <li>Install ESLint</li>
981
+ <li>Install Prettier</li>
982
+ </ul> </div>`,
983
+ createdAt: new Date(Date.now() + 5500).toISOString(),
984
+ author: {
985
+ id: 'bullet-tool',
986
+ username: 'System Tool',
987
+ givenName: 'System',
988
+ familyName: 'Tool',
989
+ picture: '/default-avatar.svg'
990
+ },
991
+ files: {
992
+ data: [],
993
+ totalCount: 0
994
+ }
995
+ }];
996
+ // Get messages directly from Apollo cache
997
+ const messages = useMemo(() => {
998
+ const messagesData = data?.messages?.data || [];
999
+ dummyMessages.forEach(msg => messagesData.push(msg));
1000
+ return orderBy(uniqBy(messagesData, 'id'), ['createdAt'], ['asc']);
1001
+ }, [data?.messages?.data]);
1002
+ const totalCount = data?.messages?.totalCount || 0;
1003
+ const scrollToBottom = useCallback(() => {
1004
+ if (messageRootListRef?.current) {
1005
+ messageRootListRef.current.scrollTop = messageRootListRef.current.scrollHeight;
1006
+ }
1007
+ }, []);
1008
+ // Auto-scroll on new messages (but not when loading older messages)
1009
+ useEffect(() => {
1010
+ if (!isLoadingOlderRef.current) {
1011
+ const timer = setTimeout(() => scrollToBottom(), 100);
1012
+ return () => clearTimeout(timer);
1013
+ }
1014
+ }, [messages.length, scrollToBottom]);
1015
+ const onFetchOld = useCallback(async skip => {
1016
+ if (channelId && fetchMoreMessages && !isLoadingOlder) {
1017
+ try {
1018
+ setIsLoadingOlder(true);
1019
+ isLoadingOlderRef.current = true;
1020
+ // Capture current scroll height before fetching
1021
+ const oldScrollHeight = messageRootListRef?.current?.scrollHeight || 0;
1022
+ await fetchMoreMessages({
1023
+ variables: {
1024
+ channelId: channelId.toString(),
1025
+ parentId: null,
1026
+ skip
1027
+ },
1028
+ updateQuery: (prev, {
1029
+ fetchMoreResult
1030
+ }) => {
1031
+ if (!fetchMoreResult) return prev;
1032
+ const newMessages = fetchMoreResult.messages.data;
1033
+ const existingMessages = prev.messages?.data || [];
1034
+ return {
1035
+ ...prev,
1036
+ messages: {
1037
+ ...fetchMoreResult.messages,
1038
+ data: uniqBy([...newMessages, ...existingMessages], 'id')
1039
+ }
1040
+ };
1041
+ }
1042
+ });
1043
+ // Maintain scroll position after loading older messages
1044
+ setTimeout(() => {
1045
+ if (messageRootListRef?.current) {
1046
+ const newScrollHeight = messageRootListRef.current.scrollHeight;
1047
+ const scrollDiff = newScrollHeight - oldScrollHeight;
1048
+ // For normal flex layout, maintain position by adjusting scroll offset
1049
+ messageRootListRef.current.scrollTop = scrollDiff;
1050
+ }
1051
+ // Reset the loading flag after position is maintained
1052
+ setTimeout(() => {
1053
+ isLoadingOlderRef.current = false;
1054
+ }, 50);
1055
+ }, 100);
1056
+ } catch (error) {
1057
+ console.error('Error fetching older messages:', error);
1058
+ isLoadingOlderRef.current = false;
1059
+ } finally {
1060
+ setIsLoadingOlder(false);
1061
+ }
1062
+ }
1063
+ }, [channelId, fetchMoreMessages, isLoadingOlder]);
1064
+ // Scroll to bottom when channel changes
1065
+ useEffect(() => {
1066
+ if (channelId && messages.length > 0) {
1067
+ isLoadingOlderRef.current = false; // Reset flag on channel change
1068
+ const timer = setTimeout(() => scrollToBottom(), 200);
1069
+ return () => clearTimeout(timer);
1070
+ }
1071
+ }, [channelId, scrollToBottom]);
1072
+ // Alternative scroll detection for Firefox
1073
+ useEffect(() => {
1074
+ const element = messageRootListRef.current;
1075
+ if (!element) return;
1076
+ // Firefox-specific scroll detection using passive listeners
1077
+ const handleScrollEnd = () => {
1078
+ if (!isLoadingOlder && element) {
1079
+ const {
1080
+ scrollTop
1081
+ } = element;
1082
+ const isAtTop = Math.round(scrollTop) <= 30;
1083
+ const hasMoreMessages = totalCount > messages.length;
1084
+ if (isAtTop && hasMoreMessages) {
1085
+ console.log('ScrollEnd triggered load more (Firefox):', {
1086
+ scrollTop: Math.round(scrollTop),
1087
+ totalCount,
1088
+ messagesLength: messages.length
1089
+ });
1090
+ onFetchOld(messages.length);
1091
+ }
1092
+ }
1093
+ };
1094
+ // Use scrollend event if available (modern Firefox/Chrome)
1095
+ if ('onscrollend' in element) {
1096
+ element.addEventListener('scrollend', handleScrollEnd, {
1097
+ passive: true
1098
+ });
1099
+ return () => {
1100
+ element.removeEventListener('scrollend', handleScrollEnd);
1101
+ };
1102
+ }
1103
+ }, [totalCount, messages.length, onFetchOld, isLoadingOlder]);
1104
+ // Cleanup scroll timeout on unmount
1105
+ useEffect(() => {
1106
+ return () => {
1107
+ if (scrollTimeoutRef.current) {
1108
+ clearTimeout(scrollTimeoutRef.current);
1109
+ }
1110
+ };
1111
+ }, []);
1112
+ const onMessagesScroll = useCallback(async e => {
1113
+ // Throttle scroll events for better performance, especially in Firefox
1114
+ if (scrollTimeoutRef.current) {
1115
+ clearTimeout(scrollTimeoutRef.current);
1116
+ }
1117
+ scrollTimeoutRef.current = setTimeout(async () => {
1118
+ if (messageRootListRef.current && !isLoadingOlder) {
1119
+ const element = messageRootListRef.current;
1120
+ const {
1121
+ clientHeight,
1122
+ scrollHeight,
1123
+ scrollTop
1124
+ } = element;
1125
+ // Firefox-compatible scroll detection
1126
+ // Use Math.ceil to handle Firefox's fractional scrollTop values
1127
+ const isAtTop = Math.ceil(scrollTop) <= 25;
1128
+ const hasMoreMessages = totalCount > messages.length;
1129
+ // Additional Firefox-specific check
1130
+ const isFirefox = navigator.userAgent.includes('Firefox');
1131
+ const firefoxAdjustedTop = isFirefox ? Math.round(scrollTop) <= 30 : isAtTop;
1132
+ if ((isAtTop || firefoxAdjustedTop) && hasMoreMessages) {
1133
+ console.log('Triggering load more:', {
1134
+ scrollTop: Math.ceil(scrollTop),
1135
+ originalScrollTop: scrollTop,
1136
+ totalCount,
1137
+ messagesLength: messages.length,
1138
+ scrollHeight,
1139
+ clientHeight,
1140
+ browser: isFirefox ? 'Firefox' : 'Other',
1141
+ isAtTop,
1142
+ firefoxAdjustedTop
1143
+ });
1144
+ await onFetchOld(messages.length);
1145
+ }
1146
+ }
1147
+ }, 100);
1148
+ }, [totalCount, messages.length, onFetchOld, isLoadingOlder]);
1149
+ // Optimistic message sending with Apollo cache updates
1150
+ useCallback(async (message, files = []) => {
1151
+ // Allow sending if there's either a message or files
1152
+ if ((!message || !message.trim()) && (!files || files.length === 0)) return;
1153
+ if (!channelId) return;
1154
+ try {
1155
+ const postId = objectId();
1156
+ const currentDate = new Date();
1157
+ const createOptimisticMessage = files => ({
1158
+ __typename: 'Post',
1159
+ id: postId,
1160
+ message,
1161
+ createdAt: currentDate.toISOString(),
1162
+ updatedAt: currentDate.toISOString(),
1163
+ author: {
1164
+ __typename: 'UserAccount',
1165
+ id: currentUser?.id,
1166
+ givenName: currentUser?.profile?.given_name || '',
1167
+ familyName: currentUser?.profile?.family_name || '',
1168
+ email: currentUser?.profile?.email || '',
1169
+ username: currentUser?.profile?.nickname || '',
1170
+ fullName: currentUser?.profile?.name || '',
1171
+ picture: currentUser?.profile?.picture || '',
1172
+ alias: [currentUser?.authUserId ?? ''],
1173
+ tokens: []
1174
+ },
1175
+ isDelivered: false,
1176
+ // Will be true once confirmed by server
1177
+ isRead: false,
1178
+ type: 'TEXT',
1179
+ parentId: null,
1180
+ fromServer: false,
1181
+ channel: {
1182
+ __typename: 'Channel',
1183
+ id: channelId
1184
+ },
1185
+ propsConfiguration: {
1186
+ __typename: 'MachineConfiguration',
1187
+ id: null,
1188
+ resource: '',
1189
+ contents: null,
1190
+ keys: null,
1191
+ target: null,
1192
+ overrides: null
1193
+ },
1194
+ props: {},
1195
+ files: {
1196
+ __typename: 'FilesInfo',
1197
+ data: files || [],
1198
+ totalCount: files?.length || 0
1199
+ },
1200
+ replies: {
1201
+ __typename: 'Messages',
1202
+ data: [],
1203
+ totalCount: 0
1204
+ }
1205
+ });
1206
+ const optimisticMessage = createOptimisticMessage(files);
1207
+ if (files?.length > 0) {
1208
+ const uploadResponse = await startUpload({
1209
+ file: files,
1210
+ saveUploadedFile: {
1211
+ variables: {
1212
+ postId
1213
+ }
1214
+ },
1215
+ createUploadLink: {
1216
+ variables: {
1217
+ postId
1218
+ }
1219
+ }
1220
+ });
1221
+ const uploadedFiles = uploadResponse.data;
1222
+ if (uploadedFiles) {
1223
+ const fileIds = uploadedFiles.map(f => f.id);
1224
+ await sendMsg({
1225
+ variables: {
1226
+ postId,
1227
+ channelId,
1228
+ content: message,
1229
+ files: fileIds
1230
+ },
1231
+ optimisticResponse: {
1232
+ __typename: 'Mutation',
1233
+ sendMessage: createOptimisticMessage(uploadedFiles)
1234
+ },
1235
+ update: (cache, {
1236
+ data: mutationData
1237
+ }) => {
1238
+ if (!mutationData?.sendMessage) return;
1239
+ // Update messages cache optimistically
1240
+ const messagesQuery = {
1241
+ query: MessagesDocument,
1242
+ variables: {
1243
+ channelId: channelId.toString(),
1244
+ parentId: null,
1245
+ limit: MESSAGES_PER_PAGE
1246
+ }
1247
+ };
1248
+ try {
1249
+ const existingData = cache.readQuery(messagesQuery);
1250
+ if (existingData?.messages) {
1251
+ cache.writeQuery({
1252
+ ...messagesQuery,
1253
+ data: {
1254
+ messages: {
1255
+ ...existingData.messages,
1256
+ data: [...(existingData.messages.data || []), mutationData.sendMessage],
1257
+ totalCount: (existingData.messages.totalCount || 0) + 1
1258
+ }
1259
+ }
1260
+ });
1261
+ }
1262
+ } catch (error) {
1263
+ console.debug('Cache update failed (expected on first message):', error);
1264
+ }
1265
+ }
1266
+ });
1267
+ }
1268
+ } else {
1269
+ await sendMsg({
1270
+ variables: {
1271
+ channelId,
1272
+ content: message
1273
+ },
1274
+ optimisticResponse: {
1275
+ __typename: 'Mutation',
1276
+ sendMessage: optimisticMessage
1277
+ },
1278
+ update: (cache, {
1279
+ data: mutationData
1280
+ }) => {
1281
+ if (!mutationData?.sendMessage) return;
1282
+ // Update messages cache optimistically
1283
+ const messagesQuery = {
1284
+ query: MessagesDocument,
1285
+ variables: {
1286
+ channelId: channelId.toString(),
1287
+ parentId: null,
1288
+ limit: MESSAGES_PER_PAGE
1289
+ }
1290
+ };
1291
+ try {
1292
+ const existingData = cache.readQuery(messagesQuery);
1293
+ if (existingData?.messages) {
1294
+ cache.writeQuery({
1295
+ ...messagesQuery,
1296
+ data: {
1297
+ messages: {
1298
+ ...existingData.messages,
1299
+ data: [...(existingData.messages.data || []), mutationData.sendMessage],
1300
+ totalCount: (existingData.messages.totalCount || 0) + 1
1301
+ }
1302
+ }
1303
+ });
1304
+ }
1305
+ } catch (error) {
1306
+ console.debug('Cache update failed (expected on first message):', error);
1307
+ }
1308
+ }
1309
+ });
1310
+ }
1311
+ } catch (error) {
1312
+ console.error('Error sending message:', error);
1313
+ }
1314
+ }, [channelId, auth, startUpload, sendMsg]);
1315
+ // Show loading spinner for initial load
1316
+ if ((messageLoading || channelLoading) && messages.length === 0) {
1317
+ return React__default.createElement("div", {
1318
+ className: "flex-1 flex justify-center items-center"
1319
+ }, React__default.createElement(Spinner, {
1320
+ className: "w-12 h-12"
1321
+ }));
1322
+ }
1323
+ // If AI Agent mode is enabled, render the AI Agent component
1324
+ if (isAIAgentMode) {
1325
+ return React__default.createElement("div", {
1326
+ className: "flex-1 flex flex-col min-h-0 overflow-hidden"
1327
+ }, React__default.createElement(AIAgent, {
1328
+ channelId: channelId,
1329
+ placeholder: "Ask me anything...",
1330
+ className: "h-full",
1331
+ currentUser: currentUser,
1332
+ channelName: channelName
1333
+ }));
1334
+ }
1335
+ // Regular messages mode
1336
+ return React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
1337
+ ref: messageRootListRef,
1338
+ className: `overflow-y-scroll bg-white ${isSmallScreen ? 'p-2 px-3' : isDesktopView ? 'p-6 px-8' : 'p-4 px-6'}`,
1339
+ onScroll: onMessagesScroll,
1340
+ style: {
1341
+ height: `${windowHeight - 140}px`,
1342
+ // Subtract header + input height
1343
+ maxHeight: '100vh',
1344
+ scrollbarWidth: 'thin',
1345
+ scrollbarColor: '#cbd5e0 #f7fafc',
1346
+ overflowY: 'scroll',
1347
+ WebkitOverflowScrolling: 'touch',
1348
+ backgroundAttachment: 'fixed'
1349
+ }
1350
+ }, React__default.createElement("div", {
1351
+ className: "min-h-full"
1352
+ }, messages.length > 0 ? React__default.createElement(React__default.Fragment, null, isLoadingOlder && React__default.createElement("div", {
1353
+ className: "flex justify-center py-4"
1354
+ }, React__default.createElement("div", {
1355
+ className: "flex items-center space-x-2 text-gray-500"
1356
+ }, React__default.createElement(Spinner, {
1357
+ className: "w-4 h-4"
1358
+ }), React__default.createElement("span", {
1359
+ className: "text-sm"
1360
+ }, "Loading older messages..."))), React__default.createElement(MessagesBuilderUi, {
1361
+ innerRef: messageListRef,
1362
+ channelId: channelId,
1363
+ currentUser: currentUser,
1364
+ channelMessages: messages,
1365
+ totalCount: totalCount,
1366
+ onMessageClick: onMessageClick,
1367
+ isDesktopView: isDesktopView || false,
1368
+ isSmallScreen: isSmallScreen || false
1369
+ }), React__default.createElement(SubscriptionHandler, {
1370
+ subscribeToMore: subscribeToMore,
1371
+ document: OnChatMessageAddedDocument,
1372
+ variables: {
1373
+ channelId: channelId.toString()
1374
+ },
1375
+ enabled: !!channelId && !!subscribeToMore,
1376
+ updateQuery: (prev, {
1377
+ subscriptionData
1378
+ }) => {
1379
+ console.log('Subscription updateQuery called:', {
1380
+ prev,
1381
+ subscriptionData
1382
+ });
1383
+ if (!subscriptionData.data) {
1384
+ console.log('No subscription data, returning prev');
1385
+ return prev;
1386
+ }
1387
+ const newMessage = subscriptionData.data.chatMessageAdded;
1388
+ console.log('New message received via subscription:', newMessage);
1389
+ return {
1390
+ ...prev,
1391
+ messages: {
1392
+ ...prev?.messages,
1393
+ data: uniqBy([...(prev?.messages?.data || []), newMessage], 'id'),
1394
+ totalCount: (prev?.messages?.totalCount || 0) + 1
1395
+ }
1396
+ };
1397
+ },
1398
+ onError: error => {
1399
+ console.error('Subscription error:', error);
1400
+ }
1401
+ })) : React__default.createElement("div", {
1402
+ className: "flex items-center justify-center text-gray-500 min-h-96"
1403
+ }, React__default.createElement("div", {
1404
+ className: "text-center max-w-sm mx-auto px-4"
1405
+ }, React__default.createElement("div", {
1406
+ className: "text-6xl mb-4 opacity-50"
1407
+ }, "\uD83D\uDCAC"), React__default.createElement("h3", {
1408
+ className: "text-lg font-semibold text-gray-600 mb-2"
1409
+ }, "No messages yet"), React__default.createElement("p", {
1410
+ className: "text-sm text-gray-500"
1411
+ }, "Start the conversation by sending a message below!"))))), React__default.createElement("div", {
1412
+ className: "flex-shrink-0 border-t border-gray-200 bg-white"
1413
+ }, React__default.createElement(InputComponent, {
1414
+ channelId: channelId,
1415
+ placeholder: "Message"
1416
+ })));
1417
+ });
1418
+ // Display names for debugging
1419
+ InboxTemplate1.displayName = 'Inbox';
1420
+ InboxTemplate1Internal.displayName = 'InboxTemplate1Internal';
1421
+ HeaderWithTabs.displayName = 'HeaderWithTabs';
1422
+ ContentComponent.displayName = 'ContentComponent';
1423
+ MessagesComponent.displayName = 'MessagesComponent';
1424
+ RightSidebarWrapper.displayName = 'RightSidebarWrapper';
1425
+ RightSidebarContent.displayName = 'RightSidebarContent';
1426
+ var InboxTemplate2 = React__default.memo(InboxTemplate1);export{InboxTemplate2 as default};//# sourceMappingURL=InboxTemplate2.js.map