@messenger-box/platform-mobile 10.0.3-alpha.18 → 10.0.3-alpha.20
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 +8 -0
- package/lib/screens/inbox/components/DialogsListItem.js +423 -50
- package/lib/screens/inbox/components/DialogsListItem.js.map +1 -1
- package/lib/screens/inbox/components/ServiceDialogsListItem.js +375 -51
- package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +1 -1
- package/lib/screens/inbox/components/workflow/dialogs-list-item-xstate.js +175 -0
- package/lib/screens/inbox/components/workflow/dialogs-list-item-xstate.js.map +1 -0
- package/lib/screens/inbox/components/workflow/service-dialogs-list-item-xstate.js +191 -0
- package/lib/screens/inbox/components/workflow/service-dialogs-list-item-xstate.js.map +1 -0
- package/lib/screens/inbox/containers/Dialogs.js +382 -181
- package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
- package/lib/screens/inbox/containers/ThreadConversationView.js +536 -48
- package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
- package/lib/screens/inbox/containers/workflow/dialogs-xstate.js +1 -25
- package/lib/screens/inbox/containers/workflow/dialogs-xstate.js.map +1 -1
- package/package.json +2 -2
- package/src/screens/inbox/components/DialogsListItem.tsx +624 -107
- package/src/screens/inbox/components/ServiceDialogsListItem.tsx +506 -114
- package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +35 -17
- 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/containers/Dialogs.tsx +531 -281
- package/src/screens/inbox/containers/ThreadConversationView.tsx +812 -37
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React__default,{useRef,useCallback,useEffect,useState,useMemo}from'react';import {Box,FlatList,Center,Spinner,Heading,Input,InputField
|
|
1
|
+
import React__default,{useRef,useCallback,useEffect,useState,useMemo}from'react';import {Box,FlatList,Center,Spinner,Text,Heading,Input,InputField}from'@admin-layout/gluestack-ui-mobile';import {Ionicons}from'@expo/vector-icons';import {useSelector}from'react-redux';import {useRoute,useNavigation,useFocusEffect}from'@react-navigation/native';import {orderBy}from'lodash-es';import {DialogsListItem}from'../components/DialogsListItem.js';import {ServiceDialogsListItem}from'../components/ServiceDialogsListItem.js';import {useGetChannelsByUserWithServiceChannelsQuery}from'common/graphql';import {RoomType}from'common';import {userSelector}from'@adminide-stack/user-auth0-client';import {config}from'../config/config.js';import colors from'tailwindcss/colors';import'./workflow/dialogs-xstate.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __defProps = Object.defineProperties;
|
|
3
3
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
@@ -17,6 +17,30 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
return a;
|
|
18
18
|
};
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
const Actions = {
|
|
21
|
+
INITIAL_CONTEXT: "INITIAL_CONTEXT",
|
|
22
|
+
ERROR_HANDLED: "ERROR_HANDLED",
|
|
23
|
+
FETCH_CHANNELS: "FETCH_CHANNELS",
|
|
24
|
+
APPEND_CHANNELS: "APPEND_CHANNELS",
|
|
25
|
+
REFRESH_CHANNELS: "REFRESH_CHANNELS",
|
|
26
|
+
SELECT_CHANNEL: "SELECT_CHANNEL",
|
|
27
|
+
START_LOADING: "START_LOADING",
|
|
28
|
+
STOP_LOADING: "STOP_LOADING",
|
|
29
|
+
LOAD_MORE_CHANNELS: "LOAD_MORE_CHANNELS",
|
|
30
|
+
SET_SEARCH_QUERY: "SET_SEARCH_QUERY"
|
|
31
|
+
};
|
|
32
|
+
const BaseState = {
|
|
33
|
+
Idle: "idle",
|
|
34
|
+
Error: "error",
|
|
35
|
+
Loading: "loading",
|
|
36
|
+
Done: "done",
|
|
37
|
+
FetchChannels: "fetchChannels"
|
|
38
|
+
};
|
|
39
|
+
const MainState = {
|
|
40
|
+
RefreshChannels: "refreshChannels",
|
|
41
|
+
SelectChannel: "selectChannel",
|
|
42
|
+
LoadMoreChannels: "loadMoreChannels"
|
|
43
|
+
};
|
|
20
44
|
function useSafeMachine(machine) {
|
|
21
45
|
const [state, setState] = useState({
|
|
22
46
|
context: {
|
|
@@ -28,50 +52,76 @@ function useSafeMachine(machine) {
|
|
|
28
52
|
selectedChannelId: null,
|
|
29
53
|
channelRole: null,
|
|
30
54
|
channelFilters: {},
|
|
31
|
-
supportServices: false
|
|
55
|
+
supportServices: false,
|
|
56
|
+
page: 1,
|
|
57
|
+
hasMoreChannels: true,
|
|
58
|
+
loadingMore: false
|
|
32
59
|
},
|
|
33
60
|
value: "idle"
|
|
34
61
|
});
|
|
35
62
|
const send = useCallback((event) => {
|
|
63
|
+
var _a, _b, _c, _d;
|
|
36
64
|
try {
|
|
37
|
-
console.log("
|
|
65
|
+
console.log("Event received:", event.type);
|
|
38
66
|
if (event.type === Actions.INITIAL_CONTEXT) {
|
|
39
67
|
setState((prev) => {
|
|
40
|
-
var
|
|
68
|
+
var _a2, _b2, _c2, _d2;
|
|
41
69
|
return __spreadProps(__spreadValues({}, prev), {
|
|
42
70
|
context: __spreadProps(__spreadValues({}, prev.context), {
|
|
43
|
-
channelRole: ((
|
|
44
|
-
channelFilters: ((
|
|
45
|
-
supportServices: ((
|
|
46
|
-
selectedChannelId: ((
|
|
71
|
+
channelRole: ((_a2 = event.data) == null ? void 0 : _a2.channelRole) || null,
|
|
72
|
+
channelFilters: ((_b2 = event.data) == null ? void 0 : _b2.channelFilters) || {},
|
|
73
|
+
supportServices: ((_c2 = event.data) == null ? void 0 : _c2.supportServices) || false,
|
|
74
|
+
selectedChannelId: ((_d2 = event.data) == null ? void 0 : _d2.selectedChannelId) || null,
|
|
75
|
+
loading: true,
|
|
76
|
+
page: 1,
|
|
77
|
+
hasMoreChannels: true
|
|
47
78
|
}),
|
|
48
79
|
value: BaseState.FetchChannels
|
|
49
80
|
});
|
|
50
81
|
});
|
|
51
|
-
} else if (event.type === Actions.
|
|
82
|
+
} else if (event.type === Actions.FETCH_CHANNELS) {
|
|
83
|
+
console.log("Setting channels:", ((_b = (_a = event.data) == null ? void 0 : _a.channels) == null ? void 0 : _b.length) || 0);
|
|
52
84
|
setState((prev) => {
|
|
53
|
-
var
|
|
85
|
+
var _a2, _b2, _c2, _d2, _e;
|
|
54
86
|
return __spreadProps(__spreadValues({}, prev), {
|
|
55
87
|
context: __spreadProps(__spreadValues({}, prev.context), {
|
|
56
|
-
|
|
57
|
-
|
|
88
|
+
channels: ((_a2 = event.data) == null ? void 0 : _a2.channels) || [],
|
|
89
|
+
hasMoreChannels: (((_c2 = (_b2 = event.data) == null ? void 0 : _b2.channels) == null ? void 0 : _c2.length) || 0) > 0,
|
|
90
|
+
loading: ((_d2 = event.data) == null ? void 0 : _d2.stopLoading) ? false : prev.context.loading,
|
|
91
|
+
refreshing: ((_e = event.data) == null ? void 0 : _e.stopLoading) ? false : prev.context.refreshing,
|
|
92
|
+
loadingMore: false
|
|
93
|
+
}),
|
|
94
|
+
value: BaseState.Idle
|
|
58
95
|
});
|
|
59
96
|
});
|
|
97
|
+
} else if (event.type === Actions.APPEND_CHANNELS) {
|
|
98
|
+
const newChannels = ((_c = event.data) == null ? void 0 : _c.channels) || [];
|
|
99
|
+
console.log("Appending channels:", newChannels.length);
|
|
100
|
+
setState((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
101
|
+
context: __spreadProps(__spreadValues({}, prev.context), {
|
|
102
|
+
channels: [...prev.context.channels, ...newChannels],
|
|
103
|
+
hasMoreChannels: newChannels.length >= 10,
|
|
104
|
+
page: prev.context.page + 1,
|
|
105
|
+
loadingMore: false
|
|
106
|
+
}),
|
|
107
|
+
value: BaseState.Idle
|
|
108
|
+
}));
|
|
60
109
|
} else if (event.type === Actions.REFRESH_CHANNELS) {
|
|
61
110
|
setState((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
62
111
|
context: __spreadProps(__spreadValues({}, prev.context), {
|
|
63
|
-
refreshing: true
|
|
112
|
+
refreshing: true,
|
|
113
|
+
page: 1,
|
|
114
|
+
hasMoreChannels: true
|
|
64
115
|
}),
|
|
65
116
|
value: MainState.RefreshChannels
|
|
66
117
|
}));
|
|
67
118
|
} else if (event.type === Actions.SELECT_CHANNEL) {
|
|
68
119
|
setState((prev) => {
|
|
69
|
-
var
|
|
120
|
+
var _a2;
|
|
70
121
|
return __spreadProps(__spreadValues({}, prev), {
|
|
71
122
|
context: __spreadProps(__spreadValues({}, prev.context), {
|
|
72
|
-
selectedChannelId: ((
|
|
73
|
-
})
|
|
74
|
-
value: MainState.SelectChannel
|
|
123
|
+
selectedChannelId: ((_a2 = event.data) == null ? void 0 : _a2.channelId) || null
|
|
124
|
+
})
|
|
75
125
|
});
|
|
76
126
|
});
|
|
77
127
|
} else if (event.type === Actions.START_LOADING) {
|
|
@@ -81,54 +131,55 @@ function useSafeMachine(machine) {
|
|
|
81
131
|
})
|
|
82
132
|
}));
|
|
83
133
|
} else if (event.type === Actions.STOP_LOADING) {
|
|
134
|
+
console.log("Explicitly stopping loading state");
|
|
84
135
|
setState((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
85
136
|
context: __spreadProps(__spreadValues({}, prev.context), {
|
|
86
|
-
loading: false
|
|
87
|
-
|
|
137
|
+
loading: false,
|
|
138
|
+
refreshing: false,
|
|
139
|
+
loadingMore: false
|
|
140
|
+
}),
|
|
141
|
+
value: prev.value === BaseState.FetchChannels ? BaseState.Idle : prev.value
|
|
88
142
|
}));
|
|
89
|
-
} else if (event.type ===
|
|
90
|
-
setState((prev) => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}),
|
|
98
|
-
value: BaseState.Idle
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
} else if (event.type === "REFRESH_CHANNELS_SUCCESS") {
|
|
143
|
+
} else if (event.type === Actions.LOAD_MORE_CHANNELS) {
|
|
144
|
+
setState((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
145
|
+
context: __spreadProps(__spreadValues({}, prev.context), {
|
|
146
|
+
loadingMore: true
|
|
147
|
+
}),
|
|
148
|
+
value: MainState.LoadMoreChannels
|
|
149
|
+
}));
|
|
150
|
+
} else if (event.type === Actions.SET_SEARCH_QUERY) {
|
|
102
151
|
setState((prev) => {
|
|
103
|
-
var
|
|
152
|
+
var _a2;
|
|
104
153
|
return __spreadProps(__spreadValues({}, prev), {
|
|
105
154
|
context: __spreadProps(__spreadValues({}, prev.context), {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}),
|
|
109
|
-
value: BaseState.Idle
|
|
155
|
+
searchQuery: ((_a2 = event.data) == null ? void 0 : _a2.searchQuery) || ""
|
|
156
|
+
})
|
|
110
157
|
});
|
|
111
158
|
});
|
|
112
|
-
} else if (event.type ===
|
|
159
|
+
} else if (event.type === Actions.ERROR_HANDLED) {
|
|
160
|
+
console.log("Error handled:", (_d = event.data) == null ? void 0 : _d.message);
|
|
113
161
|
setState((prev) => {
|
|
114
|
-
var
|
|
162
|
+
var _a2;
|
|
115
163
|
return __spreadProps(__spreadValues({}, prev), {
|
|
116
164
|
context: __spreadProps(__spreadValues({}, prev.context), {
|
|
117
|
-
error: ((
|
|
165
|
+
error: ((_a2 = event.data) == null ? void 0 : _a2.message) || null,
|
|
118
166
|
loading: false,
|
|
119
|
-
refreshing: false
|
|
167
|
+
refreshing: false,
|
|
168
|
+
loadingMore: false
|
|
120
169
|
}),
|
|
121
|
-
value: BaseState.
|
|
170
|
+
value: BaseState.Idle
|
|
122
171
|
});
|
|
123
172
|
});
|
|
124
173
|
}
|
|
125
|
-
} catch (
|
|
126
|
-
console.error("Error
|
|
174
|
+
} catch (error) {
|
|
175
|
+
console.error("Error handling event:", error);
|
|
127
176
|
}
|
|
128
177
|
}, []);
|
|
129
178
|
const stateWithMatches = useMemo(() => {
|
|
130
179
|
return __spreadProps(__spreadValues({}, state), {
|
|
131
|
-
matches: (
|
|
180
|
+
matches: (checkState) => {
|
|
181
|
+
return state.value === checkState;
|
|
182
|
+
}
|
|
132
183
|
});
|
|
133
184
|
}, [state]);
|
|
134
185
|
return [stateWithMatches, send];
|
|
@@ -146,9 +197,7 @@ const DialogsComponent = (props) => {
|
|
|
146
197
|
params
|
|
147
198
|
} = useRoute();
|
|
148
199
|
const auth = useSelector(userSelector);
|
|
149
|
-
useDispatch();
|
|
150
200
|
const navigation = useNavigation();
|
|
151
|
-
const isFocused = useIsFocused();
|
|
152
201
|
const isMountedRef = useRef(true);
|
|
153
202
|
const [state, send] = useSafeMachine();
|
|
154
203
|
useCallback(() => {
|
|
@@ -168,7 +217,7 @@ const DialogsComponent = (props) => {
|
|
|
168
217
|
return defaultValue;
|
|
169
218
|
}
|
|
170
219
|
}, [state]);
|
|
171
|
-
useCallback((stateValue) => {
|
|
220
|
+
const safeMatches = useCallback((stateValue) => {
|
|
172
221
|
var _a2;
|
|
173
222
|
try {
|
|
174
223
|
return ((_a2 = state == null ? void 0 : state.matches) == null ? void 0 : _a2.call(state, stateValue)) || false;
|
|
@@ -184,18 +233,43 @@ const DialogsComponent = (props) => {
|
|
|
184
233
|
console.error("Error sending event to state machine:", error, event);
|
|
185
234
|
}
|
|
186
235
|
}, [send]);
|
|
236
|
+
const channels = safeContextProperty("channels", []);
|
|
237
|
+
const refreshing = safeContextProperty("refreshing", false);
|
|
238
|
+
const loading = safeContextProperty("loading", false);
|
|
239
|
+
const searchQuery = safeContextProperty("searchQuery", "");
|
|
240
|
+
const selectedChannelId = safeContextProperty("selectedChannelId", null);
|
|
241
|
+
const loadingMore = safeContextProperty("loadingMore", false);
|
|
242
|
+
const hasMoreChannels = safeContextProperty("hasMoreChannels", true);
|
|
243
|
+
const page = safeContextProperty("page", 1);
|
|
187
244
|
const stateRef = useRef(state);
|
|
188
245
|
useEffect(() => {
|
|
189
246
|
stateRef.current = state;
|
|
190
247
|
}, [state]);
|
|
248
|
+
const safeGetContext = useCallback(() => {
|
|
249
|
+
if (stateRef.current && stateRef.current.context) {
|
|
250
|
+
return stateRef.current.context;
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
channels: [],
|
|
254
|
+
refreshing: false,
|
|
255
|
+
loading: false,
|
|
256
|
+
error: null,
|
|
257
|
+
searchQuery: "",
|
|
258
|
+
selectedChannelId: null,
|
|
259
|
+
channelRole: null,
|
|
260
|
+
channelFilters: {},
|
|
261
|
+
supportServices: false,
|
|
262
|
+
page: 1,
|
|
263
|
+
hasMoreChannels: true,
|
|
264
|
+
loadingMore: false
|
|
265
|
+
};
|
|
266
|
+
}, []);
|
|
191
267
|
useEffect(() => {
|
|
192
268
|
return () => {
|
|
193
269
|
isMountedRef.current = false;
|
|
194
270
|
};
|
|
195
271
|
}, []);
|
|
196
272
|
const {
|
|
197
|
-
data: userChannels,
|
|
198
|
-
loading: userChannelsLoading,
|
|
199
273
|
refetch: getChannelsRefetch
|
|
200
274
|
} = useGetChannelsByUserWithServiceChannelsQuery({
|
|
201
275
|
variables: {
|
|
@@ -204,188 +278,315 @@ const DialogsComponent = (props) => {
|
|
|
204
278
|
supportServices: supportServices ? true : false,
|
|
205
279
|
supportServiceCriteria: {
|
|
206
280
|
type: RoomType.Service
|
|
207
|
-
}
|
|
281
|
+
},
|
|
282
|
+
limit: 15,
|
|
283
|
+
skip: 0
|
|
208
284
|
},
|
|
209
|
-
|
|
210
|
-
|
|
285
|
+
fetchPolicy: "cache-and-network",
|
|
286
|
+
nextFetchPolicy: "network-only",
|
|
287
|
+
notifyOnNetworkStatusChange: true,
|
|
288
|
+
skip: true
|
|
289
|
+
});
|
|
290
|
+
const fetchChannelsDirectly = useCallback(async (pageNum = 1, append = false) => {
|
|
291
|
+
var _a2, _b, _c;
|
|
292
|
+
try {
|
|
293
|
+
const context = safeGetContext();
|
|
294
|
+
console.log(`\u{1F4AB} FETCHING channels (page: ${pageNum}, append: ${append})`);
|
|
295
|
+
const skipCount = (pageNum - 1) * 15;
|
|
296
|
+
const {
|
|
297
|
+
data
|
|
298
|
+
} = await getChannelsRefetch({
|
|
299
|
+
role: channelRole,
|
|
300
|
+
criteria: channelFilters,
|
|
301
|
+
supportServices: supportServices ? true : false,
|
|
302
|
+
supportServiceCriteria: {
|
|
303
|
+
type: RoomType.Service
|
|
304
|
+
},
|
|
305
|
+
limit: 15,
|
|
306
|
+
skip: skipCount
|
|
307
|
+
});
|
|
308
|
+
const allChannels = [...(_a2 = data == null ? void 0 : data.supportServiceChannels) != null ? _a2 : [], ...(_b = data == null ? void 0 : data.channelsByUser) != null ? _b : []];
|
|
309
|
+
const filteredChannels = (_c = allChannels == null ? void 0 : allChannels.filter((c) => c.members.some((u) => {
|
|
310
|
+
var _a3;
|
|
311
|
+
return u !== null && ((_a3 = u == null ? void 0 : u.user) == null ? void 0 : _a3.id) != (auth == null ? void 0 : auth.id) && u.user.__typename == "UserAccount";
|
|
312
|
+
}))) != null ? _c : [];
|
|
313
|
+
const sortedChannels = filteredChannels && orderBy(filteredChannels, ["updatedAt"], ["desc"]) || [];
|
|
314
|
+
console.log(`\u{1F4CA} Processed channels: ${sortedChannels.length} (page: ${pageNum}, skip: ${skipCount})`);
|
|
211
315
|
if (isMountedRef.current) {
|
|
212
|
-
|
|
316
|
+
if (append) {
|
|
317
|
+
safeSend({
|
|
318
|
+
type: Actions.APPEND_CHANNELS,
|
|
319
|
+
data: {
|
|
320
|
+
channels: sortedChannels
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
} else {
|
|
324
|
+
safeSend({
|
|
325
|
+
type: Actions.FETCH_CHANNELS,
|
|
326
|
+
data: {
|
|
327
|
+
channels: sortedChannels
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
}
|
|
213
331
|
safeSend({
|
|
214
|
-
type:
|
|
215
|
-
data: {
|
|
216
|
-
channels: allChannels
|
|
217
|
-
}
|
|
332
|
+
type: Actions.STOP_LOADING
|
|
218
333
|
});
|
|
219
334
|
}
|
|
220
|
-
}
|
|
221
|
-
|
|
335
|
+
} catch (error) {
|
|
336
|
+
console.error("Error fetching channels:", error);
|
|
222
337
|
if (isMountedRef.current) {
|
|
223
338
|
safeSend({
|
|
224
|
-
type:
|
|
339
|
+
type: Actions.ERROR_HANDLED,
|
|
225
340
|
data: {
|
|
226
|
-
message:
|
|
341
|
+
message: "Failed to fetch channels"
|
|
227
342
|
}
|
|
228
343
|
});
|
|
229
344
|
}
|
|
230
345
|
}
|
|
231
|
-
});
|
|
346
|
+
}, [getChannelsRefetch, channelRole, channelFilters, supportServices, auth == null ? void 0 : auth.id, safeSend]);
|
|
232
347
|
useEffect(() => {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
}, []);
|
|
244
|
-
const hasRefreshedRef = useRef(false);
|
|
245
|
-
const channelFiltersRef = useRef(channelFilters);
|
|
246
|
-
const refreshChannels = useCallback(() => {
|
|
247
|
-
if (safeContextProperty("refreshing", false)) {
|
|
248
|
-
console.log("Skipping refresh - already in progress");
|
|
249
|
-
return Promise.resolve();
|
|
348
|
+
if (loading) {
|
|
349
|
+
const safetyTimeout = setTimeout(() => {
|
|
350
|
+
console.log("\u26A0\uFE0F Safety timeout triggered - forcing loading state to stop");
|
|
351
|
+
if (isMountedRef.current) {
|
|
352
|
+
safeSend({
|
|
353
|
+
type: Actions.STOP_LOADING
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}, 5e3);
|
|
357
|
+
return () => clearTimeout(safetyTimeout);
|
|
250
358
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
359
|
+
}, [loading, safeSend]);
|
|
360
|
+
const fastRefresh = useCallback(async () => {
|
|
361
|
+
var _a2, _b, _c;
|
|
362
|
+
try {
|
|
363
|
+
console.log("\u{1F504} Fast refreshing channels...");
|
|
364
|
+
const clearRefreshingTimeout = setTimeout(() => {
|
|
365
|
+
if (isMountedRef.current) {
|
|
366
|
+
console.log("\u26A0\uFE0F Fast refresh timeout - stopping refresh state");
|
|
367
|
+
safeSend({
|
|
368
|
+
type: Actions.STOP_LOADING
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}, 3e3);
|
|
372
|
+
const {
|
|
373
|
+
data
|
|
374
|
+
} = await getChannelsRefetch({
|
|
375
|
+
role: channelRole,
|
|
376
|
+
criteria: channelFilters,
|
|
377
|
+
supportServices: supportServices ? true : false,
|
|
378
|
+
supportServiceCriteria: {
|
|
379
|
+
type: RoomType.Service
|
|
380
|
+
},
|
|
381
|
+
limit: 10,
|
|
382
|
+
skip: 0
|
|
383
|
+
});
|
|
384
|
+
clearTimeout(clearRefreshingTimeout);
|
|
385
|
+
if (!isMountedRef.current)
|
|
386
|
+
return;
|
|
387
|
+
const allChannels = [...(_a2 = data == null ? void 0 : data.supportServiceChannels) != null ? _a2 : [], ...(_b = data == null ? void 0 : data.channelsByUser) != null ? _b : []];
|
|
388
|
+
const filteredChannels = (_c = allChannels == null ? void 0 : allChannels.filter((c) => c.members.some((u) => {
|
|
389
|
+
var _a3;
|
|
390
|
+
return u !== null && ((_a3 = u == null ? void 0 : u.user) == null ? void 0 : _a3.id) != (auth == null ? void 0 : auth.id) && u.user.__typename == "UserAccount";
|
|
391
|
+
}))) != null ? _c : [];
|
|
392
|
+
const sortedChannels = filteredChannels && orderBy(filteredChannels, ["updatedAt"], ["desc"]) || [];
|
|
393
|
+
console.log(`\u{1F4CA} Fast refresh completed: ${sortedChannels.length} channels`);
|
|
265
394
|
if (isMountedRef.current) {
|
|
266
|
-
const allChannels = [...(_b = (_a2 = data == null ? void 0 : data.data) == null ? void 0 : _a2.supportServiceChannels) != null ? _b : [], ...(_d = (_c = data == null ? void 0 : data.data) == null ? void 0 : _c.channelsByUser) != null ? _d : []];
|
|
267
|
-
console.log(`Refresh completed, found ${allChannels.length} channels`);
|
|
268
395
|
safeSend({
|
|
269
|
-
type:
|
|
396
|
+
type: Actions.FETCH_CHANNELS,
|
|
270
397
|
data: {
|
|
271
|
-
channels:
|
|
398
|
+
channels: sortedChannels,
|
|
399
|
+
stopLoading: true
|
|
272
400
|
}
|
|
273
401
|
});
|
|
274
402
|
}
|
|
275
|
-
}
|
|
403
|
+
} catch (error) {
|
|
404
|
+
console.error("Error during fast refresh:", error);
|
|
276
405
|
if (isMountedRef.current) {
|
|
277
|
-
console.error("Channel refresh error:", error.message);
|
|
278
406
|
safeSend({
|
|
279
|
-
type:
|
|
280
|
-
data: {
|
|
281
|
-
message: error.message
|
|
282
|
-
}
|
|
407
|
+
type: Actions.STOP_LOADING
|
|
283
408
|
});
|
|
284
409
|
}
|
|
285
|
-
}
|
|
286
|
-
}, [channelRole, supportServices,
|
|
410
|
+
}
|
|
411
|
+
}, [getChannelsRefetch, channelRole, channelFilters, supportServices, auth == null ? void 0 : auth.id, safeSend]);
|
|
287
412
|
useEffect(() => {
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
413
|
+
const context = safeGetContext();
|
|
414
|
+
const isAlreadyFetching = context.refreshing || context.loading;
|
|
415
|
+
if (!isAlreadyFetching) {
|
|
416
|
+
if (safeMatches(BaseState.FetchChannels)) {
|
|
417
|
+
console.log("\u{1F504} Fetching channels...");
|
|
418
|
+
fetchChannelsDirectly(1, false);
|
|
419
|
+
} else if (safeMatches(MainState.RefreshChannels)) {
|
|
420
|
+
console.log("\u{1F504} Refreshing channels...");
|
|
421
|
+
fetchChannelsDirectly(1, false);
|
|
422
|
+
} else if (safeMatches(MainState.LoadMoreChannels)) {
|
|
423
|
+
console.log("\u{1F504} Loading more channels...");
|
|
424
|
+
fetchChannelsDirectly(page, true);
|
|
295
425
|
}
|
|
426
|
+
} else {
|
|
427
|
+
console.log("\u23E9 Skipping fetch because isAlreadyFetching:", isAlreadyFetching);
|
|
428
|
+
}
|
|
429
|
+
}, [fetchChannelsDirectly, safeMatches, safeGetContext, state.value, page]);
|
|
430
|
+
useEffect(() => {
|
|
431
|
+
console.log("State changed to:", state.value);
|
|
432
|
+
console.log("Context:", JSON.stringify({
|
|
433
|
+
channelsCount: channels.length,
|
|
434
|
+
loading,
|
|
435
|
+
refreshing
|
|
436
|
+
}));
|
|
437
|
+
}, [state.value, channels.length, loading, refreshing]);
|
|
438
|
+
useEffect(() => {
|
|
439
|
+
if (isMountedRef.current) {
|
|
440
|
+
console.log("\u{1F680} Initializing state machine with props", {
|
|
441
|
+
channelRole,
|
|
442
|
+
channelFilters,
|
|
443
|
+
supportServices,
|
|
444
|
+
selectedChannelId: params == null ? void 0 : params.channelId
|
|
445
|
+
});
|
|
446
|
+
safeSend({
|
|
447
|
+
type: Actions.INITIAL_CONTEXT,
|
|
448
|
+
data: {
|
|
449
|
+
channelRole,
|
|
450
|
+
channelFilters,
|
|
451
|
+
supportServices,
|
|
452
|
+
selectedChannelId: params == null ? void 0 : params.channelId
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
const initSafetyTimeout = setTimeout(() => {
|
|
456
|
+
if (isMountedRef.current && loading) {
|
|
457
|
+
console.log("\u26A0\uFE0F Init safety timeout triggered - forcing loading state to stop");
|
|
458
|
+
safeSend({
|
|
459
|
+
type: Actions.STOP_LOADING
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
}, 8e3);
|
|
463
|
+
return () => clearTimeout(initSafetyTimeout);
|
|
296
464
|
}
|
|
297
|
-
}, [
|
|
465
|
+
}, []);
|
|
466
|
+
const focusRefreshRef = useRef(null);
|
|
298
467
|
useFocusEffect(useCallback(() => {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
468
|
+
let hasTriggeredRefresh = false;
|
|
469
|
+
const now = Date.now();
|
|
470
|
+
const lastRefresh = focusRefreshRef.current;
|
|
471
|
+
const shouldRefresh = lastRefresh === null || now - lastRefresh > 2e3;
|
|
472
|
+
const context = safeGetContext();
|
|
473
|
+
const isAlreadyFetching = context.refreshing || context.loading;
|
|
474
|
+
if (isMountedRef.current && !hasTriggeredRefresh && !isAlreadyFetching && shouldRefresh && (channels.length > 0 || safeMatches(BaseState.Idle))) {
|
|
475
|
+
hasTriggeredRefresh = true;
|
|
476
|
+
focusRefreshRef.current = now;
|
|
477
|
+
console.log("\u{1F504} Focus effect: triggering fast refresh");
|
|
478
|
+
safeSend({
|
|
479
|
+
type: Actions.START_LOADING,
|
|
480
|
+
data: {
|
|
481
|
+
refreshing: true
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
setTimeout(() => {
|
|
485
|
+
if (isMountedRef.current) {
|
|
486
|
+
fastRefresh();
|
|
487
|
+
}
|
|
488
|
+
}, 100);
|
|
489
|
+
} else {
|
|
490
|
+
console.log("\u23E9 Skipping focus refresh:", {
|
|
491
|
+
isAlreadyFetching,
|
|
492
|
+
hasTriggeredRefresh,
|
|
493
|
+
shouldRefresh,
|
|
494
|
+
timeGap: lastRefresh === null ? "first refresh" : now - lastRefresh
|
|
495
|
+
});
|
|
306
496
|
}
|
|
307
497
|
return () => {
|
|
308
|
-
|
|
309
|
-
hasRefreshedRef.current = false;
|
|
498
|
+
hasTriggeredRefresh = false;
|
|
310
499
|
};
|
|
311
|
-
}, [
|
|
312
|
-
const handleRefresh = useCallback(() => {
|
|
313
|
-
if (safeContextProperty("refreshing", false)) {
|
|
314
|
-
console.log("Manual refresh ignored - refresh already in progress");
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
console.log("Manual refresh triggered");
|
|
318
|
-
refreshChannels();
|
|
319
|
-
}, [refreshChannels, safeContextProperty]);
|
|
320
|
-
const channels = React__default.useMemo(() => {
|
|
321
|
-
var _a2, _b, _c;
|
|
322
|
-
const allChannels = [...(_a2 = userChannels == null ? void 0 : userChannels.supportServiceChannels) != null ? _a2 : [], ...(_b = userChannels == null ? void 0 : userChannels.channelsByUser) != null ? _b : []];
|
|
323
|
-
let uChannels = (_c = allChannels == null ? void 0 : allChannels.filter((c) => c.members.some((u) => {
|
|
324
|
-
var _a3;
|
|
325
|
-
return u !== null && ((_a3 = u == null ? void 0 : u.user) == null ? void 0 : _a3.id) != (auth == null ? void 0 : auth.id) && u.user.__typename == "UserAccount";
|
|
326
|
-
}))) != null ? _c : [];
|
|
327
|
-
return uChannels && orderBy(uChannels, ["updatedAt"], ["desc"]) || [];
|
|
328
|
-
}, [userChannels, auth == null ? void 0 : auth.id]);
|
|
500
|
+
}, [safeSend, channels.length, safeMatches, safeGetContext, fastRefresh]));
|
|
329
501
|
const handleSelectChannel = useCallback((id, title) => {
|
|
330
|
-
var _a2;
|
|
331
502
|
safeSend({
|
|
332
503
|
type: Actions.SELECT_CHANNEL,
|
|
333
504
|
data: {
|
|
334
505
|
channelId: id
|
|
335
506
|
}
|
|
336
507
|
});
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
navigation.navigate(config.INBOX_MESSEGE_PATH, {
|
|
346
|
-
channelId: id,
|
|
347
|
-
role: channelRole,
|
|
348
|
-
title,
|
|
349
|
-
hideTabBar: true
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
}, [params, navigation, channelRole, safeSend]);
|
|
508
|
+
navigation.navigate(config.INBOX_MESSEGE_PATH, {
|
|
509
|
+
channelId: id,
|
|
510
|
+
role: channelRole,
|
|
511
|
+
title,
|
|
512
|
+
hideTabBar: true,
|
|
513
|
+
timestamp: new Date().getTime()
|
|
514
|
+
});
|
|
515
|
+
}, [navigation, channelRole, safeSend]);
|
|
353
516
|
const handleSelectServiceChannel = useCallback((id, title, postParentId) => {
|
|
354
|
-
var _a2;
|
|
355
517
|
safeSend({
|
|
356
518
|
type: Actions.SELECT_CHANNEL,
|
|
357
519
|
data: {
|
|
358
520
|
channelId: id
|
|
359
521
|
}
|
|
360
522
|
});
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
523
|
+
navigation.navigate(postParentId || postParentId === 0 ? config.THREAD_MESSEGE_PATH : config.THREADS_PATH, {
|
|
524
|
+
channelId: id,
|
|
525
|
+
role: channelRole,
|
|
526
|
+
title,
|
|
527
|
+
postParentId,
|
|
528
|
+
hideTabBar: true
|
|
529
|
+
});
|
|
530
|
+
}, [navigation, channelRole, safeSend]);
|
|
531
|
+
const handlePullToRefresh = useCallback(() => {
|
|
532
|
+
if (refreshing) {
|
|
533
|
+
console.log("\u23E9 Skipping refresh because already refreshing");
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
const now = Date.now();
|
|
537
|
+
focusRefreshRef.current = now;
|
|
538
|
+
console.log("\u{1F504} Pull-to-refresh triggered");
|
|
539
|
+
safeSend({
|
|
540
|
+
type: Actions.START_LOADING,
|
|
541
|
+
data: {
|
|
542
|
+
refreshing: true
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
fastRefresh();
|
|
546
|
+
}, [safeSend, refreshing, fastRefresh]);
|
|
547
|
+
const handleSearchChange = useCallback((text) => {
|
|
548
|
+
safeSend({
|
|
549
|
+
type: Actions.SET_SEARCH_QUERY,
|
|
550
|
+
data: {
|
|
551
|
+
searchQuery: text
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}, [safeSend]);
|
|
555
|
+
const handleLoadMore = useCallback(() => {
|
|
556
|
+
if (!loadingMore && hasMoreChannels) {
|
|
557
|
+
console.log("Loading more channels at page:", page + 1);
|
|
558
|
+
safeSend({
|
|
559
|
+
type: Actions.LOAD_MORE_CHANNELS
|
|
368
560
|
});
|
|
369
561
|
} else {
|
|
370
|
-
|
|
371
|
-
channelId: id,
|
|
372
|
-
role: channelRole,
|
|
373
|
-
title,
|
|
374
|
-
postParentId,
|
|
375
|
-
hideTabBar: true
|
|
376
|
-
});
|
|
562
|
+
console.log("Skip loading more: loadingMore=", loadingMore, "hasMoreChannels=", hasMoreChannels);
|
|
377
563
|
}
|
|
378
|
-
}, [
|
|
379
|
-
|
|
380
|
-
return /* @__PURE__ */ React__default.createElement(Box, { className: "p-2" }, /* @__PURE__ */ React__default.createElement(FlatList, { data: channels && (channels == null ? void 0 : channels.length) > 0 ? channels : [], onRefresh: handleRefresh, refreshing: safeContextProperty("refreshing", false), contentContainerStyle: {
|
|
564
|
+
}, [safeSend, loadingMore, hasMoreChannels, page]);
|
|
565
|
+
return /* @__PURE__ */ React__default.createElement(Box, { className: "p-2" }, /* @__PURE__ */ React__default.createElement(FlatList, { data: channels, onRefresh: handlePullToRefresh, refreshing, contentContainerStyle: {
|
|
381
566
|
minHeight: "100%"
|
|
382
567
|
}, ItemSeparatorComponent: () => /* @__PURE__ */ React__default.createElement(Box, { className: "h-0.5 bg-gray-200" }), renderItem: ({
|
|
383
568
|
item: channel
|
|
384
|
-
}) =>
|
|
385
|
-
type:
|
|
386
|
-
|
|
387
|
-
|
|
569
|
+
}) => {
|
|
570
|
+
return (channel == null ? void 0 : channel.type) === RoomType.Service ? /* @__PURE__ */ React__default.createElement(ServiceDialogsListItem, { key: `service-${channel.id}`, onOpen: handleSelectServiceChannel, currentUser: auth, channel, refreshing, selectedChannelId, role: channelRole }) : /* @__PURE__ */ React__default.createElement(DialogsListItem, { key: `direct-${channel.id}`, onOpen: handleSelectChannel, currentUser: auth, channel, selectedChannelId, forceRefresh: true });
|
|
571
|
+
}, ListFooterComponent: () => loadingMore ? /* @__PURE__ */ React__default.createElement(Center, { className: "py-4" }, /* @__PURE__ */ React__default.createElement(Spinner, { color: colors.blue[500], size: "small" })) : null, onEndReached: handleLoadMore, onEndReachedThreshold: 0.3, initialNumToRender: 10, maxToRenderPerBatch: 10, windowSize: 10, removeClippedSubviews: true, updateCellsBatchingPeriod: 50, ListEmptyComponent: () => {
|
|
572
|
+
console.log("Rendering ListEmptyComponent", {
|
|
573
|
+
loading,
|
|
574
|
+
refreshing,
|
|
575
|
+
stateValue: state.value
|
|
576
|
+
});
|
|
577
|
+
if (loading && channels.length === 0) {
|
|
578
|
+
return /* @__PURE__ */ React__default.createElement(Center, { className: "flex-1 justify-center items-center", style: {
|
|
579
|
+
height: 300
|
|
580
|
+
} }, /* @__PURE__ */ React__default.createElement(Spinner, { color: colors.blue[500], size: "large" }), /* @__PURE__ */ React__default.createElement(Text, { className: "mt-4 text-gray-500" }, "Loading conversations..."));
|
|
388
581
|
}
|
|
389
|
-
|
|
582
|
+
return /* @__PURE__ */ React__default.createElement(Box, { className: "p-6" }, /* @__PURE__ */ React__default.createElement(Box, { className: "mb-6" }, /* @__PURE__ */ React__default.createElement(Heading, { className: "text-2xl font-bold" }, "Direct Messages"), /* @__PURE__ */ React__default.createElement(Text, { className: "text-gray-600 mt-1" }, "Private conversations with other users")), /* @__PURE__ */ React__default.createElement(Input, { className: "mb-8 h-[50] rounded-md border-gray-300 border", size: "md", style: {
|
|
583
|
+
paddingVertical: 8,
|
|
584
|
+
marginBottom: 10,
|
|
585
|
+
borderColor: "#d1d5db",
|
|
586
|
+
borderRadius: 10
|
|
587
|
+
} }, /* @__PURE__ */ React__default.createElement(InputField, { placeholder: "Search messages...", onChangeText: handleSearchChange, value: searchQuery })), /* @__PURE__ */ React__default.createElement(Center, { className: "items-center", style: {
|
|
588
|
+
paddingVertical: 5
|
|
589
|
+
} }, /* @__PURE__ */ React__default.createElement(Box, { className: "w-16 h-16 rounded-full bg-blue-500 flex items-center justify-center mb-5" }, /* @__PURE__ */ React__default.createElement(Ionicons, { name: "chatbubble-ellipses", size: 30, color: "white" })), /* @__PURE__ */ React__default.createElement(Text, { className: "text-2xl font-bold text-center mb-2" }, "No messages yet"), /* @__PURE__ */ React__default.createElement(Text, { className: "text-gray-600 text-center mb-8" }, "When you start conversations with others,", "\n", "they'll appear here.")));
|
|
590
|
+
}, keyExtractor: (item) => `channel-${item.id}` }));
|
|
390
591
|
};
|
|
391
592
|
const Dialogs = React__default.memo(DialogsComponent);export{Dialogs};//# sourceMappingURL=Dialogs.js.map
|