@messenger-box/platform-mobile 10.0.3-alpha.18 → 10.0.3-alpha.180

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 (98) hide show
  1. package/lib/compute.js +2 -3
  2. package/lib/compute.js.map +1 -1
  3. package/lib/index.js.map +1 -1
  4. package/lib/module.js.map +1 -1
  5. package/lib/queries/inboxQueries.js +65 -0
  6. package/lib/queries/inboxQueries.js.map +1 -0
  7. package/lib/routes.json +2 -3
  8. package/lib/screens/inbox/DialogMessages.js +8 -3
  9. package/lib/screens/inbox/DialogMessages.js.map +1 -1
  10. package/lib/screens/inbox/DialogThreadMessages.js +6 -11
  11. package/lib/screens/inbox/DialogThreadMessages.js.map +1 -1
  12. package/lib/screens/inbox/DialogThreads.js +58 -20
  13. package/lib/screens/inbox/DialogThreads.js.map +1 -1
  14. package/lib/screens/inbox/Inbox.js.map +1 -1
  15. package/lib/screens/inbox/components/CachedImage/consts.js.map +1 -1
  16. package/lib/screens/inbox/components/CachedImage/index.js +125 -115
  17. package/lib/screens/inbox/components/CachedImage/index.js.map +1 -1
  18. package/lib/screens/inbox/components/DialogItem.js +160 -0
  19. package/lib/screens/inbox/components/DialogItem.js.map +1 -0
  20. package/lib/screens/inbox/components/GiftedChatInboxComponent.js +313 -0
  21. package/lib/screens/inbox/components/GiftedChatInboxComponent.js.map +1 -0
  22. package/lib/screens/inbox/components/SlackMessageContainer/ImageViewerModal.js +2 -0
  23. package/lib/screens/inbox/components/SlackMessageContainer/ImageViewerModal.js.map +1 -1
  24. package/lib/screens/inbox/components/SlackMessageContainer/PaymentMessage.js +194 -0
  25. package/lib/screens/inbox/components/SlackMessageContainer/PaymentMessage.js.map +1 -0
  26. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js +144 -32
  27. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js.map +1 -1
  28. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js +3 -4
  29. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js.map +1 -1
  30. package/lib/screens/inbox/components/SubscriptionHandler.js +22 -0
  31. package/lib/screens/inbox/components/SubscriptionHandler.js.map +1 -0
  32. package/lib/screens/inbox/components/ThreadsViewItem.js +67 -47
  33. package/lib/screens/inbox/components/ThreadsViewItem.js.map +1 -1
  34. package/lib/screens/inbox/config/config.js +4 -2
  35. package/lib/screens/inbox/config/config.js.map +1 -1
  36. package/lib/screens/inbox/containers/ConversationView.js +1098 -1093
  37. package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
  38. package/lib/screens/inbox/containers/Dialogs.js +179 -333
  39. package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
  40. package/lib/screens/inbox/containers/ThreadConversationView.js +873 -866
  41. package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
  42. package/lib/screens/inbox/containers/ThreadsView.js +81 -54
  43. package/lib/screens/inbox/containers/ThreadsView.js.map +1 -1
  44. package/lib/screens/inbox/hooks/useInboxMessages.js +31 -0
  45. package/lib/screens/inbox/hooks/useInboxMessages.js.map +1 -0
  46. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js +108 -0
  47. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js.map +1 -0
  48. package/lib/screens/inbox/workflow/dialog-threads-xstate.js +151 -0
  49. package/lib/screens/inbox/workflow/dialog-threads-xstate.js.map +1 -0
  50. package/package.json +5 -5
  51. package/CHANGELOG.md +0 -156
  52. package/jest.config.js +0 -24
  53. package/lib/screens/inbox/components/DialogsListItem.js +0 -175
  54. package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
  55. package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -165
  56. package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
  57. package/lib/screens/inbox/containers/workflow/conversation-xstate.js +0 -380
  58. package/lib/screens/inbox/containers/workflow/conversation-xstate.js.map +0 -1
  59. package/lib/screens/inbox/containers/workflow/dialogs-xstate.js +0 -235
  60. package/lib/screens/inbox/containers/workflow/dialogs-xstate.js.map +0 -1
  61. package/lib/screens/inbox/containers/workflow/thread-conversation-xstate.js +0 -438
  62. package/lib/screens/inbox/containers/workflow/thread-conversation-xstate.js.map +0 -1
  63. package/rollup.config.mjs +0 -45
  64. package/src/components/index.ts +0 -0
  65. package/src/compute.ts +0 -63
  66. package/src/index.ts +0 -7
  67. package/src/module.ts +0 -10
  68. package/src/navigation/InboxNavigation.tsx +0 -102
  69. package/src/navigation/index.ts +0 -1
  70. package/src/screens/inbox/DialogMessages.tsx +0 -21
  71. package/src/screens/inbox/DialogThreadMessages.tsx +0 -97
  72. package/src/screens/inbox/DialogThreads.tsx +0 -129
  73. package/src/screens/inbox/Inbox.tsx +0 -17
  74. package/src/screens/inbox/components/CachedImage/consts.ts +0 -6
  75. package/src/screens/inbox/components/CachedImage/index.tsx +0 -223
  76. package/src/screens/inbox/components/DialogsHeader.tsx +0 -30
  77. package/src/screens/inbox/components/DialogsListItem.tsx +0 -302
  78. package/src/screens/inbox/components/ServiceDialogsListItem.tsx +0 -287
  79. package/src/screens/inbox/components/SlackMessageContainer/ImageViewerModal.tsx +0 -113
  80. package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +0 -313
  81. package/src/screens/inbox/components/SlackMessageContainer/SlackMessage.tsx +0 -145
  82. package/src/screens/inbox/components/SlackMessageContainer/index.ts +0 -3
  83. package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +0 -283
  84. package/src/screens/inbox/components/ThreadsViewItem.tsx +0 -321
  85. package/src/screens/inbox/config/config.ts +0 -15
  86. package/src/screens/inbox/config/index.ts +0 -1
  87. package/src/screens/inbox/containers/ConversationView.tsx +0 -1782
  88. package/src/screens/inbox/containers/Dialogs.tsx +0 -544
  89. package/src/screens/inbox/containers/SupportServiceDialogs.tsx +0 -119
  90. package/src/screens/inbox/containers/ThreadConversationView.tsx +0 -1537
  91. package/src/screens/inbox/containers/ThreadsView.tsx +0 -305
  92. package/src/screens/inbox/containers/workflow/apollo/handleResult.ts +0 -20
  93. package/src/screens/inbox/containers/workflow/conversation-xstate.ts +0 -313
  94. package/src/screens/inbox/containers/workflow/dialogs-xstate.ts +0 -196
  95. package/src/screens/inbox/containers/workflow/thread-conversation-xstate.ts +0 -401
  96. package/src/screens/index.ts +0 -4
  97. package/tsconfig.json +0 -13
  98. 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,VStack,HStack,Avatar,AvatarFallbackText,AvatarImage,Center,Image}from'@admin-layout/gluestack-ui-mobile';import {Platform,SafeAreaView,Linking,View,TouchableHighlight}from'react-native';import {useRoute,useNavigation,useFocusEffect}from'@react-navigation/native';import {useSelector}from'react-redux';import {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,343 +25,140 @@ const {
25
25
  CALL_TO_ACTION_TEXT_COLOR
26
26
  } = config;
27
27
  const createdAtText = (value) => {
28
- if (!value)
29
- return "";
28
+ if (!value) return "";
30
29
  let date = new Date(value);
31
- if (isToday(date))
32
- return "Today";
33
- if (isYesterday(date))
34
- return "Yesterday";
30
+ if (isToday(date)) return "Today";
31
+ if (isYesterday(date)) return "Yesterday";
35
32
  return format(new Date(value), "MMM dd, yyyy");
36
33
  };
37
- function useSafeMachine(machine) {
38
- const [state, setState] = useState({
39
- context: {
40
- channelId: null,
41
- postParentId: null,
42
- role: null,
43
- threadMessages: [],
44
- totalCount: 0,
45
- skip: 0,
46
- loading: false,
47
- loadingOldMessages: false,
48
- error: null,
49
- selectedImage: "",
50
- files: [],
51
- images: [],
52
- messageText: "",
53
- imageLoading: false,
54
- postThread: null,
55
- threadPost: [],
56
- isScrollToBottom: false
57
- },
58
- value: "idle"
59
- });
60
- const send = useCallback((event) => {
61
- var _a, _b, _c, _d;
62
- try {
63
- console.log("Thread Event received:", event.type);
64
- if (event.type === Actions.INITIAL_CONTEXT) {
65
- setState((prev) => {
66
- var _a2, _b2, _c2;
67
- return __spreadProps(__spreadValues({}, prev), {
68
- context: __spreadProps(__spreadValues({}, prev.context), {
69
- channelId: ((_a2 = event.data) == null ? void 0 : _a2.channelId) || null,
70
- postParentId: ((_b2 = event.data) == null ? void 0 : _b2.postParentId) || null,
71
- role: ((_c2 = event.data) == null ? void 0 : _c2.role) || null
72
- }),
73
- value: BaseState.FetchThreadMessages
74
- });
75
- });
76
- } else if (event.type === Actions.SET_THREAD_MESSAGES) {
77
- setState((prev) => {
78
- var _a2, _b2, _c2, _d2;
79
- return __spreadProps(__spreadValues({}, prev), {
80
- context: __spreadProps(__spreadValues({}, prev.context), {
81
- threadMessages: ((_a2 = event.data) == null ? void 0 : _a2.messages) || [],
82
- totalCount: ((_b2 = event.data) == null ? void 0 : _b2.totalCount) || 0,
83
- loading: false,
84
- loadingOldMessages: false,
85
- threadPost: ((_c2 = event.data) == null ? void 0 : _c2.threadPost) || [],
86
- postThread: ((_d2 = event.data) == null ? void 0 : _d2.postThread) || null
87
- }),
88
- value: "active"
89
- });
90
- });
91
- } else if (event.type === Actions.CLEAR_MESSAGES) {
92
- setState((prev) => __spreadProps(__spreadValues({}, prev), {
93
- context: __spreadProps(__spreadValues({}, prev.context), {
94
- threadMessages: [],
95
- totalCount: 0
96
- })
97
- }));
98
- } else if (event.type === Actions.SET_MESSAGE_TEXT) {
99
- setState((prev) => {
100
- var _a2;
101
- return __spreadProps(__spreadValues({}, prev), {
102
- context: __spreadProps(__spreadValues({}, prev.context), {
103
- messageText: ((_a2 = event.data) == null ? void 0 : _a2.messageText) || ""
104
- })
105
- });
106
- });
107
- } else if (event.type === Actions.FETCH_MORE_MESSAGES) {
108
- setState((prev) => __spreadProps(__spreadValues({}, prev), {
109
- context: __spreadProps(__spreadValues({}, prev.context), {
110
- loadingOldMessages: true
111
- }),
112
- value: MainState.FetchMoreMessages
113
- }));
114
- } else if (event.type === Actions.SET_IMAGE) {
115
- setState((prev) => {
116
- var _a2, _b2, _c2;
117
- return __spreadProps(__spreadValues({}, prev), {
118
- context: __spreadProps(__spreadValues({}, prev.context), {
119
- selectedImage: ((_a2 = event.data) == null ? void 0 : _a2.image) || "",
120
- images: ((_b2 = event.data) == null ? void 0 : _b2.images) || [],
121
- files: ((_c2 = event.data) == null ? void 0 : _c2.files) || [],
122
- imageLoading: false
123
- })
124
- });
125
- });
126
- } else if (event.type === Actions.CLEAR_IMAGE) {
127
- setState((prev) => __spreadProps(__spreadValues({}, prev), {
128
- context: __spreadProps(__spreadValues({}, prev.context), {
129
- selectedImage: "",
130
- images: [],
131
- files: []
132
- })
133
- }));
134
- } else if (event.type === Actions.START_LOADING) {
135
- setState((prev) => __spreadProps(__spreadValues({}, prev), {
136
- context: __spreadProps(__spreadValues({}, prev.context), {
137
- loading: true
138
- })
139
- }));
140
- } else if (event.type === Actions.STOP_LOADING) {
141
- setState((prev) => __spreadProps(__spreadValues({}, prev), {
142
- context: __spreadProps(__spreadValues({}, prev.context), {
143
- loading: false
144
- })
145
- }));
146
- } else if (event.type === Actions.SEND_THREAD_MESSAGE) {
147
- console.log("Sending message event with text:", (_a = event.data) == null ? void 0 : _a.messageText);
148
- setState((prev) => {
149
- var _a2;
150
- return __spreadProps(__spreadValues({}, prev), {
151
- context: __spreadProps(__spreadValues({}, prev.context), {
152
- loading: true,
153
- messageText: ((_a2 = event.data) == null ? void 0 : _a2.messageText) || prev.context.messageText
154
- }),
155
- value: MainState.SendThreadMessage
156
- });
157
- });
158
- } else if (event.type === Actions.SEND_THREAD_MESSAGE_WITH_FILE) {
159
- console.log("Sending message with file event, text:", (_b = event.data) == null ? void 0 : _b.messageText);
160
- setState((prev) => {
161
- var _a2;
162
- return __spreadProps(__spreadValues({}, prev), {
163
- context: __spreadProps(__spreadValues({}, prev.context), {
164
- loading: true,
165
- messageText: ((_a2 = event.data) == null ? void 0 : _a2.messageText) || prev.context.messageText
166
- }),
167
- value: MainState.SendThreadMessageWithFile
168
- });
169
- });
170
- } else if (event.type === "SEND_THREAD_MESSAGE_SUCCESS" || event.type === "SEND_THREAD_MESSAGE_WITH_FILE_SUCCESS") {
171
- console.log("Handling send success event:", event.type, "with message:", (_d = (_c = event.data) == null ? void 0 : _c.message) == null ? void 0 : _d.id);
172
- setState((prev) => {
173
- var _a2;
174
- if (!((_a2 = event.data) == null ? void 0 : _a2.message)) {
175
- console.warn("Send success event without message data");
176
- return __spreadProps(__spreadValues({}, prev), {
177
- context: __spreadProps(__spreadValues({}, prev.context), {
178
- loading: false,
179
- messageText: "",
180
- images: [],
181
- selectedImage: "",
182
- files: []
183
- }),
184
- value: "active"
185
- });
186
- }
187
- const newMessage = event.data.message;
188
- const updatedMessages = [newMessage, ...prev.context.threadMessages];
189
- console.log("Updated thread messages list after send, now has", updatedMessages.length, "messages");
190
- return __spreadProps(__spreadValues({}, prev), {
191
- context: __spreadProps(__spreadValues({}, prev.context), {
192
- loading: false,
193
- messageText: "",
194
- images: [],
195
- selectedImage: "",
196
- files: [],
197
- threadMessages: updatedMessages,
198
- totalCount: prev.context.totalCount + 1
199
- }),
200
- value: "active"
201
- });
202
- });
203
- } else if (event.type === "FETCH_MORE_MESSAGES_SUCCESS") {
204
- setState((prev) => {
205
- var _a2;
206
- const newMessages = ((_a2 = event.data) == null ? void 0 : _a2.messages) || [];
207
- return __spreadProps(__spreadValues({}, prev), {
208
- context: __spreadProps(__spreadValues({}, prev.context), {
209
- loadingOldMessages: false,
210
- threadMessages: uniqBy([...prev.context.threadMessages, ...newMessages], ({
211
- id
212
- }) => id)
213
- }),
214
- value: "active"
215
- });
216
- });
217
- } else if (event.type === "ERROR") {
218
- setState((prev) => {
219
- var _a2;
220
- return __spreadProps(__spreadValues({}, prev), {
221
- context: __spreadProps(__spreadValues({}, prev.context), {
222
- loading: false,
223
- loadingOldMessages: false,
224
- error: ((_a2 = event.data) == null ? void 0 : _a2.message) || "Unknown error"
225
- }),
226
- value: "error"
227
- });
228
- });
229
- }
230
- } catch (error) {
231
- console.error("Error in thread conversation send function:", error);
232
- }
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);
233
53
  }, []);
234
- const stateWithMatches = useMemo(() => {
235
- return __spreadProps(__spreadValues({}, state), {
236
- matches: (checkState) => {
237
- return state.value === checkState;
238
- }
239
- });
240
- }, [state]);
241
- return [stateWithMatches, send];
242
- }
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
+ };
243
83
  const ThreadConversationViewComponent = ({
244
84
  channelId,
245
85
  postParentId,
246
86
  isPostParentIdThread,
247
87
  role
248
88
  }) => {
249
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
89
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
250
90
  const {
251
91
  params
252
92
  } = useRoute();
253
93
  const [channelToTop, setChannelToTop] = useState(0);
254
- useRef(true);
255
- const [state, send] = useSafeMachine();
256
- useCallback(() => {
257
- try {
258
- return (state == null ? void 0 : state.context) || {};
259
- } catch (error) {
260
- console.error("Error accessing state.context:", error);
261
- return {};
262
- }
263
- }, [state]);
264
- const safeContextProperty = useCallback((property, defaultValue = null) => {
265
- var _a2, _b2;
266
- try {
267
- return (_b2 = (_a2 = state == null ? void 0 : state.context) == null ? void 0 : _a2[property]) != null ? _b2 : defaultValue;
268
- } catch (error) {
269
- console.error(`Error accessing state.context.${property}:`, error);
270
- return defaultValue;
271
- }
272
- }, [state]);
273
- const safeMatches = useCallback((stateValue) => {
274
- var _a2;
275
- try {
276
- return ((_a2 = state == null ? void 0 : state.matches) == null ? void 0 : _a2.call(state, stateValue)) || false;
277
- } catch (error) {
278
- console.error(`Error calling state.matches with ${stateValue}:`, error);
279
- return false;
280
- }
281
- }, [state]);
282
- const safeSend = useCallback((event) => {
283
- try {
284
- send(event);
285
- } catch (error) {
286
- console.error("Error sending event to state machine:", error, event);
287
- }
288
- }, [send]);
289
- const stateRef = useRef(state);
290
- useEffect(() => {
291
- stateRef.current = state;
292
- }, [state]);
94
+ const [channelMessages, setChannelMessages] = useState([]);
293
95
  const auth = useSelector(userSelector);
294
- 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);
295
100
  const navigation = useNavigation();
296
101
  const [files, setFiles] = useState([]);
297
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([]);
298
108
  const [isShowImageViewer, setImageViewer] = useState(false);
299
109
  const [imageObject, setImageObject] = useState({});
300
110
  const [parentId, setParentId] = useState(postParentId);
301
- const [expoTokens, setExpoTokens] = useState([]);
302
- const threadMessageListRef = useRef(null);
303
- const [sendThreadMessage] = useCreatePostThreadMutation();
304
- const [sendExpoNotificationOnPostMutation] = useSendExpoNotificationOnPostMutation();
111
+ const [postThread, setPostThread] = useState();
305
112
  const {
306
113
  startUpload
307
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();
308
126
  const [getThreadMessages, {
309
127
  data,
310
128
  loading: threadLoading,
311
129
  fetchMore: fetchMoreMessages,
312
130
  refetch: refetchThreadMessages,
313
131
  subscribeToMore
314
- }] = useGetPostThreadLazyQuery({
132
+ }] = useGetPostThreadLazy({
315
133
  fetchPolicy: "cache-and-network"
316
134
  });
135
+ const [pendingUploads, setPendingUploads] = useState({});
136
+ const [uploadErrors, setUploadErrors] = useState({});
137
+ const [isUploadingImage, setIsUploadingImage] = useState(false);
138
+ const [refreshing, setRefreshing] = useState(false);
317
139
  useFocusEffect(React__default.useCallback(() => {
318
140
  var _a2;
319
141
  navigation.setOptions({
320
142
  title: (_a2 = params == null ? void 0 : params.title) != null ? _a2 : "Thread",
321
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" }))
322
144
  });
323
- if (channelId && postParentId) {
324
- safeSend({
325
- type: Actions.INITIAL_CONTEXT,
326
- data: {
327
- channelId,
328
- postParentId,
329
- role
330
- }
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
331
152
  });
332
153
  }
333
154
  setParentId(postParentId);
334
155
  return () => {
335
- safeSend({
336
- type: Actions.CLEAR_MESSAGES
337
- });
156
+ setTotalCount(0);
157
+ setChannelMessages([]);
158
+ setThreadPost([]);
338
159
  };
339
160
  }, [postParentId]));
340
161
  useEffect(() => {
341
- if (safeMatches(BaseState.FetchThreadMessages)) {
342
- fetchThreadMessages();
343
- }
344
- }, [state.value]);
345
- useEffect(() => {
346
- if (safeMatches(MainState.FetchMoreMessages)) {
347
- onFetchOld();
348
- }
349
- }, [state.value]);
350
- useEffect(() => {
351
- if (safeMatches(MainState.SendThreadMessage)) {
352
- const messageText = safeContextProperty("messageText", "");
353
- console.log("Sending message from state transition, text:", messageText);
354
- sendThreadMessageHandler(messageText);
355
- }
356
- }, [state.value]);
357
- useEffect(() => {
358
- if (safeMatches(MainState.SendThreadMessageWithFile)) {
359
- const messageText = safeContextProperty("messageText", "");
360
- const images2 = safeContextProperty("images", []);
361
- sendThreadMessageWithFileHandler(messageText, images2);
362
- }
363
- }, [state.value]);
364
- const fetchThreadMessages = useCallback(() => {
365
162
  if (channelId && parentId) {
366
163
  getThreadMessages({
367
164
  variables: {
@@ -371,78 +168,42 @@ const ThreadConversationViewComponent = ({
371
168
  selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
372
169
  limit: MESSAGES_PER_PAGE
373
170
  }
374
- }).then(({
375
- data: data2
376
- }) => {
377
- var _a2, _b2, _c2;
378
- if (data2 == null ? void 0 : data2.getPostThread) {
379
- const threads = data2.getPostThread;
380
- const threadPost = (_a2 = threads == null ? void 0 : threads.post) != null ? _a2 : [];
381
- const threadReplies = (_b2 = threads == null ? void 0 : threads.replies) != null ? _b2 : [];
382
- const messageTotalCount = (_c2 = threads == null ? void 0 : threads.replyCount) != null ? _c2 : 0;
383
- const messages = [...threadReplies];
384
- safeSend({
385
- type: Actions.SET_THREAD_MESSAGES,
386
- data: {
387
- messages,
388
- totalCount: messageTotalCount,
389
- threadPost,
390
- postThread: threads
391
- }
392
- });
393
- }
394
- }).catch((error) => {
395
- safeSend({
396
- type: "ERROR",
397
- data: {
398
- message: error.message
399
- }
400
- });
401
171
  });
402
172
  }
403
- }, [channelId, parentId, role]);
173
+ }, [parentId]);
404
174
  React__default.useEffect(() => {
405
175
  var _a2, _b2, _c2;
406
176
  if (data == null ? void 0 : data.getPostThread) {
407
177
  const threads = data.getPostThread;
408
- const threadPost = (_a2 = threads == null ? void 0 : threads.post) != null ? _a2 : [];
178
+ const threadPost2 = (_a2 = threads == null ? void 0 : threads.post) != null ? _a2 : [];
409
179
  const threadReplies = (_b2 = threads == null ? void 0 : threads.replies) != null ? _b2 : [];
410
180
  const messeageTotalCount = (_c2 = threads == null ? void 0 : threads.replyCount) != null ? _c2 : 0;
411
- const messages = [...threadReplies];
412
- safeSend({
413
- type: Actions.SET_THREAD_MESSAGES,
414
- data: {
415
- messages,
416
- totalCount: messeageTotalCount,
417
- threadPost,
418
- postThread: threads
419
- }
420
- });
181
+ const messages = [threadPost2, ...threadReplies];
182
+ if (messages && messages.length > 0 && messeageTotalCount > totalCount || messages && messages.length > 0 && channelMessages.length === 0) {
183
+ setThreadMessages(messages, messeageTotalCount);
184
+ }
421
185
  }
422
- }, [data]);
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
+ };
423
194
  React__default.useEffect(() => {
424
- if (safeContextProperty("selectedImage")) {
425
- safeSend({
426
- type: Actions.STOP_LOADING
427
- });
428
- }
429
- }, [safeContextProperty("selectedImage")]);
430
- React__default.useCallback(() => {
195
+ if (selectedImage) setImageLoading(false);
196
+ }, [selectedImage]);
197
+ const scrollToBottom = React__default.useCallback(() => {
431
198
  if (threadMessageListRef == null ? void 0 : threadMessageListRef.current) {
432
- threadMessageListRef.current.scrollToBottom();
199
+ setIsScrollToBottom(false);
200
+ threadMessageListRef.current.scrollTop = threadMessageListRef.current.scrollHeight;
433
201
  }
434
202
  }, [threadMessageListRef]);
435
203
  const onFetchOld = useCallback(() => {
436
- const totalCount = safeContextProperty("totalCount", 0);
437
- const threadMessages = safeContextProperty("threadMessages", []);
438
- if (totalCount > threadMessages.length && !safeContextProperty("loadingOldMessages", false)) {
439
- console.log("Loading more messages - current count:", threadMessages.length, "of", totalCount);
440
- safeSend({
441
- type: Actions.START_LOADING,
442
- data: {
443
- loadingOldMessages: true
444
- }
445
- });
204
+ if (totalCount > channelMessages.length && !loadingOldMessages) {
205
+ setLoadEarlierMsg(true);
206
+ setLoadingOldMessages(true);
446
207
  fetchMoreMessages({
447
208
  variables: {
448
209
  channelId: channelId == null ? void 0 : channelId.toString(),
@@ -450,307 +211,318 @@ const ThreadConversationViewComponent = ({
450
211
  postParentId: parentId == null ? void 0 : parentId.toString(),
451
212
  selectedFields: "id channel post replies replyCount lastReplyAt createdAt updatedAt",
452
213
  limit: MESSAGES_PER_PAGE,
453
- skip: threadMessages.length
214
+ skip: channelMessages.length - 1
454
215
  }
455
216
  }).then((res) => {
456
- var _a2, _b2, _c2;
217
+ var _a2, _b2, _c2, _d2;
457
218
  if ((_a2 = res == null ? void 0 : res.data) == null ? void 0 : _a2.getPostThread) {
458
219
  const threads = (_b2 = res == null ? void 0 : res.data) == null ? void 0 : _b2.getPostThread;
459
220
  const threadReplies = (_c2 = threads == null ? void 0 : threads.replies) != null ? _c2 : [];
460
- console.log("Successfully loaded more messages:", threadReplies.length);
461
- safeSend({
462
- type: "FETCH_MORE_MESSAGES_SUCCESS",
463
- data: {
464
- messages: threadReplies,
465
- loadingOldMessages: false
466
- }
467
- });
468
- } else {
469
- console.log("No thread data returned when loading more messages");
470
- safeSend({
471
- type: Actions.STOP_LOADING,
472
- data: {
473
- loadingOldMessages: false
474
- }
475
- });
221
+ const messeageTotalCount = (_d2 = threads == null ? void 0 : threads.replyCount) != null ? _d2 : 0;
222
+ setThreadMessages(threadReplies, messeageTotalCount);
476
223
  }
224
+ }).finally(() => {
225
+ setLoadEarlierMsg(false);
226
+ setLoadingOldMessages(false);
227
+ setRefreshing(false);
477
228
  }).catch((error) => {
478
- console.error("Error fetching more messages:", error);
479
- safeSend({
480
- type: "ERROR",
481
- data: {
482
- message: error.message,
483
- loadingOldMessages: false
484
- }
485
- });
229
+ setLoadEarlierMsg(false);
230
+ setLoadingOldMessages(false);
231
+ setRefreshing(false);
486
232
  });
487
233
  } else {
488
- console.log("No more messages to load or already loading");
489
- }
490
- }, [parentId, channelId, state.context]);
491
- const handleScrollToTop = ({
492
- nativeEvent
493
- }) => {
494
- if (isCloseToTop(nativeEvent)) {
495
- if (!safeContextProperty("loadingOldMessages", false) && safeContextProperty("totalCount", 0) > safeContextProperty("threadMessages", []).length) {
496
- console.log("Near top of list - loading older messages");
497
- safeSend({
498
- type: Actions.FETCH_MORE_MESSAGES
499
- });
500
- }
234
+ setRefreshing(false);
501
235
  }
502
- };
503
- const handleEndReached = () => {
504
- console.log("Reached end of message list");
505
- };
236
+ }, [parentId, channelId, totalCount, channelMessages]);
237
+ const onRefresh = useCallback(() => {
238
+ setRefreshing(true);
239
+ onFetchOld();
240
+ }, [onFetchOld]);
506
241
  const isCloseToTop = ({
507
242
  layoutMeasurement,
508
243
  contentOffset,
509
244
  contentSize
510
245
  }) => {
511
- const paddingToTop = 80;
512
- return contentOffset.y <= paddingToTop;
246
+ const paddingToTop = 60;
247
+ return contentSize.height - layoutMeasurement.height - paddingToTop <= contentOffset.y;
513
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
+ }, []);
514
262
  const onSelectImages = async () => {
515
- var _a2;
263
+ setLoading(true);
516
264
  try {
517
- safeSend({
518
- type: Actions.START_LOADING
519
- });
520
- const imageSource = await ImagePicker.launchImageLibraryAsync({
265
+ let imageSource = await ImagePicker.launchImageLibraryAsync({
521
266
  mediaTypes: ImagePicker.MediaTypeOptions.Images,
522
- allowsEditing: true,
267
+ allowsEditing: false,
523
268
  aspect: [4, 3],
524
269
  quality: 0.8,
525
270
  base64: true,
526
- allowsMultipleSelection: false
271
+ exif: false,
272
+ allowsMultipleSelection: true
273
+ // Enable multiple selection
527
274
  });
528
- if (imageSource.canceled) {
529
- console.log("Image selection was canceled");
530
- safeSend({
531
- type: Actions.STOP_LOADING
532
- });
533
- return;
534
- }
535
- if (!imageSource.assets || imageSource.assets.length === 0 || !((_a2 = imageSource.assets[0]) == null ? void 0 : _a2.base64)) {
536
- console.error("No valid image data received");
537
- safeSend({
538
- type: "ERROR",
539
- data: {
540
- message: "No valid image data received"
541
- }
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;
542
290
  });
543
- return;
544
- }
545
- const asset = imageSource.assets[0];
546
- const fileExtension = asset.mimeType ? asset.mimeType.split("/").pop() || "jpg" : "jpg";
547
- const filename = `image_${Date.now()}.${fileExtension}`;
548
- const mimeType = asset.mimeType || "image/jpeg";
549
- const image = `data:${mimeType};base64,${asset.base64}`;
550
- const fileData = {
551
- uri: asset.uri,
552
- type: mimeType,
553
- name: filename,
554
- base64: asset.base64
555
- };
556
- console.log(`Selected image: ${filename}, type: ${mimeType}`);
557
- safeSend({
558
- type: Actions.SET_IMAGE,
559
- data: {
560
- image,
561
- files: [fileData],
562
- 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);
563
295
  }
564
- });
296
+ setImages((currentImages) => [...currentImages, ...newImages]);
297
+ setLoading(false);
298
+ } else {
299
+ setLoading(false);
300
+ }
565
301
  } catch (error) {
566
- console.error("Error selecting image:", error);
567
- safeSend({
568
- type: "ERROR",
569
- data: {
570
- message: error.message || "Failed to select image"
571
- }
572
- });
302
+ setLoading(false);
573
303
  }
574
304
  };
575
- const sendThreadMessageHandler = useCallback(async (message) => {
576
- var _a2, _b2;
577
- console.log("Sending message:", message);
578
- if (!channelId) {
579
- console.error("No channelId provided");
580
- 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();
581
319
  }
582
- const messageContent = (message == null ? void 0 : message.trim()) || " ";
583
- 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);
584
330
  const postId = objectId();
585
- console.log("Generated postId:", postId);
586
- safeSend({
587
- type: Actions.START_LOADING
588
- });
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
+ }
589
381
  try {
590
- console.log("Sending mutation with variables:", {
591
- channelId,
592
- postThreadId: (_a2 = safeContextProperty("postThread")) == null ? void 0 : _a2.id,
593
- postParentId: !parentId || parentId == 0 ? null : parentId,
594
- message: messageContent
595
- });
596
- 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({
597
448
  variables: {
449
+ postId,
598
450
  channelId,
599
- postThreadId: safeContextProperty("postThread") && ((_b2 = safeContextProperty("postThread")) == null ? void 0 : _b2.id),
600
- postParentId: !parentId || parentId == 0 ? null : parentId,
451
+ postThreadId: postThread && (postThread == null ? void 0 : postThread.id),
452
+ postParentId: !parentId || parentId === 0 ? null : parentId,
601
453
  threadMessageInput: {
602
- content: messageContent,
454
+ content: currentMessageText,
455
+ files: fileIds,
603
456
  role
604
457
  }
605
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
+ },
606
486
  update: (cache, {
607
487
  data: data2,
608
488
  errors
609
489
  }) => {
610
- var _a3, _b3, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2;
611
- console.log("Send message update callback - data:", data2, "errors:", errors);
612
- if (!data2 || errors) {
613
- console.error("Send message failed:", errors);
614
- safeSend({
615
- type: Actions.STOP_LOADING
616
- });
617
- return;
618
- }
619
- console.log("Message sent successfully:", (_a3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _a3.lastMessage);
620
- const newMessage = (_b3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _b3.lastMessage;
621
- safeSend({
622
- type: "SEND_THREAD_MESSAGE_SUCCESS",
623
- data: {
624
- message: newMessage,
625
- messageText: ""
626
- }
627
- });
628
- if (!parentId || parentId == 0) {
629
- console.log("Setting new parentId:", (_d2 = (_c2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _c2.lastMessage) == null ? void 0 : _d2.id);
630
- 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);
631
496
  }
632
497
  setChannelToTop(channelToTop + 1);
633
- const lastMessageId = (_h2 = (_g2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _g2.lastMessage) == null ? void 0 : _h2.id;
634
- 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);
635
499
  }
636
500
  });
637
- console.log("Send mutation result:", result);
638
501
  } catch (error) {
639
502
  console.error("Error sending message:", error);
640
- safeSend({
641
- type: "ERROR",
642
- data: {
643
- 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";
644
509
  }
645
- });
646
- }
647
- }, [channelId, parentId, state.context, role]);
648
- const sendThreadMessageWithFileHandler = useCallback(async (message, images2) => {
649
- var _a2, _b2;
650
- console.log("Sending message with file:", message, "Images:", images2.length);
651
- if (!channelId) {
652
- console.error("No channelId provided");
653
- return;
654
- }
655
- if (images2.length === 0) {
656
- console.error("No images to send");
657
- return;
658
- }
659
- const messageContent = (message == null ? void 0 : message.trim()) || " ";
660
- console.log("Using message content for file send:", messageContent);
661
- const postId = objectId();
662
- console.log("Generated postId for file upload:", postId);
663
- try {
664
- const preparedImages = images2.map((img) => ({
665
- uri: img.uri,
666
- type: img.mimeType || "image/jpeg",
667
- name: img.fileName || `image_${Date.now()}.jpg`,
668
- base64: img.base64,
669
- width: img.width || 0,
670
- height: img.height || 0
671
- }));
672
- console.log("Starting file upload with prepared images:", preparedImages.length);
673
- const uploadResponse = await startUpload({
674
- file: preparedImages,
675
- saveUploadedFile: {
676
- variables: {
677
- postId
678
- }
679
- },
680
- createUploadLink: {
681
- variables: {
682
- postId
683
- }
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.";
684
515
  }
685
- });
686
- if (uploadResponse == null ? void 0 : uploadResponse.error) {
687
- console.error("File upload failed:", uploadResponse.error);
688
- safeSend({
689
- type: Actions.STOP_LOADING
690
- });
691
- return;
692
- }
693
- const uploadedFiles = uploadResponse.data;
694
- console.log("Files uploaded successfully:", uploadedFiles == null ? void 0 : uploadedFiles.length);
695
- if (uploadResponse.data) {
696
- const files2 = (_a2 = uploadedFiles == null ? void 0 : uploadedFiles.map((f) => f.id)) != null ? _a2 : null;
697
- console.log("File IDs for message:", files2);
698
- console.log("Sending message with attached files");
699
- const result = await sendThreadMessage({
700
- variables: {
701
- postId,
702
- channelId,
703
- postThreadId: safeContextProperty("postThread") && ((_b2 = safeContextProperty("postThread")) == null ? void 0 : _b2.id),
704
- postParentId: !parentId || parentId == 0 ? null : parentId,
705
- threadMessageInput: {
706
- content: messageContent,
707
- files: files2,
708
- role
709
- }
710
- },
711
- update: (cache, {
712
- data: data2,
713
- errors
714
- }) => {
715
- var _a3, _b3, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2;
716
- console.log("Send message with file update callback - data:", data2, "errors:", errors);
717
- if (!data2 || errors) {
718
- console.error("Send message with file failed:", errors);
719
- safeSend({
720
- type: Actions.STOP_LOADING
721
- });
722
- return;
723
- }
724
- console.log("Message with file sent successfully:", (_a3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _a3.lastMessage);
725
- const newMessage = (_b3 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _b3.lastMessage;
726
- safeSend({
727
- type: "SEND_THREAD_MESSAGE_WITH_FILE_SUCCESS",
728
- data: {
729
- message: newMessage,
730
- messageText: ""
731
- }
732
- });
733
- if (!parentId || parentId == 0) {
734
- console.log("Setting new parentId:", (_d2 = (_c2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _c2.lastMessage) == null ? void 0 : _d2.id);
735
- setParentId((_f2 = (_e2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _e2.lastMessage) == null ? void 0 : _f2.id);
736
- }
737
- setChannelToTop(channelToTop + 1);
738
- const lastMessageId = (_h2 = (_g2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _g2.lastMessage) == null ? void 0 : _h2.id;
739
- sendPushNotification(lastMessageId, channelId, parentId, (_j2 = (_i2 = data2 == null ? void 0 : data2.createPostThread) == null ? void 0 : _i2.data) == null ? void 0 : _j2.id);
740
- }
741
- });
742
- console.log("Send with file mutation result:", result);
743
516
  }
744
- } catch (error) {
745
- console.error("Error sending message with file:", error);
746
- safeSend({
747
- type: "ERROR",
748
- data: {
749
- message: error.message || "Failed to send message with file"
750
- }
751
- });
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);
752
524
  }
753
- }, [channelId, parentId, state.context, role, startUpload]);
525
+ }, [auth, channelId, channelToTop, images, parentId, postThread, selectedImage, setChannelMessages, removeMessageFromUI, role]);
754
526
  const sendPushNotification = async (messageId, channelId2, parentId2, threadId) => {
755
527
  var _a2;
756
528
  const notificationData = {
@@ -779,74 +551,264 @@ const ThreadConversationViewComponent = ({
779
551
  }
780
552
  };
781
553
  const messageList = useMemo(() => {
782
- const threadMessages = safeContextProperty("threadMessages", []);
783
- console.log(`Creating message list from ${threadMessages.length} thread messages`);
784
554
  let res = [];
785
- if (threadMessages == null ? void 0 : threadMessages.length) {
786
- const messageIds = /* @__PURE__ */ new Set();
787
- res = threadMessages.filter((msg) => {
788
- if (!msg.id || messageIds.has(msg.id)) {
789
- console.log("Skipping duplicate message ID:", msg.id);
790
- return false;
791
- }
792
- messageIds.add(msg.id);
793
- return true;
794
- }).map((msg) => {
795
- var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2;
796
- const uniqueId = msg.id || `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
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;
797
561
  let message = {
798
- _id: uniqueId,
799
- text: msg.message || "",
800
- createdAt: new Date(msg.createdAt),
562
+ _id: "",
563
+ text: "",
564
+ createdAt: 0,
801
565
  user: {
802
- _id: (_c2 = (_a2 = msg == null ? void 0 : msg.author) == null ? void 0 : _a2.id) != null ? _c2 : (_b2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _b2.id,
803
- name: (_i2 = (_g2 = (_d2 = msg == null ? void 0 : msg.author) == null ? void 0 : _d2.givenName) != null ? _g2 : ((_e2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _e2.given_name) + " " + ((_f2 = msg == null ? void 0 : msg.author) == null ? void 0 : _f2.familyName)) != null ? _i2 : (_h2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _h2.family_name,
804
- avatar: (_l2 = (_j2 = msg == null ? void 0 : msg.author) == null ? void 0 : _j2.picture) != null ? _l2 : (_k2 = auth == null ? void 0 : auth.profile) == null ? void 0 : _k2.picture
566
+ _id: "",
567
+ name: "",
568
+ avatar: ""
805
569
  },
806
- type: (msg == null ? void 0 : msg.type) || "",
807
- image: (_o2 = (_n2 = (_m2 = msg == null ? void 0 : msg.files) == null ? void 0 : _m2.data) == null ? void 0 : _n2[0]) == null ? void 0 : _o2.url,
808
- sent: (msg == null ? void 0 : msg.isDelivered) || true,
809
- received: (msg == null ? void 0 : msg.isRead) || false,
810
- propsConfiguration: msg == null ? void 0 : msg.propsConfiguration
570
+ type: ""
571
+ };
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
811
580
  };
812
- return message;
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);
813
604
  });
814
605
  }
815
- const sortedMessages = res.sort((a, b) => b.createdAt - a.createdAt);
816
- return sortedMessages;
817
- }, [safeContextProperty("threadMessages"), auth]);
818
- const renderSend = (props) => {
819
- const hasImage = safeContextProperty("selectedImage", "") !== "";
820
- const isDisabled = !hasImage && (!props.text || props.text.trim().length === 0);
821
- return /* @__PURE__ */ React__default.createElement(Send, __spreadProps(__spreadValues({}, props), { containerStyle: {
822
- alignItems: "center",
823
- justifyContent: "center",
824
- marginHorizontal: 4,
825
- marginBottom: 0
826
- }, disabled: isDisabled }), /* @__PURE__ */ React__default.createElement(Box, { style: {
827
- width: 32,
828
- height: 32,
829
- alignItems: "center",
830
- justifyContent: "center"
831
- } }, /* @__PURE__ */ React__default.createElement(MaterialCommunityIcons, { name: "send-circle", size: 30, color: isDisabled ? colors.gray[400] : colors.blue[500] })));
832
- };
833
- const renderActions = (props) => {
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
+ };
669
+ }
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
+ };
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) : ""))));
794
+ }
795
+ }, [navigation, channelId, role]);
796
+ useCallback((props) => {
834
797
  return /* @__PURE__ */ React__default.createElement(
835
- Actions$1,
798
+ Actions,
836
799
  __spreadProps(__spreadValues({}, props), {
800
+ onPressActionButton: onSelectImages,
837
801
  options: {
838
- ["Choose from Library"]: onSelectImages,
802
+ ["Choose from Library"]: () => {
803
+ onSelectImages();
804
+ },
839
805
  ["Cancel"]: () => {
840
806
  }
807
+ // Add this option to make the sheet dismissible
841
808
  },
842
809
  optionTintColor: "#000000",
843
810
  cancelButtonIndex: 1,
844
- icon: () => /* @__PURE__ */ React__default.createElement(Box, { style: {
845
- width: 32,
846
- height: 32,
847
- alignItems: "center",
848
- justifyContent: "center"
849
- } }, /* @__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] })),
850
812
  containerStyle: {
851
813
  alignItems: "center",
852
814
  justifyContent: "center",
@@ -855,61 +817,91 @@ const ThreadConversationViewComponent = ({
855
817
  }
856
818
  })
857
819
  );
858
- };
859
- const renderAccessory = (props) => {
860
- var _a2, _b2;
861
- const selectedImage2 = safeContextProperty("selectedImage", "");
862
- if (!selectedImage2) {
863
- return null;
864
- }
865
- return /* @__PURE__ */ React__default.createElement(View, { style: {
866
- height: 80,
867
- padding: 10,
868
- backgroundColor: "white",
869
- borderTopWidth: 1,
870
- borderTopColor: "#e0e0e0",
871
- flexDirection: "row",
872
- alignItems: "center"
873
- } }, /* @__PURE__ */ React__default.createElement(View, { style: {
874
- 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: {
875
829
  flexDirection: "row",
830
+ paddingLeft: 15,
831
+ paddingRight: 5
832
+ }, contentContainerStyle: {
876
833
  alignItems: "center",
877
- paddingHorizontal: 20
878
- } }, /* @__PURE__ */ React__default.createElement(Image, { key: (_a2 = state == null ? void 0 : state.context) == null ? void 0 : _a2.selectedImage, alt: "selected image", source: {
879
- uri: (_b2 = state == null ? void 0 : state.context) == null ? void 0 : _b2.selectedImage
880
- }, size: "xs", style: {
881
- width: 5,
882
- height: 5,
883
- borderRadius: 5,
884
- marginRight: 20
885
- } }), /* @__PURE__ */ React__default.createElement(TouchableHighlight, { underlayColor: "#dddddd", onPress: () => safeSend({
886
- type: Actions.CLEAR_IMAGE
887
- }), style: {
888
- backgroundColor: "#f44336",
889
- paddingVertical: 2,
890
- paddingHorizontal: 5,
891
- borderRadius: 5,
892
- marginLeft: 10,
893
- elevation: 3,
894
- shadowColor: "#000",
895
- shadowOffset: {
896
- width: 0,
897
- height: 1
898
- },
899
- shadowOpacity: 0.3,
900
- shadowRadius: 2
901
- } }, /* @__PURE__ */ React__default.createElement(Text, { style: {
902
- color: "white",
903
- fontWeight: "bold"
904
- } }, "X"))));
905
- };
906
- 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) => {
907
900
  setImageObject(obj);
908
901
  setImageViewer(v);
909
- };
910
- const modalContent = React__default.useMemo(() => {
911
- if (!imageObject)
912
- 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);
913
905
  const {
914
906
  image,
915
907
  _id
@@ -922,174 +914,189 @@ const ThreadConversationViewComponent = ({
922
914
  expiresIn: 86400
923
915
  }, alt: "image" });
924
916
  }, [imageObject]);
925
- 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) => {
926
931
  return /* @__PURE__ */ React__default.createElement(Message, __spreadProps(__spreadValues({}, props), { isShowImageViewer, setImageViewer: setImageViewerObject }));
927
- };
928
- const currentMessageText = useMemo(() => {
929
- const text = safeContextProperty("messageText", "") || " ";
930
- return text;
931
- }, [safeContextProperty("messageText")]);
932
- const renderInputToolbar = (props) => {
933
- return /* @__PURE__ */ React__default.createElement(InputToolbar, __spreadProps(__spreadValues({}, props), { containerStyle: {
934
- backgroundColor: "white",
935
- borderTopWidth: 1,
936
- borderTopColor: colors.gray[200],
937
- paddingHorizontal: 4,
938
- paddingVertical: 4
939
- }, 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,
940
959
  alignItems: "center"
941
- } }));
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
+ }
942
974
  };
943
- return /* @__PURE__ */ React__default.createElement(SafeAreaView, { style: {
944
- flex: 1
945
- } }, safeContextProperty("loadingOldMessages", false) && /* @__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..."))), 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: {
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
988
+ }) => {
989
+ var _a2, _b2, _c2;
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
+ })
1006
+ });
1007
+ }
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();
1018
+ }
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: {
946
1025
  borderRadius: 6,
947
1026
  borderWidth: 2,
948
1027
  borderColor: "#fff"
949
1028
  }, source: {
950
- uri: (_f = (_e = safeContextProperty("threadPost")[0]) == null ? void 0 : _e.author) == null ? void 0 : _f.picture
951
- } })), /* @__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", " ", format(new Date((_n = safeContextProperty("threadPost")[0]) == null ? void 0 : _n.createdAt), "hh:ss:a")))), /* @__PURE__ */ React__default.createElement(HStack, { space: "sm", className: "px-2 items-center" }, /* @__PURE__ */ React__default.createElement(Text, null, (_p = (_o = safeContextProperty("threadPost")[0]) == null ? void 0 : _o.message) != null ? _p : ""))), /* @__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" }, (_r = (_q = safeContextProperty("threadPost")[0]) == null ? void 0 : _q.replies) == null ? void 0 : _r.totalCount, " ", ((_t = (_s = safeContextProperty("threadPost")[0]) == null ? void 0 : _s.replies) == null ? void 0 : _t.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: {
952
- onScroll: handleScrollToTop,
953
- onEndReached: handleEndReached,
954
- onEndReachedThreshold: 0.2,
955
- contentContainerStyle: {
956
- paddingBottom: 10
957
- },
958
- maintainVisibleContentPosition: {
959
- minIndexForVisible: 0,
960
- autoscrollToTopThreshold: 100
961
- },
962
- scrollEventThrottle: 100,
963
- keyboardDismissMode: "on-drag",
964
- keyboardShouldPersistTaps: "handled"
965
- }, onSend: (messages) => {
966
- var _a2, _b2;
967
- if (!messages || messages.length === 0) {
968
- console.log("No messages to send");
969
- return;
970
- }
971
- const currentInputText = currentMessageText;
972
- const messageToSend = (currentInputText == null ? void 0 : currentInputText.trim()) || ((_b2 = (_a2 = messages[0]) == null ? void 0 : _a2.text) == null ? void 0 : _b2.trim()) || " ";
973
- console.log("GiftedChat onSend triggered with text from state:", messageToSend);
974
- safeSend({
975
- type: Actions.SET_MESSAGE_TEXT,
976
- data: {
977
- messageText: ""
978
- }
979
- });
980
- if (safeContextProperty("images", []).length > 0) {
981
- console.log("Sending message with file:", messageToSend, "Images:", safeContextProperty("images", []).length);
982
- safeSend({
983
- type: Actions.SEND_THREAD_MESSAGE_WITH_FILE,
984
- data: {
985
- messageText: messageToSend
986
- }
987
- });
988
- } else {
989
- console.log("Sending text message:", messageToSend);
990
- safeSend({
991
- type: Actions.SEND_THREAD_MESSAGE,
992
- data: {
993
- messageText: messageToSend
994
- }
995
- });
996
- }
997
- }, text: currentMessageText, onInputTextChanged: (text) => {
998
- if (text.length % 5 === 0 || text.length < 5) {
999
- console.log("Input text changed:", text);
1000
- }
1001
- safeSend({
1002
- type: Actions.SET_MESSAGE_TEXT,
1003
- data: {
1004
- messageText: text
1005
- }
1006
- });
1007
- }, 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: {
1008
- _id: (auth == null ? void 0 : auth.id) || ""
1009
- }, isTyping: true, alwaysShowSend: safeContextProperty("loading", false) ? false : true, infiniteScroll: true, renderSend, renderInputToolbar, minInputToolbarHeight: 50, renderActions, renderAccessory: !!((_u = state == null ? void 0 : state.context) == null ? void 0 : _u.selectedImage) ? renderAccessory : void 0, renderMessage, maxInputLength: 1e3, placeholder: "Type a message...", showUserAvatar: true, showAvatarForEveryMessage: false, inverted: true, parsePatterns: (linkStyle) => [{
1010
- type: "url",
1011
- style: __spreadProps(__spreadValues({}, linkStyle), {
1012
- color: colors.blue[500]
1013
- }),
1014
- onPress: (url) => Linking.openURL(url)
1015
- }, {
1016
- type: "phone",
1017
- style: __spreadProps(__spreadValues({}, linkStyle), {
1018
- color: colors.blue[500]
1019
- }),
1020
- onPress: (phone) => Linking.openURL(`tel:${phone}`)
1021
- }, {
1022
- type: "email",
1023
- style: __spreadProps(__spreadValues({}, linkStyle), {
1024
- color: colors.blue[500]
1025
- }),
1026
- onPress: (email) => Linking.openURL(`mailto:${email}`)
1027
- }], textInputProps: {
1028
- style: {
1029
- borderWidth: 1,
1030
- borderColor: colors.gray[300],
1031
- backgroundColor: "#f8f8f8",
1032
- borderRadius: 20,
1033
- minHeight: 40,
1034
- maxHeight: 80,
1035
- color: "#000",
1036
- padding: 10,
1037
- paddingHorizontal: 20,
1038
- fontSize: 16,
1039
- flex: 1
1040
- },
1041
- multiline: true,
1042
- returnKeyType: "default",
1043
- enablesReturnKeyAutomatically: true,
1044
- placeholderTextColor: colors.gray[400]
1045
- }, 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({
1046
- document: OnThreadChatMessageAddedDocument,
1047
- variables: {
1048
- channelId: channelId == null ? void 0 : channelId.toString(),
1049
- postParentId: !parentId || parentId == 0 ? null : parentId == null ? void 0 : parentId.toString()
1050
- },
1051
- updateQuery: (prev, {
1052
- subscriptionData
1053
- }) => {
1054
- var _a2, _b2, _c2;
1055
- if (!subscriptionData.data)
1056
- return prev;
1057
- const newMessage = (_a2 = subscriptionData == null ? void 0 : subscriptionData.data) == null ? void 0 : _a2.threadChatMessageAdded;
1058
- const prevReplyCount = (_b2 = prev == null ? void 0 : prev.getPostThread) == null ? void 0 : _b2.replyCount;
1059
- const newReplyCount = prevReplyCount || 0 + 1;
1060
- const replies = ((_c2 = prev == null ? void 0 : prev.getPostThread) == null ? void 0 : _c2.replies) || [];
1061
- safeSend({
1062
- type: Actions.SET_THREAD_MESSAGES,
1063
- data: {
1064
- messages: uniqBy([...safeContextProperty("threadMessages", []), newMessage], ({
1065
- id
1066
- }) => id),
1067
- totalCount: newReplyCount,
1068
- threadPost: safeContextProperty("threadPost", []),
1069
- postThread: safeContextProperty("postThread", null)
1070
- }
1071
- });
1072
- return Object.assign({}, prev, {
1073
- getPostThread: __spreadProps(__spreadValues({}, prev == null ? void 0 : prev.getPostThread), {
1074
- lastReplyAt: newMessage.createdAt,
1075
- replies: [newMessage, ...replies],
1076
- replyCount: newReplyCount,
1077
- updatedAt: newMessage.createdAt
1078
- })
1079
- });
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
+ })
1080
1098
  }
1081
- }) })), messagesContainerStyle: (messageList == null ? void 0 : messageList.length) == 0 && {
1082
- transform: [{
1083
- scaleY: -1
1084
- }]
1085
- }, 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: {
1086
- underlayColor: "transparent",
1087
- springConfig: {
1088
- tension: 9e4,
1089
- friction: 9e4
1090
- },
1091
- disabled: true
1092
- } }));
1099
+ ));
1093
1100
  };
1094
1101
  const SubscriptionHandler = ({
1095
1102
  subscribeToNewMessages,
@@ -1098,4 +1105,4 @@ const SubscriptionHandler = ({
1098
1105
  useEffect(() => subscribeToNewMessages(), [channelId]);
1099
1106
  return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null);
1100
1107
  };
1101
- const ThreadConversationView = React__default.memo(ThreadConversationViewComponent);export{ThreadConversationView};//# sourceMappingURL=ThreadConversationView.js.map
1108
+ const ThreadConversationView = ThreadConversationViewComponent;export{ThreadConversationView};//# sourceMappingURL=ThreadConversationView.js.map