@messenger-box/platform-mobile 10.0.3-alpha.5 → 10.0.3-alpha.50
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 +92 -0
- package/lib/compute.js +2 -3
- package/lib/compute.js.map +1 -1
- package/lib/index.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 +1 -1
- package/lib/screens/inbox/DialogMessages.js.map +1 -1
- package/lib/screens/inbox/DialogThreadMessages.js +4 -8
- package/lib/screens/inbox/DialogThreadMessages.js.map +1 -1
- package/lib/screens/inbox/DialogThreads.js +57 -12
- package/lib/screens/inbox/DialogThreads.js.map +1 -1
- package/lib/screens/inbox/Inbox.js +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/SlackBubble.js +147 -31
- package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js.map +1 -1
- package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js +6 -1
- 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 -55
- 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 +1111 -434
- 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 +725 -216
- 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/compute.ts +5 -6
- package/src/index.ts +2 -0
- package/src/navigation/InboxNavigation.tsx +3 -3
- 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/DialogMessages.tsx +1 -1
- package/src/screens/inbox/DialogThreadMessages.tsx +7 -14
- package/src/screens/inbox/DialogThreads.tsx +55 -61
- package/src/screens/inbox/Inbox.tsx +1 -1
- 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/DialogsHeader.tsx +6 -13
- package/src/screens/inbox/components/DialogsListItem.tsx +262 -198
- 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 +337 -194
- package/src/screens/inbox/components/SlackInput.tsx +23 -0
- package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +233 -23
- package/src/screens/inbox/components/SlackMessageContainer/SlackMessage.tsx +1 -1
- 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 +53 -55
- package/src/screens/inbox/components/ThreadsViewItem.tsx +178 -285
- 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 +402 -204
- package/src/screens/inbox/containers/SupportServiceDialogs.tsx +4 -4
- package/src/screens/inbox/containers/ThreadConversationView.tsx +1350 -319
- package/src/screens/inbox/containers/ThreadsView.tsx +105 -193
- 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 -171
- package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
- package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -171
- package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import { assign, setup } from 'xstate';
|
|
2
|
+
import { merge } from 'lodash-es';
|
|
3
|
+
|
|
4
|
+
export const enum Actions {
|
|
5
|
+
INITIAL_CONTEXT = 'INITIAL_CONTEXT',
|
|
6
|
+
ERROR_HANDLED = 'ERROR_HANDLED',
|
|
7
|
+
SEND_THREAD_MESSAGE = 'SEND_THREAD_MESSAGE',
|
|
8
|
+
SEND_THREAD_MESSAGE_WITH_FILE = 'SEND_THREAD_MESSAGE_WITH_FILE',
|
|
9
|
+
SET_THREAD_MESSAGES = 'SET_THREAD_MESSAGES',
|
|
10
|
+
CLEAR_MESSAGES = 'CLEAR_MESSAGES',
|
|
11
|
+
FETCH_MORE_MESSAGES = 'FETCH_MORE_MESSAGES',
|
|
12
|
+
SUBSCRIBE_TO_THREAD_MESSAGES = 'SUBSCRIBE_TO_THREAD_MESSAGES',
|
|
13
|
+
START_LOADING = 'START_LOADING',
|
|
14
|
+
STOP_LOADING = 'STOP_LOADING',
|
|
15
|
+
SET_IMAGE = 'SET_IMAGE',
|
|
16
|
+
CLEAR_IMAGE = 'CLEAR_IMAGE',
|
|
17
|
+
SET_MESSAGE_TEXT = 'SET_MESSAGE_TEXT',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const enum BaseState {
|
|
21
|
+
Idle = 'idle',
|
|
22
|
+
Error = 'error',
|
|
23
|
+
Loading = 'loading',
|
|
24
|
+
Done = 'done',
|
|
25
|
+
FetchThreadMessages = 'fetchThreadMessages',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const enum MainState {
|
|
29
|
+
SendThreadMessage = 'sendThreadMessage',
|
|
30
|
+
SendThreadMessageWithFile = 'sendThreadMessageWithFile',
|
|
31
|
+
FetchMoreMessages = 'fetchMoreMessages',
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const threadConversationXstate = setup({
|
|
35
|
+
types: {
|
|
36
|
+
context: {} as {
|
|
37
|
+
channelId: string | null;
|
|
38
|
+
postParentId: string | null;
|
|
39
|
+
role: string | null;
|
|
40
|
+
threadMessages: any[];
|
|
41
|
+
totalCount: number;
|
|
42
|
+
skip: number;
|
|
43
|
+
loading: boolean;
|
|
44
|
+
loadingOldMessages: boolean;
|
|
45
|
+
error: string | null;
|
|
46
|
+
selectedImage: string;
|
|
47
|
+
files: any[];
|
|
48
|
+
images: any[];
|
|
49
|
+
messageText: string;
|
|
50
|
+
imageLoading: boolean;
|
|
51
|
+
postThread: any;
|
|
52
|
+
threadPost: any[];
|
|
53
|
+
isScrollToBottom: boolean;
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
actions: {
|
|
57
|
+
errorState: assign(({ context, event }) => {
|
|
58
|
+
return {
|
|
59
|
+
...context,
|
|
60
|
+
error: event.data?.message || 'An error occurred',
|
|
61
|
+
loading: false,
|
|
62
|
+
loadingOldMessages: false,
|
|
63
|
+
imageLoading: false,
|
|
64
|
+
};
|
|
65
|
+
}),
|
|
66
|
+
setInitialContext: assign(({ context, event }) => {
|
|
67
|
+
return merge({
|
|
68
|
+
...context,
|
|
69
|
+
channelId: event.data?.channelId || null,
|
|
70
|
+
postParentId: event.data?.postParentId || null,
|
|
71
|
+
role: event.data?.role || null,
|
|
72
|
+
loading: false,
|
|
73
|
+
});
|
|
74
|
+
}),
|
|
75
|
+
setThreadMessages: assign(({ context, event }) => {
|
|
76
|
+
const messages = event.data?.messages || [];
|
|
77
|
+
console.log(`setThreadMessages: Setting ${messages.length} messages`);
|
|
78
|
+
|
|
79
|
+
// Create a set of unique IDs to remove duplicates
|
|
80
|
+
const messageIds = new Set();
|
|
81
|
+
const uniqueMessages = [];
|
|
82
|
+
|
|
83
|
+
// Process messages to ensure uniqueness
|
|
84
|
+
messages.forEach((msg) => {
|
|
85
|
+
if (msg.id && !messageIds.has(msg.id)) {
|
|
86
|
+
messageIds.add(msg.id);
|
|
87
|
+
uniqueMessages.push(msg);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
console.log(`setThreadMessages: After deduplication, have ${uniqueMessages.length} unique messages`);
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
...context,
|
|
95
|
+
threadMessages: uniqueMessages,
|
|
96
|
+
totalCount: event.data?.totalCount || 0,
|
|
97
|
+
loading: false,
|
|
98
|
+
loadingOldMessages: false,
|
|
99
|
+
threadPost: event.data?.threadPost || [],
|
|
100
|
+
postThread: event.data?.postThread || null,
|
|
101
|
+
};
|
|
102
|
+
}),
|
|
103
|
+
addThreadMessages: assign(({ context, event }) => {
|
|
104
|
+
const newMessages = event.data?.messages || [];
|
|
105
|
+
console.log('Adding thread messages and disabling loading state. New messages:', newMessages.length);
|
|
106
|
+
|
|
107
|
+
if (newMessages.length === 0) {
|
|
108
|
+
return {
|
|
109
|
+
...context,
|
|
110
|
+
loadingOldMessages: false,
|
|
111
|
+
loading: false,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Create a map of existing message IDs for quick lookup
|
|
116
|
+
const existingMessageIds = new Set();
|
|
117
|
+
context.threadMessages.forEach((msg) => existingMessageIds.add(msg.id));
|
|
118
|
+
|
|
119
|
+
// Filter out any duplicate messages
|
|
120
|
+
const uniqueNewMessages = newMessages.filter((msg) => {
|
|
121
|
+
if (!msg.id || existingMessageIds.has(msg.id)) {
|
|
122
|
+
console.log('Skipping duplicate message:', msg.id);
|
|
123
|
+
return false; // Skip messages with no ID or duplicates
|
|
124
|
+
}
|
|
125
|
+
existingMessageIds.add(msg.id); // Add to set to catch duplicates in the new messages
|
|
126
|
+
return true;
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
console.log(`After filtering, adding ${uniqueNewMessages.length} unique messages`);
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
...context,
|
|
133
|
+
threadMessages: [...context.threadMessages, ...uniqueNewMessages],
|
|
134
|
+
loadingOldMessages: false,
|
|
135
|
+
loading: false,
|
|
136
|
+
};
|
|
137
|
+
}),
|
|
138
|
+
addNewMessage: assign(({ context, event }) => {
|
|
139
|
+
const message = event.data?.message;
|
|
140
|
+
console.log('Adding new message to thread:', message?.id);
|
|
141
|
+
if (!message) {
|
|
142
|
+
console.warn('No message data provided to addNewMessage action');
|
|
143
|
+
return context;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Prevent duplicate messages by checking for the same ID
|
|
147
|
+
const existingMessageIndex = context.threadMessages.findIndex((msg) => msg.id === message.id);
|
|
148
|
+
if (existingMessageIndex !== -1) {
|
|
149
|
+
console.log('Message already exists, not adding duplicate:', message.id);
|
|
150
|
+
return {
|
|
151
|
+
...context,
|
|
152
|
+
loading: false,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Use a set to ensure we only have unique message IDs
|
|
157
|
+
const messageIds = new Set();
|
|
158
|
+
const uniqueMessages = [...context.threadMessages];
|
|
159
|
+
|
|
160
|
+
// Add all existing message IDs to the set
|
|
161
|
+
uniqueMessages.forEach((msg) => messageIds.add(msg.id));
|
|
162
|
+
|
|
163
|
+
// Only add the new message if its ID isn't already in the set
|
|
164
|
+
if (!messageIds.has(message.id)) {
|
|
165
|
+
uniqueMessages.unshift(message); // Add to beginning (newest first)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
console.log('Successfully added new message to thread');
|
|
169
|
+
return {
|
|
170
|
+
...context,
|
|
171
|
+
threadMessages: uniqueMessages,
|
|
172
|
+
totalCount: context.totalCount + 1,
|
|
173
|
+
loading: false,
|
|
174
|
+
};
|
|
175
|
+
}),
|
|
176
|
+
updateSkip: assign(({ context, event }) => {
|
|
177
|
+
console.log('Setting loadingOldMessages to true');
|
|
178
|
+
return {
|
|
179
|
+
...context,
|
|
180
|
+
skip: context.threadMessages.length,
|
|
181
|
+
loadingOldMessages: true,
|
|
182
|
+
loading: event.data?.loading !== undefined ? event.data.loading : context.loading,
|
|
183
|
+
};
|
|
184
|
+
}),
|
|
185
|
+
clearMessages: assign(({ context }) => {
|
|
186
|
+
return {
|
|
187
|
+
...context,
|
|
188
|
+
threadMessages: [],
|
|
189
|
+
totalCount: 0,
|
|
190
|
+
skip: 0,
|
|
191
|
+
};
|
|
192
|
+
}),
|
|
193
|
+
setPostParentId: assign(({ context, event }) => {
|
|
194
|
+
return {
|
|
195
|
+
...context,
|
|
196
|
+
postParentId: event.data?.postParentId || null,
|
|
197
|
+
};
|
|
198
|
+
}),
|
|
199
|
+
setPostThread: assign(({ context, event }) => {
|
|
200
|
+
return {
|
|
201
|
+
...context,
|
|
202
|
+
postThread: event.data?.postThread || null,
|
|
203
|
+
};
|
|
204
|
+
}),
|
|
205
|
+
startLoading: assign(({ context, event }) => {
|
|
206
|
+
return {
|
|
207
|
+
...context,
|
|
208
|
+
loading: true,
|
|
209
|
+
loadingOldMessages:
|
|
210
|
+
event.data?.loadingOldMessages !== undefined
|
|
211
|
+
? event.data.loadingOldMessages
|
|
212
|
+
: context.loadingOldMessages,
|
|
213
|
+
};
|
|
214
|
+
}),
|
|
215
|
+
stopLoading: assign(({ context, event }) => {
|
|
216
|
+
return {
|
|
217
|
+
...context,
|
|
218
|
+
loading: false,
|
|
219
|
+
loadingOldMessages:
|
|
220
|
+
event.data?.loadingOldMessages !== undefined
|
|
221
|
+
? event.data.loadingOldMessages
|
|
222
|
+
: context.loadingOldMessages,
|
|
223
|
+
};
|
|
224
|
+
}),
|
|
225
|
+
startImageLoading: assign(({ context }) => {
|
|
226
|
+
return {
|
|
227
|
+
...context,
|
|
228
|
+
imageLoading: true,
|
|
229
|
+
};
|
|
230
|
+
}),
|
|
231
|
+
stopImageLoading: assign(({ context }) => {
|
|
232
|
+
return {
|
|
233
|
+
...context,
|
|
234
|
+
imageLoading: false,
|
|
235
|
+
};
|
|
236
|
+
}),
|
|
237
|
+
setSelectedImage: assign(({ context, event }) => {
|
|
238
|
+
return {
|
|
239
|
+
...context,
|
|
240
|
+
selectedImage: event.data?.image || '',
|
|
241
|
+
files: event.data?.files || context.files,
|
|
242
|
+
images: event.data?.images || context.images,
|
|
243
|
+
imageLoading: false,
|
|
244
|
+
};
|
|
245
|
+
}),
|
|
246
|
+
clearImageData: assign(({ context }) => {
|
|
247
|
+
return {
|
|
248
|
+
...context,
|
|
249
|
+
selectedImage: '',
|
|
250
|
+
files: [],
|
|
251
|
+
images: [],
|
|
252
|
+
};
|
|
253
|
+
}),
|
|
254
|
+
setMessageText: assign(({ context, event }) => {
|
|
255
|
+
return {
|
|
256
|
+
...context,
|
|
257
|
+
messageText: event.data?.messageText || '',
|
|
258
|
+
};
|
|
259
|
+
}),
|
|
260
|
+
setScrollToBottom: assign(({ context, event }) => {
|
|
261
|
+
return {
|
|
262
|
+
...context,
|
|
263
|
+
isScrollToBottom: event.data?.isScrollToBottom || false,
|
|
264
|
+
};
|
|
265
|
+
}),
|
|
266
|
+
},
|
|
267
|
+
guards: {
|
|
268
|
+
hasMoreMessages: ({ context }) => {
|
|
269
|
+
return context.totalCount > context.threadMessages.length;
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
}).createMachine({
|
|
273
|
+
id: 'thread-conversation-view',
|
|
274
|
+
initial: BaseState.Idle,
|
|
275
|
+
context: {
|
|
276
|
+
channelId: null,
|
|
277
|
+
postParentId: null,
|
|
278
|
+
role: null,
|
|
279
|
+
threadMessages: [],
|
|
280
|
+
totalCount: 0,
|
|
281
|
+
skip: 0,
|
|
282
|
+
loading: false,
|
|
283
|
+
loadingOldMessages: false,
|
|
284
|
+
error: null,
|
|
285
|
+
selectedImage: '',
|
|
286
|
+
files: [],
|
|
287
|
+
images: [],
|
|
288
|
+
messageText: '',
|
|
289
|
+
imageLoading: false,
|
|
290
|
+
postThread: null,
|
|
291
|
+
threadPost: [],
|
|
292
|
+
isScrollToBottom: false,
|
|
293
|
+
},
|
|
294
|
+
states: {
|
|
295
|
+
[BaseState.Idle]: {
|
|
296
|
+
on: {
|
|
297
|
+
[Actions.INITIAL_CONTEXT]: {
|
|
298
|
+
target: BaseState.FetchThreadMessages,
|
|
299
|
+
actions: ['setInitialContext'],
|
|
300
|
+
},
|
|
301
|
+
[Actions.SEND_THREAD_MESSAGE]: {
|
|
302
|
+
target: MainState.SendThreadMessage,
|
|
303
|
+
actions: ['startLoading'],
|
|
304
|
+
},
|
|
305
|
+
[Actions.SEND_THREAD_MESSAGE_WITH_FILE]: {
|
|
306
|
+
target: MainState.SendThreadMessageWithFile,
|
|
307
|
+
actions: ['startLoading'],
|
|
308
|
+
},
|
|
309
|
+
[Actions.FETCH_MORE_MESSAGES]: {
|
|
310
|
+
target: MainState.FetchMoreMessages,
|
|
311
|
+
actions: ['updateSkip'],
|
|
312
|
+
guard: 'hasMoreMessages',
|
|
313
|
+
},
|
|
314
|
+
[Actions.CLEAR_MESSAGES]: {
|
|
315
|
+
target: BaseState.Idle,
|
|
316
|
+
actions: ['clearMessages'],
|
|
317
|
+
},
|
|
318
|
+
[Actions.START_LOADING]: {
|
|
319
|
+
target: BaseState.Idle,
|
|
320
|
+
actions: ['startLoading'],
|
|
321
|
+
},
|
|
322
|
+
[Actions.STOP_LOADING]: {
|
|
323
|
+
target: BaseState.Idle,
|
|
324
|
+
actions: ['stopLoading'],
|
|
325
|
+
},
|
|
326
|
+
[Actions.SET_IMAGE]: {
|
|
327
|
+
target: BaseState.Idle,
|
|
328
|
+
actions: ['setSelectedImage'],
|
|
329
|
+
},
|
|
330
|
+
[Actions.CLEAR_IMAGE]: {
|
|
331
|
+
target: BaseState.Idle,
|
|
332
|
+
actions: ['clearImageData'],
|
|
333
|
+
},
|
|
334
|
+
[Actions.SET_MESSAGE_TEXT]: {
|
|
335
|
+
target: BaseState.Idle,
|
|
336
|
+
actions: ['setMessageText'],
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
[BaseState.Error]: {
|
|
341
|
+
entry: ['errorState'],
|
|
342
|
+
on: {
|
|
343
|
+
[Actions.ERROR_HANDLED]: {
|
|
344
|
+
target: BaseState.Idle,
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
[BaseState.FetchThreadMessages]: {
|
|
349
|
+
invoke: {
|
|
350
|
+
src: 'fetchThreadMessages',
|
|
351
|
+
input: ({ context, event }) => ({ context, event }),
|
|
352
|
+
onDone: {
|
|
353
|
+
target: BaseState.Idle,
|
|
354
|
+
actions: ['setThreadMessages'],
|
|
355
|
+
},
|
|
356
|
+
onError: {
|
|
357
|
+
target: BaseState.Error,
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
[MainState.SendThreadMessage]: {
|
|
362
|
+
invoke: {
|
|
363
|
+
src: 'sendThreadMessage',
|
|
364
|
+
input: ({ context, event }) => ({ context, event }),
|
|
365
|
+
onDone: {
|
|
366
|
+
target: BaseState.Idle,
|
|
367
|
+
actions: ['addNewMessage', 'stopLoading'],
|
|
368
|
+
},
|
|
369
|
+
onError: {
|
|
370
|
+
target: BaseState.Error,
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
[MainState.SendThreadMessageWithFile]: {
|
|
375
|
+
invoke: {
|
|
376
|
+
src: 'sendThreadMessageWithFile',
|
|
377
|
+
input: ({ context, event }) => ({ context, event }),
|
|
378
|
+
onDone: {
|
|
379
|
+
target: BaseState.Idle,
|
|
380
|
+
actions: ['addNewMessage', 'clearImageData', 'stopLoading'],
|
|
381
|
+
},
|
|
382
|
+
onError: {
|
|
383
|
+
target: BaseState.Error,
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
[MainState.FetchMoreMessages]: {
|
|
388
|
+
invoke: {
|
|
389
|
+
src: 'fetchMoreThreadMessages',
|
|
390
|
+
input: ({ context, event }) => ({ context, event }),
|
|
391
|
+
onDone: {
|
|
392
|
+
target: BaseState.Idle,
|
|
393
|
+
actions: ['addThreadMessages'],
|
|
394
|
+
},
|
|
395
|
+
onError: {
|
|
396
|
+
target: BaseState.Error,
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
} as any);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* useInboxMessages - a generic hook for fetching and subscribing to messages
|
|
5
|
+
*
|
|
6
|
+
* @param useQueryHook - Apollo query hook (e.g., useChannelMessagesQuery)
|
|
7
|
+
* @param queryVariables - variables for the query
|
|
8
|
+
* @param subscriptionDocument - GraphQL subscription document
|
|
9
|
+
* @param subscriptionVariables - variables for the subscription
|
|
10
|
+
* @param updateQuery - Apollo updateQuery function (optional)
|
|
11
|
+
* @param onError - error handler (optional)
|
|
12
|
+
* @returns { data, loading, error, refetch, subscribe }
|
|
13
|
+
*/
|
|
14
|
+
export function useInboxMessages({
|
|
15
|
+
useQueryHook,
|
|
16
|
+
queryVariables,
|
|
17
|
+
subscriptionDocument,
|
|
18
|
+
subscriptionVariables,
|
|
19
|
+
updateQuery,
|
|
20
|
+
onError,
|
|
21
|
+
}) {
|
|
22
|
+
const { data, loading, error, refetch, subscribeToMore } = useQueryHook(queryVariables);
|
|
23
|
+
|
|
24
|
+
const subscribe = useCallback(() => {
|
|
25
|
+
return subscribeToMore({
|
|
26
|
+
document: subscriptionDocument,
|
|
27
|
+
variables: subscriptionVariables,
|
|
28
|
+
updateQuery,
|
|
29
|
+
onError,
|
|
30
|
+
});
|
|
31
|
+
}, [subscribeToMore, subscriptionDocument, subscriptionVariables, updateQuery, onError]);
|
|
32
|
+
|
|
33
|
+
return { data, loading, error, refetch, subscribe };
|
|
34
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { useState, useCallback, useMemo } from 'react';
|
|
2
|
+
import { BaseState, Actions, dialogThreadsXstate } from '../workflow/dialog-threads-xstate';
|
|
3
|
+
|
|
4
|
+
// Define proper types for the state and context
|
|
5
|
+
export interface DialogThreadsContext {
|
|
6
|
+
channelId?: string;
|
|
7
|
+
postParentId?: string | number;
|
|
8
|
+
role?: string;
|
|
9
|
+
channelsDetail: any;
|
|
10
|
+
threadData: any[];
|
|
11
|
+
loading: boolean;
|
|
12
|
+
error: any;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DialogThreadsState {
|
|
16
|
+
context: DialogThreadsContext;
|
|
17
|
+
value: BaseState;
|
|
18
|
+
matches: (stateValue: string) => boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Define proper action types
|
|
22
|
+
export type DialogThreadsEvent =
|
|
23
|
+
| { type: typeof Actions.INITIALIZE; data: { channelId?: string; postParentId?: string | number; role?: string } }
|
|
24
|
+
| { type: typeof Actions.FETCH_CHANNEL_DETAIL; data: { id: string } }
|
|
25
|
+
| { type: typeof Actions.SET_CHANNEL_DETAIL; data: { channelsDetail: any } }
|
|
26
|
+
| { type: typeof Actions.FETCH_THREADS; data?: any }
|
|
27
|
+
| { type: typeof Actions.SET_THREADS; data: { threadData: any[] } }
|
|
28
|
+
| { type: typeof Actions.ERROR; data: { error: any } };
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Custom hook to safely use the dialog threads state machine
|
|
32
|
+
* This provides a fallback implementation in case useMachine from XState has issues
|
|
33
|
+
*/
|
|
34
|
+
export function useSafeDialogThreadsMachine(): [DialogThreadsState, (event: DialogThreadsEvent) => void] {
|
|
35
|
+
// Initialize with default state from the machine's initial context
|
|
36
|
+
const [state, setState] = useState<DialogThreadsState>({
|
|
37
|
+
context: {
|
|
38
|
+
channelId: undefined,
|
|
39
|
+
postParentId: undefined,
|
|
40
|
+
role: undefined,
|
|
41
|
+
channelsDetail: null,
|
|
42
|
+
threadData: [],
|
|
43
|
+
loading: true,
|
|
44
|
+
error: null,
|
|
45
|
+
},
|
|
46
|
+
value: BaseState.Idle,
|
|
47
|
+
matches: (value: string) => value === BaseState.Idle,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Create a memoized function to determine state matching
|
|
51
|
+
const matches = useCallback((value: string) => value === state.value, [state.value]);
|
|
52
|
+
|
|
53
|
+
// Update the matches function when state changes
|
|
54
|
+
useMemo(() => {
|
|
55
|
+
setState((prev) => ({
|
|
56
|
+
...prev,
|
|
57
|
+
matches,
|
|
58
|
+
}));
|
|
59
|
+
}, [matches]);
|
|
60
|
+
|
|
61
|
+
// Create a safe send function to handle events
|
|
62
|
+
const send = useCallback((event: DialogThreadsEvent) => {
|
|
63
|
+
try {
|
|
64
|
+
// Handle specific events based on the event type
|
|
65
|
+
if (event.type === Actions.INITIALIZE) {
|
|
66
|
+
setState((prev) => ({
|
|
67
|
+
...prev,
|
|
68
|
+
context: {
|
|
69
|
+
...prev.context,
|
|
70
|
+
channelId: event.data?.channelId,
|
|
71
|
+
postParentId: event.data?.postParentId,
|
|
72
|
+
role: event.data?.role,
|
|
73
|
+
loading: true,
|
|
74
|
+
error: null,
|
|
75
|
+
},
|
|
76
|
+
value: BaseState.LoadingChannel,
|
|
77
|
+
}));
|
|
78
|
+
} else if (event.type === Actions.SET_CHANNEL_DETAIL) {
|
|
79
|
+
setState((prev) => ({
|
|
80
|
+
...prev,
|
|
81
|
+
context: {
|
|
82
|
+
...prev.context,
|
|
83
|
+
channelsDetail: event.data?.channelsDetail,
|
|
84
|
+
loading: false,
|
|
85
|
+
},
|
|
86
|
+
value: BaseState.LoadingThreads,
|
|
87
|
+
}));
|
|
88
|
+
} else if (event.type === Actions.SET_THREADS) {
|
|
89
|
+
setState((prev) => ({
|
|
90
|
+
...prev,
|
|
91
|
+
context: {
|
|
92
|
+
...prev.context,
|
|
93
|
+
threadData: event.data?.threadData || [],
|
|
94
|
+
loading: false,
|
|
95
|
+
},
|
|
96
|
+
value: BaseState.Active,
|
|
97
|
+
}));
|
|
98
|
+
} else if (event.type === Actions.FETCH_THREADS) {
|
|
99
|
+
setState((prev) => ({
|
|
100
|
+
...prev,
|
|
101
|
+
context: {
|
|
102
|
+
...prev.context,
|
|
103
|
+
loading: true,
|
|
104
|
+
},
|
|
105
|
+
value: BaseState.LoadingThreads,
|
|
106
|
+
}));
|
|
107
|
+
} else if (event.type === Actions.ERROR) {
|
|
108
|
+
setState((prev) => ({
|
|
109
|
+
...prev,
|
|
110
|
+
context: {
|
|
111
|
+
...prev.context,
|
|
112
|
+
error: event.data?.error,
|
|
113
|
+
loading: false,
|
|
114
|
+
},
|
|
115
|
+
value: BaseState.Error,
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
} catch (error) {
|
|
119
|
+
// Handle errors gracefully
|
|
120
|
+
setState((prev) => ({
|
|
121
|
+
...prev,
|
|
122
|
+
context: {
|
|
123
|
+
...prev.context,
|
|
124
|
+
error,
|
|
125
|
+
loading: false,
|
|
126
|
+
},
|
|
127
|
+
value: BaseState.Error,
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
}, []);
|
|
131
|
+
|
|
132
|
+
// Return as a tuple to match useMachine API
|
|
133
|
+
return [state, send];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export default useSafeDialogThreadsMachine;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// State machines
|
|
2
|
+
export {
|
|
3
|
+
dialogThreadsXstate,
|
|
4
|
+
Actions as DialogThreadsActions,
|
|
5
|
+
BaseState as DialogThreadsState,
|
|
6
|
+
} from './workflow/dialog-threads-xstate';
|
|
7
|
+
export {
|
|
8
|
+
threadConversationXstate,
|
|
9
|
+
Actions as ThreadConversationActions,
|
|
10
|
+
BaseState as ThreadConversationState,
|
|
11
|
+
} from './containers/workflow/thread-conversation-xstate';
|
|
12
|
+
export {
|
|
13
|
+
conversationXstate,
|
|
14
|
+
Actions as ConversationActions,
|
|
15
|
+
BaseState as ConversationState,
|
|
16
|
+
} from './containers/workflow/conversation-xstate';
|
|
17
|
+
export {
|
|
18
|
+
dialogsXstate,
|
|
19
|
+
Actions as DialogsActions,
|
|
20
|
+
BaseState as DialogsState,
|
|
21
|
+
} from './containers/workflow/dialogs-xstate';
|
|
22
|
+
|
|
23
|
+
// Hooks
|
|
24
|
+
export { default as useSafeDialogThreadsMachine } from './hooks/useSafeDialogThreadsMachine';
|
|
25
|
+
|
|
26
|
+
// Components
|
|
27
|
+
export { DialogThreads } from './DialogThreads';
|
|
28
|
+
export { ThreadsView } from './containers/ThreadsView';
|
|
29
|
+
export { ThreadConversationView } from './containers/ThreadConversationView';
|
|
30
|
+
export { ConversationView } from './containers/ConversationView';
|
|
31
|
+
export { Dialogs } from './containers/Dialogs';
|
|
32
|
+
|
|
33
|
+
// Configuration
|
|
34
|
+
export { config } from './config';
|
|
35
|
+
|
|
36
|
+
// Utility
|
|
37
|
+
export { threadsMachineConfig, setupThreadSubscription } from './machines/threadsMachine';
|