@messenger-box/platform-mobile 10.0.3-alpha.10 → 10.0.3-alpha.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +156 -0
- package/lib/compute.js +2 -3
- package/lib/compute.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/module.js.map +1 -1
- package/lib/queries/inboxQueries.js +65 -0
- package/lib/queries/inboxQueries.js.map +1 -0
- package/lib/routes.json +2 -3
- package/lib/screens/inbox/DialogMessages.js.map +1 -1
- package/lib/screens/inbox/DialogThreadMessages.js +3 -7
- package/lib/screens/inbox/DialogThreadMessages.js.map +1 -1
- package/lib/screens/inbox/DialogThreads.js +57 -18
- package/lib/screens/inbox/DialogThreads.js.map +1 -1
- package/lib/screens/inbox/Inbox.js.map +1 -1
- package/lib/screens/inbox/components/CachedImage/consts.js +1 -1
- package/lib/screens/inbox/components/CachedImage/consts.js.map +1 -1
- package/lib/screens/inbox/components/CachedImage/index.js +168 -46
- package/lib/screens/inbox/components/CachedImage/index.js.map +1 -1
- package/lib/screens/inbox/components/DialogItem.js +169 -0
- package/lib/screens/inbox/components/DialogItem.js.map +1 -0
- package/lib/screens/inbox/components/GiftedChatInboxComponent.js +313 -0
- package/lib/screens/inbox/components/GiftedChatInboxComponent.js.map +1 -0
- package/lib/screens/inbox/components/SlackMessageContainer/ImageViewerModal.js.map +1 -1
- package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js +147 -31
- package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js.map +1 -1
- package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js +5 -0
- package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js.map +1 -1
- package/lib/screens/inbox/components/SubscriptionHandler.js +24 -0
- package/lib/screens/inbox/components/SubscriptionHandler.js.map +1 -0
- package/lib/screens/inbox/components/ThreadsViewItem.js +66 -44
- package/lib/screens/inbox/components/ThreadsViewItem.js.map +1 -1
- package/lib/screens/inbox/config/config.js +2 -2
- package/lib/screens/inbox/config/config.js.map +1 -1
- package/lib/screens/inbox/containers/ConversationView.js +1105 -428
- package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
- package/lib/screens/inbox/containers/Dialogs.js +193 -80
- package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
- package/lib/screens/inbox/containers/ThreadConversationView.js +724 -207
- package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
- package/lib/screens/inbox/containers/ThreadsView.js +83 -50
- package/lib/screens/inbox/containers/ThreadsView.js.map +1 -1
- package/lib/screens/inbox/hooks/useInboxMessages.js +31 -0
- package/lib/screens/inbox/hooks/useInboxMessages.js.map +1 -0
- package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js +108 -0
- package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js.map +1 -0
- package/lib/screens/inbox/workflow/dialog-threads-xstate.js +151 -0
- package/lib/screens/inbox/workflow/dialog-threads-xstate.js.map +1 -0
- package/package.json +4 -4
- package/src/index.ts +2 -0
- package/src/queries/inboxQueries.ts +299 -0
- package/src/queries/index.d.ts +2 -0
- package/src/queries/index.ts +1 -0
- package/src/screens/inbox/DialogThreadMessages.tsx +3 -11
- package/src/screens/inbox/DialogThreads.tsx +53 -60
- package/src/screens/inbox/components/Actionsheet.tsx +30 -0
- package/src/screens/inbox/components/CachedImage/consts.ts +4 -3
- package/src/screens/inbox/components/CachedImage/index.tsx +232 -61
- package/src/screens/inbox/components/DialogItem.tsx +306 -0
- package/src/screens/inbox/components/DialogsListItem.tsx +257 -176
- package/src/screens/inbox/components/ExpandableInput.tsx +460 -0
- package/src/screens/inbox/components/ExpandableInputActionSheet.tsx +518 -0
- package/src/screens/inbox/components/GiftedChatInboxComponent.tsx +411 -0
- package/src/screens/inbox/components/ServiceDialogsListItem.tsx +334 -172
- package/src/screens/inbox/components/SlackInput.tsx +23 -0
- package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +233 -23
- package/src/screens/inbox/components/SmartLoader.tsx +61 -0
- package/src/screens/inbox/components/SubscriptionHandler.tsx +41 -0
- package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +41 -24
- package/src/screens/inbox/components/ThreadsViewItem.tsx +177 -265
- package/src/screens/inbox/components/workflow/dialogs-list-item-xstate.ts +145 -0
- package/src/screens/inbox/components/workflow/service-dialogs-list-item-xstate.ts +159 -0
- package/src/screens/inbox/config/config.ts +2 -2
- package/src/screens/inbox/containers/ConversationView.tsx +1843 -702
- package/src/screens/inbox/containers/ConversationView.tsx.bk +1467 -0
- package/src/screens/inbox/containers/Dialogs.tsx +400 -197
- package/src/screens/inbox/containers/SupportServiceDialogs.tsx +2 -2
- package/src/screens/inbox/containers/ThreadConversationView.tsx +1337 -301
- package/src/screens/inbox/containers/ThreadsView.tsx +105 -186
- package/src/screens/inbox/containers/workflow/apollo/handleResult.ts +20 -0
- package/src/screens/inbox/containers/workflow/conversation-xstate.ts +313 -0
- package/src/screens/inbox/containers/workflow/dialogs-xstate.ts +196 -0
- package/src/screens/inbox/containers/workflow/thread-conversation-xstate.ts +401 -0
- package/src/screens/inbox/hooks/useInboxMessages.ts +34 -0
- package/src/screens/inbox/hooks/useSafeDialogThreadsMachine.ts +136 -0
- package/src/screens/inbox/index.ts +37 -0
- package/src/screens/inbox/machines/threadsMachine.ts +147 -0
- package/src/screens/inbox/workflow/dialog-threads-xstate.ts +163 -0
- package/tsconfig.json +11 -54
- package/lib/screens/inbox/components/DialogsListItem.js +0 -159
- package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
- package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -159
- package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
|
@@ -56,45 +56,255 @@ export default class Bubble extends React.Component<any> {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
renderMessageImage() {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
const { currentMessage, containerStyle, wrapperStyle, ...messageImageProps } = this.props;
|
|
60
|
+
|
|
61
|
+
// Check if we have multiple images
|
|
62
|
+
if (currentMessage.images && Array.isArray(currentMessage.images) && currentMessage.images.length > 0) {
|
|
63
|
+
// Filter out any invalid or empty image URLs first
|
|
64
|
+
const validImages = currentMessage.images.filter((url) => url && typeof url === 'string');
|
|
65
|
+
|
|
66
|
+
// If no valid images after filtering, don't render anything
|
|
67
|
+
if (validImages.length === 0) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Render multiple images in a scrollable horizontal row
|
|
72
|
+
return (
|
|
73
|
+
<View style={{ marginVertical: 0 }}>
|
|
74
|
+
<View
|
|
75
|
+
style={{
|
|
76
|
+
flexDirection: 'row',
|
|
77
|
+
flexWrap: 'wrap',
|
|
78
|
+
gap: 8,
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
{validImages.map((imageUrl, index) => {
|
|
82
|
+
// Check if this is a local image
|
|
83
|
+
const isLocalImage =
|
|
84
|
+
imageUrl.startsWith('file:') ||
|
|
85
|
+
imageUrl.startsWith('data:') ||
|
|
86
|
+
imageUrl.startsWith('content:') ||
|
|
87
|
+
(!imageUrl.startsWith('http://') && !imageUrl.startsWith('https://'));
|
|
88
|
+
|
|
89
|
+
const imageSize =
|
|
90
|
+
validImages.length === 1
|
|
91
|
+
? { width: windowWidth * 0.6, height: windowWidth * 0.4 }
|
|
92
|
+
: { width: windowWidth * 0.3, height: windowWidth * 0.3 };
|
|
93
|
+
|
|
94
|
+
// Show upload indicator if this message is uploading
|
|
95
|
+
const isUploading = currentMessage.isUploading;
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<TouchableHighlight
|
|
99
|
+
key={`image-${index}-${currentMessage._id}`}
|
|
100
|
+
underlayColor={'transparent'}
|
|
101
|
+
onPress={() => {
|
|
102
|
+
// Don't allow viewing while uploading
|
|
103
|
+
if (isUploading) return;
|
|
104
|
+
|
|
105
|
+
// Create a message-like object with this image for the viewer
|
|
106
|
+
const imageObject = {
|
|
107
|
+
_id: `${currentMessage._id}-img-${index}`,
|
|
108
|
+
image: imageUrl,
|
|
109
|
+
};
|
|
110
|
+
this.props.setImageViewer(imageObject, true);
|
|
111
|
+
}}
|
|
112
|
+
>
|
|
113
|
+
<View
|
|
114
|
+
style={{
|
|
115
|
+
...imageSize,
|
|
116
|
+
maxHeight: 200,
|
|
117
|
+
borderRadius: 8,
|
|
118
|
+
overflow: 'hidden',
|
|
119
|
+
borderWidth: 1,
|
|
120
|
+
borderColor: '#e0e0e0',
|
|
121
|
+
backgroundColor: '#f7f7f7',
|
|
122
|
+
}}
|
|
123
|
+
>
|
|
124
|
+
{isLocalImage ? (
|
|
125
|
+
// For local images, use direct Image component with no loading state
|
|
126
|
+
<View style={{ width: '100%', height: '100%' }}>
|
|
127
|
+
<MessageImage
|
|
128
|
+
{...messageImageProps}
|
|
129
|
+
currentMessage={{ ...currentMessage, image: imageUrl }}
|
|
130
|
+
imageStyle={{
|
|
131
|
+
width: '100%',
|
|
132
|
+
height: '100%',
|
|
133
|
+
borderRadius: 8,
|
|
134
|
+
}}
|
|
135
|
+
/>
|
|
136
|
+
|
|
137
|
+
{/* Show upload indicator if needed */}
|
|
138
|
+
{isUploading && (
|
|
139
|
+
<View
|
|
140
|
+
style={{
|
|
141
|
+
position: 'absolute',
|
|
142
|
+
top: 0,
|
|
143
|
+
left: 0,
|
|
144
|
+
right: 0,
|
|
145
|
+
bottom: 0,
|
|
146
|
+
backgroundColor: 'rgba(0,0,0,0.2)',
|
|
147
|
+
justifyContent: 'center',
|
|
148
|
+
alignItems: 'center',
|
|
149
|
+
}}
|
|
150
|
+
>
|
|
151
|
+
<Text style={{ color: 'white', fontWeight: 'bold' }}>
|
|
152
|
+
Uploading...
|
|
153
|
+
</Text>
|
|
154
|
+
</View>
|
|
155
|
+
)}
|
|
156
|
+
</View>
|
|
157
|
+
) : (
|
|
158
|
+
// For remote images, use CachedImage with loading placeholder
|
|
159
|
+
<CachedImage
|
|
160
|
+
style={[styles.slackImage, { width: '100%', height: '100%' }]}
|
|
161
|
+
cacheKey={`${currentMessage._id}-img-${index}-slack-bubble-imageKey`}
|
|
162
|
+
source={{
|
|
163
|
+
uri: imageUrl,
|
|
164
|
+
expiresIn: 86400,
|
|
165
|
+
}}
|
|
166
|
+
resizeMode={'cover'}
|
|
167
|
+
alt={'image'}
|
|
168
|
+
placeholderContent={
|
|
169
|
+
<View
|
|
170
|
+
style={[
|
|
171
|
+
styles.slackImage,
|
|
172
|
+
{
|
|
173
|
+
width: '100%',
|
|
174
|
+
height: '100%',
|
|
175
|
+
backgroundColor: '#e1e1e1',
|
|
176
|
+
justifyContent: 'center',
|
|
177
|
+
alignItems: 'center',
|
|
178
|
+
borderRadius: 8,
|
|
179
|
+
},
|
|
180
|
+
]}
|
|
181
|
+
>
|
|
182
|
+
<Text>{isUploading ? 'Uploading...' : 'Loading...'}</Text>
|
|
183
|
+
</View>
|
|
184
|
+
}
|
|
185
|
+
/>
|
|
186
|
+
)}
|
|
187
|
+
</View>
|
|
188
|
+
</TouchableHighlight>
|
|
189
|
+
);
|
|
190
|
+
})}
|
|
191
|
+
</View>
|
|
192
|
+
</View>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Fall back to single image rendering if no images array
|
|
197
|
+
if (currentMessage.image) {
|
|
61
198
|
if (this.props.renderMessageImage) {
|
|
62
199
|
return this.props.renderMessageImage(messageImageProps);
|
|
63
200
|
}
|
|
64
|
-
const { image, _id } =
|
|
201
|
+
const { image, _id } = currentMessage;
|
|
202
|
+
|
|
203
|
+
// Add validation for image URL
|
|
204
|
+
if (!image || typeof image !== 'string') {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
65
207
|
|
|
208
|
+
// Check if this is a local image (from device camera/library)
|
|
209
|
+
const isLocalImage =
|
|
210
|
+
image.startsWith('file:') ||
|
|
211
|
+
image.startsWith('data:') ||
|
|
212
|
+
image.startsWith('content:') ||
|
|
213
|
+
// Check if the image is a pendingUpload by checking if it doesn't start with http/https
|
|
214
|
+
(!image.startsWith('http://') && !image.startsWith('https://'));
|
|
215
|
+
|
|
216
|
+
// Check uploading state
|
|
217
|
+
const isUploading = currentMessage.isUploading;
|
|
218
|
+
|
|
219
|
+
// Class components can't use hooks like useMemo
|
|
220
|
+
// Directly render the CachedImage instead
|
|
66
221
|
return (
|
|
67
222
|
<TouchableHighlight
|
|
68
|
-
// underlayColor={'#c0c0c0'}
|
|
69
223
|
underlayColor={'transparent'}
|
|
70
|
-
style={{ width: '100%' }}
|
|
71
|
-
onPress={() =>
|
|
224
|
+
style={{ width: '100%', marginVertical: 0 }}
|
|
225
|
+
onPress={() => {
|
|
226
|
+
// Don't allow viewing while uploading
|
|
227
|
+
if (isUploading) return;
|
|
228
|
+
this.props.setImageViewer(currentMessage, true);
|
|
229
|
+
}}
|
|
72
230
|
>
|
|
73
231
|
<View
|
|
74
232
|
style={{
|
|
75
|
-
width: windowWidth
|
|
76
|
-
height:
|
|
233
|
+
width: windowWidth * 0.6, // 60% of screen width
|
|
234
|
+
height: windowWidth * 0.4, // Maintain aspect ratio
|
|
235
|
+
maxHeight: 200,
|
|
236
|
+
borderRadius: 8,
|
|
237
|
+
overflow: 'hidden',
|
|
238
|
+
borderWidth: 1,
|
|
239
|
+
borderColor: '#e0e0e0',
|
|
240
|
+
backgroundColor: '#f7f7f7',
|
|
77
241
|
}}
|
|
78
242
|
>
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
243
|
+
{isLocalImage ? (
|
|
244
|
+
// For local images, use direct Image component with no loading state
|
|
245
|
+
<View style={{ width: '100%', height: '100%', position: 'relative' }}>
|
|
246
|
+
<MessageImage
|
|
247
|
+
{...messageImageProps}
|
|
248
|
+
imageStyle={{
|
|
249
|
+
width: '100%',
|
|
250
|
+
height: '100%',
|
|
251
|
+
borderRadius: 8,
|
|
252
|
+
}}
|
|
253
|
+
/>
|
|
254
|
+
|
|
255
|
+
{/* Show upload indicator if needed */}
|
|
256
|
+
{isUploading && (
|
|
257
|
+
<View
|
|
258
|
+
style={{
|
|
259
|
+
position: 'absolute',
|
|
260
|
+
top: 0,
|
|
261
|
+
left: 0,
|
|
262
|
+
right: 0,
|
|
263
|
+
bottom: 0,
|
|
264
|
+
backgroundColor: 'rgba(0,0,0,0.2)',
|
|
265
|
+
justifyContent: 'center',
|
|
266
|
+
alignItems: 'center',
|
|
267
|
+
}}
|
|
268
|
+
>
|
|
269
|
+
<Text style={{ color: 'white', fontWeight: 'bold' }}>Uploading...</Text>
|
|
270
|
+
</View>
|
|
271
|
+
)}
|
|
272
|
+
</View>
|
|
273
|
+
) : (
|
|
274
|
+
// For remote images, use CachedImage with loading placeholder
|
|
275
|
+
<CachedImage
|
|
276
|
+
style={[styles.slackImage, { width: '100%', height: '100%' }]}
|
|
277
|
+
cacheKey={`${_id}-slack-bubble-imageKey`}
|
|
278
|
+
source={{
|
|
279
|
+
uri: image,
|
|
280
|
+
expiresIn: 86400,
|
|
281
|
+
}}
|
|
282
|
+
resizeMode={'cover'}
|
|
283
|
+
alt={'image'}
|
|
284
|
+
placeholderContent={
|
|
285
|
+
<View
|
|
286
|
+
style={[
|
|
287
|
+
styles.slackImage,
|
|
288
|
+
{
|
|
289
|
+
width: '100%',
|
|
290
|
+
height: '100%',
|
|
291
|
+
backgroundColor: '#e1e1e1',
|
|
292
|
+
justifyContent: 'center',
|
|
293
|
+
alignItems: 'center',
|
|
294
|
+
borderRadius: 8,
|
|
295
|
+
},
|
|
296
|
+
]}
|
|
297
|
+
>
|
|
298
|
+
<Text>{isUploading ? 'Uploading...' : 'Loading...'}</Text>
|
|
299
|
+
</View>
|
|
300
|
+
}
|
|
301
|
+
/>
|
|
302
|
+
)}
|
|
94
303
|
</View>
|
|
95
304
|
</TouchableHighlight>
|
|
96
305
|
);
|
|
97
306
|
}
|
|
307
|
+
|
|
98
308
|
return null;
|
|
99
309
|
}
|
|
100
310
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { Box, Spinner, Text, VStack, Button, ButtonText } from '@admin-layout/gluestack-ui-mobile';
|
|
3
|
+
import colors from 'tailwindcss/colors';
|
|
4
|
+
|
|
5
|
+
interface SmartLoaderProps {
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
message?: string;
|
|
9
|
+
onRetry?: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* SmartLoader component that automatically shows a timeout message
|
|
14
|
+
* if loading takes too long, preventing infinite loading states
|
|
15
|
+
*/
|
|
16
|
+
export const SmartLoader: React.FC<SmartLoaderProps> = ({
|
|
17
|
+
isLoading,
|
|
18
|
+
timeoutMs = 20000, // Default 20 seconds
|
|
19
|
+
message = 'Taking longer than expected...',
|
|
20
|
+
onRetry,
|
|
21
|
+
}) => {
|
|
22
|
+
const [showTimeout, setShowTimeout] = useState(false);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (!isLoading) {
|
|
26
|
+
setShowTimeout(false);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const timeoutId = setTimeout(() => {
|
|
31
|
+
if (isLoading) {
|
|
32
|
+
setShowTimeout(true);
|
|
33
|
+
}
|
|
34
|
+
}, timeoutMs);
|
|
35
|
+
|
|
36
|
+
return () => clearTimeout(timeoutId);
|
|
37
|
+
}, [isLoading, timeoutMs]);
|
|
38
|
+
|
|
39
|
+
if (!isLoading) return null;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Box className="flex-1 bg-gray-100 dark:bg-gray-800 items-center justify-center">
|
|
43
|
+
<VStack space="md" className="items-center">
|
|
44
|
+
<Spinner color={colors.blue[500]} size="large" />
|
|
45
|
+
|
|
46
|
+
{showTimeout && (
|
|
47
|
+
<VStack space="sm" className="p-4 items-center">
|
|
48
|
+
<Text className="text-gray-700 dark:text-gray-300 text-center">{message}</Text>
|
|
49
|
+
{onRetry && (
|
|
50
|
+
<Button onPress={onRetry} className="bg-blue-500 mt-3 rounded-full">
|
|
51
|
+
<ButtonText>Try Again</ButtonText>
|
|
52
|
+
</Button>
|
|
53
|
+
)}
|
|
54
|
+
</VStack>
|
|
55
|
+
)}
|
|
56
|
+
</VStack>
|
|
57
|
+
</Box>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default SmartLoader;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared SubscriptionHandler for Apollo subscribeToMore
|
|
5
|
+
*
|
|
6
|
+
* @param subscribeToMore - Apollo subscribeToMore function
|
|
7
|
+
* @param document - GraphQL subscription document
|
|
8
|
+
* @param variables - Variables for the subscription
|
|
9
|
+
* @param updateQuery - Apollo updateQuery function
|
|
10
|
+
* @param onError - Optional error handler
|
|
11
|
+
* @param enabled - If false, disables the subscription
|
|
12
|
+
*/
|
|
13
|
+
export function SubscriptionHandler({
|
|
14
|
+
subscribeToMore,
|
|
15
|
+
document,
|
|
16
|
+
variables,
|
|
17
|
+
updateQuery,
|
|
18
|
+
onError,
|
|
19
|
+
enabled = true,
|
|
20
|
+
}: {
|
|
21
|
+
subscribeToMore: Function;
|
|
22
|
+
document: any;
|
|
23
|
+
variables: Record<string, any>;
|
|
24
|
+
updateQuery: (prev: any, { subscriptionData }: any) => any;
|
|
25
|
+
onError?: (error: any) => void;
|
|
26
|
+
enabled?: boolean;
|
|
27
|
+
}) {
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!enabled) return;
|
|
30
|
+
const unsubscribe = subscribeToMore({
|
|
31
|
+
document,
|
|
32
|
+
variables,
|
|
33
|
+
updateQuery,
|
|
34
|
+
onError,
|
|
35
|
+
});
|
|
36
|
+
return () => {
|
|
37
|
+
if (unsubscribe && typeof unsubscribe === 'function') unsubscribe();
|
|
38
|
+
};
|
|
39
|
+
}, [subscribeToMore, document, JSON.stringify(variables), updateQuery, onError, enabled]);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
@@ -16,23 +16,35 @@ import { format, isToday, isYesterday } from 'date-fns';
|
|
|
16
16
|
import { useFocusEffect } from '@react-navigation/native';
|
|
17
17
|
import { IChannel, IUserAccount } from 'common';
|
|
18
18
|
import {
|
|
19
|
+
THREAD_CREATED_UPDATED,
|
|
20
|
+
CHAT_MESSAGE_ADDED,
|
|
19
21
|
useThreadMessagesQuery,
|
|
22
|
+
useThreadCreatedUpdatedSubscription,
|
|
23
|
+
useThreadChatMessageAddedSubscription,
|
|
20
24
|
useMessagesQuery,
|
|
21
|
-
|
|
22
|
-
useOnThreadCreatedUpdatedSubscription,
|
|
23
|
-
useOnThreadChatMessageAddedSubscription,
|
|
24
|
-
OnThreadCreatedUpdatedDocument as THREAD_CHAT_ADDED,
|
|
25
|
-
OnThreadChatMessageAddedDocument as CHAT_MESSAGE_ADDED,
|
|
26
|
-
} from 'common/lib/generated/generated.js';
|
|
25
|
+
} from '../../../queries/inboxQueries';
|
|
27
26
|
import { startCase } from 'lodash-es';
|
|
28
27
|
import colors from 'tailwindcss/colors';
|
|
29
28
|
|
|
30
29
|
const createdAtText = (value: string) => {
|
|
31
30
|
if (!value) return '';
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
// Validate the date before processing
|
|
34
|
+
const timestamp = new Date(value).getTime();
|
|
35
|
+
if (isNaN(timestamp)) {
|
|
36
|
+
console.warn(`Invalid date value in createdAtText: ${value}`);
|
|
37
|
+
return 'Unknown date';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let date = new Date(value);
|
|
41
|
+
if (isToday(date)) return 'Today';
|
|
42
|
+
if (isYesterday(date)) return 'Yesterday';
|
|
43
|
+
return format(date, 'MMM dd, yyyy');
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error(`Error processing date in createdAtText: ${value}`, error);
|
|
46
|
+
return 'Unknown date';
|
|
47
|
+
}
|
|
36
48
|
};
|
|
37
49
|
|
|
38
50
|
export interface IDialogListChannel extends IChannel {
|
|
@@ -191,7 +203,7 @@ export const SupportServiceDialogsListItemComponent: React.FC<IDialogListItemPro
|
|
|
191
203
|
lastMessage={lastMessage}
|
|
192
204
|
subscribeToNewMessages={() =>
|
|
193
205
|
subscribeToMore({
|
|
194
|
-
document:
|
|
206
|
+
document: THREAD_CREATED_UPDATED,
|
|
195
207
|
variables: {
|
|
196
208
|
channelId: channel?.id?.toString(),
|
|
197
209
|
postParentId: postParentId ? servicePostParentId : null,
|
|
@@ -250,6 +262,23 @@ export const SupportServiceDialogsListItemComponent: React.FC<IDialogListItemPro
|
|
|
250
262
|
|
|
251
263
|
const ServiceChannelWithLastMessage = React.memo(({ channel, lastMessage, subscribeToNewMessages }: any) => {
|
|
252
264
|
React.useEffect(() => subscribeToNewMessages(), []);
|
|
265
|
+
|
|
266
|
+
// Define message display text
|
|
267
|
+
let displayMessage = 'No messages yet';
|
|
268
|
+
|
|
269
|
+
if (lastMessage) {
|
|
270
|
+
// Check for file attachments
|
|
271
|
+
const hasFileAttachments = lastMessage.files?.data?.length > 0;
|
|
272
|
+
|
|
273
|
+
if (hasFileAttachments) {
|
|
274
|
+
displayMessage = '📎 File attachment';
|
|
275
|
+
} else if (lastMessage.message && lastMessage.message.trim() !== '') {
|
|
276
|
+
displayMessage = lastMessage.message;
|
|
277
|
+
} else {
|
|
278
|
+
displayMessage = '(Empty message)';
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
253
282
|
return (
|
|
254
283
|
<HStack space={'sm'} className="flex-1 justify-center items-center">
|
|
255
284
|
<Box className="flex-[0.8]">
|
|
@@ -257,23 +286,11 @@ const ServiceChannelWithLastMessage = React.memo(({ channel, lastMessage, subscr
|
|
|
257
286
|
{channel?.title}
|
|
258
287
|
</Text>
|
|
259
288
|
<Text color={colors.gray[600]} numberOfLines={1}>
|
|
260
|
-
{
|
|
261
|
-
? lastMessageCreatorAndMembers?.message ?? ''
|
|
262
|
-
: lastMessage?.message ?? ''} */}
|
|
263
|
-
{lastMessage?.message ?? ''}
|
|
289
|
+
{displayMessage}
|
|
264
290
|
</Text>
|
|
265
291
|
</Box>
|
|
266
292
|
|
|
267
293
|
<Box className="flex-[0.2]">
|
|
268
|
-
{/* {creatorAndMembersId?.length && creatorAndMembersId?.includes(currentUser?.id) ? (
|
|
269
|
-
<Text color="gray.500">
|
|
270
|
-
{lastMessageCreatorAndMembers
|
|
271
|
-
? createdAtText(lastMessageCreatorAndMembers?.createdAt)
|
|
272
|
-
: ''}
|
|
273
|
-
</Text>
|
|
274
|
-
) : (
|
|
275
|
-
<Text color="gray.500">{lastMessage ? createdAtText(lastMessage?.createdAt) : ''}</Text>
|
|
276
|
-
)} */}
|
|
277
294
|
<Text color={colors.gray[500]}>{lastMessage ? createdAtText(lastMessage?.createdAt) : ''}</Text>
|
|
278
295
|
</Box>
|
|
279
296
|
</HStack>
|