@messenger-box/platform-mobile 10.0.3-alpha.20 → 10.0.3-alpha.201

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 (112) hide show
  1. package/lib/components/messages-container-ui/BuildModeView.js +428 -0
  2. package/lib/components/messages-container-ui/BuildModeView.js.map +1 -0
  3. package/lib/components/messages-container-ui/MessagesContainerUI.js +55 -0
  4. package/lib/components/messages-container-ui/MessagesContainerUI.js.map +1 -0
  5. package/lib/components/messages-container-ui/PlanModeView.js +336 -0
  6. package/lib/components/messages-container-ui/PlanModeView.js.map +1 -0
  7. package/lib/compute.js +2 -3
  8. package/lib/compute.js.map +1 -1
  9. package/lib/index.js +1 -1
  10. package/lib/index.js.map +1 -1
  11. package/lib/module.js.map +1 -1
  12. package/lib/queries/inboxQueries.js +62 -0
  13. package/lib/queries/inboxQueries.js.map +1 -0
  14. package/lib/routes.json +2 -3
  15. package/lib/screens/inbox/DialogMessages.js +8 -3
  16. package/lib/screens/inbox/DialogMessages.js.map +1 -1
  17. package/lib/screens/inbox/DialogThreadMessages.js +6 -11
  18. package/lib/screens/inbox/DialogThreadMessages.js.map +1 -1
  19. package/lib/screens/inbox/DialogThreads.js +58 -20
  20. package/lib/screens/inbox/DialogThreads.js.map +1 -1
  21. package/lib/screens/inbox/Inbox.js.map +1 -1
  22. package/lib/screens/inbox/components/CachedImage/consts.js +1 -1
  23. package/lib/screens/inbox/components/CachedImage/consts.js.map +1 -1
  24. package/lib/screens/inbox/components/CachedImage/index.js +125 -115
  25. package/lib/screens/inbox/components/CachedImage/index.js.map +1 -1
  26. package/lib/screens/inbox/components/DialogItem.js +160 -0
  27. package/lib/screens/inbox/components/DialogItem.js.map +1 -0
  28. package/lib/screens/inbox/components/GiftedChatInboxComponent.js +315 -0
  29. package/lib/screens/inbox/components/GiftedChatInboxComponent.js.map +1 -0
  30. package/lib/screens/inbox/components/SlackMessageContainer/ImageViewerModal.js +3 -1
  31. package/lib/screens/inbox/components/SlackMessageContainer/ImageViewerModal.js.map +1 -1
  32. package/lib/screens/inbox/components/SlackMessageContainer/PaymentMessage.js +194 -0
  33. package/lib/screens/inbox/components/SlackMessageContainer/PaymentMessage.js.map +1 -0
  34. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js +149 -36
  35. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js.map +1 -1
  36. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js +4 -5
  37. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js.map +1 -1
  38. package/lib/screens/inbox/components/SubscriptionHandler.js +22 -0
  39. package/lib/screens/inbox/components/SubscriptionHandler.js.map +1 -0
  40. package/lib/screens/inbox/components/ThreadsViewItem.js +67 -47
  41. package/lib/screens/inbox/components/ThreadsViewItem.js.map +1 -1
  42. package/lib/screens/inbox/config/config.js +4 -2
  43. package/lib/screens/inbox/config/config.js.map +1 -1
  44. package/lib/screens/inbox/containers/ConversationView.js +1099 -1094
  45. package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
  46. package/lib/screens/inbox/containers/Dialogs.js +132 -534
  47. package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
  48. package/lib/screens/inbox/containers/ThreadConversationView.js +876 -1357
  49. package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
  50. package/lib/screens/inbox/containers/ThreadsView.js +81 -54
  51. package/lib/screens/inbox/containers/ThreadsView.js.map +1 -1
  52. package/lib/screens/inbox/hooks/useInboxMessages.js +31 -0
  53. package/lib/screens/inbox/hooks/useInboxMessages.js.map +1 -0
  54. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js +108 -0
  55. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js.map +1 -0
  56. package/lib/screens/inbox/workflow/dialog-threads-xstate.js +151 -0
  57. package/lib/screens/inbox/workflow/dialog-threads-xstate.js.map +1 -0
  58. package/package.json +9 -7
  59. package/CHANGELOG.md +0 -164
  60. package/jest.config.js +0 -24
  61. package/lib/screens/inbox/components/DialogsListItem.js +0 -548
  62. package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
  63. package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -489
  64. package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
  65. package/lib/screens/inbox/components/workflow/dialogs-list-item-xstate.js +0 -175
  66. package/lib/screens/inbox/components/workflow/dialogs-list-item-xstate.js.map +0 -1
  67. package/lib/screens/inbox/components/workflow/service-dialogs-list-item-xstate.js +0 -191
  68. package/lib/screens/inbox/components/workflow/service-dialogs-list-item-xstate.js.map +0 -1
  69. package/lib/screens/inbox/containers/workflow/conversation-xstate.js +0 -380
  70. package/lib/screens/inbox/containers/workflow/conversation-xstate.js.map +0 -1
  71. package/lib/screens/inbox/containers/workflow/dialogs-xstate.js +0 -211
  72. package/lib/screens/inbox/containers/workflow/dialogs-xstate.js.map +0 -1
  73. package/lib/screens/inbox/containers/workflow/thread-conversation-xstate.js +0 -438
  74. package/lib/screens/inbox/containers/workflow/thread-conversation-xstate.js.map +0 -1
  75. package/rollup.config.mjs +0 -45
  76. package/src/components/index.ts +0 -0
  77. package/src/compute.ts +0 -63
  78. package/src/index.ts +0 -7
  79. package/src/module.ts +0 -10
  80. package/src/navigation/InboxNavigation.tsx +0 -102
  81. package/src/navigation/index.ts +0 -1
  82. package/src/screens/inbox/DialogMessages.tsx +0 -21
  83. package/src/screens/inbox/DialogThreadMessages.tsx +0 -97
  84. package/src/screens/inbox/DialogThreads.tsx +0 -129
  85. package/src/screens/inbox/Inbox.tsx +0 -17
  86. package/src/screens/inbox/components/CachedImage/consts.ts +0 -6
  87. package/src/screens/inbox/components/CachedImage/index.tsx +0 -223
  88. package/src/screens/inbox/components/DialogsHeader.tsx +0 -30
  89. package/src/screens/inbox/components/DialogsListItem.tsx +0 -819
  90. package/src/screens/inbox/components/ServiceDialogsListItem.tsx +0 -679
  91. package/src/screens/inbox/components/SlackMessageContainer/ImageViewerModal.tsx +0 -113
  92. package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +0 -313
  93. package/src/screens/inbox/components/SlackMessageContainer/SlackMessage.tsx +0 -145
  94. package/src/screens/inbox/components/SlackMessageContainer/index.ts +0 -3
  95. package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +0 -301
  96. package/src/screens/inbox/components/ThreadsViewItem.tsx +0 -321
  97. package/src/screens/inbox/components/workflow/dialogs-list-item-xstate.ts +0 -145
  98. package/src/screens/inbox/components/workflow/service-dialogs-list-item-xstate.ts +0 -159
  99. package/src/screens/inbox/config/config.ts +0 -15
  100. package/src/screens/inbox/config/index.ts +0 -1
  101. package/src/screens/inbox/containers/ConversationView.tsx +0 -1782
  102. package/src/screens/inbox/containers/Dialogs.tsx +0 -794
  103. package/src/screens/inbox/containers/SupportServiceDialogs.tsx +0 -119
  104. package/src/screens/inbox/containers/ThreadConversationView.tsx +0 -2312
  105. package/src/screens/inbox/containers/ThreadsView.tsx +0 -305
  106. package/src/screens/inbox/containers/workflow/apollo/handleResult.ts +0 -20
  107. package/src/screens/inbox/containers/workflow/conversation-xstate.ts +0 -313
  108. package/src/screens/inbox/containers/workflow/dialogs-xstate.ts +0 -196
  109. package/src/screens/inbox/containers/workflow/thread-conversation-xstate.ts +0 -401
  110. package/src/screens/index.ts +0 -4
  111. package/tsconfig.json +0 -13
  112. package/webpack.config.js +0 -58
@@ -1,4 +1,4 @@
1
- import React__default,{useState,useRef,useCallback,useEffect,useMemo}from'react';import {Button,Box,Spinner,Text,HStack,VStack,Avatar,AvatarFallbackText,AvatarImage,Center,Image}from'@admin-layout/gluestack-ui-mobile';import {Platform,SafeAreaView,TouchableHighlight,Alert,Linking,View}from'react-native';import {useRoute,useNavigation,useFocusEffect}from'@react-navigation/native';import {useSelector}from'react-redux';import {orderBy,startCase,uniqBy}from'lodash-es';import*as ImagePicker from'expo-image-picker';import {MaterialIcons,Ionicons,MaterialCommunityIcons}from'@expo/vector-icons';import {GiftedChat,Actions as Actions$1,InputToolbar,Send}from'react-native-gifted-chat';import'common';import {useCreatePostThreadMutation,useSendExpoNotificationOnPostMutation,useGetPostThreadLazyQuery,OnThreadChatMessageAddedDocument}from'common/graphql';import {useUploadFilesNative}from'@messenger-box/platform-client';import {objectId}from'@messenger-box/core';import {format,isToday,isYesterday}from'date-fns';import {userSelector}from'@adminide-stack/user-auth0-client';import {config}from'../config/config.js';import Message from'../components/SlackMessageContainer/SlackMessage.js';import ImageViewerModal from'../components/SlackMessageContainer/ImageViewerModal.js';import CachedImage from'../components/CachedImage/index.js';import colors from'tailwindcss/colors';import {Actions,BaseState,MainState}from'./workflow/thread-conversation-xstate.js';var __defProp = Object.defineProperty;
1
+ import React__default,{useState,useRef,useEffect,useCallback,useMemo}from'react';import {useToast,Button,Spinner,Box,ButtonText,HStack,Avatar,AvatarFallbackText,AvatarImage,Text,Image,VStack,Skeleton}from'@admin-layout/gluestack-ui-mobile';import {Platform,Keyboard,View,TouchableHighlight,ScrollView,TouchableOpacity,RefreshControl,Animated}from'react-native';import {useRoute,useNavigation,useFocusEffect}from'@react-navigation/native';import {useSelector}from'react-redux';import {uniqBy,orderBy,startCase}from'lodash-es';import*as ImagePicker from'expo-image-picker';import'base-64';import {MaterialIcons,MaterialCommunityIcons,Ionicons}from'@expo/vector-icons';import {Send,MessageText,Actions,InputToolbar}from'react-native-gifted-chat';import {FileRefType,PreDefinedRole}from'common';import {useCreatePostThread,useSendExpoNotification,useGetPostThreadLazy,CHAT_MESSAGE_ADDED}from'../../../queries/inboxQueries.js';import {useUploadFilesNative}from'@messenger-box/platform-client';import {objectId}from'@messenger-box/core';import {format,isToday,isYesterday}from'date-fns';import {userSelector}from'@adminide-stack/user-auth0-client';import {config}from'../config/config.js';import Message from'../components/SlackMessageContainer/SlackMessage.js';import ImageViewerModal from'../components/SlackMessageContainer/ImageViewerModal.js';import CachedImage from'../components/CachedImage/index.js';import colors from'tailwindcss/colors';import {GiftedChatInboxComponent}from'../components/GiftedChatInboxComponent.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -25,942 +25,504 @@ const {
25
25
  CALL_TO_ACTION_TEXT_COLOR
26
26
  } = config;
27
27
  const createdAtText = (value) => {
28
- if (!value)
29
- return "";
30
- try {
31
- const timestamp = new Date(value).getTime();
32
- if (isNaN(timestamp)) {
33
- console.warn(`Invalid date value in createdAtText: ${value}`);
34
- return "Unknown date";
35
- }
36
- let date = new Date(value);
37
- if (isToday(date))
38
- return "Today";
39
- if (isYesterday(date))
40
- return "Yesterday";
41
- return format(date, "MMM dd, yyyy");
42
- } catch (error) {
43
- console.error(`Error processing date in createdAtText: ${value}`, error);
44
- return "Unknown date";
45
- }
28
+ if (!value) return "";
29
+ let date = new Date(value);
30
+ if (isToday(date)) return "Today";
31
+ if (isYesterday(date)) return "Yesterday";
32
+ return format(new Date(value), "MMM dd, yyyy");
46
33
  };
47
- function useSafeMachine(machine) {
48
- const [state, setState] = useState({
49
- context: {
50
- channelId: null,
51
- postParentId: null,
52
- role: null,
53
- threadMessages: [],
54
- totalCount: 0,
55
- skip: 0,
56
- loading: false,
57
- loadingOldMessages: false,
58
- error: null,
59
- selectedImage: "",
60
- files: [],
61
- images: [],
62
- messageText: "",
63
- imageLoading: false,
64
- postThread: null,
65
- threadPost: [],
66
- isScrollToBottom: false
67
- },
68
- value: "idle"
69
- });
70
- const send = useCallback((event) => {
71
- var _a, _b, _c, _d;
72
- try {
73
- console.log("Thread Event received:", event.type);
74
- if (event.type === Actions.INITIAL_CONTEXT) {
75
- setState((prev) => {
76
- var _a2, _b2, _c2;
77
- return __spreadProps(__spreadValues({}, prev), {
78
- context: __spreadProps(__spreadValues({}, prev.context), {
79
- channelId: ((_a2 = event.data) == null ? void 0 : _a2.channelId) || null,
80
- postParentId: ((_b2 = event.data) == null ? void 0 : _b2.postParentId) || null,
81
- role: ((_c2 = event.data) == null ? void 0 : _c2.role) || null
82
- }),
83
- value: BaseState.FetchThreadMessages
84
- });
85
- });
86
- } else if (event.type === Actions.SET_THREAD_MESSAGES) {
87
- setState((prev) => {
88
- var _a2, _b2, _c2, _d2;
89
- return __spreadProps(__spreadValues({}, prev), {
90
- context: __spreadProps(__spreadValues({}, prev.context), {
91
- threadMessages: ((_a2 = event.data) == null ? void 0 : _a2.messages) || [],
92
- totalCount: ((_b2 = event.data) == null ? void 0 : _b2.totalCount) || 0,
93
- loading: false,
94
- loadingOldMessages: false,
95
- threadPost: ((_c2 = event.data) == null ? void 0 : _c2.threadPost) || [],
96
- postThread: ((_d2 = event.data) == null ? void 0 : _d2.postThread) || null
97
- }),
98
- value: "active"
99
- });
100
- });
101
- } else if (event.type === Actions.CLEAR_MESSAGES) {
102
- setState((prev) => __spreadProps(__spreadValues({}, prev), {
103
- context: __spreadProps(__spreadValues({}, prev.context), {
104
- threadMessages: [],
105
- totalCount: 0
106
- })
107
- }));
108
- } else if (event.type === Actions.SET_MESSAGE_TEXT) {
109
- setState((prev) => {
110
- var _a2;
111
- return __spreadProps(__spreadValues({}, prev), {
112
- context: __spreadProps(__spreadValues({}, prev.context), {
113
- messageText: ((_a2 = event.data) == null ? void 0 : _a2.messageText) || ""
114
- })
115
- });
116
- });
117
- } else if (event.type === Actions.FETCH_MORE_MESSAGES) {
118
- setState((prev) => __spreadProps(__spreadValues({}, prev), {
119
- context: __spreadProps(__spreadValues({}, prev.context), {
120
- loadingOldMessages: true
121
- }),
122
- value: MainState.FetchMoreMessages
123
- }));
124
- } else if (event.type === Actions.SET_IMAGE) {
125
- setState((prev) => {
126
- var _a2, _b2, _c2;
127
- return __spreadProps(__spreadValues({}, prev), {
128
- context: __spreadProps(__spreadValues({}, prev.context), {
129
- selectedImage: ((_a2 = event.data) == null ? void 0 : _a2.image) || "",
130
- images: ((_b2 = event.data) == null ? void 0 : _b2.images) || [],
131
- files: ((_c2 = event.data) == null ? void 0 : _c2.files) || [],
132
- imageLoading: false
133
- })
134
- });
135
- });
136
- } else if (event.type === Actions.CLEAR_IMAGE) {
137
- setState((prev) => __spreadProps(__spreadValues({}, prev), {
138
- context: __spreadProps(__spreadValues({}, prev.context), {
139
- selectedImage: "",
140
- images: [],
141
- files: []
142
- })
143
- }));
144
- } else if (event.type === Actions.START_LOADING) {
145
- setState((prev) => __spreadProps(__spreadValues({}, prev), {
146
- context: __spreadProps(__spreadValues({}, prev.context), {
147
- loading: true
148
- })
149
- }));
150
- } else if (event.type === Actions.STOP_LOADING) {
151
- setState((prev) => {
152
- var _a2;
153
- return __spreadProps(__spreadValues({}, prev), {
154
- context: __spreadProps(__spreadValues({}, prev.context), {
155
- loading: false,
156
- loadingOldMessages: ((_a2 = event.data) == null ? void 0 : _a2.loadingOldMessages) === false ? false : prev.context.loadingOldMessages
157
- })
158
- });
159
- });
160
- } else if (event.type === Actions.SEND_THREAD_MESSAGE) {
161
- console.log("Sending message event with text:", (_a = event.data) == null ? void 0 : _a.messageText);
162
- setState((prev) => {
163
- var _a2;
164
- return __spreadProps(__spreadValues({}, prev), {
165
- context: __spreadProps(__spreadValues({}, prev.context), {
166
- loading: true,
167
- messageText: ((_a2 = event.data) == null ? void 0 : _a2.messageText) || prev.context.messageText
168
- }),
169
- value: MainState.SendThreadMessage
170
- });
171
- });
172
- } else if (event.type === Actions.SEND_THREAD_MESSAGE_WITH_FILE) {
173
- console.log("Sending message with file event, text:", (_b = event.data) == null ? void 0 : _b.messageText);
174
- setState((prev) => {
175
- var _a2;
176
- return __spreadProps(__spreadValues({}, prev), {
177
- context: __spreadProps(__spreadValues({}, prev.context), {
178
- loading: true,
179
- messageText: ((_a2 = event.data) == null ? void 0 : _a2.messageText) || prev.context.messageText
180
- }),
181
- value: MainState.SendThreadMessageWithFile
182
- });
183
- });
184
- } else if (event.type === "SEND_THREAD_MESSAGE_SUCCESS" || event.type === "SEND_THREAD_MESSAGE_WITH_FILE_SUCCESS") {
185
- console.log("Handling send success event:", event.type, "with message:", (_d = (_c = event.data) == null ? void 0 : _c.message) == null ? void 0 : _d.id);
186
- setState((prev) => {
187
- var _a2;
188
- if (!((_a2 = event.data) == null ? void 0 : _a2.message)) {
189
- console.warn("Send success event without message data");
190
- return __spreadProps(__spreadValues({}, prev), {
191
- context: __spreadProps(__spreadValues({}, prev.context), {
192
- loading: false,
193
- messageText: "",
194
- images: [],
195
- selectedImage: "",
196
- files: []
197
- }),
198
- value: "active"
199
- });
200
- }
201
- const newMessage = event.data.message;
202
- const updatedMessages = [newMessage, ...prev.context.threadMessages];
203
- console.log("Updated thread messages list after send, now has", updatedMessages.length, "messages");
204
- return __spreadProps(__spreadValues({}, prev), {
205
- context: __spreadProps(__spreadValues({}, prev.context), {
206
- loading: false,
207
- messageText: "",
208
- images: [],
209
- selectedImage: "",
210
- files: [],
211
- threadMessages: updatedMessages,
212
- totalCount: prev.context.totalCount + 1
213
- }),
214
- value: "active"
215
- });
216
- });
217
- } else if (event.type === "FETCH_MORE_MESSAGES_SUCCESS") {
218
- setState((prev) => {
219
- var _a2, _b2;
220
- const newMessages = ((_a2 = event.data) == null ? void 0 : _a2.messages) || [];
221
- const apiTotalCount = (_b2 = event.data) == null ? void 0 : _b2.totalCount;
222
- console.log(`Merging ${newMessages.length} older messages with ${prev.context.threadMessages.length} existing messages`);
223
- if (newMessages.length > 0) {
224
- try {
225
- console.log("First new message date:", !isNaN(new Date(newMessages[0].createdAt).getTime()) ? new Date(newMessages[0].createdAt).toISOString() : "Invalid date");
226
- console.log("Last new message date:", !isNaN(new Date(newMessages[newMessages.length - 1].createdAt).getTime()) ? new Date(newMessages[newMessages.length - 1].createdAt).toISOString() : "Invalid date");
227
- } catch (error) {
228
- console.error("Error logging new message dates:", error);
229
- }
230
- }
231
- if (prev.context.threadMessages.length > 0) {
232
- try {
233
- console.log("First existing message date:", !isNaN(new Date(prev.context.threadMessages[0].createdAt).getTime()) ? new Date(prev.context.threadMessages[0].createdAt).toISOString() : "Invalid date");
234
- console.log("Last existing message date:", !isNaN(new Date(prev.context.threadMessages[prev.context.threadMessages.length - 1].createdAt).getTime()) ? new Date(prev.context.threadMessages[prev.context.threadMessages.length - 1].createdAt).toISOString() : "Invalid date");
235
- } catch (error) {
236
- console.error("Error logging existing message dates:", error);
237
- }
238
- }
239
- if (newMessages.length === 0 && prev.context.totalCount > prev.context.threadMessages.length) {
240
- console.log("No new messages found despite totalCount indicating more should exist");
241
- return __spreadProps(__spreadValues({}, prev), {
242
- context: __spreadProps(__spreadValues({}, prev.context), {
243
- loadingOldMessages: false,
244
- totalCount: prev.context.threadMessages.length
245
- }),
246
- value: "active"
247
- });
248
- }
249
- const combinedMessages = uniqBy([...prev.context.threadMessages, ...newMessages], "id");
250
- const sortedMessages = orderBy(combinedMessages, [(msg) => {
251
- try {
252
- return !isNaN(new Date(msg.createdAt).getTime()) ? new Date(msg.createdAt).getTime() : 0;
253
- } catch (error) {
254
- console.error(`Error sorting message by date: ${msg.id}`, error);
255
- return 0;
256
- }
257
- }], ["desc"]);
258
- const newTotalCount = typeof apiTotalCount === "number" ? apiTotalCount : Math.max(sortedMessages.length, prev.context.totalCount);
259
- console.log(`Total messages after merge and sort: ${sortedMessages.length}, totalCount: ${newTotalCount}`);
260
- return __spreadProps(__spreadValues({}, prev), {
261
- context: __spreadProps(__spreadValues({}, prev.context), {
262
- loadingOldMessages: false,
263
- threadMessages: sortedMessages,
264
- totalCount: newTotalCount
265
- }),
266
- value: "active"
267
- });
268
- });
269
- } else if (event.type === "ERROR") {
270
- setState((prev) => {
271
- var _a2;
272
- return __spreadProps(__spreadValues({}, prev), {
273
- context: __spreadProps(__spreadValues({}, prev.context), {
274
- loading: false,
275
- loadingOldMessages: false,
276
- error: ((_a2 = event.data) == null ? void 0 : _a2.message) || "Unknown error"
277
- }),
278
- value: "error"
279
- });
280
- });
281
- }
282
- } catch (error) {
283
- console.error("Error in thread conversation send function:", error);
284
- }
34
+ const ErrorNotification = ({
35
+ message,
36
+ onClose
37
+ }) => {
38
+ const opacity = useRef(new Animated.Value(0)).current;
39
+ useEffect(() => {
40
+ Animated.timing(opacity, {
41
+ toValue: 1,
42
+ duration: 300,
43
+ useNativeDriver: true
44
+ }).start();
45
+ const timer = setTimeout(() => {
46
+ Animated.timing(opacity, {
47
+ toValue: 0,
48
+ duration: 300,
49
+ useNativeDriver: true
50
+ }).start(() => onClose && onClose());
51
+ }, 4e3);
52
+ return () => clearTimeout(timer);
285
53
  }, []);
286
- const stateWithMatches = useMemo(() => {
287
- return __spreadProps(__spreadValues({}, state), {
288
- matches: (checkState) => {
289
- return state.value === checkState;
290
- }
291
- });
292
- }, [state]);
293
- return [stateWithMatches, send];
294
- }
54
+ return /* @__PURE__ */ React__default.createElement(Animated.View, { style: {
55
+ position: "absolute",
56
+ top: 10,
57
+ left: 10,
58
+ right: 10,
59
+ backgroundColor: "#f44336",
60
+ padding: 15,
61
+ borderRadius: 8,
62
+ shadowColor: "#000",
63
+ shadowOffset: {
64
+ width: 0,
65
+ height: 2
66
+ },
67
+ shadowOpacity: 0.25,
68
+ shadowRadius: 3.84,
69
+ elevation: 5,
70
+ zIndex: 1e3,
71
+ opacity
72
+ } }, /* @__PURE__ */ React__default.createElement(HStack, { className: "items-center justify-between" }, /* @__PURE__ */ React__default.createElement(Text, { style: {
73
+ color: "white",
74
+ fontWeight: "bold"
75
+ } }, "Upload Failed"), /* @__PURE__ */ React__default.createElement(TouchableOpacity, { onPress: onClose }, /* @__PURE__ */ React__default.createElement(Ionicons, { name: "close", size: 20, color: "white" }))), /* @__PURE__ */ React__default.createElement(Text, { style: {
76
+ color: "white",
77
+ marginTop: 5
78
+ } }, message));
79
+ };
80
+ const isValidFileUrl = (url) => {
81
+ return !!url && typeof url === "string" && url.length > 0;
82
+ };
295
83
  const ThreadConversationViewComponent = ({
296
84
  channelId,
297
85
  postParentId,
298
86
  isPostParentIdThread,
299
87
  role
300
88
  }) => {
301
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
89
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
302
90
  const {
303
91
  params
304
92
  } = useRoute();
305
93
  const [channelToTop, setChannelToTop] = useState(0);
306
- useRef(true);
307
- const [state, send] = useSafeMachine();
308
- useCallback(() => {
309
- try {
310
- return (state == null ? void 0 : state.context) || {};
311
- } catch (error) {
312
- console.error("Error accessing state.context:", error);
313
- return {};
314
- }
315
- }, [state]);
316
- const safeContextProperty = useCallback((property, defaultValue = null) => {
317
- var _a2, _b2;
318
- try {
319
- return (_b2 = (_a2 = state == null ? void 0 : state.context) == null ? void 0 : _a2[property]) != null ? _b2 : defaultValue;
320
- } catch (error) {
321
- console.error(`Error accessing state.context.${property}:`, error);
322
- return defaultValue;
323
- }
324
- }, [state]);
325
- const safeMatches = useCallback((stateValue) => {
326
- var _a2;
327
- try {
328
- return ((_a2 = state == null ? void 0 : state.matches) == null ? void 0 : _a2.call(state, stateValue)) || false;
329
- } catch (error) {
330
- console.error(`Error calling state.matches with ${stateValue}:`, error);
331
- return false;
332
- }
333
- }, [state]);
334
- const safeSend = useCallback((event) => {
335
- try {
336
- send(event);
337
- } catch (error) {
338
- console.error("Error sending event to state machine:", error, event);
339
- }
340
- }, [send]);
341
- const stateRef = useRef(state);
342
- useEffect(() => {
343
- stateRef.current = state;
344
- }, [state]);
94
+ const [channelMessages, setChannelMessages] = useState([]);
345
95
  const auth = useSelector(userSelector);
346
- const [selectedImage, setImage] = useState("");
96
+ const [totalCount, setTotalCount] = useState(0);
97
+ const [selectedImage, setSelectedImage] = useState("");
98
+ const [loadingOldMessages, setLoadingOldMessages] = useState(false);
99
+ const [loadEarlierMsg, setLoadEarlierMsg] = useState(false);
347
100
  const navigation = useNavigation();
348
101
  const [files, setFiles] = useState([]);
349
102
  const [images, setImages] = useState([]);
103
+ const [msg, setMsg] = useState("");
104
+ const [loading, setLoading] = useState(false);
105
+ const [imageLoading, setImageLoading] = useState(false);
106
+ const [uploadingMessageId, setUploadingMessageId] = useState(null);
107
+ const [expoTokens, setExpoTokens] = useState([]);
350
108
  const [isShowImageViewer, setImageViewer] = useState(false);
351
109
  const [imageObject, setImageObject] = useState({});
352
110
  const [parentId, setParentId] = useState(postParentId);
353
- const [expoTokens, setExpoTokens] = useState([]);
354
- const threadMessageListRef = useRef(null);
355
- const [sendThreadMessage] = useCreatePostThreadMutation();
356
- const [sendExpoNotificationOnPostMutation] = useSendExpoNotificationOnPostMutation();
111
+ const [postThread, setPostThread] = useState();
357
112
  const {
358
113
  startUpload
359
114
  } = useUploadFilesNative();
115
+ const [threadPost, setThreadPost] = useState([]);
116
+ const [isScrollToBottom, setIsScrollToBottom] = useState(false);
117
+ const threadMessageListRef = useRef(null);
118
+ useToast();
119
+ const [errorMessage, setErrorMessage] = useState("");
120
+ const [isActionSheetVisible, setActionSheetVisible] = useState(false);
121
+ const [textUpdatedInActionSheet, setTextUpdatedInActionSheet] = useState(false);
122
+ const [lastShownMsg, setLastShownMsg] = useState("");
123
+ const textInputRef = useRef(null);
124
+ const [sendThreadMessage] = useCreatePostThread();
125
+ const [sendExpoNotificationOnPostMutation] = useSendExpoNotification();
360
126
  const [getThreadMessages, {
361
127
  data,
362
128
  loading: threadLoading,
363
129
  fetchMore: fetchMoreMessages,
364
130
  refetch: refetchThreadMessages,
365
131
  subscribeToMore
366
- }] = useGetPostThreadLazyQuery({
132
+ }] = useGetPostThreadLazy({
367
133
  fetchPolicy: "cache-and-network"
368
134
  });
369
- const forceRefreshMessages = useCallback(() => {
370
- console.log("Force refreshing all messages");
371
- safeSend({
372
- type: Actions.CLEAR_MESSAGES
373
- });
374
- if (channelId && parentId) {
375
- safeSend({
376
- type: Actions.START_LOADING,
377
- data: {
378
- loading: true
379
- }
380
- });
381
- getThreadMessages({
382
- variables: {
383
- channelId: channelId == null ? void 0 : channelId.toString(),
384
- role: role == null ? void 0 : role.toString(),
385
- postParentId: !parentId || parentId == 0 ? null : parentId == null ? void 0 : parentId.toString(),
386
- selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
387
- limit: 50
388
- }
389
- }).then(({
390
- data: data2
391
- }) => {
392
- var _a2, _b2, _c2;
393
- if (data2 == null ? void 0 : data2.getPostThread) {
394
- const threads = data2.getPostThread;
395
- const threadPost = (_a2 = threads == null ? void 0 : threads.post) != null ? _a2 : [];
396
- const threadReplies = (_b2 = threads == null ? void 0 : threads.replies) != null ? _b2 : [];
397
- const messageTotalCount = (_c2 = threads == null ? void 0 : threads.replyCount) != null ? _c2 : 0;
398
- const messages = [...threadReplies];
399
- console.log(`Force refresh complete. Got ${messages.length} messages of ${messageTotalCount} total`);
400
- safeSend({
401
- type: Actions.SET_THREAD_MESSAGES,
402
- data: {
403
- messages,
404
- totalCount: messageTotalCount,
405
- threadPost,
406
- postThread: threads
407
- }
408
- });
409
- }
410
- }).catch((error) => {
411
- console.error("Error during force refresh:", error);
412
- safeSend({
413
- type: "ERROR",
414
- data: {
415
- message: error.message
416
- }
417
- });
418
- });
419
- }
420
- }, [channelId, parentId, getThreadMessages, safeSend]);
135
+ const [pendingUploads, setPendingUploads] = useState({});
136
+ const [uploadErrors, setUploadErrors] = useState({});
137
+ const [isUploadingImage, setIsUploadingImage] = useState(false);
138
+ const [refreshing, setRefreshing] = useState(false);
421
139
  useFocusEffect(React__default.useCallback(() => {
422
140
  var _a2;
423
141
  navigation.setOptions({
424
142
  title: (_a2 = params == null ? void 0 : params.title) != null ? _a2 : "Thread",
425
- headerLeft: (props) => /* @__PURE__ */ React__default.createElement(Button, { className: "bg-transparent active:bg-gray-200 ", onPress: () => navigation.goBack() }, /* @__PURE__ */ React__default.createElement(MaterialIcons, { size: 20, name: "arrow-back-ios", color: "black" })),
426
- headerRight: () => /* @__PURE__ */ React__default.createElement(Button, { className: "bg-transparent active:bg-gray-200 mr-2", onPress: forceRefreshMessages }, /* @__PURE__ */ React__default.createElement(MaterialIcons, { size: 20, name: "refresh", color: "black" }))
143
+ headerLeft: (props) => /* @__PURE__ */ React__default.createElement(Button, { className: "bg-transparent active:bg-gray-200 ", onPress: () => navigation.goBack() }, /* @__PURE__ */ React__default.createElement(MaterialIcons, { size: 20, name: "arrow-back-ios", color: "black" }))
427
144
  });
428
- if (channelId && postParentId) {
429
- safeSend({
430
- type: Actions.INITIAL_CONTEXT,
431
- data: {
432
- channelId,
433
- postParentId,
434
- role
435
- }
145
+ if (postParentId) {
146
+ refetchThreadMessages({
147
+ channelId: channelId == null ? void 0 : channelId.toString(),
148
+ role: role == null ? void 0 : role.toString(),
149
+ postParentId: postParentId == null ? void 0 : postParentId.toString(),
150
+ selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
151
+ limit: MESSAGES_PER_PAGE
436
152
  });
437
153
  }
438
154
  setParentId(postParentId);
439
155
  return () => {
440
- safeSend({
441
- type: Actions.CLEAR_MESSAGES
442
- });
156
+ setTotalCount(0);
157
+ setChannelMessages([]);
158
+ setThreadPost([]);
443
159
  };
444
- }, [postParentId, forceRefreshMessages]));
445
- useEffect(() => {
446
- if (safeMatches(BaseState.FetchThreadMessages)) {
447
- fetchThreadMessages();
448
- }
449
- }, [state.value]);
450
- useEffect(() => {
451
- if (safeMatches(MainState.FetchMoreMessages)) {
452
- onFetchOld();
453
- }
454
- }, [state.value]);
160
+ }, [postParentId]));
455
161
  useEffect(() => {
456
- if (safeMatches(MainState.SendThreadMessage)) {
457
- const messageText = safeContextProperty("messageText", "");
458
- console.log("Sending message from state transition, text:", messageText);
459
- sendThreadMessageHandler(messageText);
460
- }
461
- }, [state.value]);
462
- useEffect(() => {
463
- if (safeMatches(MainState.SendThreadMessageWithFile)) {
464
- const messageText = safeContextProperty("messageText", "");
465
- const images2 = safeContextProperty("images", []);
466
- sendThreadMessageWithFileHandler(messageText, images2);
467
- }
468
- }, [state.value]);
469
- const fetchThreadMessages = useCallback(() => {
470
162
  if (channelId && parentId) {
471
- console.log("Initial fetch of thread messages using larger limit (50)");
472
163
  getThreadMessages({
473
164
  variables: {
474
165
  channelId: channelId == null ? void 0 : channelId.toString(),
475
166
  role: role == null ? void 0 : role.toString(),
476
167
  postParentId: !parentId || parentId == 0 ? null : parentId == null ? void 0 : parentId.toString(),
477
168
  selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
478
- limit: 50
479
- }
480
- }).then(({
481
- data: data2
482
- }) => {
483
- var _a2, _b2, _c2;
484
- if (data2 == null ? void 0 : data2.getPostThread) {
485
- const threads = data2.getPostThread;
486
- const threadPost = (_a2 = threads == null ? void 0 : threads.post) != null ? _a2 : [];
487
- const threadReplies = (_b2 = threads == null ? void 0 : threads.replies) != null ? _b2 : [];
488
- const messageTotalCount = (_c2 = threads == null ? void 0 : threads.replyCount) != null ? _c2 : 0;
489
- const messages = [...threadReplies];
490
- console.log(`Initial fetch complete. Got ${messages.length} messages of ${messageTotalCount} total`);
491
- safeSend({
492
- type: Actions.SET_THREAD_MESSAGES,
493
- data: {
494
- messages,
495
- totalCount: messageTotalCount,
496
- threadPost,
497
- postThread: threads
498
- }
499
- });
169
+ limit: MESSAGES_PER_PAGE
500
170
  }
501
- }).catch((error) => {
502
- safeSend({
503
- type: "ERROR",
504
- data: {
505
- message: error.message
506
- }
507
- });
508
171
  });
509
172
  }
510
- }, [channelId, parentId, role]);
173
+ }, [parentId]);
511
174
  React__default.useEffect(() => {
512
175
  var _a2, _b2, _c2;
513
176
  if (data == null ? void 0 : data.getPostThread) {
514
177
  const threads = data.getPostThread;
515
- const threadPost = (_a2 = threads == null ? void 0 : threads.post) != null ? _a2 : [];
178
+ const threadPost2 = (_a2 = threads == null ? void 0 : threads.post) != null ? _a2 : [];
516
179
  const threadReplies = (_b2 = threads == null ? void 0 : threads.replies) != null ? _b2 : [];
517
180
  const messeageTotalCount = (_c2 = threads == null ? void 0 : threads.replyCount) != null ? _c2 : 0;
518
- const messages = [...threadReplies];
519
- safeSend({
520
- type: Actions.SET_THREAD_MESSAGES,
521
- data: {
522
- messages,
523
- totalCount: messeageTotalCount,
524
- threadPost,
525
- postThread: threads
526
- }
527
- });
528
- }
529
- }, [data]);
530
- React__default.useEffect(() => {
531
- if (safeContextProperty("selectedImage")) {
532
- safeSend({
533
- type: Actions.STOP_LOADING
534
- });
535
- }
536
- }, [safeContextProperty("selectedImage")]);
537
- React__default.useEffect(() => {
538
- const isLoading = safeContextProperty("loadingOldMessages", false);
539
- if (isLoading) {
540
- console.log("Message loading timeout safety started");
541
- const timeoutId = setTimeout(() => {
542
- if (safeContextProperty("loadingOldMessages", false)) {
543
- console.log("Message loading timed out - resetting state");
544
- safeSend({
545
- type: Actions.STOP_LOADING,
546
- data: {
547
- loadingOldMessages: false
548
- }
549
- });
550
- }
551
- }, 1e4);
552
- return () => clearTimeout(timeoutId);
553
- }
554
- }, [safeContextProperty("loadingOldMessages")]);
555
- const failedLoadAttemptsRef = useRef(0);
556
- const registerLoadAttemptResult = useCallback((success) => {
557
- if (!success) {
558
- failedLoadAttemptsRef.current += 1;
559
- console.log(`Failed load attempt registered, count: ${failedLoadAttemptsRef.current}`);
560
- } else {
561
- failedLoadAttemptsRef.current = 0;
562
- }
563
- }, []);
564
- React__default.useEffect(() => {
565
- const isLoading = safeContextProperty("loadingOldMessages", false);
566
- const totalCount = safeContextProperty("totalCount", 0);
567
- const messagesCount = safeContextProperty("threadMessages", []).length;
568
- if (!isLoading && totalCount > messagesCount) {
569
- if (failedLoadAttemptsRef.current >= 2) {
570
- console.log(`Auto-fixing incorrect message count after ${failedLoadAttemptsRef.current + 1} failed load attempts`);
571
- console.log(`Adjusting totalCount from ${totalCount} to ${messagesCount}`);
572
- safeSend({
573
- type: Actions.SET_THREAD_MESSAGES,
574
- data: {
575
- messages: safeContextProperty("threadMessages", []),
576
- totalCount: messagesCount,
577
- threadPost: safeContextProperty("threadPost", []),
578
- postThread: safeContextProperty("postThread", null)
579
- }
580
- });
581
- failedLoadAttemptsRef.current = 0;
181
+ const messages = [threadPost2, ...threadReplies];
182
+ if (messages && messages.length > 0 && messeageTotalCount > totalCount || messages && messages.length > 0 && channelMessages.length === 0) {
183
+ setThreadMessages(messages, messeageTotalCount);
582
184
  }
583
185
  }
584
- }, [safeContextProperty("loadingOldMessages"), safeContextProperty("threadMessages")]);
585
- React__default.useCallback(() => {
186
+ if (isScrollToBottom && channelMessages) scrollToBottom();
187
+ }, [data, channelMessages, loadingOldMessages, totalCount, isPostParentIdThread, isScrollToBottom]);
188
+ const setThreadMessages = (messages, messagesTotalCount) => {
189
+ setChannelMessages((oldMessages) => uniqBy([...messages, ...oldMessages], ({
190
+ id
191
+ }) => id));
192
+ setTotalCount(messagesTotalCount);
193
+ };
194
+ React__default.useEffect(() => {
195
+ if (selectedImage) setImageLoading(false);
196
+ }, [selectedImage]);
197
+ const scrollToBottom = React__default.useCallback(() => {
586
198
  if (threadMessageListRef == null ? void 0 : threadMessageListRef.current) {
587
- threadMessageListRef.current.scrollToBottom();
199
+ setIsScrollToBottom(false);
200
+ threadMessageListRef.current.scrollTop = threadMessageListRef.current.scrollHeight;
588
201
  }
589
202
  }, [threadMessageListRef]);
590
203
  const onFetchOld = useCallback(() => {
591
- const totalCount = safeContextProperty("totalCount", 0);
592
- const threadMessages = safeContextProperty("threadMessages", []);
593
- if (totalCount > threadMessages.length && !safeContextProperty("loadingOldMessages", false)) {
594
- console.log("Loading more messages - current count:", threadMessages.length, "of", totalCount);
595
- safeSend({
596
- type: Actions.FETCH_MORE_MESSAGES,
597
- data: {
598
- loadingOldMessages: true
599
- }
600
- });
601
- console.log("Using proven approach: Skip=0, Limit=50");
602
- const queryVariables = {
603
- channelId: channelId == null ? void 0 : channelId.toString(),
604
- role: role == null ? void 0 : role.toString(),
605
- postParentId: !parentId || parentId == 0 ? null : parentId == null ? void 0 : parentId.toString(),
606
- selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
607
- limit: 50,
608
- skip: 0
609
- };
610
- console.log("Query variables:", JSON.stringify(queryVariables));
204
+ if (totalCount > channelMessages.length && !loadingOldMessages) {
205
+ setLoadEarlierMsg(true);
206
+ setLoadingOldMessages(true);
611
207
  fetchMoreMessages({
612
- variables: queryVariables
208
+ variables: {
209
+ channelId: channelId == null ? void 0 : channelId.toString(),
210
+ role: role == null ? void 0 : role.toString(),
211
+ postParentId: parentId == null ? void 0 : parentId.toString(),
212
+ selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
213
+ limit: MESSAGES_PER_PAGE,
214
+ skip: channelMessages.length - 1
215
+ }
613
216
  }).then((res) => {
614
217
  var _a2, _b2, _c2, _d2;
615
- console.log("API response received:", JSON.stringify(res == null ? void 0 : res.data, null, 2));
616
218
  if ((_a2 = res == null ? void 0 : res.data) == null ? void 0 : _a2.getPostThread) {
617
219
  const threads = (_b2 = res == null ? void 0 : res.data) == null ? void 0 : _b2.getPostThread;
618
220
  const threadReplies = (_c2 = threads == null ? void 0 : threads.replies) != null ? _c2 : [];
619
- const actualTotalCount = (_d2 = threads == null ? void 0 : threads.replyCount) != null ? _d2 : 0;
620
- console.log("API response details:");
621
- console.log("- replyCount:", threads == null ? void 0 : threads.replyCount);
622
- console.log("- replies array length:", threadReplies.length);
623
- console.log("- replies structure:", threadReplies.length > 0 ? `First item has fields: ${Object.keys(threadReplies[0]).join(", ")}` : "No items");
624
- if (threadReplies.length > 0) {
625
- console.log("- Sample message:", JSON.stringify(threadReplies[0], null, 2));
626
- }
627
- console.log("Successfully loaded more messages:", threadReplies.length, "of total:", actualTotalCount);
628
- console.log("Thread reply IDs:", threadReplies.map((msg) => msg.id).join(", "));
629
- const existingIds = new Set(threadMessages.map((msg) => msg.id));
630
- const newUniqueMessages = threadReplies.filter((msg) => !existingIds.has(msg.id));
631
- console.log(`Found ${newUniqueMessages.length} unique new messages out of ${threadReplies.length} received`);
632
- if (actualTotalCount !== totalCount) {
633
- console.log(`Updating totalCount from ${totalCount} to ${actualTotalCount} based on API response`);
634
- }
635
- if (newUniqueMessages.length === 0) {
636
- console.log("No new unique messages found, adjusting total count");
637
- registerLoadAttemptResult(false);
638
- safeSend({
639
- type: Actions.SET_THREAD_MESSAGES,
640
- data: {
641
- messages: threadMessages,
642
- totalCount: threadMessages.length,
643
- threadPost: safeContextProperty("threadPost", []),
644
- postThread: safeContextProperty("postThread", null)
645
- }
646
- });
647
- return;
648
- }
649
- registerLoadAttemptResult(true);
650
- console.log(`Adding ${newUniqueMessages.length} new messages to thread`);
651
- safeSend({
652
- type: "FETCH_MORE_MESSAGES_SUCCESS",
653
- data: {
654
- messages: newUniqueMessages,
655
- totalCount: actualTotalCount,
656
- loadingOldMessages: false
657
- }
658
- });
659
- } else {
660
- console.log("No thread data returned when loading more messages");
661
- registerLoadAttemptResult(false);
662
- safeSend({
663
- type: Actions.STOP_LOADING,
664
- data: {
665
- loadingOldMessages: false
666
- }
667
- });
221
+ const messeageTotalCount = (_d2 = threads == null ? void 0 : threads.replyCount) != null ? _d2 : 0;
222
+ setThreadMessages(threadReplies, messeageTotalCount);
668
223
  }
224
+ }).finally(() => {
225
+ setLoadEarlierMsg(false);
226
+ setLoadingOldMessages(false);
227
+ setRefreshing(false);
669
228
  }).catch((error) => {
670
- console.error("Error fetching more messages:", error);
671
- registerLoadAttemptResult(false);
672
- safeSend({
673
- type: "ERROR",
674
- data: {
675
- message: error.message,
676
- loadingOldMessages: false
677
- }
678
- });
229
+ setLoadEarlierMsg(false);
230
+ setLoadingOldMessages(false);
231
+ setRefreshing(false);
679
232
  });
680
233
  } else {
681
- console.log("No more messages to load or already loading");
682
- if (safeContextProperty("loadingOldMessages", false)) {
683
- safeSend({
684
- type: Actions.STOP_LOADING,
685
- data: {
686
- loadingOldMessages: false
687
- }
688
- });
689
- }
234
+ setRefreshing(false);
690
235
  }
691
- }, [parentId, channelId, state.context, registerLoadAttemptResult]);
692
- const handleScrollToTop = ({
693
- nativeEvent
694
- }) => {
695
- if (isCloseToTop(nativeEvent)) {
696
- const isLoading = safeContextProperty("loadingOldMessages", false);
697
- const totalCount = safeContextProperty("totalCount", 0);
698
- const currentCount = safeContextProperty("threadMessages", []).length;
699
- const hasMoreMessages = totalCount > currentCount;
700
- console.log(`Scroll near top - Loading state: ${isLoading}, Messages: ${currentCount}/${totalCount}, Has more: ${hasMoreMessages}`);
701
- if (!isLoading && hasMoreMessages) {
702
- console.log("Near top of list - loading older messages");
703
- safeSend({
704
- type: Actions.FETCH_MORE_MESSAGES
705
- });
706
- }
707
- }
708
- };
709
- const handleEndReached = () => {
710
- console.log("Reached end of message list");
711
- };
236
+ }, [parentId, channelId, totalCount, channelMessages]);
237
+ const onRefresh = useCallback(() => {
238
+ setRefreshing(true);
239
+ onFetchOld();
240
+ }, [onFetchOld]);
712
241
  const isCloseToTop = ({
713
242
  layoutMeasurement,
714
243
  contentOffset,
715
244
  contentSize
716
245
  }) => {
717
- const visibleHeight = layoutMeasurement.height;
718
- const topThreshold = Math.min(80, visibleHeight * 0.15);
719
- const distanceFromTop = contentOffset.y;
720
- const totalContentHeight = contentSize.height;
721
- console.log(`Scroll position: ${distanceFromTop.toFixed(0)}px from top, threshold: ${topThreshold.toFixed(0)}px, content height: ${totalContentHeight.toFixed(0)}px`);
722
- return contentOffset.y <= topThreshold;
246
+ const paddingToTop = 60;
247
+ return contentSize.height - layoutMeasurement.height - paddingToTop <= contentOffset.y;
723
248
  };
249
+ const removeMessageFromUI = useCallback((messageId) => {
250
+ setPendingUploads((prev) => {
251
+ const newPending = __spreadValues({}, prev);
252
+ delete newPending[messageId];
253
+ return newPending;
254
+ });
255
+ setUploadErrors((prev) => {
256
+ const newErrors = __spreadValues({}, prev);
257
+ delete newErrors[messageId];
258
+ return newErrors;
259
+ });
260
+ setIsUploadingImage(false);
261
+ }, []);
724
262
  const onSelectImages = async () => {
725
- var _a2;
263
+ setLoading(true);
726
264
  try {
727
- safeSend({
728
- type: Actions.START_LOADING
729
- });
730
- const imageSource = await ImagePicker.launchImageLibraryAsync({
265
+ let imageSource = await ImagePicker.launchImageLibraryAsync({
731
266
  mediaTypes: ImagePicker.MediaTypeOptions.Images,
732
- allowsEditing: true,
267
+ allowsEditing: false,
733
268
  aspect: [4, 3],
734
269
  quality: 0.8,
735
270
  base64: true,
736
- allowsMultipleSelection: false
271
+ exif: false,
272
+ allowsMultipleSelection: true
273
+ // Enable multiple selection
737
274
  });
738
- if (imageSource.canceled) {
739
- console.log("Image selection was canceled");
740
- safeSend({
741
- type: Actions.STOP_LOADING
742
- });
743
- return;
744
- }
745
- if (!imageSource.assets || imageSource.assets.length === 0 || !((_a2 = imageSource.assets[0]) == null ? void 0 : _a2.base64)) {
746
- console.error("No valid image data received");
747
- safeSend({
748
- type: "ERROR",
749
- data: {
750
- message: "No valid image data received"
751
- }
275
+ if (!(imageSource == null ? void 0 : imageSource.canceled)) {
276
+ const selectedAssets = (imageSource == null ? void 0 : imageSource.assets) || [];
277
+ if (selectedAssets.length === 0) {
278
+ setLoading(false);
279
+ return;
280
+ }
281
+ const newImages = selectedAssets.map((selectedAsset) => {
282
+ const base64Data = selectedAsset.base64;
283
+ const previewImage = base64Data ? `data:image/jpeg;base64,${base64Data}` : selectedAsset.uri;
284
+ const asset = __spreadProps(__spreadValues({}, selectedAsset), {
285
+ url: selectedAsset.uri,
286
+ fileName: selectedAsset.fileName || `image_${Date.now()}.jpg`,
287
+ mimeType: "image/jpeg"
288
+ });
289
+ return asset;
752
290
  });
753
- return;
754
- }
755
- const asset = imageSource.assets[0];
756
- const fileExtension = asset.mimeType ? asset.mimeType.split("/").pop() || "jpg" : "jpg";
757
- const filename = `image_${Date.now()}.${fileExtension}`;
758
- const mimeType = asset.mimeType || "image/jpeg";
759
- const image = `data:${mimeType};base64,${asset.base64}`;
760
- const fileData = {
761
- uri: asset.uri,
762
- type: mimeType,
763
- name: filename,
764
- base64: asset.base64
765
- };
766
- console.log(`Selected image: ${filename}, type: ${mimeType}`);
767
- safeSend({
768
- type: Actions.SET_IMAGE,
769
- data: {
770
- image,
771
- files: [fileData],
772
- images: [asset]
291
+ if (newImages.length > 0) {
292
+ const base64Data = newImages[0].base64;
293
+ const previewImage = base64Data ? `data:image/jpeg;base64,${base64Data}` : newImages[0].uri;
294
+ setSelectedImage(previewImage);
773
295
  }
774
- });
296
+ setImages((currentImages) => [...currentImages, ...newImages]);
297
+ setLoading(false);
298
+ } else {
299
+ setLoading(false);
300
+ }
775
301
  } catch (error) {
776
- console.error("Error selecting image:", error);
777
- safeSend({
778
- type: "ERROR",
779
- data: {
780
- message: error.message || "Failed to select image"
781
- }
782
- });
302
+ setLoading(false);
783
303
  }
784
304
  };
785
- const sendThreadMessageHandler = useCallback(async (message) => {
786
- var _a2, _b2;
787
- console.log("Sending message:", message);
788
- if (!channelId) {
789
- console.error("No channelId provided");
790
- return;
305
+ useCallback(() => {
306
+ setLastShownMsg(msg);
307
+ setActionSheetVisible(true);
308
+ }, [msg]);
309
+ useCallback(() => {
310
+ setActionSheetVisible(false);
311
+ if (!textUpdatedInActionSheet) {
312
+ setMsg(lastShownMsg);
313
+ }
314
+ setTextUpdatedInActionSheet(false);
315
+ }, [textUpdatedInActionSheet, lastShownMsg]);
316
+ useEffect(() => {
317
+ if (isActionSheetVisible && Platform.OS === "ios") {
318
+ Keyboard.dismiss();
791
319
  }
792
- const messageContent = (message == null ? void 0 : message.trim()) || " ";
793
- console.log("Using message content for sending:", messageContent);
320
+ }, [isActionSheetVisible]);
321
+ const [isGiftedInputFocused, setIsGiftedInputFocused] = useState(false);
322
+ const handleSend = useCallback(async (message) => {
323
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2;
324
+ const newMessageText = message && message.length > 0 ? message || " " : " ";
325
+ if (!channelId) return;
326
+ const hasText = newMessageText !== " ";
327
+ const hasImages = images && images.length > 0;
328
+ if (!hasText && !hasImages) return;
329
+ setLoading(true);
794
330
  const postId = objectId();
795
- console.log("Generated postId:", postId);
796
- safeSend({
797
- type: Actions.START_LOADING
798
- });
331
+ const currentDate = /* @__PURE__ */ new Date();
332
+ const currentMessageText = message || "";
333
+ const currentImages = [...images];
334
+ setMsg("");
335
+ setSelectedImage("");
336
+ setImages([]);
337
+ setFiles([]);
338
+ if (isActionSheetVisible) {
339
+ setActionSheetVisible(false);
340
+ }
341
+ const optimisticMessage = {
342
+ id: postId,
343
+ message: currentMessageText || (currentImages.length > 0 ? " " : ""),
344
+ createdAt: currentDate.toISOString(),
345
+ author: {
346
+ id: (_a2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _a2.id,
347
+ givenName: (_b2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _b2.given_name,
348
+ familyName: (_c2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _c2.family_name,
349
+ picture: (_d2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _d2.picture
350
+ },
351
+ isDelivered: false,
352
+ // Mark as not delivered yet during upload
353
+ isRead: false,
354
+ isOptimistic: true,
355
+ // Flag to identify optimistic messages
356
+ files: currentImages.length > 0 ? {
357
+ data: currentImages.filter((img) => img && (img.uri || img.url)).map((img) => ({
358
+ id: objectId(),
359
+ url: img.uri || img.url,
360
+ localUri: img.uri || img.url,
361
+ // Keep local URI for preview
362
+ name: img.fileName || `image_${Date.now()}.jpg`,
363
+ extension: "jpg",
364
+ mimeType: "image/jpeg",
365
+ refType: FileRefType.Post,
366
+ height: img.height || 0,
367
+ width: img.width || 0,
368
+ isUploading: true
369
+ // Flag to indicate this file is uploading
370
+ })),
371
+ totalCount: currentImages.filter((img) => img && (img.uri || img.url)).length
372
+ // Only count valid images
373
+ } : void 0
374
+ };
375
+ if (optimisticMessage.message && optimisticMessage.message.trim() !== "" || optimisticMessage.files && optimisticMessage.files.data && optimisticMessage.files.data.length > 0) {
376
+ setChannelMessages((oldMessages) => uniqBy([optimisticMessage, ...oldMessages], ({
377
+ id
378
+ }) => id));
379
+ setIsScrollToBottom(true);
380
+ }
799
381
  try {
800
- console.log("Sending mutation with variables:", {
801
- channelId,
802
- postThreadId: (_a2 = safeContextProperty("postThread")) == null ? void 0 : _a2.id,
803
- postParentId: !parentId || parentId == 0 ? null : parentId,
804
- message: messageContent
805
- });
806
- const result = await sendThreadMessage({
382
+ let fileIds = null;
383
+ if (currentImages && currentImages.length > 0) {
384
+ const validImages = currentImages.filter((img) => img && (img.uri || img.url));
385
+ if (validImages.length === 0) {
386
+ setIsUploadingImage(false);
387
+ } else {
388
+ setIsUploadingImage(true);
389
+ const imagesToUpload = validImages.map((img) => {
390
+ return __spreadProps(__spreadValues({}, img), {
391
+ uri: img.uri || img.url,
392
+ // Use either uri or url
393
+ type: img.mimeType || "image/jpeg",
394
+ name: img.fileName || `image_${Date.now()}.jpg`
395
+ });
396
+ });
397
+ setUploadingMessageId(postId);
398
+ setPendingUploads((prev) => __spreadProps(__spreadValues({}, prev), {
399
+ [postId]: {
400
+ images: validImages,
401
+ message: currentMessageText
402
+ }
403
+ }));
404
+ const uploadResponse = await startUpload({
405
+ file: imagesToUpload,
406
+ saveUploadedFile: {
407
+ variables: {
408
+ postId
409
+ }
410
+ },
411
+ createUploadLink: {
412
+ variables: {
413
+ postId
414
+ }
415
+ }
416
+ });
417
+ if (uploadResponse == null ? void 0 : uploadResponse.error) {
418
+ throw new Error(uploadResponse.error.toString());
419
+ }
420
+ const uploadedFiles = uploadResponse.data;
421
+ if (uploadResponse.data) {
422
+ fileIds = (_e2 = uploadedFiles == null ? void 0 : uploadedFiles.map((f) => f.id)) != null ? _e2 : null;
423
+ setChannelMessages((oldMessages) => {
424
+ return oldMessages.map((msg2) => {
425
+ if (msg2.id === postId && msg2.isOptimistic) {
426
+ return __spreadProps(__spreadValues({}, msg2), {
427
+ isOptimistic: false,
428
+ files: __spreadProps(__spreadValues({}, msg2.files), {
429
+ data: uploadedFiles.filter((file) => isValidFileUrl(file.url)).map((file, index) => __spreadProps(__spreadValues({}, msg2.files.data[index]), {
430
+ url: file.url,
431
+ isUploading: false
432
+ }))
433
+ })
434
+ });
435
+ }
436
+ return msg2;
437
+ });
438
+ });
439
+ }
440
+ setPendingUploads((prev) => {
441
+ const newPending = __spreadValues({}, prev);
442
+ delete newPending[postId];
443
+ return newPending;
444
+ });
445
+ }
446
+ }
447
+ await sendThreadMessage({
807
448
  variables: {
449
+ postId,
808
450
  channelId,
809
- postThreadId: safeContextProperty("postThread") && ((_b2 = safeContextProperty("postThread")) == null ? void 0 : _b2.id),
810
- postParentId: !parentId || parentId == 0 ? null : parentId,
451
+ postThreadId: postThread && (postThread == null ? void 0 : postThread.id),
452
+ postParentId: !parentId || parentId === 0 ? null : parentId,
811
453
  threadMessageInput: {
812
- content: messageContent,
454
+ content: currentMessageText,
455
+ files: fileIds,
813
456
  role
814
457
  }
815
458
  },
459
+ optimisticResponse: {
460
+ createPostThread: {
461
+ __typename: "ThreadMessageSent",
462
+ lastMessage: {
463
+ __typename: "Post",
464
+ id: postId,
465
+ message: currentMessageText || " ",
466
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
467
+ author: {
468
+ __typename: "UserAccount",
469
+ id: (_f2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _f2.id,
470
+ givenName: (_g2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _g2.given_name,
471
+ familyName: (_h2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _h2.family_name,
472
+ picture: (_i2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _i2.picture
473
+ },
474
+ channel: {
475
+ __typename: "Channel",
476
+ id: channelId.toString()
477
+ }
478
+ },
479
+ // Type assertion to avoid TypeScript errors
480
+ data: {
481
+ __typename: "PostThread",
482
+ id: (postThread == null ? void 0 : postThread.id) || objectId()
483
+ }
484
+ }
485
+ },
816
486
  update: (cache, {
817
487
  data: data2,
818
488
  errors
819
489
  }) => {
820
- var _a3, _b3, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2;
821
- console.log("Send message update callback - data:", data2, "errors:", errors);
822
- if (!data2 || errors) {
823
- console.error("Send message failed:", errors);
824
- safeSend({
825
- type: Actions.STOP_LOADING
826
- });
827
- return;
828
- }
829
- console.log("Message sent successfully:", (_a3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _a3.lastMessage);
830
- const newMessage = (_b3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _b3.lastMessage;
831
- safeSend({
832
- type: "SEND_THREAD_MESSAGE_SUCCESS",
833
- data: {
834
- message: newMessage,
835
- messageText: ""
836
- }
837
- });
838
- if (!parentId || parentId == 0) {
839
- console.log("Setting new parentId:", (_d2 = (_c2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _c2.lastMessage) == null ? void 0 : _d2.id);
840
- setParentId((_f2 = (_e2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _e2.lastMessage) == null ? void 0 : _f2.id);
490
+ var _a3, _b3, _c3, _d3, _e3, _f3, _g3;
491
+ if (!data2 || errors) return;
492
+ setPostThread((_a3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _a3.data);
493
+ const lastMessageId = (_c3 = (_b3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _b3.lastMessage) == null ? void 0 : _c3.id;
494
+ if (!parentId || parentId === 0) {
495
+ setParentId((_e3 = (_d3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _d3.lastMessage) == null ? void 0 : _e3.id);
841
496
  }
842
497
  setChannelToTop(channelToTop + 1);
843
- const lastMessageId = (_h2 = (_g2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _g2.lastMessage) == null ? void 0 : _h2.id;
844
- sendPushNotification(lastMessageId, channelId, parentId, (_j2 = (_i2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _i2.data) == null ? void 0 : _j2.id);
498
+ sendPushNotification(lastMessageId, channelId, parentId, (_g3 = (_f3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _f3.data) == null ? void 0 : _g3.id);
845
499
  }
846
500
  });
847
- console.log("Send mutation result:", result);
848
501
  } catch (error) {
849
502
  console.error("Error sending message:", error);
850
- safeSend({
851
- type: "ERROR",
852
- data: {
853
- message: error.message || "Failed to send message"
503
+ let formattedErrorMessage = "Failed to upload image. Please try again.";
504
+ if (__DEV__) {
505
+ if (error.name === "ApolloError") {
506
+ formattedErrorMessage = error.message.replace("[ApolloError: ", "").replace("]", "").split(";")[0];
507
+ } else {
508
+ formattedErrorMessage = error.message || "Unknown error occurred";
854
509
  }
855
- });
856
- }
857
- }, [channelId, parentId, state.context, role]);
858
- const sendThreadMessageWithFileHandler = useCallback(async (message, images2) => {
859
- var _a2, _b2;
860
- console.log("Sending message with file:", message, "Images:", images2.length);
861
- if (!channelId) {
862
- console.error("No channelId provided");
863
- return;
864
- }
865
- if (images2.length === 0) {
866
- console.error("No images to send");
867
- return;
868
- }
869
- const messageContent = (message == null ? void 0 : message.trim()) || " ";
870
- console.log("Using message content for file send:", messageContent);
871
- const postId = objectId();
872
- console.log("Generated postId for file upload:", postId);
873
- try {
874
- const preparedImages = images2.map((img) => ({
875
- uri: img.uri,
876
- type: img.mimeType || "image/jpeg",
877
- name: img.fileName || `image_${Date.now()}.jpg`,
878
- base64: img.base64,
879
- width: img.width || 0,
880
- height: img.height || 0
881
- }));
882
- console.log("Starting file upload with prepared images:", preparedImages.length);
883
- const uploadResponse = await startUpload({
884
- file: preparedImages,
885
- saveUploadedFile: {
886
- variables: {
887
- postId
888
- }
889
- },
890
- createUploadLink: {
891
- variables: {
892
- postId
893
- }
510
+ } else {
511
+ if (((_j2 = error.message) == null ? void 0 : _j2.includes("network")) || ((_k2 = error.message) == null ? void 0 : _k2.includes("timeout"))) {
512
+ formattedErrorMessage = "Network error. Please check your connection.";
513
+ } else if ((_l2 = error.message) == null ? void 0 : _l2.includes("permission")) {
514
+ formattedErrorMessage = "Permission denied for this operation.";
894
515
  }
895
- });
896
- if (uploadResponse == null ? void 0 : uploadResponse.error) {
897
- console.error("File upload failed:", uploadResponse.error);
898
- safeSend({
899
- type: Actions.STOP_LOADING
900
- });
901
- return;
902
516
  }
903
- const uploadedFiles = uploadResponse.data;
904
- console.log("Files uploaded successfully:", uploadedFiles == null ? void 0 : uploadedFiles.length);
905
- if (uploadResponse.data) {
906
- const files2 = (_a2 = uploadedFiles == null ? void 0 : uploadedFiles.map((f) => f.id)) != null ? _a2 : null;
907
- console.log("File IDs for message:", files2);
908
- console.log("Sending message with attached files");
909
- const result = await sendThreadMessage({
910
- variables: {
911
- postId,
912
- channelId,
913
- postThreadId: safeContextProperty("postThread") && ((_b2 = safeContextProperty("postThread")) == null ? void 0 : _b2.id),
914
- postParentId: !parentId || parentId == 0 ? null : parentId,
915
- threadMessageInput: {
916
- content: messageContent,
917
- files: files2,
918
- role
919
- }
920
- },
921
- update: (cache, {
922
- data: data2,
923
- errors
924
- }) => {
925
- var _a3, _b3, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2;
926
- console.log("Send message with file update callback - data:", data2, "errors:", errors);
927
- if (!data2 || errors) {
928
- console.error("Send message with file failed:", errors);
929
- safeSend({
930
- type: Actions.STOP_LOADING
931
- });
932
- return;
933
- }
934
- console.log("Message with file sent successfully:", (_a3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _a3.lastMessage);
935
- const newMessage = (_b3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _b3.lastMessage;
936
- safeSend({
937
- type: "SEND_THREAD_MESSAGE_WITH_FILE_SUCCESS",
938
- data: {
939
- message: newMessage,
940
- messageText: ""
941
- }
942
- });
943
- if (!parentId || parentId == 0) {
944
- console.log("Setting new parentId:", (_d2 = (_c2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _c2.lastMessage) == null ? void 0 : _d2.id);
945
- setParentId((_f2 = (_e2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _e2.lastMessage) == null ? void 0 : _f2.id);
946
- }
947
- setChannelToTop(channelToTop + 1);
948
- const lastMessageId = (_h2 = (_g2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _g2.lastMessage) == null ? void 0 : _h2.id;
949
- sendPushNotification(lastMessageId, channelId, parentId, (_j2 = (_i2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _i2.data) == null ? void 0 : _j2.id);
950
- }
951
- });
952
- console.log("Send with file mutation result:", result);
953
- }
954
- } catch (error) {
955
- console.error("Error sending message with file:", error);
956
- safeSend({
957
- type: "ERROR",
958
- data: {
959
- message: error.message || "Failed to send message with file"
960
- }
961
- });
517
+ setErrorMessage(formattedErrorMessage);
518
+ setChannelMessages((oldMessages) => oldMessages.filter((msg2) => msg2.id !== postId));
519
+ removeMessageFromUI(postId);
520
+ } finally {
521
+ setLoading(false);
522
+ setIsUploadingImage(false);
523
+ setUploadingMessageId(null);
962
524
  }
963
- }, [channelId, parentId, state.context, role, startUpload]);
525
+ }, [auth, channelId, channelToTop, images, parentId, postThread, selectedImage, setChannelMessages, removeMessageFromUI, role]);
964
526
  const sendPushNotification = async (messageId, channelId2, parentId2, threadId) => {
965
527
  var _a2;
966
528
  const notificationData = {
@@ -989,111 +551,264 @@ const ThreadConversationViewComponent = ({
989
551
  }
990
552
  };
991
553
  const messageList = useMemo(() => {
992
- const threadMessages = safeContextProperty("threadMessages", []);
993
- console.log(`Creating message list from ${threadMessages.length} thread messages`);
994
554
  let res = [];
995
- if (threadMessages == null ? void 0 : threadMessages.length) {
996
- const messageIds = /* @__PURE__ */ new Set();
997
- res = threadMessages.filter((msg) => {
998
- if (!msg.id || messageIds.has(msg.id)) {
999
- console.log("Skipping duplicate message ID:", msg.id);
1000
- return false;
1001
- }
1002
- messageIds.add(msg.id);
1003
- return true;
1004
- }).map((msg) => {
1005
- var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2;
1006
- const uniqueId = msg.id || `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1007
- let messageDate;
1008
- try {
1009
- if (msg.createdAt && !isNaN(new Date(msg.createdAt).getTime())) {
1010
- messageDate = new Date(msg.createdAt);
1011
- } else {
1012
- console.warn(`Invalid date value for message ${msg.id}: ${msg.createdAt}`);
1013
- messageDate = new Date();
1014
- }
1015
- } catch (error) {
1016
- console.error(`Error creating date for message ${msg.id}:`, error);
1017
- messageDate = new Date();
1018
- }
1019
- let imageUrl = null;
1020
- if (((_a2 = msg.files) == null ? void 0 : _a2.data) && msg.files.data.length > 0) {
1021
- const fileData = msg.files.data[0];
1022
- if (fileData && fileData.url) {
1023
- imageUrl = fileData.url;
1024
- console.log("\u{1F4F7} Found image URL for message", msg.id, ":", imageUrl);
1025
- }
1026
- }
1027
- let messageText = msg.message || "";
555
+ const filteredMessages = channelMessages && (channelMessages == null ? void 0 : channelMessages.length) > 0 ? uniqBy([...channelMessages], ({
556
+ id
557
+ }) => id) : [];
558
+ if (filteredMessages == null ? void 0 : filteredMessages.length) {
559
+ orderBy(filteredMessages, ["createdAt"], ["desc"]).map((msg2) => {
560
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2, _p2;
1028
561
  let message = {
1029
- _id: uniqueId,
1030
- text: messageText,
1031
- createdAt: messageDate,
562
+ _id: "",
563
+ text: "",
564
+ createdAt: 0,
1032
565
  user: {
1033
- _id: (_d2 = (_b2 = msg == null ? void 0 : msg.author) == null ? void 0 : _b2.id) != null ? _d2 : (_c2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _c2.id,
1034
- name: (_j2 = (_h2 = (_e2 = msg == null ? void 0 : msg.author) == null ? void 0 : _e2.givenName) != null ? _h2 : ((_f2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _f2.given_name) + " " + ((_g2 = msg == null ? void 0 : msg.author) == null ? void 0 : _g2.familyName)) != null ? _j2 : (_i2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _i2.family_name,
1035
- avatar: (_m2 = (_k2 = msg == null ? void 0 : msg.author) == null ? void 0 : _k2.picture) != null ? _m2 : (_l2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _l2.picture
566
+ _id: "",
567
+ name: "",
568
+ avatar: ""
1036
569
  },
1037
- type: (msg == null ? void 0 : msg.type) || "",
1038
- image: imageUrl,
1039
- sent: (msg == null ? void 0 : msg.isDelivered) || true,
1040
- received: (msg == null ? void 0 : msg.isRead) || false,
1041
- propsConfiguration: msg == null ? void 0 : msg.propsConfiguration
570
+ type: ""
1042
571
  };
1043
- return message;
572
+ const date = new Date(msg2.createdAt);
573
+ message._id = msg2.id;
574
+ message.text = msg2.message;
575
+ message.createdAt = date;
576
+ message.user = {
577
+ _id: (_c2 = (_a2 = msg2 == null ? void 0 : msg2.author) == null ? void 0 : _a2.id) != null ? _c2 : (_b2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _b2.id,
578
+ name: (_i2 = (_g2 = (_d2 = msg2 == null ? void 0 : msg2.author) == null ? void 0 : _d2.givenName) != null ? _g2 : ((_e2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _e2.given_name) + " " + ((_f2 = msg2 == null ? void 0 : msg2.author) == null ? void 0 : _f2.familyName)) != null ? _i2 : (_h2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _h2.family_name,
579
+ avatar: (_l2 = (_j2 = msg2 == null ? void 0 : msg2.author) == null ? void 0 : _j2.picture) != null ? _l2 : (_k2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _k2.picture
580
+ };
581
+ message.isOptimistic = (msg2 == null ? void 0 : msg2.isOptimistic) || false;
582
+ message.isUploading = ((_n2 = (_m2 = msg2.files) == null ? void 0 : _m2.data) == null ? void 0 : _n2.some((file) => file.isUploading)) || false;
583
+ if (((_p2 = (_o2 = msg2.files) == null ? void 0 : _o2.data) == null ? void 0 : _p2.length) > 0) {
584
+ const validFiles = msg2.files.data.filter((file) => file && (file.url || file.localUri) && typeof (file.url || file.localUri) === "string");
585
+ if (validFiles.length > 0) {
586
+ const firstFile = validFiles[0];
587
+ const imageUrl = firstFile.isUploading ? firstFile.localUri || firstFile.url : firstFile.url || firstFile.localUri;
588
+ if (imageUrl) {
589
+ message.image = imageUrl;
590
+ }
591
+ if (validFiles.length > 1) {
592
+ message.images = validFiles.map((file) => file.isUploading ? file.localUri || file.url : file.url || file.localUri).filter((url) => !!url);
593
+ if (message.images.length === 0) {
594
+ delete message.images;
595
+ }
596
+ }
597
+ }
598
+ }
599
+ message.sent = msg2 == null ? void 0 : msg2.isDelivered;
600
+ message.received = msg2 == null ? void 0 : msg2.isRead;
601
+ message.type = msg2 == null ? void 0 : msg2.type;
602
+ message.propsConfiguration = msg2 == null ? void 0 : msg2.propsConfiguration;
603
+ res.push(message);
1044
604
  });
1045
605
  }
1046
- const sortedMessages = orderBy(res, [(msg) => {
1047
- try {
1048
- return msg.createdAt instanceof Date ? msg.createdAt.getTime() : new Date().getTime();
1049
- } catch (error) {
1050
- console.error("Error sorting message by date:", error);
1051
- return 0;
606
+ return (res == null ? void 0 : res.length) > 0 ? uniqBy([...res], ({
607
+ _id
608
+ }) => _id) : [];
609
+ }, [channelMessages]);
610
+ const renderSend = useCallback((props) => {
611
+ if (isActionSheetVisible) {
612
+ return null;
613
+ }
614
+ const hasContent = !!props.text || (images == null ? void 0 : images.length) > 0;
615
+ const canSend = channelId && hasContent;
616
+ const isDisabled = !canSend || isUploadingImage || loading;
617
+ return /* @__PURE__ */ React__default.createElement(
618
+ Send,
619
+ __spreadProps(__spreadValues({}, props), {
620
+ disabled: isDisabled,
621
+ containerStyle: {
622
+ justifyContent: "center",
623
+ alignItems: "center",
624
+ height: 40,
625
+ width: 44,
626
+ marginRight: 4,
627
+ marginBottom: 0,
628
+ marginLeft: 4
629
+ }
630
+ }),
631
+ /* @__PURE__ */ React__default.createElement(View, { style: {
632
+ padding: 4
633
+ } }, isUploadingImage || loading ? /* @__PURE__ */ React__default.createElement(Spinner, { size: "small", color: colors.blue[500] }) : /* @__PURE__ */ React__default.createElement(MaterialCommunityIcons, { name: "send-circle", size: 32, color: isDisabled ? colors.gray[400] : colors.blue[500] }))
634
+ );
635
+ }, [channelId, images, isUploadingImage, loading, isActionSheetVisible]);
636
+ useCallback((props) => {
637
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2, _p2, _q2, _r2, _s2, _t, _u, _v, _w, _x, _y;
638
+ const {
639
+ currentMessage
640
+ } = props;
641
+ if (currentMessage.type === "ALERT") {
642
+ const attachment = (_b2 = (_a2 = currentMessage == null ? void 0 : currentMessage.propsConfiguration) == null ? void 0 : _a2.contents) == null ? void 0 : _b2.attachment;
643
+ let action = "";
644
+ let actionId = "";
645
+ let params2 = {};
646
+ if ((_c2 = attachment == null ? void 0 : attachment.callToAction) == null ? void 0 : _c2.extraParams) {
647
+ const extraParams = (_d2 = attachment == null ? void 0 : attachment.callToAction) == null ? void 0 : _d2.extraParams;
648
+ const route = (_e2 = extraParams == null ? void 0 : extraParams.route) != null ? _e2 : null;
649
+ let path = null;
650
+ let param = null;
651
+ if (role && role == PreDefinedRole.Guest) {
652
+ path = ((_f2 = route == null ? void 0 : route.guest) == null ? void 0 : _f2.name) ? (_h2 = (_g2 = route == null ? void 0 : route.guest) == null ? void 0 : _g2.name) != null ? _h2 : null : null;
653
+ param = ((_i2 = route == null ? void 0 : route.guest) == null ? void 0 : _i2.params) ? (_k2 = (_j2 = route == null ? void 0 : route.guest) == null ? void 0 : _j2.params) != null ? _k2 : null : null;
654
+ } else if (role && role == PreDefinedRole.Owner) {
655
+ path = ((_l2 = route == null ? void 0 : route.host) == null ? void 0 : _l2.name) ? (_n2 = (_m2 = route == null ? void 0 : route.host) == null ? void 0 : _m2.name) != null ? _n2 : null : null;
656
+ param = ((_o2 = route == null ? void 0 : route.host) == null ? void 0 : _o2.params) ? (_q2 = (_p2 = route == null ? void 0 : route.host) == null ? void 0 : _p2.params) != null ? _q2 : null : null;
657
+ } else {
658
+ path = ((_r2 = route == null ? void 0 : route.host) == null ? void 0 : _r2.name) ? (_t = (_s2 = route == null ? void 0 : route.host) == null ? void 0 : _s2.name) != null ? _t : null : null;
659
+ param = ((_u = route == null ? void 0 : route.host) == null ? void 0 : _u.params) ? (_w = (_v = route == null ? void 0 : route.host) == null ? void 0 : _v.params) != null ? _w : null : null;
660
+ }
661
+ action = path;
662
+ params2 = __spreadValues({}, param);
663
+ } else if ((_x = attachment == null ? void 0 : attachment.callToAction) == null ? void 0 : _x.link) {
664
+ action = CALL_TO_ACTION_PATH;
665
+ actionId = (_y = attachment == null ? void 0 : attachment.callToAction) == null ? void 0 : _y.link.split("/").pop();
666
+ params2 = {
667
+ reservationId: actionId
668
+ };
1052
669
  }
1053
- }], ["desc"]);
1054
- if (sortedMessages.length > 0) {
1055
- try {
1056
- const firstMsg = sortedMessages[0];
1057
- const lastMsg = sortedMessages[sortedMessages.length - 1];
1058
- console.log("Message date range:", lastMsg.createdAt instanceof Date ? lastMsg.createdAt.toISOString() : "invalid date", "to", firstMsg.createdAt instanceof Date ? firstMsg.createdAt.toISOString() : "invalid date");
1059
- } catch (error) {
1060
- console.error("Error logging message date range:", error);
670
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, (attachment == null ? void 0 : attachment.callToAction) && action ? /* @__PURE__ */ React__default.createElement(Box, { className: `bg-[${CALL_TO_ACTION_BOX_BGCOLOR}] rounded-[15] pb-2` }, /* @__PURE__ */ React__default.createElement(Button, { variant: "outline", size: "sm", className: `border-[${CALL_TO_ACTION_BUTTON_BORDERCOLOR}]`, onPress: () => action && params2 && navigation.navigate(action, params2) }, /* @__PURE__ */ React__default.createElement(ButtonText, { className: `color-[${CALL_TO_ACTION_TEXT_COLOR}]` }, attachment.callToAction.title)), /* @__PURE__ */ React__default.createElement(MessageText, __spreadProps(__spreadValues({}, props), { textStyle: {
671
+ left: {
672
+ marginLeft: 5,
673
+ color: CALL_TO_ACTION_TEXT_COLOR,
674
+ paddingHorizontal: 2
675
+ }
676
+ } }))) : /* @__PURE__ */ React__default.createElement(MessageText, __spreadProps(__spreadValues({}, props), { textStyle: {
677
+ left: {
678
+ marginLeft: 5
679
+ }
680
+ } })));
681
+ } else {
682
+ return /* @__PURE__ */ React__default.createElement(MessageText, __spreadProps(__spreadValues({}, props), { textStyle: {
683
+ left: {
684
+ marginLeft: 5
685
+ }
686
+ } }));
687
+ }
688
+ }, [navigation, role]);
689
+ const renderMessageText = useCallback((props) => {
690
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2, _p2, _q2, _r2, _s2, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U;
691
+ const {
692
+ currentMessage
693
+ } = props;
694
+ const lastReply = ((_b2 = (_a2 = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _a2.data) == null ? void 0 : _b2.length) > 0 ? (_d2 = (_c2 = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _c2.data) == null ? void 0 : _d2[0] : null;
695
+ if (!(currentMessage == null ? void 0 : currentMessage.text) || currentMessage.text.trim() === "") {
696
+ return null;
697
+ }
698
+ if (currentMessage.type === "ALERT") {
699
+ const attachment = (_f2 = (_e2 = currentMessage == null ? void 0 : currentMessage.propsConfiguration) == null ? void 0 : _e2.contents) == null ? void 0 : _f2.attachment;
700
+ let action = "";
701
+ let actionId = "";
702
+ let params2 = {};
703
+ if ((_g2 = attachment == null ? void 0 : attachment.callToAction) == null ? void 0 : _g2.extraParams) {
704
+ const extraParams = (_h2 = attachment == null ? void 0 : attachment.callToAction) == null ? void 0 : _h2.extraParams;
705
+ const route = (_i2 = extraParams == null ? void 0 : extraParams.route) != null ? _i2 : null;
706
+ let path = null;
707
+ let param = null;
708
+ if (role && role == PreDefinedRole.Guest) {
709
+ path = ((_j2 = route == null ? void 0 : route.guest) == null ? void 0 : _j2.name) ? (_l2 = (_k2 = route == null ? void 0 : route.guest) == null ? void 0 : _k2.name) != null ? _l2 : null : null;
710
+ param = ((_m2 = route == null ? void 0 : route.guest) == null ? void 0 : _m2.params) ? (_o2 = (_n2 = route == null ? void 0 : route.guest) == null ? void 0 : _n2.params) != null ? _o2 : null : null;
711
+ } else if (role && role == PreDefinedRole.Owner) {
712
+ path = ((_p2 = route == null ? void 0 : route.host) == null ? void 0 : _p2.name) ? (_r2 = (_q2 = route == null ? void 0 : route.host) == null ? void 0 : _q2.name) != null ? _r2 : null : null;
713
+ param = ((_s2 = route == null ? void 0 : route.host) == null ? void 0 : _s2.params) ? (_u = (_t = route == null ? void 0 : route.host) == null ? void 0 : _t.params) != null ? _u : null : null;
714
+ } else {
715
+ path = ((_v = route == null ? void 0 : route.host) == null ? void 0 : _v.name) ? (_x = (_w = route == null ? void 0 : route.host) == null ? void 0 : _w.name) != null ? _x : null : null;
716
+ param = ((_y = route == null ? void 0 : route.host) == null ? void 0 : _y.params) ? (_A = (_z = route == null ? void 0 : route.host) == null ? void 0 : _z.params) != null ? _A : null : null;
717
+ }
718
+ action = path;
719
+ params2 = __spreadValues({}, param);
720
+ } else if ((_B = attachment == null ? void 0 : attachment.callToAction) == null ? void 0 : _B.link) {
721
+ action = CALL_TO_ACTION_PATH;
722
+ actionId = (_C = attachment == null ? void 0 : attachment.callToAction) == null ? void 0 : _C.link.split("/").pop();
723
+ params2 = {
724
+ reservationId: actionId
725
+ };
1061
726
  }
727
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, (attachment == null ? void 0 : attachment.callToAction) && action ? /* @__PURE__ */ React__default.createElement(Box, { className: `bg-[${CALL_TO_ACTION_BOX_BGCOLOR}] rounded-[15] pb-2` }, /* @__PURE__ */ React__default.createElement(Button, { variant: "outline", size: "sm", className: `border-[${CALL_TO_ACTION_BUTTON_BORDERCOLOR}]`, onPress: () => action && params2 && navigation.navigate(action, params2) }, /* @__PURE__ */ React__default.createElement(ButtonText, { className: `color-[${CALL_TO_ACTION_TEXT_COLOR}]` }, attachment.callToAction.title)), /* @__PURE__ */ React__default.createElement(MessageText, __spreadProps(__spreadValues({}, props), { textStyle: {
728
+ left: {
729
+ marginLeft: 5,
730
+ color: CALL_TO_ACTION_TEXT_COLOR,
731
+ paddingHorizontal: 2
732
+ }
733
+ } }))) : /* @__PURE__ */ React__default.createElement(TouchableHighlight, { underlayColor: "#c0c0c0", style: {
734
+ width: "100%"
735
+ }, onPress: () => {
736
+ if (currentMessage == null ? void 0 : currentMessage.isShowThreadMessage) navigation.navigate(config.THREAD_MESSEGE_PATH, {
737
+ channelId,
738
+ title: "Message",
739
+ postParentId: currentMessage == null ? void 0 : currentMessage._id,
740
+ isPostParentIdThread: true
741
+ });
742
+ } }, /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(MessageText, __spreadProps(__spreadValues({}, props), { textStyle: {
743
+ left: {
744
+ marginLeft: 5
745
+ }
746
+ } })), ((_E = (_D = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _D.data) == null ? void 0 : _E.length) > 0 && /* @__PURE__ */ React__default.createElement(HStack, { space: "sm", className: "px-1 items-center" }, /* @__PURE__ */ React__default.createElement(HStack, null, (_J = (_I = (_H = (_G = (_F = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _F.data) == null ? void 0 : _G.filter((v, i, a) => a.findIndex((t) => {
747
+ var _a3, _b3;
748
+ return ((_a3 = t == null ? void 0 : t.author) == null ? void 0 : _a3.id) === ((_b3 = v == null ? void 0 : v.author) == null ? void 0 : _b3.id);
749
+ }) === i)) == null ? void 0 : _H.slice(0, 2)) == null ? void 0 : _I.reverse()) == null ? void 0 : _J.map((p, i) => {
750
+ var _a3, _b3, _c3;
751
+ return /* @__PURE__ */ React__default.createElement(Avatar, { key: "conversations-view-key-" + i, size: "sm", className: "bg-transparent" }, /* @__PURE__ */ React__default.createElement(AvatarFallbackText, null, startCase((_b3 = (_a3 = p == null ? void 0 : p.author) == null ? void 0 : _a3.username) == null ? void 0 : _b3.charAt(0))), /* @__PURE__ */ React__default.createElement(AvatarImage, { alt: "user image", style: {
752
+ borderRadius: 6,
753
+ borderWidth: 2,
754
+ borderColor: "#fff"
755
+ }, source: {
756
+ uri: (_c3 = p == null ? void 0 : p.author) == null ? void 0 : _c3.picture
757
+ } }));
758
+ })), /* @__PURE__ */ React__default.createElement(Text, { style: {
759
+ fontSize: 12
760
+ }, className: "font-bold color-blue-800" }, (_K = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _K.totalCount, " ", ((_L = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _L.totalCount) == 1 ? "reply" : "replies"), /* @__PURE__ */ React__default.createElement(Text, { style: {
761
+ fontSize: 12
762
+ }, className: "font-bold color-gray-500" }, lastReply ? createdAtText(lastReply == null ? void 0 : lastReply.createdAt) : "")))));
763
+ } else {
764
+ return /* @__PURE__ */ React__default.createElement(TouchableHighlight, { underlayColor: "#c0c0c0", style: {
765
+ width: "100%"
766
+ }, onPress: () => {
767
+ if (currentMessage == null ? void 0 : currentMessage.isShowThreadMessage) navigation.navigate(config.THREAD_MESSEGE_PATH, {
768
+ channelId,
769
+ title: "Message",
770
+ postParentId: currentMessage == null ? void 0 : currentMessage._id,
771
+ isPostParentIdThread: true
772
+ });
773
+ } }, /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(MessageText, __spreadProps(__spreadValues({}, props), { textStyle: {
774
+ left: {
775
+ marginLeft: 5
776
+ }
777
+ } })), ((_N = (_M = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _M.data) == null ? void 0 : _N.length) > 0 && /* @__PURE__ */ React__default.createElement(HStack, { space: "sm", className: "px-1 items-center" }, /* @__PURE__ */ React__default.createElement(HStack, null, (_S = (_R = (_Q = (_P = (_O = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _O.data) == null ? void 0 : _P.filter((v, i, a) => a.findIndex((t) => {
778
+ var _a3, _b3;
779
+ return ((_a3 = t == null ? void 0 : t.author) == null ? void 0 : _a3.id) === ((_b3 = v == null ? void 0 : v.author) == null ? void 0 : _b3.id);
780
+ }) === i)) == null ? void 0 : _Q.slice(0, 2)) == null ? void 0 : _R.reverse()) == null ? void 0 : _S.map((p, i) => {
781
+ var _a3, _b3, _c3;
782
+ return /* @__PURE__ */ React__default.createElement(Avatar, { key: "conversation-replies-key-" + i, className: "bg-transparent", size: "sm" }, /* @__PURE__ */ React__default.createElement(AvatarFallbackText, null, startCase((_b3 = (_a3 = p == null ? void 0 : p.author) == null ? void 0 : _a3.username) == null ? void 0 : _b3.charAt(0))), /* @__PURE__ */ React__default.createElement(AvatarImage, { alt: "user image", style: {
783
+ borderRadius: 6,
784
+ borderWidth: 2,
785
+ borderColor: "#fff"
786
+ }, source: {
787
+ uri: (_c3 = p == null ? void 0 : p.author) == null ? void 0 : _c3.picture
788
+ } }));
789
+ })), /* @__PURE__ */ React__default.createElement(Text, { style: {
790
+ fontSize: 12
791
+ }, className: "font-bold color-blue-800" }, (_T = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _T.totalCount, " ", ((_U = currentMessage == null ? void 0 : currentMessage.replies) == null ? void 0 : _U.totalCount) == 1 ? "reply" : "replies"), /* @__PURE__ */ React__default.createElement(Text, { style: {
792
+ fontSize: 12
793
+ }, className: "font-bold color-gray-500" }, lastReply ? createdAtText(lastReply == null ? void 0 : lastReply.createdAt) : ""))));
1062
794
  }
1063
- return sortedMessages;
1064
- }, [safeContextProperty("threadMessages"), auth]);
1065
- const renderSend = (props) => {
1066
- const hasImage = safeContextProperty("selectedImage", "") !== "";
1067
- const isDisabled = !hasImage && (!props.text || props.text.trim().length === 0);
1068
- return /* @__PURE__ */ React__default.createElement(Send, __spreadProps(__spreadValues({}, props), { containerStyle: {
1069
- alignItems: "center",
1070
- justifyContent: "center",
1071
- marginHorizontal: 4,
1072
- marginBottom: 0
1073
- }, disabled: isDisabled }), /* @__PURE__ */ React__default.createElement(Box, { style: {
1074
- width: 32,
1075
- height: 32,
1076
- alignItems: "center",
1077
- justifyContent: "center"
1078
- } }, /* @__PURE__ */ React__default.createElement(MaterialCommunityIcons, { name: "send-circle", size: 30, color: isDisabled ? colors.gray[400] : colors.blue[500] })));
1079
- };
1080
- const renderActions = (props) => {
795
+ }, [navigation, channelId, role]);
796
+ useCallback((props) => {
1081
797
  return /* @__PURE__ */ React__default.createElement(
1082
- Actions$1,
798
+ Actions,
1083
799
  __spreadProps(__spreadValues({}, props), {
800
+ onPressActionButton: onSelectImages,
1084
801
  options: {
1085
- ["Choose from Library"]: onSelectImages,
802
+ ["Choose from Library"]: () => {
803
+ onSelectImages();
804
+ },
1086
805
  ["Cancel"]: () => {
1087
806
  }
807
+ // Add this option to make the sheet dismissible
1088
808
  },
1089
809
  optionTintColor: "#000000",
1090
810
  cancelButtonIndex: 1,
1091
- icon: () => /* @__PURE__ */ React__default.createElement(Box, { style: {
1092
- width: 32,
1093
- height: 32,
1094
- alignItems: "center",
1095
- justifyContent: "center"
1096
- } }, /* @__PURE__ */ React__default.createElement(Ionicons, { name: "image", size: 24, color: colors.blue[500] })),
811
+ icon: () => /* @__PURE__ */ React__default.createElement(Box, { className: "w-8 h-8 items-center justify-center" }, /* @__PURE__ */ React__default.createElement(Ionicons, { name: "image", size: 24, color: colors.blue[500] })),
1097
812
  containerStyle: {
1098
813
  alignItems: "center",
1099
814
  justifyContent: "center",
@@ -1102,61 +817,91 @@ const ThreadConversationViewComponent = ({
1102
817
  }
1103
818
  })
1104
819
  );
1105
- };
1106
- const renderAccessory = (props) => {
1107
- var _a2, _b2;
1108
- const selectedImage2 = safeContextProperty("selectedImage", "");
1109
- if (!selectedImage2) {
1110
- return null;
1111
- }
1112
- return /* @__PURE__ */ React__default.createElement(View, { style: {
1113
- height: 80,
1114
- padding: 10,
1115
- backgroundColor: "white",
1116
- borderTopWidth: 1,
1117
- borderTopColor: "#e0e0e0",
1118
- flexDirection: "row",
1119
- alignItems: "center"
1120
- } }, /* @__PURE__ */ React__default.createElement(View, { style: {
1121
- flex: 1,
820
+ }, [onSelectImages]);
821
+ useCallback(() => {
822
+ if (!images.length) return null;
823
+ return /* @__PURE__ */ React__default.createElement(Box, { style: {
824
+ position: "relative",
825
+ height: 70,
826
+ backgroundColor: "transparent",
827
+ justifyContent: "center"
828
+ } }, /* @__PURE__ */ React__default.createElement(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, style: {
1122
829
  flexDirection: "row",
830
+ paddingLeft: 15,
831
+ paddingRight: 5
832
+ }, contentContainerStyle: {
1123
833
  alignItems: "center",
1124
- paddingHorizontal: 20
1125
- } }, /* @__PURE__ */ React__default.createElement(Image, { key: (_a2 = state == null ? void 0 : state.context) == null ? void 0 : _a2.selectedImage, alt: "selected image", source: {
1126
- uri: (_b2 = state == null ? void 0 : state.context) == null ? void 0 : _b2.selectedImage
1127
- }, size: "xs", style: {
1128
- width: 5,
1129
- height: 5,
1130
- borderRadius: 5,
1131
- marginRight: 20
1132
- } }), /* @__PURE__ */ React__default.createElement(TouchableHighlight, { underlayColor: "#dddddd", onPress: () => safeSend({
1133
- type: Actions.CLEAR_IMAGE
1134
- }), style: {
1135
- backgroundColor: "#f44336",
1136
- paddingVertical: 2,
1137
- paddingHorizontal: 5,
1138
- borderRadius: 5,
1139
- marginLeft: 10,
1140
- elevation: 3,
1141
- shadowColor: "#000",
1142
- shadowOffset: {
1143
- width: 0,
1144
- height: 1
1145
- },
1146
- shadowOpacity: 0.3,
1147
- shadowRadius: 2
1148
- } }, /* @__PURE__ */ React__default.createElement(Text, { style: {
1149
- color: "white",
1150
- fontWeight: "bold"
1151
- } }, "X"))));
1152
- };
1153
- const setImageViewerObject = (obj, v) => {
834
+ height: "100%"
835
+ } }, images.map((img, index) => /* @__PURE__ */ React__default.createElement(View, { key: `image-preview-${index}`, style: {
836
+ width: 40,
837
+ height: 40,
838
+ marginRight: 15,
839
+ borderRadius: 4,
840
+ backgroundColor: colors.gray[200],
841
+ overflow: "hidden",
842
+ borderWidth: 1,
843
+ borderColor: "#e0e0e0",
844
+ position: "relative",
845
+ zIndex: 10
846
+ } }, /* @__PURE__ */ React__default.createElement(Image, { alt: `selected image ${index + 1}`, source: {
847
+ uri: img.uri || img.url
848
+ }, style: {
849
+ width: "100%",
850
+ height: "100%"
851
+ }, size: "md" }), /* @__PURE__ */ React__default.createElement(TouchableOpacity, { onPress: () => {
852
+ const newImages = [...images];
853
+ newImages.splice(index, 1);
854
+ setImages(newImages);
855
+ if (newImages.length === 0) {
856
+ setSelectedImage("");
857
+ }
858
+ }, style: {
859
+ position: "absolute",
860
+ top: -1,
861
+ right: -1,
862
+ backgroundColor: "rgba(0,0,0,0.6)",
863
+ borderRadius: 12,
864
+ width: 20,
865
+ height: 20,
866
+ alignItems: "center",
867
+ justifyContent: "center",
868
+ zIndex: 9999
869
+ } }, /* @__PURE__ */ React__default.createElement(Ionicons, { name: "close", size: 16, color: "white" }))))));
870
+ }, [images]);
871
+ useCallback((props) => /* @__PURE__ */ React__default.createElement(TouchableOpacity, { style: {
872
+ flexDirection: "row",
873
+ alignItems: "center",
874
+ backgroundColor: "#fff",
875
+ minHeight: 48,
876
+ maxHeight: 48,
877
+ paddingHorizontal: 12,
878
+ paddingVertical: 0,
879
+ marginHorizontal: 8,
880
+ flex: 1
881
+ }, activeOpacity: 0.7, onPress: () => {
882
+ setActionSheetVisible(true);
883
+ } }, /* @__PURE__ */ React__default.createElement(TouchableOpacity, { onPress: (e) => {
884
+ e.stopPropagation();
885
+ onSelectImages();
886
+ }, style: {
887
+ width: 25,
888
+ height: 25,
889
+ borderRadius: 20,
890
+ backgroundColor: "#f5f5f5",
891
+ alignItems: "center",
892
+ justifyContent: "center",
893
+ marginRight: 8
894
+ } }, /* @__PURE__ */ React__default.createElement(MaterialIcons, { name: "add", size: 20, color: "#888" })), /* @__PURE__ */ React__default.createElement(Text, { style: {
895
+ fontSize: 16,
896
+ color: msg ? colors.gray[800] : colors.gray[400],
897
+ flex: 1
898
+ }, numberOfLines: 1, ellipsizeMode: "tail" }, msg ? msg : "Jot something down")), [msg, onSelectImages]);
899
+ const setImageViewerObject = useCallback((obj, v) => {
1154
900
  setImageObject(obj);
1155
901
  setImageViewer(v);
1156
- };
1157
- const modalContent = React__default.useMemo(() => {
1158
- if (!imageObject)
1159
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null);
902
+ }, []);
903
+ const modalContent = useMemo(() => {
904
+ if (!imageObject) return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null);
1160
905
  const {
1161
906
  image,
1162
907
  _id
@@ -1169,415 +914,189 @@ const ThreadConversationViewComponent = ({
1169
914
  expiresIn: 86400
1170
915
  }, alt: "image" });
1171
916
  }, [imageObject]);
1172
- const renderMessage = (props) => {
917
+ useCallback((props) => {
918
+ const {
919
+ currentMessage
920
+ } = props;
921
+ const customProps = __spreadProps(__spreadValues({}, props), {
922
+ isShowImageViewer,
923
+ setImageViewer: setImageViewerObject,
924
+ // Pass custom flags to indicate uploading/optimistic states
925
+ isUploading: currentMessage.isUploading || false,
926
+ isOptimistic: currentMessage.isOptimistic || false
927
+ });
928
+ return /* @__PURE__ */ React__default.createElement(Message, __spreadValues({}, customProps));
929
+ }, [isShowImageViewer, setImageViewerObject]);
930
+ const renderMessage = useCallback((props) => {
1173
931
  return /* @__PURE__ */ React__default.createElement(Message, __spreadProps(__spreadValues({}, props), { isShowImageViewer, setImageViewer: setImageViewerObject }));
1174
- };
1175
- const currentMessageText = useMemo(() => {
1176
- const text = safeContextProperty("messageText", "") || " ";
1177
- return text;
1178
- }, [safeContextProperty("messageText")]);
1179
- const renderInputToolbar = (props) => {
1180
- return /* @__PURE__ */ React__default.createElement(InputToolbar, __spreadProps(__spreadValues({}, props), { containerStyle: {
1181
- backgroundColor: "white",
1182
- borderTopWidth: 1,
1183
- borderTopColor: colors.gray[200],
1184
- paddingHorizontal: 4,
1185
- paddingVertical: 4
1186
- }, primaryStyle: {
932
+ }, [isShowImageViewer]);
933
+ useCallback((props) => {
934
+ if (isActionSheetVisible) return null;
935
+ return /* @__PURE__ */ React__default.createElement(
936
+ InputToolbar,
937
+ __spreadProps(__spreadValues({}, props), {
938
+ containerStyle: {
939
+ backgroundColor: "transparent",
940
+ padding: 0,
941
+ margin: 0,
942
+ borderTopWidth: 1,
943
+ borderTopColor: colors.gray[200]
944
+ },
945
+ primaryStyle: {
946
+ alignItems: "center",
947
+ justifyContent: "center",
948
+ flex: 1
949
+ }
950
+ })
951
+ );
952
+ }, [isActionSheetVisible, onSelectImages]);
953
+ const renderLoadEarlier = useCallback(() => {
954
+ return loadingOldMessages && !refreshing ? /* @__PURE__ */ React__default.createElement(Box, { style: {
955
+ padding: 10,
956
+ backgroundColor: "rgba(255,255,255,0.8)",
957
+ borderRadius: 10,
958
+ marginTop: 10,
1187
959
  alignItems: "center"
1188
- } }));
960
+ } }, /* @__PURE__ */ React__default.createElement(Spinner, { size: "small", color: colors.blue[500] }), /* @__PURE__ */ React__default.createElement(Text, { style: {
961
+ fontSize: 12,
962
+ color: colors.gray[600],
963
+ marginTop: 4
964
+ } }, "Loading earlier messages...")) : null;
965
+ }, [loadingOldMessages, refreshing]);
966
+ let onScroll = false;
967
+ const onMomentumScrollBegin = ({
968
+ nativeEvent
969
+ }) => {
970
+ onScroll = true;
971
+ if (!loadingOldMessages && isCloseToTop(nativeEvent) && totalCount > (channelMessages == null ? void 0 : channelMessages.length)) {
972
+ onFetchOld();
973
+ }
1189
974
  };
1190
- const forceLoadMessages = useCallback((skipValue) => {
1191
- console.log(`Force loading messages with explicit skip=${skipValue}, limit=50`);
1192
- if (channelId && parentId) {
1193
- safeSend({
1194
- type: Actions.START_LOADING,
1195
- data: {
1196
- loading: true
1197
- }
1198
- });
1199
- getThreadMessages({
1200
- variables: {
1201
- channelId: channelId == null ? void 0 : channelId.toString(),
1202
- role: role == null ? void 0 : role.toString(),
1203
- postParentId: !parentId || parentId == 0 ? null : parentId == null ? void 0 : parentId.toString(),
1204
- selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
1205
- skip: skipValue,
1206
- limit: 50
1207
- }
1208
- }).then(({
1209
- data: data2
975
+ const onEndReached = () => {
976
+ if (!onScroll) return;
977
+ onScroll = false;
978
+ };
979
+ const renderChatFooter = useCallback(() => {
980
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(ImageViewerModal, { isVisible: isShowImageViewer, setVisible: setImageViewer, modalContent }), /* @__PURE__ */ React__default.createElement(SubscriptionHandler, { channelId, subscribeToNewMessages: () => subscribeToMore({
981
+ document: CHAT_MESSAGE_ADDED,
982
+ variables: {
983
+ channelId: channelId == null ? void 0 : channelId.toString(),
984
+ postParentId: !parentId || parentId == 0 ? null : parentId == null ? void 0 : parentId.toString()
985
+ },
986
+ updateQuery: (prev, {
987
+ subscriptionData
1210
988
  }) => {
1211
989
  var _a2, _b2, _c2;
1212
- if (data2 == null ? void 0 : data2.getPostThread) {
1213
- const threads = data2.getPostThread;
1214
- const threadPost = (_a2 = threads == null ? void 0 : threads.post) != null ? _a2 : [];
1215
- const threadReplies = (_b2 = threads == null ? void 0 : threads.replies) != null ? _b2 : [];
1216
- const messageTotalCount = (_c2 = threads == null ? void 0 : threads.replyCount) != null ? _c2 : 0;
1217
- const messages = [...threadReplies];
1218
- console.log(`Force load with skip=${skipValue} complete. Got ${messages.length} messages of ${messageTotalCount} total`);
1219
- safeSend({
1220
- type: Actions.SET_THREAD_MESSAGES,
1221
- data: {
1222
- messages,
1223
- totalCount: messageTotalCount,
1224
- threadPost,
1225
- postThread: threads
1226
- }
1227
- });
1228
- }
1229
- }).catch((error) => {
1230
- console.error("Error during force load:", error);
1231
- safeSend({
1232
- type: "ERROR",
1233
- data: {
1234
- message: error.message
1235
- }
1236
- });
1237
- });
1238
- }
1239
- }, [channelId, parentId, getThreadMessages, safeSend]);
1240
- return /* @__PURE__ */ React__default.createElement(SafeAreaView, { style: {
1241
- flex: 1
1242
- } }, safeContextProperty("loadingOldMessages", false) === true && /* @__PURE__ */ React__default.createElement(Box, { className: "absolute top-10 left-0 right-0 z-10 items-center" }, /* @__PURE__ */ React__default.createElement(Box, { className: "bg-blue-500/20 rounded-full px-4 py-2 flex-row items-center" }, /* @__PURE__ */ React__default.createElement(Spinner, { color: colors.blue[500], size: "small" }), /* @__PURE__ */ React__default.createElement(Text, { className: "text-sm font-medium color-blue-600 ml-2" }, "Loading messages..."))), !safeContextProperty("loadingOldMessages", false) && safeContextProperty("totalCount", 0) > safeContextProperty("threadMessages", []).length && /* @__PURE__ */ React__default.createElement(Box, { className: "absolute top-10 left-0 right-0 z-10 items-center" }, /* @__PURE__ */ React__default.createElement(HStack, { space: 2, className: "px-2" }, /* @__PURE__ */ React__default.createElement(TouchableHighlight, { onPress: () => {
1243
- console.log("Manual load more pressed");
1244
- Alert.alert("Load Options", "Choose loading method", [{
1245
- text: "Normal Load",
1246
- onPress: () => safeSend({
1247
- type: Actions.FETCH_MORE_MESSAGES
1248
- })
1249
- }, {
1250
- text: "Try Skip=0",
1251
- onPress: () => forceLoadMessages(0)
1252
- }, {
1253
- text: "Try Skip=0, Limit=50",
1254
- onPress: () => {
1255
- console.log("Force loading with explicit skip=0, limit=50");
1256
- safeSend({
1257
- type: Actions.START_LOADING,
1258
- data: {
1259
- loadingOldMessages: true
1260
- }
1261
- });
1262
- fetchMoreMessages({
1263
- variables: {
1264
- channelId: channelId == null ? void 0 : channelId.toString(),
1265
- role: role == null ? void 0 : role.toString(),
1266
- postParentId: !parentId || parentId == 0 ? null : parentId == null ? void 0 : parentId.toString(),
1267
- selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
1268
- limit: 50,
1269
- skip: 0
1270
- }
1271
- }).then((res) => {
1272
- var _a2, _b2, _c2, _d2;
1273
- console.log("LARGE LIMIT response:", JSON.stringify(res == null ? void 0 : res.data, null, 2));
1274
- if ((_a2 = res == null ? void 0 : res.data) == null ? void 0 : _a2.getPostThread) {
1275
- const threads = (_b2 = res == null ? void 0 : res.data) == null ? void 0 : _b2.getPostThread;
1276
- const threadReplies = (_c2 = threads == null ? void 0 : threads.replies) != null ? _c2 : [];
1277
- const actualTotalCount = (_d2 = threads == null ? void 0 : threads.replyCount) != null ? _d2 : 0;
1278
- console.log(`Large limit load complete. Got ${threadReplies.length} messages of ${actualTotalCount} total`);
1279
- if (threadReplies.length > 0) {
1280
- safeSend({
1281
- type: Actions.SET_THREAD_MESSAGES,
1282
- data: {
1283
- messages: threadReplies,
1284
- totalCount: actualTotalCount,
1285
- threadPost: safeContextProperty("threadPost", []),
1286
- postThread: threads
1287
- }
1288
- });
1289
- } else {
1290
- safeSend({
1291
- type: Actions.SET_THREAD_MESSAGES,
1292
- data: {
1293
- messages: safeContextProperty("threadMessages", []),
1294
- totalCount: safeContextProperty("threadMessages", []).length,
1295
- threadPost: safeContextProperty("threadPost", []),
1296
- postThread: safeContextProperty("postThread", null)
1297
- }
1298
- });
1299
- }
1300
- } else {
1301
- safeSend({
1302
- type: Actions.STOP_LOADING,
1303
- data: {
1304
- loadingOldMessages: false
1305
- }
1306
- });
1307
- }
1308
- }).catch((error) => {
1309
- console.error("Error in large limit load:", error);
1310
- safeSend({
1311
- type: Actions.STOP_LOADING,
1312
- data: {
1313
- loadingOldMessages: false
1314
- }
1315
- });
1316
- });
1317
- }
1318
- }, {
1319
- text: "Try Direct Fetch",
1320
- onPress: () => {
1321
- const currentCount = safeContextProperty("threadMessages", []).length;
1322
- const totalCount = safeContextProperty("totalCount", 0);
1323
- const missingCount = totalCount - currentCount;
1324
- if (missingCount <= 0) {
1325
- Alert.alert("Info", "No missing messages to fetch");
1326
- return;
1327
- }
1328
- console.log(`Attempting direct fetch of missing ${missingCount} messages`);
1329
- safeSend({
1330
- type: Actions.START_LOADING,
1331
- data: {
1332
- loadingOldMessages: true
1333
- }
1334
- });
1335
- getThreadMessages({
1336
- variables: {
1337
- channelId: channelId == null ? void 0 : channelId.toString(),
1338
- role: role == null ? void 0 : role.toString(),
1339
- postParentId: !parentId || parentId == 0 ? null : parentId == null ? void 0 : parentId.toString(),
1340
- selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
1341
- limit: missingCount,
1342
- skip: 0
1343
- }
1344
- }).then(({
1345
- data: data2
1346
- }) => {
1347
- var _a2, _b2;
1348
- console.log("DIRECT FETCH response:", JSON.stringify(data2, null, 2));
1349
- if (data2 == null ? void 0 : data2.getPostThread) {
1350
- const threads = data2.getPostThread;
1351
- const threadReplies = (_a2 = threads == null ? void 0 : threads.replies) != null ? _a2 : [];
1352
- const actualTotalCount = (_b2 = threads == null ? void 0 : threads.replyCount) != null ? _b2 : 0;
1353
- console.log(`Direct fetch complete. Got ${threadReplies.length} messages of ${actualTotalCount} total`);
1354
- console.log("Message IDs:", threadReplies.map((msg) => msg.id).join(", "));
1355
- const existingIds = new Set(safeContextProperty("threadMessages", []).map((msg) => msg.id));
1356
- const newMessages = threadReplies.filter((msg) => !existingIds.has(msg.id));
1357
- console.log(`Found ${newMessages.length} new messages that we didn't have before`);
1358
- if (newMessages.length > 0) {
1359
- safeSend({
1360
- type: "FETCH_MORE_MESSAGES_SUCCESS",
1361
- data: {
1362
- messages: newMessages,
1363
- totalCount: actualTotalCount,
1364
- loadingOldMessages: false
1365
- }
1366
- });
1367
- Alert.alert("Success", `Found ${newMessages.length} new messages`);
1368
- } else {
1369
- console.log("No new messages found, adjusting count");
1370
- safeSend({
1371
- type: Actions.SET_THREAD_MESSAGES,
1372
- data: {
1373
- messages: safeContextProperty("threadMessages", []),
1374
- totalCount: safeContextProperty("threadMessages", []).length,
1375
- threadPost: safeContextProperty("threadPost", []),
1376
- postThread: safeContextProperty("postThread", null)
1377
- }
1378
- });
1379
- Alert.alert("Info", "No new messages found. Count has been adjusted.");
1380
- }
1381
- } else {
1382
- Alert.alert("Error", "Could not fetch thread messages");
1383
- safeSend({
1384
- type: Actions.STOP_LOADING,
1385
- data: {
1386
- loadingOldMessages: false
1387
- }
1388
- });
1389
- }
1390
- }).catch((error) => {
1391
- console.error("Error in direct fetch:", error);
1392
- Alert.alert("Error", "Failed to fetch messages: " + error.message);
1393
- safeSend({
1394
- type: Actions.STOP_LOADING,
1395
- data: {
1396
- loadingOldMessages: false
1397
- }
1398
- });
990
+ if (!subscriptionData.data) return prev;
991
+ const newMessage = (_a2 = subscriptionData == null ? void 0 : subscriptionData.data) == null ? void 0 : _a2.threadChatMessageAdded;
992
+ const prevReplyCount = (_b2 = prev == null ? void 0 : prev.getPostThread) == null ? void 0 : _b2.replyCount;
993
+ const newReplyCount = prevReplyCount || 0 + 1;
994
+ const replies = ((_c2 = prev == null ? void 0 : prev.getPostThread) == null ? void 0 : _c2.replies) || [];
995
+ setChannelMessages((oldMessages) => uniqBy([...oldMessages, newMessage], ({
996
+ id
997
+ }) => id));
998
+ setTotalCount(newReplyCount);
999
+ return Object.assign({}, prev, {
1000
+ getPostThread: __spreadProps(__spreadValues({}, prev == null ? void 0 : prev.getPostThread), {
1001
+ lastReplyAt: newMessage.createdAt,
1002
+ replies: [newMessage, ...replies],
1003
+ replyCount: newReplyCount,
1004
+ updatedAt: newMessage.createdAt
1005
+ })
1399
1006
  });
1400
1007
  }
1401
- }, {
1402
- text: "Reset Count",
1403
- style: "destructive",
1404
- onPress: () => {
1405
- console.log("Resetting message count to match reality");
1406
- safeSend({
1407
- type: Actions.SET_THREAD_MESSAGES,
1408
- data: {
1409
- messages: safeContextProperty("threadMessages", []),
1410
- totalCount: safeContextProperty("threadMessages", []).length,
1411
- threadPost: safeContextProperty("threadPost", []),
1412
- postThread: safeContextProperty("postThread", null)
1413
- }
1414
- });
1008
+ }) }));
1009
+ }, [channelId, isShowImageViewer, modalContent, parentId, setImageViewer, subscribeToMore]);
1010
+ const handleRemoveImage = useCallback((index) => {
1011
+ const newImages = [...images];
1012
+ newImages.splice(index, 1);
1013
+ setImages(newImages);
1014
+ if (newImages.length === 0) {
1015
+ setSelectedImage("");
1016
+ if (textInputRef.current && typeof textInputRef.current.focus === "function") {
1017
+ textInputRef.current.focus();
1415
1018
  }
1416
- }, {
1417
- text: "Cancel",
1418
- style: "cancel"
1419
- }]);
1420
- }, underlayColor: "#e6e6e6" }, /* @__PURE__ */ React__default.createElement(Box, { className: "bg-gray-200 rounded-full px-4 py-2 flex-row items-center" }, /* @__PURE__ */ React__default.createElement(MaterialIcons, { name: "arrow-upward", size: 16, color: colors.blue[500] }), /* @__PURE__ */ React__default.createElement(Text, { className: "text-sm font-medium color-blue-600 ml-2" }, "Load More (", safeContextProperty("totalCount", 0) - safeContextProperty("threadMessages", []).length, ")"))), /* @__PURE__ */ React__default.createElement(TouchableHighlight, { onPress: forceRefreshMessages, underlayColor: "#e6e6e6" }, /* @__PURE__ */ React__default.createElement(Box, { className: "bg-gray-200 rounded-full px-4 py-2 flex-row items-center" }, /* @__PURE__ */ React__default.createElement(MaterialIcons, { name: "refresh", size: 16, color: colors.blue[500] }), /* @__PURE__ */ React__default.createElement(Text, { className: "text-sm font-medium color-blue-600 ml-2" }, "Refresh All"))))), isPostParentIdThread && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, ((_a = safeContextProperty("threadPost", [])) == null ? void 0 : _a.length) > 0 && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(VStack, { className: "px-2 pt-2 pb-0", space: "sm" }, /* @__PURE__ */ React__default.createElement(HStack, { space: "sm", className: "items-center" }, /* @__PURE__ */ React__default.createElement(Avatar, { className: "bg-transparent", size: "md" }, /* @__PURE__ */ React__default.createElement(AvatarFallbackText, null, startCase((_d = (_c = (_b = safeContextProperty("threadPost")[0]) == null ? void 0 : _b.author) == null ? void 0 : _c.username) == null ? void 0 : _d.charAt(0))), /* @__PURE__ */ React__default.createElement(AvatarImage, { alt: "image", style: {
1019
+ }
1020
+ }, [images]);
1021
+ return /* @__PURE__ */ React__default.createElement(View, { style: {
1022
+ flex: 1,
1023
+ marginTop: -40
1024
+ } }, errorMessage ? /* @__PURE__ */ React__default.createElement(ErrorNotification, { message: errorMessage, onClose: () => setErrorMessage("") }) : null, loading && /* @__PURE__ */ React__default.createElement(Spinner, { color: "#3b82f6" }), isPostParentIdThread && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, (threadPost == null ? void 0 : threadPost.length) > 0 && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(VStack, { className: "px-2 pt-2 pb-0", space: "sm" }, /* @__PURE__ */ React__default.createElement(HStack, { space: "sm", className: "items-center" }, /* @__PURE__ */ React__default.createElement(Avatar, { className: "bg-transparent", size: "md" }, /* @__PURE__ */ React__default.createElement(AvatarFallbackText, null, startCase((_c = (_b = (_a = threadPost[0]) == null ? void 0 : _a.author) == null ? void 0 : _b.username) == null ? void 0 : _c.charAt(0))), /* @__PURE__ */ React__default.createElement(AvatarImage, { alt: "image", style: {
1421
1025
  borderRadius: 6,
1422
1026
  borderWidth: 2,
1423
1027
  borderColor: "#fff"
1424
1028
  }, source: {
1425
- uri: (_f = (_e = safeContextProperty("threadPost")[0]) == null ? void 0 : _e.author) == null ? void 0 : _f.picture
1426
- } })), /* @__PURE__ */ React__default.createElement(Box, null, /* @__PURE__ */ React__default.createElement(Text, { className: "font-bold color-black" }, (_i = (_h = (_g = safeContextProperty("threadPost")[0]) == null ? void 0 : _g.author) == null ? void 0 : _h.givenName) != null ? _i : "", " ", (_l = (_k = (_j = safeContextProperty("threadPost")[0]) == null ? void 0 : _j.author) == null ? void 0 : _k.familyName) != null ? _l : ""), /* @__PURE__ */ React__default.createElement(Text, { className: "pl-0 color-gray-500" }, createdAtText((_m = safeContextProperty("threadPost")[0]) == null ? void 0 : _m.createdAt), " at", " ", (() => {
1427
- var _a2;
1428
- try {
1429
- const createdAt = (_a2 = safeContextProperty("threadPost")[0]) == null ? void 0 : _a2.createdAt;
1430
- if (createdAt && !isNaN(new Date(createdAt).getTime())) {
1431
- return format(new Date(createdAt), "hh:mm:a");
1432
- } else {
1433
- return "unknown time";
1434
- }
1435
- } catch (error) {
1436
- console.error("Error formatting thread post time:", error);
1437
- return "unknown time";
1438
- }
1439
- })()))), /* @__PURE__ */ React__default.createElement(HStack, { space: "sm", className: "px-2 items-center" }, /* @__PURE__ */ React__default.createElement(Text, null, (_o = (_n = safeContextProperty("threadPost")[0]) == null ? void 0 : _n.message) != null ? _o : ""))), /* @__PURE__ */ React__default.createElement(Box, { className: "py-4" }, /* @__PURE__ */ React__default.createElement(Box, { className: "px-4 py-2 border-t border-b border-gray-200" }, /* @__PURE__ */ React__default.createElement(Text, { className: "font-bold color-gray-600" }, (_q = (_p = safeContextProperty("threadPost")[0]) == null ? void 0 : _p.replies) == null ? void 0 : _q.totalCount, " ", ((_s = (_r = safeContextProperty("threadPost")[0]) == null ? void 0 : _r.replies) == null ? void 0 : _s.totalCount) > 0 ? "replies" : "reply"))))), /* @__PURE__ */ React__default.createElement(GiftedChat, { ref: threadMessageListRef, wrapInSafeArea: false, renderLoading: () => /* @__PURE__ */ React__default.createElement(Spinner, { color: colors.blue[500] }), messages: messageList, listViewProps: {
1440
- onScroll: handleScrollToTop,
1441
- onEndReached: handleEndReached,
1442
- onEndReachedThreshold: 0.2,
1443
- contentContainerStyle: {
1444
- paddingBottom: 10
1445
- },
1446
- maintainVisibleContentPosition: {
1447
- minIndexForVisible: 0,
1448
- autoscrollToTopThreshold: 100
1449
- },
1450
- scrollEventThrottle: 16,
1451
- keyboardDismissMode: "on-drag",
1452
- keyboardShouldPersistTaps: "handled"
1453
- }, onSend: (messages) => {
1454
- var _a2, _b2;
1455
- if (!messages || messages.length === 0) {
1456
- console.log("No messages to send");
1457
- return;
1458
- }
1459
- const currentInputText = currentMessageText;
1460
- const messageToSend = (currentInputText == null ? void 0 : currentInputText.trim()) || ((_b2 = (_a2 = messages[0]) == null ? void 0 : _a2.text) == null ? void 0 : _b2.trim()) || " ";
1461
- console.log("GiftedChat onSend triggered with text from state:", messageToSend);
1462
- safeSend({
1463
- type: Actions.SET_MESSAGE_TEXT,
1464
- data: {
1465
- messageText: ""
1466
- }
1467
- });
1468
- if (safeContextProperty("images", []).length > 0) {
1469
- console.log("Sending message with file:", messageToSend, "Images:", safeContextProperty("images", []).length);
1470
- safeSend({
1471
- type: Actions.SEND_THREAD_MESSAGE_WITH_FILE,
1472
- data: {
1473
- messageText: messageToSend
1474
- }
1475
- });
1476
- } else {
1477
- console.log("Sending text message:", messageToSend);
1478
- safeSend({
1479
- type: Actions.SEND_THREAD_MESSAGE,
1480
- data: {
1481
- messageText: messageToSend
1482
- }
1483
- });
1484
- }
1485
- }, text: currentMessageText, onInputTextChanged: (text) => {
1486
- if (text.length % 5 === 0 || text.length < 5) {
1487
- console.log("Input text changed:", text);
1488
- }
1489
- safeSend({
1490
- type: Actions.SET_MESSAGE_TEXT,
1491
- data: {
1492
- messageText: text
1493
- }
1494
- });
1495
- }, renderFooter: () => safeContextProperty("loading", false) && !safeContextProperty("loadingOldMessages", false) ? /* @__PURE__ */ React__default.createElement(Box, { className: "w-full py-2 items-center" }, /* @__PURE__ */ React__default.createElement(Spinner, { color: colors.blue[500] })) : safeContextProperty("imageLoading", false) ? /* @__PURE__ */ React__default.createElement(Box, { className: "w-full py-2 items-center" }, /* @__PURE__ */ React__default.createElement(Spinner, { color: colors.blue[500] })) : /* @__PURE__ */ React__default.createElement(React__default.Fragment, null), scrollToBottom: true, loadEarlier: false, isLoadingEarlier: false, user: {
1496
- _id: (auth == null ? void 0 : auth.id) || ""
1497
- }, isTyping: true, alwaysShowSend: safeContextProperty("loading", false) ? false : true, infiniteScroll: true, renderSend, renderInputToolbar, minInputToolbarHeight: 50, renderActions, renderAccessory: !!((_t = state == null ? void 0 : state.context) == null ? void 0 : _t.selectedImage) ? renderAccessory : void 0, renderMessage, maxInputLength: 1e3, placeholder: "Type a message...", showUserAvatar: true, showAvatarForEveryMessage: false, inverted: true, parsePatterns: (linkStyle) => [{
1498
- type: "url",
1499
- style: __spreadProps(__spreadValues({}, linkStyle), {
1500
- color: colors.blue[500]
1501
- }),
1502
- onPress: (url) => Linking.openURL(url)
1503
- }, {
1504
- type: "phone",
1505
- style: __spreadProps(__spreadValues({}, linkStyle), {
1506
- color: colors.blue[500]
1507
- }),
1508
- onPress: (phone) => Linking.openURL(`tel:${phone}`)
1509
- }, {
1510
- type: "email",
1511
- style: __spreadProps(__spreadValues({}, linkStyle), {
1512
- color: colors.blue[500]
1513
- }),
1514
- onPress: (email) => Linking.openURL(`mailto:${email}`)
1515
- }], textInputProps: {
1516
- style: {
1517
- borderWidth: 1,
1518
- borderColor: colors.gray[300],
1519
- backgroundColor: "#f8f8f8",
1520
- borderRadius: 20,
1521
- minHeight: 40,
1522
- maxHeight: 80,
1523
- color: "#000",
1524
- padding: 10,
1525
- paddingHorizontal: 20,
1526
- fontSize: 16,
1527
- flex: 1
1528
- },
1529
- multiline: true,
1530
- returnKeyType: "default",
1531
- enablesReturnKeyAutomatically: true,
1532
- placeholderTextColor: colors.gray[400]
1533
- }, minComposerHeight: 44, isKeyboardInternallyHandled: true, bottomOffset: Platform.OS === "ios" ? 20 : 0, renderChatFooter: () => /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(ImageViewerModal, { isVisible: isShowImageViewer, setVisible: setImageViewer, modalContent }), /* @__PURE__ */ React__default.createElement(SubscriptionHandler, { channelId, subscribeToNewMessages: () => subscribeToMore({
1534
- document: OnThreadChatMessageAddedDocument,
1535
- variables: {
1536
- channelId: channelId == null ? void 0 : channelId.toString(),
1537
- postParentId: !parentId || parentId == 0 ? null : parentId == null ? void 0 : parentId.toString()
1538
- },
1539
- updateQuery: (prev, {
1540
- subscriptionData
1541
- }) => {
1542
- var _a2, _b2, _c2;
1543
- if (!subscriptionData.data)
1544
- return prev;
1545
- const newMessage = (_a2 = subscriptionData == null ? void 0 : subscriptionData.data) == null ? void 0 : _a2.threadChatMessageAdded;
1546
- const prevReplyCount = (_b2 = prev == null ? void 0 : prev.getPostThread) == null ? void 0 : _b2.replyCount;
1547
- const newReplyCount = prevReplyCount || 0 + 1;
1548
- const replies = ((_c2 = prev == null ? void 0 : prev.getPostThread) == null ? void 0 : _c2.replies) || [];
1549
- safeSend({
1550
- type: Actions.SET_THREAD_MESSAGES,
1551
- data: {
1552
- messages: uniqBy([...safeContextProperty("threadMessages", []), newMessage], ({
1553
- id
1554
- }) => id),
1555
- totalCount: newReplyCount,
1556
- threadPost: safeContextProperty("threadPost", []),
1557
- postThread: safeContextProperty("postThread", null)
1558
- }
1559
- });
1560
- return Object.assign({}, prev, {
1561
- getPostThread: __spreadProps(__spreadValues({}, prev == null ? void 0 : prev.getPostThread), {
1562
- lastReplyAt: newMessage.createdAt,
1563
- replies: [newMessage, ...replies],
1564
- replyCount: newReplyCount,
1565
- updatedAt: newMessage.createdAt
1566
- })
1567
- });
1029
+ uri: (_e = (_d = threadPost[0]) == null ? void 0 : _d.author) == null ? void 0 : _e.picture
1030
+ } })), /* @__PURE__ */ React__default.createElement(Box, null, /* @__PURE__ */ React__default.createElement(Text, { className: "font-bold color-black" }, (_h = (_g = (_f = threadPost[0]) == null ? void 0 : _f.author) == null ? void 0 : _g.givenName) != null ? _h : "", " ", (_k = (_j = (_i = threadPost[0]) == null ? void 0 : _i.author) == null ? void 0 : _j.familyName) != null ? _k : ""), /* @__PURE__ */ React__default.createElement(Text, { className: "pl-0 color-gray-500" }, createdAtText((_l = threadPost[0]) == null ? void 0 : _l.createdAt), " at", " ", format(new Date((_m = threadPost[0]) == null ? void 0 : _m.createdAt), "hh:ss:a")))), /* @__PURE__ */ React__default.createElement(HStack, { space: "sm", className: "px-2 items-center" }, /* @__PURE__ */ React__default.createElement(Text, null, (_o = (_n = threadPost[0]) == null ? void 0 : _n.message) != null ? _o : ""))), /* @__PURE__ */ React__default.createElement(Box, { className: "py-4" }, /* @__PURE__ */ React__default.createElement(Box, { className: "px-4 py-2 border-t border-b border-gray-200" }, /* @__PURE__ */ React__default.createElement(Text, { className: "font-bold color-gray-600" }, (_q = (_p = threadPost[0]) == null ? void 0 : _p.replies) == null ? void 0 : _q.totalCount, " ", ((_s = (_r = threadPost[0]) == null ? void 0 : _r.replies) == null ? void 0 : _s.totalCount) > 0 ? "replies" : "reply"))))), /* @__PURE__ */ React__default.createElement(
1031
+ GiftedChatInboxComponent,
1032
+ {
1033
+ ref: threadMessageListRef,
1034
+ onRemoveImage: handleRemoveImage,
1035
+ images,
1036
+ onSelectImages,
1037
+ selectedImage,
1038
+ setSelectedImage,
1039
+ isUploadingImage,
1040
+ loading,
1041
+ wrapInSafeArea: true,
1042
+ inverted: true,
1043
+ renderLoading: () => /* @__PURE__ */ React__default.createElement(Skeleton, { variant: "rounded", style: {
1044
+ flex: 1
1045
+ } }),
1046
+ messages: messageList,
1047
+ listViewProps: {
1048
+ onEndReached,
1049
+ onEndReachedThreshold: 0.5,
1050
+ onMomentumScrollBegin,
1051
+ style: {
1052
+ marginTop: 0
1053
+ },
1054
+ contentContainerStyle: {
1055
+ paddingTop: 0,
1056
+ paddingBottom: selectedImage ? 90 : 0
1057
+ },
1058
+ refreshControl: /* @__PURE__ */ React__default.createElement(RefreshControl, { refreshing, onRefresh, colors: [colors.blue[500]], tintColor: colors.blue[500], title: "Loading earlier messages...", titleColor: colors.gray[600] })
1059
+ },
1060
+ onSend: (messages) => {
1061
+ var _a2, _b2;
1062
+ return handleSend((_b2 = (_a2 = messages[0]) == null ? void 0 : _a2.text) != null ? _b2 : " ");
1063
+ },
1064
+ text: msg || " ",
1065
+ onInputTextChanged: (text) => setMsg(text),
1066
+ renderFooter: () => null,
1067
+ scrollToBottom: true,
1068
+ user: {
1069
+ _id: (auth == null ? void 0 : auth.id) || ""
1070
+ },
1071
+ placeholder: "Jot something down",
1072
+ infiniteScroll: true,
1073
+ renderSend,
1074
+ renderMessageText,
1075
+ renderMessage,
1076
+ renderLoadEarlier,
1077
+ loadEarlier: totalCount > channelMessages.length,
1078
+ isLoadingEarlier: loadingOldMessages,
1079
+ textInputProps: {
1080
+ multiline: true,
1081
+ returnKeyType: "default",
1082
+ enablesReturnKeyAutomatically: true,
1083
+ placeholderTextColor: colors.gray[400],
1084
+ // Allow direct editing in the main input too for better UX
1085
+ editable: true,
1086
+ onFocus: () => setIsGiftedInputFocused(true),
1087
+ onBlur: () => setIsGiftedInputFocused(false)
1088
+ },
1089
+ renderChatFooter,
1090
+ messagesContainerStyle: __spreadProps(__spreadValues({}, (messageList == null ? void 0 : messageList.length) == 0 ? {
1091
+ transform: [{
1092
+ scaleY: -1
1093
+ }]
1094
+ } : {}), {
1095
+ // marginTop: -40, // Negative margin to remove the top padding
1096
+ paddingTop: 0
1097
+ })
1568
1098
  }
1569
- }) })), messagesContainerStyle: (messageList == null ? void 0 : messageList.length) == 0 && {
1570
- transform: [{
1571
- scaleY: -1
1572
- }]
1573
- }, renderChatEmpty: () => /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, !threadLoading && messageList && (messageList == null ? void 0 : messageList.length) == 0 && /* @__PURE__ */ React__default.createElement(Box, { className: "p-5" }, /* @__PURE__ */ React__default.createElement(Center, { className: "mt-6" }, /* @__PURE__ */ React__default.createElement(Ionicons, { name: "chatbubbles", size: 30 }), /* @__PURE__ */ React__default.createElement(Text, null, "You don't have any message yet!")))), lightboxProps: {
1574
- underlayColor: "transparent",
1575
- springConfig: {
1576
- tension: 9e4,
1577
- friction: 9e4
1578
- },
1579
- disabled: true
1580
- } }));
1099
+ ));
1581
1100
  };
1582
1101
  const SubscriptionHandler = ({
1583
1102
  subscribeToNewMessages,
@@ -1586,4 +1105,4 @@ const SubscriptionHandler = ({
1586
1105
  useEffect(() => subscribeToNewMessages(), [channelId]);
1587
1106
  return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null);
1588
1107
  };
1589
- const ThreadConversationView = React__default.memo(ThreadConversationViewComponent);export{ThreadConversationView};//# sourceMappingURL=ThreadConversationView.js.map
1108
+ const ThreadConversationView = ThreadConversationViewComponent;export{ThreadConversationView};//# sourceMappingURL=ThreadConversationView.js.map