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

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@messenger-box/platform-mobile",
3
- "version": "10.0.3-alpha.18",
3
+ "version": "10.0.3-alpha.19",
4
4
  "description": "Sample core for higher packages to depend on",
5
5
  "license": "ISC",
6
6
  "author": "CDMBase LLC",
@@ -43,5 +43,5 @@
43
43
  "typescript": {
44
44
  "definition": "lib/index.d.ts"
45
45
  },
46
- "gitHead": "2c28c3aa50c7b38da5d1ef8b637d22b3bb42f42e"
46
+ "gitHead": "3a16f701de3692fdf794a03dd74cc0cfa765b90b"
47
47
  }
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useMemo, useEffect, useState, useRef } from 'react';
1
+ import React, { useCallback, useMemo, useEffect, useState } from 'react';
2
2
  import {
3
3
  FlatList,
4
4
  Box,
@@ -22,7 +22,6 @@ import { userSelector } from '@adminide-stack/user-auth0-client';
22
22
  import { CHANGE_SETTINGS_ACTION } from '@admin-layout/client';
23
23
  import { config } from '../config';
24
24
  import colors from 'tailwindcss/colors';
25
- import { dialogsXstate, Actions as DialogsActions, BaseState, MainState } from './workflow/dialogs-xstate';
26
25
 
27
26
  export interface InboxProps {
28
27
  channelFilters?: Record<string, unknown>;
@@ -30,155 +29,6 @@ export interface InboxProps {
30
29
  supportServices: boolean;
31
30
  }
32
31
 
33
- // Define state type for the state machine
34
- interface SafeStateType {
35
- context: {
36
- channels: any[];
37
- refreshing: boolean;
38
- loading: boolean;
39
- error: string | null;
40
- searchQuery: string;
41
- selectedChannelId: string | null;
42
- channelRole: string | null;
43
- channelFilters: Record<string, any>;
44
- supportServices: boolean;
45
- };
46
- value: string;
47
- matches?: (stateValue: string) => boolean;
48
- }
49
-
50
- // Interface for the return type to ensure proper typing
51
- type UseSafeMachineReturnType = [SafeStateType & { matches: (stateValue: string) => boolean }, (event: any) => void];
52
-
53
- // Create a safer version of useMachine to handle potential errors
54
- function useSafeMachine(machine): UseSafeMachineReturnType {
55
- // Initialize with default state
56
- const [state, setState] = useState<SafeStateType>({
57
- context: {
58
- channels: [],
59
- refreshing: false,
60
- loading: false,
61
- error: null,
62
- searchQuery: '',
63
- selectedChannelId: null,
64
- channelRole: null,
65
- channelFilters: {},
66
- supportServices: false,
67
- },
68
- value: 'idle',
69
- });
70
-
71
- // Create a safe send function
72
- const send = useCallback((event) => {
73
- try {
74
- // Log event for debugging
75
- console.log('Dialogs Event received:', event.type);
76
-
77
- // Handle specific events manually
78
- if (event.type === DialogsActions.INITIAL_CONTEXT) {
79
- setState((prev) => ({
80
- ...prev,
81
- context: {
82
- ...prev.context,
83
- channelRole: event.data?.channelRole || null,
84
- channelFilters: event.data?.channelFilters || {},
85
- supportServices: event.data?.supportServices || false,
86
- selectedChannelId: event.data?.selectedChannelId || null,
87
- },
88
- value: BaseState.FetchChannels,
89
- }));
90
- } else if (event.type === DialogsActions.SET_SEARCH_QUERY) {
91
- setState((prev) => ({
92
- ...prev,
93
- context: {
94
- ...prev.context,
95
- searchQuery: event.data?.searchQuery || '',
96
- },
97
- }));
98
- } else if (event.type === DialogsActions.REFRESH_CHANNELS) {
99
- setState((prev) => ({
100
- ...prev,
101
- context: {
102
- ...prev.context,
103
- refreshing: true,
104
- },
105
- value: MainState.RefreshChannels,
106
- }));
107
- } else if (event.type === DialogsActions.SELECT_CHANNEL) {
108
- setState((prev) => ({
109
- ...prev,
110
- context: {
111
- ...prev.context,
112
- selectedChannelId: event.data?.channelId || null,
113
- },
114
- value: MainState.SelectChannel,
115
- }));
116
- } else if (event.type === DialogsActions.START_LOADING) {
117
- setState((prev) => ({
118
- ...prev,
119
- context: {
120
- ...prev.context,
121
- loading: true,
122
- },
123
- }));
124
- } else if (event.type === DialogsActions.STOP_LOADING) {
125
- setState((prev) => ({
126
- ...prev,
127
- context: {
128
- ...prev.context,
129
- loading: false,
130
- },
131
- }));
132
- } else if (event.type === 'FETCH_CHANNELS_SUCCESS') {
133
- setState((prev) => ({
134
- ...prev,
135
- context: {
136
- ...prev.context,
137
- channels: event.data?.channels || [],
138
- loading: false,
139
- refreshing: false,
140
- },
141
- value: BaseState.Idle,
142
- }));
143
- } else if (event.type === 'REFRESH_CHANNELS_SUCCESS') {
144
- setState((prev) => ({
145
- ...prev,
146
- context: {
147
- ...prev.context,
148
- channels: event.data?.channels || [],
149
- refreshing: false,
150
- },
151
- value: BaseState.Idle,
152
- }));
153
- } else if (event.type === 'ERROR') {
154
- setState((prev) => ({
155
- ...prev,
156
- context: {
157
- ...prev.context,
158
- error: event.data?.message || 'An error occurred',
159
- loading: false,
160
- refreshing: false,
161
- },
162
- value: BaseState.Error,
163
- }));
164
- }
165
- } catch (err) {
166
- console.error('Error in send function:', err);
167
- }
168
- }, []);
169
-
170
- // Add a matches method for state compatibility
171
- const stateWithMatches = useMemo(() => {
172
- return {
173
- ...state,
174
- matches: (value: string) => state.value === value,
175
- };
176
- }, [state]);
177
-
178
- // Return as a tuple to match useMachine API
179
- return [stateWithMatches, send];
180
- }
181
-
182
32
  const DialogsComponent = (props: InboxProps) => {
183
33
  const { channelFilters: channelFilterProp, channelRole, supportServices } = props;
184
34
  const channelFilters = { ...channelFilterProp };
@@ -188,70 +38,8 @@ const DialogsComponent = (props: InboxProps) => {
188
38
  const dispatch = useDispatch();
189
39
  const navigation = useNavigation<any>();
190
40
  const isFocused = useIsFocused();
191
- const isMountedRef = useRef(true);
192
-
193
- // Use our safer custom implementation instead of the problematic useMachine
194
- const [state, send] = useSafeMachine(dialogsXstate);
195
-
196
- // Define safe functions first to avoid "used before declaration" errors
197
- const safeContext = useCallback(() => {
198
- try {
199
- return state?.context || {};
200
- } catch (error) {
201
- console.error('Error accessing state.context:', error);
202
- return {};
203
- }
204
- }, [state]);
205
-
206
- const safeContextProperty = useCallback(
207
- (property, defaultValue = null) => {
208
- try {
209
- return state?.context?.[property] ?? defaultValue;
210
- } catch (error) {
211
- console.error(`Error accessing state.context.${property}:`, error);
212
- return defaultValue;
213
- }
214
- },
215
- [state],
216
- );
217
-
218
- const safeMatches = useCallback(
219
- (stateValue) => {
220
- try {
221
- return state?.matches?.(stateValue) || false;
222
- } catch (error) {
223
- console.error(`Error calling state.matches with ${stateValue}:`, error);
224
- return false;
225
- }
226
- },
227
- [state],
228
- );
229
-
230
- const safeSend = useCallback(
231
- (event) => {
232
- try {
233
- send(event);
234
- } catch (error) {
235
- console.error('Error sending event to state machine:', error, event);
236
- }
237
- },
238
- [send],
239
- );
240
-
241
- // Use a ref to track the current machine snapshot for safer access
242
- const stateRef = useRef(state);
243
-
244
- // Keep the ref updated with the latest snapshot
245
- useEffect(() => {
246
- stateRef.current = state;
247
- }, [state]);
248
-
249
- // Use cleanup function to prevent setting state after unmount
250
- useEffect(() => {
251
- return () => {
252
- isMountedRef.current = false;
253
- };
254
- }, []);
41
+ const [refreshing, setRefresh] = useState<boolean>(false);
42
+ // const [userDirectChannel, setUserDirectChannel] = useState<any>([]);
255
43
 
256
44
  const {
257
45
  data: userChannels,
@@ -266,145 +54,50 @@ const DialogsComponent = (props: InboxProps) => {
266
54
  type: RoomType.Service,
267
55
  },
268
56
  },
269
- onCompleted: (data) => {
270
- if (isMountedRef.current) {
271
- const allChannels = [...(data?.supportServiceChannels ?? []), ...(data?.channelsByUser ?? [])];
272
- safeSend({
273
- type: 'FETCH_CHANNELS_SUCCESS',
274
- data: { channels: allChannels },
275
- });
276
- }
277
- },
278
- onError: (error) => {
279
- if (isMountedRef.current) {
280
- safeSend({
281
- type: 'ERROR',
282
- data: { message: error.message },
283
- });
284
- }
285
- },
286
57
  });
287
58
 
288
- // Set initial context once on mount, but don't fetch data as useFocusEffect will handle it
289
- useEffect(() => {
290
- console.log('Setting initial context');
291
- // Only set the initial context with configuration, but don't trigger data fetching
292
- // This prevents double fetching with useFocusEffect
293
- safeSend({
294
- type: DialogsActions.INITIAL_CONTEXT,
295
- data: {
296
- channelRole,
297
- channelFilters: channelFiltersRef.current,
298
- supportServices,
299
- selectedChannelId: params?.channelId,
300
- },
301
- });
302
- // eslint-disable-next-line react-hooks/exhaustive-deps
303
- }, []); // Empty dependency array ensures this runs only once on mount
304
-
305
- // Ref to track if we've already refreshed to prevent infinite loop
306
- const hasRefreshedRef = useRef(false);
307
- // Ref to store the current channelFilters to detect real changes
308
- const channelFiltersRef = useRef(channelFilters);
309
-
310
- // Shared function to handle channel refreshing
311
- const refreshChannels = useCallback(() => {
312
- // Skip if already refreshing to prevent loops
313
- if (safeContextProperty('refreshing', false)) {
314
- console.log('Skipping refresh - already in progress');
315
- return Promise.resolve();
316
- }
317
-
318
- console.log('Starting channel refresh');
59
+ // const {
60
+ // data: userChannels,
61
+ // loading: userChannelsLoading,
62
+ // refetch: getChannelsRefetch,
63
+ // } = useGetChannelsByUserQuery({
64
+ // variables: {
65
+ // role: channelRole,
66
+ // criteria: channelFilters,
67
+ // },
68
+ // onCompleted: (data: any) => {
69
+ // setRefresh(false);
70
+ // },
71
+ // });
319
72
 
320
- // Start refreshing
321
- safeSend({
322
- type: DialogsActions.REFRESH_CHANNELS,
323
- });
324
-
325
- // Use ref for filters to avoid dependency cycles
326
- const currentFilters = channelFiltersRef.current;
327
-
328
- // Fetch the channels
329
- return getChannelsRefetch({
330
- role: channelRole,
331
- criteria: currentFilters,
332
- supportServices: supportServices ? true : false,
333
- supportServiceCriteria: {
334
- type: RoomType.Service,
335
- },
336
- })
337
- .then((data) => {
338
- if (isMountedRef.current) {
339
- const allChannels = [
340
- ...(data?.data?.supportServiceChannels ?? []),
341
- ...(data?.data?.channelsByUser ?? []),
342
- ];
343
- console.log(`Refresh completed, found ${allChannels.length} channels`);
344
- safeSend({
345
- type: 'REFRESH_CHANNELS_SUCCESS',
346
- data: { channels: allChannels },
347
- });
348
- }
349
- })
350
- .catch((error) => {
351
- if (isMountedRef.current) {
352
- console.error('Channel refresh error:', error.message);
353
- safeSend({
354
- type: 'ERROR',
355
- data: { message: error.message },
356
- });
357
- }
358
- });
359
- }, [channelRole, supportServices, getChannelsRefetch, safeSend, safeContextProperty]);
360
-
361
- // Update the channelFiltersRef when channelFilters changes
362
- useEffect(() => {
363
- const filtersChanged = JSON.stringify(channelFiltersRef.current) !== JSON.stringify(channelFilters);
364
- if (filtersChanged) {
365
- console.log('Channel filters changed, updating ref');
366
- channelFiltersRef.current = channelFilters;
367
-
368
- // Only refresh if already mounted and initialized
369
- if (isMountedRef.current && safeContextProperty('channelRole') !== null) {
370
- console.log('Refreshing due to filter change');
371
- refreshChannels();
372
- }
373
- }
374
- }, [channelFilters, refreshChannels, safeContextProperty]);
375
-
376
- // Handle focus effects
377
73
  useFocusEffect(
378
- useCallback(() => {
379
- if (!isFocused) return;
380
-
381
- console.log('Screen focused, checking if refresh needed');
382
-
383
- // Only refresh on focus if we're not already loading and haven't refreshed
384
- if (isMountedRef.current && !hasRefreshedRef.current) {
385
- console.log('Refreshing on focus');
386
- hasRefreshedRef.current = true;
387
- refreshChannels();
388
- }
389
-
74
+ React.useCallback(() => {
75
+ // Do something when the screen is focused
76
+ setRefresh(false);
77
+ //getChannelsRefetch({ role: channelRole, criteria: channelFilters });
78
+ getChannelsRefetch({
79
+ role: channelRole,
80
+ criteria: channelFilters,
81
+ supportServices: supportServices ? true : false,
82
+ supportServiceCriteria: {
83
+ type: RoomType.Service,
84
+ },
85
+ });
390
86
  return () => {
391
- // Reset the ref when the screen loses focus
392
- console.log('Screen unfocused, resetting refresh state');
393
- hasRefreshedRef.current = false;
87
+ // Do something when the screen is unfocused
88
+ // Useful for cleanup functions
394
89
  };
395
- }, [isFocused, refreshChannels]),
90
+ }, [channelFilters]),
396
91
  );
397
92
 
398
- const handleRefresh = useCallback(() => {
399
- // Don't allow manual refresh while already refreshing
400
- if (safeContextProperty('refreshing', false)) {
401
- console.log('Manual refresh ignored - refresh already in progress');
402
- return;
403
- }
404
-
405
- console.log('Manual refresh triggered');
406
- refreshChannels();
407
- }, [refreshChannels, safeContextProperty]);
93
+ // const channels = React.useMemo(() => {
94
+ // if (!userChannels?.channelsByUser?.length) return null;
95
+ // let uChannels: any =
96
+ // userChannels?.channelsByUser?.filter((c: any) =>
97
+ // c.members.some((u: any) => u !== null && u?.user?.id != auth?.id && u.user.__typename == 'UserAccount'),
98
+ // ) ?? [];
99
+ // return (uChannels && orderBy(uChannels, ['updatedAt'], ['desc'])) || [];
100
+ // }, [userChannels]);
408
101
 
409
102
  const channels = React.useMemo(() => {
410
103
  const allChannels = [...(userChannels?.supportServiceChannels ?? []), ...(userChannels?.channelsByUser ?? [])];
@@ -413,78 +106,102 @@ const DialogsComponent = (props: InboxProps) => {
413
106
  c.members.some((u: any) => u !== null && u?.user?.id != auth?.id && u.user.__typename == 'UserAccount'),
414
107
  ) ?? [];
415
108
  return (uChannels && orderBy(uChannels, ['updatedAt'], ['desc'])) || [];
416
- }, [userChannels, auth?.id]);
417
-
418
- const handleSelectChannel = useCallback(
419
- (id: any, title: any) => {
420
- safeSend({
421
- type: DialogsActions.SELECT_CHANNEL,
422
- data: { channelId: id },
109
+ }, [userChannels]);
110
+
111
+ // useEffect(() => {
112
+ // setTimeout(() => {
113
+ // dispatch({
114
+ // type: CHANGE_SETTINGS_ACTION,
115
+ // payload: {
116
+ // footerRender: false,
117
+ // },
118
+ // } as any);
119
+ // }, 0);
120
+ // return () => {
121
+ // dispatch({
122
+ // type: CHANGE_SETTINGS_ACTION,
123
+ // payload: {
124
+ // footerRender: true,
125
+ // },
126
+ // } as any);
127
+ // };
128
+ // }, []);
129
+
130
+ // useEffect(() => {
131
+ // if (userChannels?.channelsByUser) {
132
+ // if (userChannels?.channelsByUser?.length == 0) {
133
+ // setUserDirectChannel([]);
134
+ // }
135
+ // //Direct channel
136
+ // let userDirectChannels: any =
137
+ // userChannels?.channelsByUser
138
+ // ?.filter((i: any) => i.type == 'DIRECT')
139
+ // ?.filter((c: any) =>
140
+ // c.members.some((u: any) => u?.user?.id != auth?.id && u.user.__typename == 'UserAccount'),
141
+ // ) ?? [];
142
+
143
+ // if (userDirectChannels?.length > 0) setUserDirectChannel(userDirectChannels);
144
+ // }
145
+ // }, [userChannels?.channelsByUser]);
146
+
147
+ const handleSelectChannel = useCallback((id: any, title: any) => {
148
+ if (params?.channelId) {
149
+ navigation.navigate(config.INBOX_MESSEGE_PATH as any, {
150
+ channelId: params?.channelId,
151
+ role: params?.role,
152
+ title: params?.title ?? null,
153
+ hideTabBar: true,
154
+ });
155
+ } else {
156
+ navigation.navigate(config.INBOX_MESSEGE_PATH as any, {
157
+ channelId: id,
158
+ role: channelRole,
159
+ title: title,
160
+ hideTabBar: true,
423
161
  });
162
+ }
163
+ }, []);
424
164
 
425
- if (params?.channelId) {
426
- navigation.navigate(config.INBOX_MESSEGE_PATH as any, {
165
+ const handleSelectServiceChannel = useCallback((id: any, title: any, postParentId: any) => {
166
+ if (params?.channelId) {
167
+ navigation.navigate(
168
+ params?.postParentId || params?.postParentId == 0
169
+ ? config.THREAD_MESSEGE_PATH
170
+ : (config.THREADS_PATH as any),
171
+ {
427
172
  channelId: params?.channelId,
428
173
  role: params?.role,
429
174
  title: params?.title ?? null,
175
+ postParentId: params?.postParentId,
430
176
  hideTabBar: true,
431
- });
432
- } else {
433
- navigation.navigate(config.INBOX_MESSEGE_PATH as any, {
177
+ },
178
+ );
179
+ } else {
180
+ navigation.navigate(
181
+ postParentId || postParentId == 0 ? config.THREAD_MESSEGE_PATH : (config.THREADS_PATH as any),
182
+ {
434
183
  channelId: id,
435
184
  role: channelRole,
436
185
  title: title,
186
+ postParentId: postParentId,
437
187
  hideTabBar: true,
438
- });
439
- }
440
- },
441
- [params, navigation, channelRole, safeSend],
442
- );
443
-
444
- const handleSelectServiceChannel = useCallback(
445
- (id: any, title: any, postParentId: any) => {
446
- safeSend({
447
- type: DialogsActions.SELECT_CHANNEL,
448
- data: { channelId: id },
449
- });
450
-
451
- if (params?.channelId) {
452
- navigation.navigate(
453
- params?.postParentId || params?.postParentId == 0
454
- ? config.THREAD_MESSEGE_PATH
455
- : (config.THREADS_PATH as any),
456
- {
457
- channelId: params?.channelId,
458
- role: params?.role,
459
- title: params?.title ?? null,
460
- postParentId: params?.postParentId,
461
- hideTabBar: true,
462
- },
463
- );
464
- } else {
465
- navigation.navigate(
466
- postParentId || postParentId == 0 ? config.THREAD_MESSEGE_PATH : (config.THREADS_PATH as any),
467
- {
468
- channelId: id,
469
- role: channelRole,
470
- title: title,
471
- postParentId: postParentId,
472
- hideTabBar: true,
473
- },
474
- );
475
- }
476
- },
477
- [params, navigation, channelRole, safeSend],
478
- );
188
+ },
189
+ );
190
+ }
191
+ }, []);
479
192
 
480
- const searchQuery = safeContextProperty('searchQuery', '');
193
+ const handleRefresh = useCallback(() => {
194
+ //if(userChannels?.channelsByUser?.length != channels?.length)setRefresh(true);
195
+ setRefresh(true);
196
+ getChannelsRefetch({ role: channelRole, criteria: channelFilters })?.finally(() => setRefresh(false));
197
+ }, []);
481
198
 
482
199
  return (
483
200
  <Box className="p-2">
484
201
  <FlatList
485
202
  data={channels && channels?.length > 0 ? channels : []}
486
203
  onRefresh={handleRefresh}
487
- refreshing={safeContextProperty('refreshing', false)}
204
+ refreshing={refreshing}
488
205
  contentContainerStyle={{ minHeight: '100%' }}
489
206
  ItemSeparatorComponent={() => <Box className="h-0.5 bg-gray-200" />}
490
207
  renderItem={({ item: channel }: any) =>
@@ -493,8 +210,8 @@ const DialogsComponent = (props: InboxProps) => {
493
210
  onOpen={handleSelectServiceChannel}
494
211
  currentUser={auth}
495
212
  channel={channel}
496
- refreshing={safeContextProperty('refreshing', false)}
497
- selectedChannelId={safeContextProperty('selectedChannelId', params?.channelId)}
213
+ refreshing={refreshing}
214
+ selectedChannelId={params?.channelId}
498
215
  role={channelRole}
499
216
  />
500
217
  ) : (
@@ -502,13 +219,13 @@ const DialogsComponent = (props: InboxProps) => {
502
219
  onOpen={handleSelectChannel}
503
220
  currentUser={auth}
504
221
  channel={channel}
505
- selectedChannelId={safeContextProperty('selectedChannelId', params?.channelId)}
222
+ selectedChannelId={params?.channelId}
506
223
  />
507
224
  )
508
225
  }
509
226
  ListEmptyComponent={() => (
510
227
  <>
511
- {userChannelsLoading || safeContextProperty('loading', false) ? (
228
+ {userChannelsLoading ? (
512
229
  <Center className="flex-1 justify-center items-center">
513
230
  <Spinner color={colors.blue[500]} />
514
231
  </Center>
@@ -516,16 +233,7 @@ const DialogsComponent = (props: InboxProps) => {
516
233
  <Box className="p-5">
517
234
  <Heading>Chat</Heading>
518
235
  <Input className={`h-[50] mt-3 rounded-[50] border-gray-200 border `}>
519
- <InputField
520
- placeholder="Search"
521
- value={searchQuery}
522
- onChangeText={(text) =>
523
- safeSend({
524
- type: DialogsActions.SET_SEARCH_QUERY,
525
- data: { searchQuery: text },
526
- })
527
- }
528
- />
236
+ <InputField placeholder="Search" />
529
237
  </Input>
530
238
  <Center className="mt-6">
531
239
  <Ionicons name="chatbubbles" size={50} />