@messenger-box/platform-mobile 10.0.3-alpha.20 → 10.0.3-alpha.201

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 (112) 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 +58 -20
  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 -115
  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 +67 -47
  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 +1099 -1094
  45. package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
  46. package/lib/screens/inbox/containers/Dialogs.js +132 -534
  47. package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
  48. package/lib/screens/inbox/containers/ThreadConversationView.js +876 -1357
  49. package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
  50. package/lib/screens/inbox/containers/ThreadsView.js +81 -54
  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 +108 -0
  55. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js.map +1 -0
  56. package/lib/screens/inbox/workflow/dialog-threads-xstate.js +151 -0
  57. package/lib/screens/inbox/workflow/dialog-threads-xstate.js.map +1 -0
  58. package/package.json +9 -7
  59. package/CHANGELOG.md +0 -164
  60. package/jest.config.js +0 -24
  61. package/lib/screens/inbox/components/DialogsListItem.js +0 -548
  62. package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
  63. package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -489
  64. package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
  65. package/lib/screens/inbox/components/workflow/dialogs-list-item-xstate.js +0 -175
  66. package/lib/screens/inbox/components/workflow/dialogs-list-item-xstate.js.map +0 -1
  67. package/lib/screens/inbox/components/workflow/service-dialogs-list-item-xstate.js +0 -191
  68. package/lib/screens/inbox/components/workflow/service-dialogs-list-item-xstate.js.map +0 -1
  69. package/lib/screens/inbox/containers/workflow/conversation-xstate.js +0 -380
  70. package/lib/screens/inbox/containers/workflow/conversation-xstate.js.map +0 -1
  71. package/lib/screens/inbox/containers/workflow/dialogs-xstate.js +0 -211
  72. package/lib/screens/inbox/containers/workflow/dialogs-xstate.js.map +0 -1
  73. package/lib/screens/inbox/containers/workflow/thread-conversation-xstate.js +0 -438
  74. package/lib/screens/inbox/containers/workflow/thread-conversation-xstate.js.map +0 -1
  75. package/rollup.config.mjs +0 -45
  76. package/src/components/index.ts +0 -0
  77. package/src/compute.ts +0 -63
  78. package/src/index.ts +0 -7
  79. package/src/module.ts +0 -10
  80. package/src/navigation/InboxNavigation.tsx +0 -102
  81. package/src/navigation/index.ts +0 -1
  82. package/src/screens/inbox/DialogMessages.tsx +0 -21
  83. package/src/screens/inbox/DialogThreadMessages.tsx +0 -97
  84. package/src/screens/inbox/DialogThreads.tsx +0 -129
  85. package/src/screens/inbox/Inbox.tsx +0 -17
  86. package/src/screens/inbox/components/CachedImage/consts.ts +0 -6
  87. package/src/screens/inbox/components/CachedImage/index.tsx +0 -223
  88. package/src/screens/inbox/components/DialogsHeader.tsx +0 -30
  89. package/src/screens/inbox/components/DialogsListItem.tsx +0 -819
  90. package/src/screens/inbox/components/ServiceDialogsListItem.tsx +0 -679
  91. package/src/screens/inbox/components/SlackMessageContainer/ImageViewerModal.tsx +0 -113
  92. package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +0 -313
  93. package/src/screens/inbox/components/SlackMessageContainer/SlackMessage.tsx +0 -145
  94. package/src/screens/inbox/components/SlackMessageContainer/index.ts +0 -3
  95. package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +0 -301
  96. package/src/screens/inbox/components/ThreadsViewItem.tsx +0 -321
  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 -1782
  102. package/src/screens/inbox/containers/Dialogs.tsx +0 -794
  103. package/src/screens/inbox/containers/SupportServiceDialogs.tsx +0 -119
  104. package/src/screens/inbox/containers/ThreadConversationView.tsx +0 -2312
  105. package/src/screens/inbox/containers/ThreadsView.tsx +0 -305
  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/index.ts +0 -4
  111. package/tsconfig.json +0 -13
  112. 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,129 +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
- const { MESSAGES_PER_PAGE } = config;
11
-
12
- export function DialogThreads({ channelId, postParentId, role }) {
13
- const {
14
- data: channelData,
15
- loading: channelLoading,
16
- refetch: channelRefetch,
17
- } = useViewChannelDetailQuery({
18
- variables: {
19
- id: channelId?.toString(),
20
- },
21
- });
22
-
23
- const {
24
- data: threadsData,
25
- loading: threadLoading,
26
- error: threadsError,
27
- refetch: threadsRefetch,
28
- subscribeToMore: threadsSubscribeToMore,
29
- } = useThreadMessagesQuery({
30
- variables: {
31
- channelId: channelId?.toString(),
32
- role: role?.toString(),
33
- limit: MESSAGES_PER_PAGE,
34
- repliesLimit2: 5,
35
- },
36
- // fetchPolicy: 'cache-and-network',
37
- });
38
-
39
- const channelsDetail = React.useMemo(() => {
40
- if (!channelData?.viewChannelDetail) return null;
41
- return channelData?.viewChannelDetail;
42
- }, [channelData]);
43
-
44
- const refetchChannelDetail = React.useCallback(
45
- (id: string) => {
46
- return channelRefetch({ id: id?.toString() });
47
- },
48
- [channelId],
49
- );
50
-
51
- useFocusEffect(
52
- React.useCallback(() => {
53
- // Do something when the screen is focused
54
- if (channelId) refetchChannelDetail(channelId);
55
- return () => {};
56
- }, []),
57
- );
58
-
59
- return (
60
- // <Box bg={'white'} flex={1} pt={5}>
61
- <>
62
- {channelLoading ? (
63
- <Spinner color={colors.blue[500]} />
64
- ) : (
65
- <>
66
- <Box
67
- // $dark-borderColor="$coolGray600"
68
- // $dark-backgroundColor="$trueGray700"
69
- // $light-backgroundColor="$trueGray50"
70
- className="flex-1 bg-gray-200 dark:border-gray-500 dark:bg-gray-500 "
71
- >
72
- <ThreadsView
73
- data={threadsData}
74
- loading={threadLoading}
75
- refetch={threadsRefetch}
76
- subscribeToMore={threadsSubscribeToMore}
77
- error={threadsError}
78
- channelId={channelId}
79
- role={role}
80
- channelsDetail={channelsDetail}
81
- refetchChannelDetail={refetchChannelDetail}
82
- />
83
- </Box>
84
- </>
85
- )}
86
- </>
87
- );
88
-
89
- // return (
90
- // // <Box bg={'white'} flex={1} pt={5}>
91
- // <>
92
- // {channelLoading ? (
93
- // <Spinner />
94
- // ) : (
95
- // <>
96
- // {postParentId || postParentId == 0 ? (
97
- // <Box bg={'white'} flex={1}>
98
- // <ThreadConversationView
99
- // channelId={channelId}
100
- // postParentId={postParentId}
101
- // channelsDetail={channelsDetail}
102
- // refetchChannelDetail={refetchChannelDetail}
103
- // />
104
- // </Box>
105
- // ) : (
106
- // <Box
107
- // flex={1}
108
- // _dark={{
109
- // borderColor: 'coolGray.600',
110
- // backgroundColor: 'gray.700',
111
- // }}
112
- // _light={{
113
- // backgroundColor: 'gray.50',
114
- // }}
115
- // >
116
- // <ThreadsView
117
- // channelId={channelId}
118
- // channelsDetail={channelsDetail}
119
- // refetchChannelDetail={refetchChannelDetail}
120
- // />
121
- // </Box>
122
- // )}
123
- // </>
124
- // )}
125
- // </>
126
- // );
127
- }
128
-
129
- 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
- }