@messenger-box/platform-mobile 10.0.3-alpha.23 → 10.0.3-alpha.232

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/lib/components/messages-container-ui/BuildModeView.js +428 -0
  2. package/lib/components/messages-container-ui/BuildModeView.js.map +1 -0
  3. package/lib/components/messages-container-ui/MessagesContainerUI.js +55 -0
  4. package/lib/components/messages-container-ui/MessagesContainerUI.js.map +1 -0
  5. package/lib/components/messages-container-ui/PlanModeView.js +336 -0
  6. package/lib/components/messages-container-ui/PlanModeView.js.map +1 -0
  7. package/lib/compute.js +2 -3
  8. package/lib/compute.js.map +1 -1
  9. package/lib/index.js +1 -1
  10. package/lib/index.js.map +1 -1
  11. package/lib/module.js.map +1 -1
  12. package/lib/queries/inboxQueries.js +62 -0
  13. package/lib/queries/inboxQueries.js.map +1 -0
  14. package/lib/routes.json +2 -3
  15. package/lib/screens/inbox/DialogMessages.js +8 -3
  16. package/lib/screens/inbox/DialogMessages.js.map +1 -1
  17. package/lib/screens/inbox/DialogThreadMessages.js +6 -11
  18. package/lib/screens/inbox/DialogThreadMessages.js.map +1 -1
  19. package/lib/screens/inbox/DialogThreads.js +9 -11
  20. package/lib/screens/inbox/DialogThreads.js.map +1 -1
  21. package/lib/screens/inbox/Inbox.js.map +1 -1
  22. package/lib/screens/inbox/components/CachedImage/consts.js +1 -1
  23. package/lib/screens/inbox/components/CachedImage/consts.js.map +1 -1
  24. package/lib/screens/inbox/components/CachedImage/index.js +125 -96
  25. package/lib/screens/inbox/components/CachedImage/index.js.map +1 -1
  26. package/lib/screens/inbox/components/DialogItem.js +160 -0
  27. package/lib/screens/inbox/components/DialogItem.js.map +1 -0
  28. package/lib/screens/inbox/components/GiftedChatInboxComponent.js +315 -0
  29. package/lib/screens/inbox/components/GiftedChatInboxComponent.js.map +1 -0
  30. package/lib/screens/inbox/components/SlackMessageContainer/ImageViewerModal.js +3 -1
  31. package/lib/screens/inbox/components/SlackMessageContainer/ImageViewerModal.js.map +1 -1
  32. package/lib/screens/inbox/components/SlackMessageContainer/PaymentMessage.js +194 -0
  33. package/lib/screens/inbox/components/SlackMessageContainer/PaymentMessage.js.map +1 -0
  34. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js +149 -36
  35. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js.map +1 -1
  36. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js +4 -5
  37. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js.map +1 -1
  38. package/lib/screens/inbox/components/SubscriptionHandler.js +22 -0
  39. package/lib/screens/inbox/components/SubscriptionHandler.js.map +1 -0
  40. package/lib/screens/inbox/components/ThreadsViewItem.js +2 -4
  41. package/lib/screens/inbox/components/ThreadsViewItem.js.map +1 -1
  42. package/lib/screens/inbox/config/config.js +4 -2
  43. package/lib/screens/inbox/config/config.js.map +1 -1
  44. package/lib/screens/inbox/containers/ConversationView.js +1093 -1090
  45. package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
  46. package/lib/screens/inbox/containers/Dialogs.js +130 -577
  47. package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
  48. package/lib/screens/inbox/containers/ThreadConversationView.js +864 -1408
  49. package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
  50. package/lib/screens/inbox/containers/ThreadsView.js +9 -15
  51. package/lib/screens/inbox/containers/ThreadsView.js.map +1 -1
  52. package/lib/screens/inbox/hooks/useInboxMessages.js +31 -0
  53. package/lib/screens/inbox/hooks/useInboxMessages.js.map +1 -0
  54. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js +1 -1
  55. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js.map +1 -1
  56. package/lib/screens/inbox/workflow/dialog-threads-xstate.js.map +1 -1
  57. package/package.json +10 -8
  58. package/CHANGELOG.md +0 -172
  59. package/jest.config.js +0 -24
  60. package/lib/screens/inbox/components/DialogsListItem.js +0 -548
  61. package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
  62. package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -489
  63. package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
  64. package/lib/screens/inbox/components/workflow/dialogs-list-item-xstate.js +0 -175
  65. package/lib/screens/inbox/components/workflow/dialogs-list-item-xstate.js.map +0 -1
  66. package/lib/screens/inbox/components/workflow/service-dialogs-list-item-xstate.js +0 -191
  67. package/lib/screens/inbox/components/workflow/service-dialogs-list-item-xstate.js.map +0 -1
  68. package/lib/screens/inbox/containers/workflow/conversation-xstate.js +0 -380
  69. package/lib/screens/inbox/containers/workflow/conversation-xstate.js.map +0 -1
  70. package/lib/screens/inbox/containers/workflow/dialogs-xstate.js +0 -211
  71. package/lib/screens/inbox/containers/workflow/dialogs-xstate.js.map +0 -1
  72. package/lib/screens/inbox/containers/workflow/thread-conversation-xstate.js +0 -438
  73. package/lib/screens/inbox/containers/workflow/thread-conversation-xstate.js.map +0 -1
  74. package/rollup.config.mjs +0 -45
  75. package/src/components/index.ts +0 -0
  76. package/src/compute.ts +0 -63
  77. package/src/index.ts +0 -7
  78. package/src/module.ts +0 -10
  79. package/src/navigation/InboxNavigation.tsx +0 -102
  80. package/src/navigation/index.ts +0 -1
  81. package/src/screens/inbox/DialogMessages.tsx +0 -21
  82. package/src/screens/inbox/DialogThreadMessages.tsx +0 -97
  83. package/src/screens/inbox/DialogThreads.tsx +0 -125
  84. package/src/screens/inbox/Inbox.tsx +0 -17
  85. package/src/screens/inbox/components/CachedImage/consts.ts +0 -6
  86. package/src/screens/inbox/components/CachedImage/index.tsx +0 -223
  87. package/src/screens/inbox/components/DialogsHeader.tsx +0 -30
  88. package/src/screens/inbox/components/DialogsListItem.tsx +0 -819
  89. package/src/screens/inbox/components/ServiceDialogsListItem.tsx +0 -679
  90. package/src/screens/inbox/components/SlackMessageContainer/ImageViewerModal.tsx +0 -113
  91. package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +0 -313
  92. package/src/screens/inbox/components/SlackMessageContainer/SlackMessage.tsx +0 -145
  93. package/src/screens/inbox/components/SlackMessageContainer/index.ts +0 -3
  94. package/src/screens/inbox/components/SmartLoader.tsx +0 -61
  95. package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +0 -301
  96. package/src/screens/inbox/components/ThreadsViewItem.tsx +0 -233
  97. package/src/screens/inbox/components/workflow/dialogs-list-item-xstate.ts +0 -145
  98. package/src/screens/inbox/components/workflow/service-dialogs-list-item-xstate.ts +0 -159
  99. package/src/screens/inbox/config/config.ts +0 -15
  100. package/src/screens/inbox/config/index.ts +0 -1
  101. package/src/screens/inbox/containers/ConversationView.tsx +0 -1784
  102. package/src/screens/inbox/containers/Dialogs.tsx +0 -829
  103. package/src/screens/inbox/containers/SupportServiceDialogs.tsx +0 -119
  104. package/src/screens/inbox/containers/ThreadConversationView.tsx +0 -2295
  105. package/src/screens/inbox/containers/ThreadsView.tsx +0 -224
  106. package/src/screens/inbox/containers/workflow/apollo/handleResult.ts +0 -20
  107. package/src/screens/inbox/containers/workflow/conversation-xstate.ts +0 -313
  108. package/src/screens/inbox/containers/workflow/dialogs-xstate.ts +0 -196
  109. package/src/screens/inbox/containers/workflow/thread-conversation-xstate.ts +0 -401
  110. package/src/screens/inbox/hooks/useSafeDialogThreadsMachine.ts +0 -136
  111. package/src/screens/inbox/index.ts +0 -37
  112. package/src/screens/inbox/machines/threadsMachine.ts +0 -147
  113. package/src/screens/inbox/workflow/dialog-threads-xstate.ts +0 -163
  114. package/src/screens/index.ts +0 -4
  115. package/tsconfig.json +0 -13
  116. package/webpack.config.js +0 -58
@@ -1,102 +0,0 @@
1
- import * as React from 'react';
2
- import { Feature } from '@common-stack/client-react';
3
- import { DialogMessages } from '../screens/inbox/DialogMessages';
4
- import { DialogThreads } from '../screens/inbox/DialogThreads';
5
- import { DialogThreadMessages } from '../screens/inbox/DialogThreadMessages';
6
- import { Button, Icon } from '@admin-layout/gluestack-ui-mobile';
7
- import { MaterialIcons } from '@expo/vector-icons';
8
-
9
- const inboxConfig = {
10
- ['//message']: {
11
- exact: true,
12
- name: 'Message',
13
- props: {
14
- initialParams: { channelId: null, role: null, isShowThreadMessage: true },
15
- component: (props: any) => (
16
- <DialogMessages
17
- {...props}
18
- channelId={props?.route?.params?.channelId}
19
- role={props?.route?.params?.role}
20
- isShowThreadMessage={props?.route?.params?.isShowThreadMessage}
21
- />
22
- ),
23
- options: ({ navigation }: any) => {
24
- return {
25
- headerShown: true,
26
- title: 'Inbox',
27
- headerBackTitleVisible: false,
28
- gestureEnabled: false,
29
- swipeEnabled: false,
30
- headerLeft: (props: any) => (
31
- <Button className="bg-transparent" onPress={() => navigation.goBack()}>
32
- <MaterialIcons size={20} name="arrow-back-ios" color={'black'} />
33
- </Button>
34
- ),
35
- };
36
- },
37
- },
38
- },
39
- ['//thread']: {
40
- exact: true,
41
- name: 'Thread',
42
- props: {
43
- initialParams: { channelId: null, postParentId: null, role: null },
44
- component: (props: any) => (
45
- <DialogThreads
46
- {...props}
47
- channelId={props?.route?.params?.channelId}
48
- postParentId={props?.route?.params?.postParentId}
49
- role={props?.route?.params?.role}
50
- />
51
- ),
52
- options: ({ navigation }: any) => {
53
- return {
54
- headerShown: true,
55
- title: 'Thread',
56
- headerBackTitleVisible: false,
57
- gestureEnabled: false,
58
- swipeEnabled: false,
59
- headerLeft: (props: any) => (
60
- <Button className="bg-transparent" onPress={() => navigation.goBack()}>
61
- <MaterialIcons size={20} name="arrow-back-ios" color={'black'} />
62
- </Button>
63
- ),
64
- };
65
- },
66
- },
67
- },
68
- ['//threadmessage']: {
69
- exact: true,
70
- name: 'ThreadMessage',
71
- props: {
72
- initialParams: { channelId: null, postParentId: null, isPostParentIdThread: null, role: null },
73
- component: (props: any) => (
74
- <DialogThreadMessages
75
- {...props}
76
- channelId={props?.route?.params?.channelId}
77
- postParentId={props?.route?.params?.postParentId}
78
- isPostParentIdThread={props?.route?.params?.isPostParentIdThread}
79
- role={props?.route?.params?.role}
80
- />
81
- ),
82
- options: ({ navigation }: any) => {
83
- return {
84
- headerShown: true,
85
- title: 'Inbox',
86
- headerBackTitleVisible: false,
87
- gestureEnabled: false,
88
- swipeEnabled: false,
89
- headerLeft: (props: any) => (
90
- <Button className="bg-transparent" onPress={() => navigation.goBack()}>
91
- <MaterialIcons size={20} name="arrow-back-ios" color={'black'} />
92
- </Button>
93
- ),
94
- };
95
- },
96
- },
97
- },
98
- };
99
-
100
- export const inboxFeature = new Feature({
101
- routeConfig: inboxConfig as any,
102
- });
@@ -1 +0,0 @@
1
- export * from './InboxNavigation';
@@ -1,21 +0,0 @@
1
- import * as React from 'react';
2
- import { Box } from '@admin-layout/gluestack-ui-mobile';
3
- import { ConversationView } from './containers/ConversationView';
4
- import { navigationRef } from '@common-stack/client-react';
5
-
6
- export function DialogMessages({ channelId, role, isShowThreadMessage = true, ...rest }) {
7
- const currentRoute = navigationRef.isReady() ? navigationRef?.getCurrentRoute() : null;
8
- return (
9
- // <Box bg={'white'} flex={1} pt={5}>
10
- <Box className="bg-white flex-1">
11
- <ConversationView
12
- {...rest}
13
- channelId={currentRoute?.params?.channelId ?? channelId}
14
- role={role}
15
- isShowThreadMessage={isShowThreadMessage}
16
- />
17
- </Box>
18
- );
19
- }
20
-
21
- export default DialogMessages;
@@ -1,97 +0,0 @@
1
- import * as React from 'react';
2
- import { Box, Spinner, Text } from '@admin-layout/gluestack-ui-mobile';
3
- import { ThreadConversationView } from './containers/ThreadConversationView';
4
- import { ThreadsView } from './containers/ThreadsView';
5
- import { useViewChannelDetailQuery, useSendThreadMessageMutation } from 'common/graphql';
6
- import { useFocusEffect } from '@react-navigation/native';
7
- // import { useSelector } from 'react-redux';
8
- import colors from 'tailwindcss/colors';
9
-
10
- export function DialogThreadMessages({ channelId, postParentId, isPostParentIdThread, role }) {
11
- const {
12
- data,
13
- loading: channelLoading,
14
- refetch,
15
- } = useViewChannelDetailQuery({
16
- variables: {
17
- id: channelId?.toString(),
18
- },
19
- });
20
-
21
- const [sendThreadMessage] = useSendThreadMessageMutation();
22
- const [loading, setLoading] = React.useState<boolean>(true);
23
- const [channel, setChannel] = React.useState<any>(null);
24
- const [parentId, setParentId] = React.useState<any>(postParentId);
25
-
26
- const refetchChannelDetail = React.useCallback(
27
- (id: string) => {
28
- return refetch({ id: id?.toString() });
29
- },
30
- [channelId],
31
- );
32
-
33
- useFocusEffect(
34
- React.useCallback(() => {
35
- // Do something when the screen is focused
36
- if (channelId) refetch({ id: channelId?.toString() });
37
- return () => {};
38
- }, [channelId]),
39
- );
40
-
41
- React.useEffect(() => {
42
- setParentId(postParentId);
43
- }, [postParentId]);
44
-
45
- React.useEffect(() => {
46
- if (data?.viewChannelDetail) {
47
- setChannel(data?.viewChannelDetail);
48
- setLoading(false);
49
- }
50
- }, [data]);
51
-
52
- // React.useEffect(() => {
53
- // async function sendInitialMessage(channel: any) {
54
- // const content = `Welcome to ${channel?.title}`;
55
- // const createdBy = channel?.creator?.id;
56
- // await sendThreadMessage({
57
- // variables: {
58
- // channelId,
59
- // threadMessageInput: {
60
- // content,
61
- // role,
62
- // },
63
- // responderId: createdBy,
64
- // },
65
- // update: (cache, { data, errors }: any) => {
66
- // if (!data) {
67
- // return;
68
- // }
69
- // setParentId(data?.sendThreadMessage?.lastMessage?.id);
70
- // },
71
- // });
72
- // }
73
- // if ((!parentId || parentId == 0) && channel) {
74
- // sendInitialMessage(channel);
75
- // }
76
-
77
- // if (parentId) setLoading(false);
78
- // }, [parentId, channel]);
79
-
80
- return (
81
- <Box className="bg-white flex-1">
82
- {/* {loading && !parentId ? ( */}
83
- {loading ? (
84
- <Spinner color={colors.blue[500]} />
85
- ) : (
86
- <ThreadConversationView
87
- channelId={channelId}
88
- postParentId={parentId}
89
- isPostParentIdThread={isPostParentIdThread}
90
- role={role}
91
- />
92
- )}
93
- </Box>
94
- );
95
- }
96
-
97
- export default DialogThreadMessages;
@@ -1,125 +0,0 @@
1
- import * as React from 'react';
2
- import { Box, Spinner, Text } from '@admin-layout/gluestack-ui-mobile';
3
- import { ThreadConversationView } from './containers/ThreadConversationView';
4
- import { ThreadsView } from './containers/ThreadsView';
5
- import { useViewChannelDetailQuery, useThreadMessagesQuery } from 'common/graphql';
6
- import { useFocusEffect } from '@react-navigation/native';
7
- import { useSelector } from 'react-redux';
8
- import { config } from './config';
9
- import colors from 'tailwindcss/colors';
10
- import { useSafeDialogThreadsMachine } from './hooks/useSafeDialogThreadsMachine';
11
- import { Actions, BaseState } from './workflow/dialog-threads-xstate';
12
- const { MESSAGES_PER_PAGE } = config;
13
-
14
- export function DialogThreads({ channelId, postParentId, role }) {
15
- // Use the XState machine for state management
16
- const [state, send] = useSafeDialogThreadsMachine();
17
- const { context, value } = state;
18
- const { channelsDetail, loading, error } = context;
19
-
20
- // Fetch channel details
21
- const {
22
- data: channelData,
23
- loading: channelLoading,
24
- refetch: channelRefetch,
25
- } = useViewChannelDetailQuery({
26
- variables: {
27
- id: channelId?.toString(),
28
- },
29
- });
30
-
31
- // Fetch thread messages
32
- const {
33
- data: threadsData,
34
- loading: threadLoading,
35
- error: threadsError,
36
- refetch: threadsRefetch,
37
- subscribeToMore: threadsSubscribeToMore,
38
- } = useThreadMessagesQuery({
39
- variables: {
40
- channelId: channelId?.toString(),
41
- role: role?.toString(),
42
- limit: MESSAGES_PER_PAGE,
43
- repliesLimit2: 5,
44
- },
45
- });
46
-
47
- // Initialize the machine with props
48
- React.useEffect(() => {
49
- send({
50
- type: Actions.INITIALIZE,
51
- data: { channelId, postParentId, role },
52
- });
53
- }, [channelId, postParentId, role]);
54
-
55
- // Update channel detail in state when data changes
56
- React.useEffect(() => {
57
- if (channelData?.viewChannelDetail) {
58
- send({
59
- type: Actions.SET_CHANNEL_DETAIL,
60
- data: { channelsDetail: channelData.viewChannelDetail },
61
- });
62
- }
63
- }, [channelData]);
64
-
65
- // Update thread data in state when data changes
66
- React.useEffect(() => {
67
- if (threadsData) {
68
- send({
69
- type: Actions.SET_THREADS,
70
- data: { threadData: threadsData?.threadMessages?.data || [] },
71
- });
72
- }
73
- }, [threadsData]);
74
-
75
- // Handle errors
76
- React.useEffect(() => {
77
- if (threadsError) {
78
- send({
79
- type: Actions.ERROR,
80
- data: { error: threadsError },
81
- });
82
- }
83
- }, [threadsError]);
84
-
85
- const refetchChannelDetail = React.useCallback(
86
- (id: string) => {
87
- return channelRefetch({ id: id?.toString() });
88
- },
89
- [channelId],
90
- );
91
-
92
- useFocusEffect(
93
- React.useCallback(() => {
94
- // Do something when the screen is focused
95
- if (channelId) refetchChannelDetail(channelId);
96
- return () => {};
97
- }, []),
98
- );
99
-
100
- return (
101
- <>
102
- {state.matches(BaseState.LoadingChannel) || channelLoading ? (
103
- <Spinner color={colors.blue[500]} />
104
- ) : (
105
- <>
106
- <Box className="flex-1 bg-gray-200 dark:border-gray-500 dark:bg-gray-500">
107
- <ThreadsView
108
- data={threadsData}
109
- loading={threadLoading || state.matches(BaseState.LoadingThreads)}
110
- refetch={threadsRefetch}
111
- subscribeToMore={threadsSubscribeToMore}
112
- error={error || threadsError}
113
- channelId={channelId}
114
- role={role}
115
- channelsDetail={channelsDetail}
116
- refetchChannelDetail={refetchChannelDetail}
117
- />
118
- </Box>
119
- </>
120
- )}
121
- </>
122
- );
123
- }
124
-
125
- export default DialogThreads;
@@ -1,17 +0,0 @@
1
- import * as React from 'react';
2
- import { Box, Text } from '@admin-layout/gluestack-ui-mobile';
3
-
4
- import { Dialogs } from './containers/Dialogs';
5
- // import { SupportServiceDialogs } from './containers/SupportServiceDialogs';
6
-
7
- export const Inbox = (props: any) => {
8
- const { channelFilters, channelRole, supportServices } = props;
9
- return (
10
- <Box className="flex-1 bg-white">
11
- {/* {supportServices && (
12
- <SupportServiceDialogs channelFilters={channelFilters} channelRole={channelRole} {...props} />
13
- )} */}
14
- <Dialogs channelFilters={channelFilters} channelRole={channelRole} {...props} />
15
- </Box>
16
- );
17
- };
@@ -1,6 +0,0 @@
1
- import * as FileSystem from 'expo-file-system';
2
-
3
- // Make sure cache directory path ends with a slash
4
- export const IMAGE_CACHE_FOLDER = `${FileSystem.cacheDirectory}/image-cache/`;
5
- // export const IMAGE_CACHE_FOLDER = `${FileSystem.documentDirectory}images/`
6
- export default IMAGE_CACHE_FOLDER;
@@ -1,223 +0,0 @@
1
- import React, { useEffect, useState, useRef } from 'react';
2
- import { Image, View, Text } from 'react-native';
3
- // import { Image } from "react-native"
4
- import * as FileSystem from 'expo-file-system';
5
-
6
- import * as CONST from './consts';
7
-
8
- // Ensure the cache directory exists
9
- const ensureCacheDirectory = async () => {
10
- try {
11
- const dirInfo = await FileSystem.getInfoAsync(CONST.IMAGE_CACHE_FOLDER);
12
- if (!dirInfo.exists) {
13
- console.log('Creating cache directory:', CONST.IMAGE_CACHE_FOLDER);
14
- await FileSystem.makeDirectoryAsync(CONST.IMAGE_CACHE_FOLDER, { intermediates: true });
15
- }
16
- } catch (error) {
17
- console.error('Failed to create cache directory:', error);
18
- }
19
- };
20
-
21
- // Validate and sanitize the image URL
22
- const validateImageUri = (uri: string): string | null => {
23
- if (!uri) return null;
24
-
25
- // Trim whitespace
26
- uri = uri.trim();
27
-
28
- // Check if it's a valid URL format
29
- try {
30
- new URL(uri);
31
- } catch (e) {
32
- console.log('Invalid URL format:', uri);
33
- return null;
34
- }
35
-
36
- // Add more validation as needed for your specific case
37
- return uri;
38
- };
39
-
40
- const CachedImage = (props: any) => {
41
- const { source, cacheKey, placeholderContent } = props;
42
- const { uri: originalUri, headers, expiresIn } = source;
43
-
44
- // Validate and sanitize the URI
45
- const uri = validateImageUri(originalUri);
46
-
47
- const fileURI = `${CONST.IMAGE_CACHE_FOLDER}${cacheKey}`;
48
-
49
- const [imgUri, setImgUri] = useState<any>(fileURI);
50
- const [loadError, setLoadError] = useState<boolean>(false);
51
- const [useFallbackUri, setUseFallbackUri] = useState<boolean>(false);
52
-
53
- const componentIsMounted = useRef(true);
54
- const requestOption = headers ? { headers } : {};
55
-
56
- const _callback = (downloadProgress: any) => {
57
- if (componentIsMounted.current === false) {
58
- downloadResumableRef.current?.pauseAsync();
59
- FileSystem.deleteAsync(fileURI, { idempotent: true }); // delete file locally if it was not downloaded properly
60
- }
61
- };
62
-
63
- const downloadResumableRef = useRef(
64
- uri ? FileSystem.createDownloadResumable(uri, fileURI, requestOption, _callback) : null,
65
- );
66
-
67
- useEffect(() => {
68
- const initCache = async () => {
69
- await ensureCacheDirectory();
70
- if (uri) {
71
- loadImage();
72
- } else {
73
- console.log('Image URI is invalid, not loading');
74
- setLoadError(true);
75
- }
76
- };
77
-
78
- // console.log('CachedImage loading with URI:', uri);
79
- console.log('Cache key:', cacheKey);
80
-
81
- initCache();
82
-
83
- return () => {
84
- componentIsMounted.current = false;
85
- };
86
- }, []); // eslint-disable-line react-hooks/exhaustive-deps
87
-
88
- const loadImage = async () => {
89
- try {
90
- // Use the cached image if it exists
91
- const metadata: any = await FileSystem.getInfoAsync(fileURI);
92
- const expired = expiresIn && new Date().getTime() / 1000 - metadata?.modificationTime > expiresIn;
93
- console.log({ expiresIn, expired });
94
-
95
- // console.log({ modificationTime: metadata.modificationTime, currentTime: new Date().getTime() / 1000 });
96
- // console.log({ metadata });
97
-
98
- if (!metadata.exists || metadata?.size === 0 || expired) {
99
- if (componentIsMounted.current) {
100
- setImgUri(null);
101
-
102
- if (expired) {
103
- await FileSystem.deleteAsync(fileURI, { idempotent: true });
104
- }
105
- // download to cache
106
- setImgUri(null);
107
-
108
- // console.log('Downloading image from URI:', uri);
109
- if (!uri) {
110
- // console.log('Image URI is undefined or null');
111
- setLoadError(true);
112
- return;
113
- }
114
-
115
- if (!downloadResumableRef.current) {
116
- console.log('Download resumable is null');
117
- setUseFallbackUri(true);
118
- setImgUri(uri);
119
- return;
120
- }
121
-
122
- try {
123
- const response: any = await downloadResumableRef.current.downloadAsync();
124
- // console.log('Download response:', response);
125
-
126
- if (componentIsMounted.current && response && response.status === 200) {
127
- setImgUri(`${fileURI}?`); // deep clone to force re-render
128
- // console.log('Image cached successfully, new URI:', `${fileURI}?`);
129
- } else {
130
- console.log('Failed to download image, status:', response?.status);
131
- console.log('Falling back to original URI');
132
- setUseFallbackUri(true);
133
- setImgUri(uri);
134
- FileSystem.deleteAsync(fileURI, { idempotent: true }); // delete file locally if it was not downloaded properly
135
- }
136
- } catch (downloadError) {
137
- console.log('Error downloading image:', downloadError);
138
- console.log('Falling back to original URI');
139
- setUseFallbackUri(true);
140
- setImgUri(uri);
141
- }
142
- }
143
- } else {
144
- //console.log('Using cached image at:', fileURI);
145
- }
146
- } catch (err) {
147
- console.log({ err });
148
- console.log('Falling back to original URI');
149
- setUseFallbackUri(true);
150
- setImgUri(uri);
151
- }
152
- };
153
-
154
- //console.log({ placeholderContent, imgUri, loadError, useFallbackUri });
155
-
156
- // Default placeholder if none is provided
157
- const defaultPlaceholder = (
158
- <View
159
- style={{
160
- width: '100%',
161
- height: '100%',
162
- backgroundColor: '#e1e1e1',
163
- justifyContent: 'center',
164
- alignItems: 'center',
165
- borderRadius: 3,
166
- }}
167
- >
168
- <Text>Image not available</Text>
169
- </View>
170
- );
171
-
172
- if (!imgUri) {
173
- return placeholderContent || defaultPlaceholder;
174
- }
175
-
176
- return (
177
- <Image
178
- // eslint-disable-next-line react/jsx-props-no-spreading
179
- {...props}
180
- source={{
181
- ...source,
182
- uri: useFallbackUri ? uri : imgUri,
183
- }}
184
- onError={(e) => {
185
- console.log('Image loading error:', e.nativeEvent.error);
186
- // If we're already using the fallback URI and still getting an error,
187
- // then show the placeholder
188
- if (useFallbackUri) {
189
- setLoadError(true);
190
- setImgUri(null);
191
- } else {
192
- console.log('Falling back to original URI after onError');
193
- setUseFallbackUri(true);
194
- setImgUri(uri);
195
- }
196
- }}
197
- />
198
- );
199
- };
200
-
201
- export const CacheManager = {
202
- addToCache: async ({ file, key }: any) => {
203
- await FileSystem.copyAsync({
204
- from: file,
205
- to: `${CONST.IMAGE_CACHE_FOLDER}${key}`,
206
- });
207
- // const uri = await FileSystem.getContentUriAsync(`${CONST.IMAGE_CACHE_FOLDER}${key}`)
208
- // return uri
209
- const uri = await CacheManager.getCachedUri({ key });
210
- return uri;
211
- },
212
-
213
- getCachedUri: async ({ key }: any) => {
214
- const uri = await FileSystem.getContentUriAsync(`${CONST.IMAGE_CACHE_FOLDER}${key}`);
215
- return uri;
216
- },
217
-
218
- downloadAsync: async ({ uri, key, options }: any) => {
219
- return await FileSystem.downloadAsync(uri, `${CONST.IMAGE_CACHE_FOLDER}${key}`, options);
220
- },
221
- };
222
-
223
- export default CachedImage;
@@ -1,30 +0,0 @@
1
- import * as React from 'react';
2
- import { HStack, Text, View } from '@admin-layout/gluestack-ui-mobile';
3
- import { AntDesign } from '@expo/vector-icons';
4
- import { StyleProp, ViewStyle } from 'react-native';
5
-
6
- export function DialogsHeader({
7
- onBack,
8
- extra,
9
- style,
10
- title,
11
- }: {
12
- onBack?: () => void;
13
- extra?: any;
14
- style?: StyleProp<ViewStyle>;
15
- title: string;
16
- }) {
17
- return (
18
- <HStack className="px-4 py-2 items-center justify-between" style={style}>
19
- <View style={{ flex: 1 }}>{onBack ? <AntDesign onPress={onBack} name="left" size={18} /> : null}</View>
20
- <View style={{ flexDirection: 'row', flex: 1, flexGrow: 1 }}>
21
- <Text numberOfLines={1} style={{ fontSize: 20 }} className="shrink font-semibold text-center grow">
22
- {title || ' '}
23
- </Text>
24
- </View>
25
- <View style={{ flex: 1, alignItems: 'flex-end', justifyContent: 'center' }}>
26
- <Text className="text-right">{extra}</Text>
27
- </View>
28
- </HStack>
29
- );
30
- }