mirror of
https://github.com/papra-hq/papra.git
synced 2025-12-16 20:24:27 -06:00
feat(mobile): in-app document viewer (#667)
* Keep the phone logged in * Added document sheet * Make button outline * Fix colors * Design accroding to base design * Design accroding to base design * Added download and share * Added view document screen * Added view document screen * Screen is launching * fix toolbar issue * Fix the button * fix all the conflicts * revert unncessary bloat * remove packages * pnpnm i * Fixed some issues * Added error state * added header in loading and error state * Removed duplication in render * added correct name of app * Update apps/mobile/app.json Co-authored-by: Corentin Thomasset <corentin.thomasset74@gmail.com> --------- Co-authored-by: jibraniqbal666 <jibran.iqbal@protonmail.com> Co-authored-by: Corentin Thomasset <corentin.thomasset74@gmail.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "mobile",
|
||||
"slug": "mobile",
|
||||
"name": "Papra",
|
||||
"slug": "papra",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./src/assets/images/icon.png",
|
||||
@@ -19,7 +19,8 @@
|
||||
"monochromeImage": "./src/assets/images/android-icon-monochrome.png"
|
||||
},
|
||||
"edgeToEdgeEnabled": true,
|
||||
"predictiveBackGestureEnabled": false
|
||||
"predictiveBackGestureEnabled": false,
|
||||
"package": "app.papra.android"
|
||||
},
|
||||
"web": {
|
||||
"output": "static",
|
||||
|
||||
@@ -11,6 +11,14 @@ export default function RootLayout() {
|
||||
<Stack.Screen name="auth/login" options={{ headerShown: false }} />
|
||||
<Stack.Screen name="auth/signup" options={{ headerShown: false }} />
|
||||
<Stack.Screen name="(with-organizations)" options={{ headerShown: false }} />
|
||||
<Stack.Screen
|
||||
name="document/view"
|
||||
options={{
|
||||
headerShown: false,
|
||||
presentation: 'modal',
|
||||
animation: 'slide_from_bottom',
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
<StatusBar style="auto" />
|
||||
</ApiProvider>
|
||||
|
||||
3
apps/mobile/app/(app)/document/view.tsx
Normal file
3
apps/mobile/app/(app)/document/view.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
import DocumentViewScreen from '@/modules/documents-actions/screens/document-view.screen';
|
||||
|
||||
export default DocumentViewScreen;
|
||||
@@ -7,8 +7,8 @@
|
||||
"scripts": {
|
||||
"dev": "pnpm start",
|
||||
"start": "expo start",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
"web": "expo start --web",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
@@ -48,6 +48,7 @@
|
||||
"react-dom": "19.1.0",
|
||||
"react-native": "0.81.5",
|
||||
"react-native-gesture-handler": "~2.28.0",
|
||||
"react-native-pdf": "^7.0.3",
|
||||
"react-native-reanimated": "~4.1.1",
|
||||
"react-native-safe-area-context": "~5.6.0",
|
||||
"react-native-screens": "~4.16.0",
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { CoerceDates } from '@/modules/api/api.models';
|
||||
import type { Document } from '@/modules/documents/documents.types';
|
||||
import type { ThemeColors } from '@/modules/ui/theme.constants';
|
||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import { router } from 'expo-router';
|
||||
import * as Sharing from 'expo-sharing';
|
||||
import {
|
||||
Modal,
|
||||
@@ -21,14 +22,12 @@ type DocumentActionSheetProps = {
|
||||
visible: boolean;
|
||||
document: CoerceDates<Document> | undefined;
|
||||
onClose: () => void;
|
||||
onView: () => void;
|
||||
};
|
||||
|
||||
export function DocumentActionSheet({
|
||||
visible,
|
||||
document,
|
||||
onClose,
|
||||
onView,
|
||||
}: DocumentActionSheetProps) {
|
||||
const themeColors = useThemeColor();
|
||||
const styles = createStyles({ themeColors });
|
||||
@@ -64,6 +63,17 @@ export function DocumentActionSheet({
|
||||
});
|
||||
};
|
||||
|
||||
const handleView = async () => {
|
||||
onClose();
|
||||
router.push({
|
||||
pathname: '/(app)/document/view',
|
||||
params: {
|
||||
documentId: document.id,
|
||||
organizationId: document.organizationId,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleDownloadAndShare = async () => {
|
||||
const baseUrl = await configLocalStorage.getApiServerBaseUrl();
|
||||
|
||||
@@ -166,9 +176,9 @@ export function DocumentActionSheet({
|
||||
{isViewable && (
|
||||
<TouchableOpacity
|
||||
style={styles.actionButton}
|
||||
onPress={() => {
|
||||
onPress={async () => {
|
||||
onClose();
|
||||
onView();
|
||||
await handleView();
|
||||
}}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
import type { CoerceDates } from '@/modules/api/api.models';
|
||||
import type { Document } from '@/modules/documents/documents.types';
|
||||
import type { ThemeColors } from '@/modules/ui/theme.constants';
|
||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useLocalSearchParams, useRouter } from 'expo-router';
|
||||
import React from 'react';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import Pdf from 'react-native-pdf';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useApiClient, useAuthClient } from '@/modules/api/providers/api.provider';
|
||||
import { configLocalStorage } from '@/modules/config/config.local-storage';
|
||||
import { fetchDocument, fetchDocumentFile } from '@/modules/documents/documents.services';
|
||||
import { useAlert } from '@/modules/ui/providers/alert-provider';
|
||||
import { useThemeColor } from '@/modules/ui/providers/use-theme-color';
|
||||
|
||||
type DocumentFile = {
|
||||
uri: string;
|
||||
doc: CoerceDates<Document>;
|
||||
};
|
||||
|
||||
export default function DocumentViewScreen() {
|
||||
const router = useRouter();
|
||||
const params = useLocalSearchParams<{ documentId: string; organizationId: string }>();
|
||||
const themeColors = useThemeColor();
|
||||
const styles = createStyles({ themeColors });
|
||||
const { showAlert } = useAlert();
|
||||
const apiClient = useApiClient();
|
||||
const authClient = useAuthClient();
|
||||
const { documentId, organizationId } = params;
|
||||
|
||||
const documentQuery = useQuery({
|
||||
queryKey: ['organizations', organizationId, 'documents', documentId],
|
||||
queryFn: async () => {
|
||||
if (organizationId == null || documentId == null) {
|
||||
throw new Error('Organization ID and Document ID are required');
|
||||
}
|
||||
return fetchDocument({ organizationId, documentId, apiClient });
|
||||
},
|
||||
enabled: organizationId != null && documentId != null,
|
||||
});
|
||||
|
||||
const documentFileQuery = useQuery({
|
||||
queryKey: ['organizations', organizationId, 'documents', documentId, 'file'],
|
||||
queryFn: async () => {
|
||||
if (documentQuery.data == null) {
|
||||
throw new Error('Document not loaded');
|
||||
}
|
||||
|
||||
const baseUrl = await configLocalStorage.getApiServerBaseUrl();
|
||||
if (baseUrl == null) {
|
||||
throw new Error('Base URL not found');
|
||||
}
|
||||
|
||||
const fileUri = await fetchDocumentFile({
|
||||
document: documentQuery.data.document,
|
||||
organizationId,
|
||||
baseUrl,
|
||||
authClient,
|
||||
});
|
||||
|
||||
return {
|
||||
uri: fileUri,
|
||||
doc: documentQuery.data.document,
|
||||
} as DocumentFile;
|
||||
},
|
||||
enabled: documentQuery.isSuccess && documentQuery.data != null,
|
||||
});
|
||||
|
||||
const renderHeader = (documentName: string) => {
|
||||
return (
|
||||
<View style={styles.header}>
|
||||
<TouchableOpacity
|
||||
style={styles.backButton}
|
||||
onPress={() => router.back()}
|
||||
>
|
||||
<MaterialCommunityIcons
|
||||
name="close"
|
||||
size={24}
|
||||
color={themeColors.foreground}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.headerTitle} numberOfLines={1}>
|
||||
{documentName}
|
||||
</Text>
|
||||
<View style={styles.headerSpacer} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const renderDocumentFile = (file: DocumentFile) => {
|
||||
if (file.doc.mimeType.startsWith('image/')) {
|
||||
return (
|
||||
<Image
|
||||
source={{ uri: file.uri }}
|
||||
style={styles.pdfViewer}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (file.doc.mimeType.startsWith('application/pdf')) {
|
||||
return (
|
||||
<Pdf
|
||||
source={{ uri: file.uri, cache: true }}
|
||||
style={styles.pdfViewer}
|
||||
onError={(error) => {
|
||||
console.error('PDF error:', error);
|
||||
showAlert({
|
||||
title: 'Error',
|
||||
message: 'Failed to load PDF',
|
||||
});
|
||||
}}
|
||||
enablePaging={true}
|
||||
horizontal={false}
|
||||
enableAnnotationRendering={true}
|
||||
fitPolicy={0}
|
||||
spacing={10}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <View style={styles.pdfViewer} />;
|
||||
};
|
||||
|
||||
const isLoading = documentQuery.isLoading || documentFileQuery.isLoading;
|
||||
const error = documentQuery.error ?? documentFileQuery.error;
|
||||
const documentFile = documentFileQuery.data;
|
||||
const documentName = documentFile?.doc.name ?? 'Document';
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
{renderHeader(documentName)}
|
||||
{isLoading
|
||||
? (
|
||||
<View style={styles.loadingContainer}>
|
||||
<ActivityIndicator size="large" color={themeColors.primary} />
|
||||
<Text style={styles.loadingText}>Loading document...</Text>
|
||||
</View>
|
||||
)
|
||||
: error != null
|
||||
? (
|
||||
<View style={styles.errorContainer}>
|
||||
<MaterialCommunityIcons
|
||||
name="file-pdf-box"
|
||||
size={64}
|
||||
color={themeColors.mutedForeground}
|
||||
/>
|
||||
<Text style={styles.errorText}>Failed to load document</Text>
|
||||
<TouchableOpacity
|
||||
style={styles.errorButton}
|
||||
onPress={() => {
|
||||
void documentQuery.refetch();
|
||||
}}
|
||||
>
|
||||
<Text style={styles.errorButtonText}>Retry</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={styles.errorButton}
|
||||
onPress={() => router.back()}
|
||||
>
|
||||
<Text style={styles.errorButtonText}>Go Back</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)
|
||||
: documentFile != null
|
||||
? (
|
||||
<View style={styles.pdfContainer}>
|
||||
{renderDocumentFile(documentFile)}
|
||||
</View>
|
||||
)
|
||||
: null}
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
function createStyles({ themeColors }: { themeColors: ThemeColors }) {
|
||||
return StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: themeColors.background,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 24,
|
||||
paddingVertical: 16,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: themeColors.border,
|
||||
},
|
||||
backButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 20,
|
||||
backgroundColor: themeColors.secondaryBackground,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'flex-start',
|
||||
},
|
||||
headerTitle: {
|
||||
flex: 1,
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
color: themeColors.foreground,
|
||||
marginHorizontal: 16,
|
||||
},
|
||||
headerSpacer: {
|
||||
width: 40,
|
||||
},
|
||||
pdfContainer: {
|
||||
flex: 1,
|
||||
backgroundColor: themeColors.background,
|
||||
},
|
||||
pdfViewer: {
|
||||
flex: 1,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
loadingContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
loadingText: {
|
||||
marginTop: 16,
|
||||
fontSize: 16,
|
||||
color: themeColors.mutedForeground,
|
||||
},
|
||||
errorContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: 32,
|
||||
},
|
||||
errorText: {
|
||||
fontSize: 18,
|
||||
color: themeColors.foreground,
|
||||
marginTop: 16,
|
||||
marginBottom: 24,
|
||||
},
|
||||
errorButton: {
|
||||
paddingHorizontal: 24,
|
||||
paddingVertical: 16,
|
||||
backgroundColor: themeColors.secondaryBackground,
|
||||
borderRadius: 12,
|
||||
marginTop: 16,
|
||||
},
|
||||
errorButtonText: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: themeColors.primary,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -76,6 +76,24 @@ export async function fetchOrganizationDocuments({
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchDocument({
|
||||
organizationId,
|
||||
documentId,
|
||||
apiClient,
|
||||
}: {
|
||||
organizationId: string;
|
||||
documentId: string;
|
||||
apiClient: ApiClient;
|
||||
}) {
|
||||
const { document } = await apiClient<{ document: Document }>({
|
||||
method: 'GET',
|
||||
path: `/api/organizations/${organizationId}/documents/${documentId}`,
|
||||
});
|
||||
return {
|
||||
document: coerceDates(document),
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchDocumentFile({
|
||||
document,
|
||||
organizationId,
|
||||
|
||||
@@ -85,7 +85,6 @@ export function DocumentsListScreen() {
|
||||
visible={true}
|
||||
document={onDocumentActionSheet}
|
||||
onClose={() => setOnDocumentActionSheet(undefined)}
|
||||
onView={() => {}}
|
||||
/>
|
||||
)}
|
||||
<View style={styles.header}>
|
||||
|
||||
84
pnpm-lock.yaml
generated
84
pnpm-lock.yaml
generated
@@ -225,6 +225,9 @@ importers:
|
||||
react-native-gesture-handler:
|
||||
specifier: ~2.28.0
|
||||
version: 2.28.0(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||
react-native-pdf:
|
||||
specifier: ^7.0.3
|
||||
version: 7.0.3(react-native-blob-util@0.23.2(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||
react-native-reanimated:
|
||||
specifier: ~4.1.1
|
||||
version: 4.1.5(@babel/core@7.28.4)(react-native-worklets@0.5.1(@babel/core@7.28.4)(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||
@@ -4046,6 +4049,9 @@ packages:
|
||||
resolution: {integrity: sha512-fB7M1CMOCIUudTRuj7kzxIBTVw2KXnsgbQ6+4cbqSxo8NmRRhA0Ul4ZUzZj3rFd3VznTL4Brmocv1oiN0bWZ8w==}
|
||||
engines: {node: '>= 20.19.4'}
|
||||
|
||||
'@react-native/normalize-color@2.1.0':
|
||||
resolution: {integrity: sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA==}
|
||||
|
||||
'@react-native/normalize-colors@0.74.89':
|
||||
resolution: {integrity: sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==}
|
||||
|
||||
@@ -5874,6 +5880,9 @@ packages:
|
||||
bare-events:
|
||||
optional: true
|
||||
|
||||
base-64@0.1.0:
|
||||
resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==}
|
||||
|
||||
base-64@1.0.0:
|
||||
resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==}
|
||||
|
||||
@@ -6403,6 +6412,9 @@ packages:
|
||||
crypt@0.0.2:
|
||||
resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
|
||||
|
||||
crypto-js@4.2.0:
|
||||
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
|
||||
|
||||
crypto-random-string@2.0.0:
|
||||
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -6560,6 +6572,9 @@ packages:
|
||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
deprecated-react-native-prop-types@2.3.0:
|
||||
resolution: {integrity: sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA==}
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -7824,9 +7839,6 @@ packages:
|
||||
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-tsconfig@4.10.0:
|
||||
resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==}
|
||||
|
||||
get-tsconfig@4.10.1:
|
||||
resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
|
||||
|
||||
@@ -10091,6 +10103,12 @@ packages:
|
||||
react-is@19.2.0:
|
||||
resolution: {integrity: sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==}
|
||||
|
||||
react-native-blob-util@0.23.2:
|
||||
resolution: {integrity: sha512-ZsUUFQYyZ7BI57c31XdPCkPlteoH7+PvcVy2w6wh1OPSUWGtKL79pj7fa6MepMX0v87fn0V9Heq0n6OjEpLdCw==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
||||
react-native-gesture-handler@2.28.0:
|
||||
resolution: {integrity: sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==}
|
||||
peerDependencies:
|
||||
@@ -10103,6 +10121,13 @@ packages:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
|
||||
react-native-pdf@7.0.3:
|
||||
resolution: {integrity: sha512-zDtF6CGXPAfGptQZqX7LQK3CVQrIGsD+rYuBnMK0sVmd8mrq7ciwmWXINT+d92emMtZ7+PLnx1IQZIdsh0fphA==}
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
react-native: '*'
|
||||
react-native-blob-util: '>=0.13.7'
|
||||
|
||||
react-native-reanimated@4.1.5:
|
||||
resolution: {integrity: sha512-UA6VUbxwhRjEw2gSNrvhkusUq3upfD3Cv+AnB07V+kC8kpvwRVI+ivwY95ePbWNFkFpP+Y2Sdw1WHpHWEV+P2Q==}
|
||||
peerDependencies:
|
||||
@@ -11264,11 +11289,6 @@ packages:
|
||||
tslib@2.8.1:
|
||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||
|
||||
tsx@4.20.3:
|
||||
resolution: {integrity: sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
hasBin: true
|
||||
|
||||
tsx@4.20.6:
|
||||
resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
@@ -14046,7 +14066,7 @@ snapshots:
|
||||
'@esbuild-kit/esm-loader@2.6.5':
|
||||
dependencies:
|
||||
'@esbuild-kit/core-utils': 3.3.2
|
||||
get-tsconfig: 4.10.0
|
||||
get-tsconfig: 4.10.1
|
||||
|
||||
'@esbuild/aix-ppc64@0.19.12':
|
||||
optional: true
|
||||
@@ -16421,6 +16441,8 @@ snapshots:
|
||||
|
||||
'@react-native/js-polyfills@0.81.5': {}
|
||||
|
||||
'@react-native/normalize-color@2.1.0': {}
|
||||
|
||||
'@react-native/normalize-colors@0.74.89': {}
|
||||
|
||||
'@react-native/normalize-colors@0.76.2': {}
|
||||
@@ -18705,6 +18727,8 @@ snapshots:
|
||||
bare-events: 2.5.4
|
||||
optional: true
|
||||
|
||||
base-64@0.1.0: {}
|
||||
|
||||
base-64@1.0.0: {}
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
@@ -19274,6 +19298,8 @@ snapshots:
|
||||
|
||||
crypt@0.0.2: {}
|
||||
|
||||
crypto-js@4.2.0: {}
|
||||
|
||||
crypto-random-string@2.0.0: {}
|
||||
|
||||
css-in-js-utils@3.1.0:
|
||||
@@ -19406,6 +19432,12 @@ snapshots:
|
||||
|
||||
depd@2.0.0: {}
|
||||
|
||||
deprecated-react-native-prop-types@2.3.0:
|
||||
dependencies:
|
||||
'@react-native/normalize-color': 2.1.0
|
||||
invariant: 2.2.4
|
||||
prop-types: 15.8.1
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
destr@2.0.5: {}
|
||||
@@ -21054,10 +21086,6 @@ snapshots:
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.3.0
|
||||
|
||||
get-tsconfig@4.10.0:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
|
||||
get-tsconfig@4.10.1:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
@@ -21545,7 +21573,7 @@ snapshots:
|
||||
jiti: 2.0.0-beta.3
|
||||
jiti-v1: jiti@1.21.7
|
||||
pathe: 1.1.2
|
||||
tsx: 4.20.3
|
||||
tsx: 4.20.6
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -22724,7 +22752,7 @@ snapshots:
|
||||
metro-transform-plugins@0.83.3:
|
||||
dependencies:
|
||||
'@babel/core': 7.28.4
|
||||
'@babel/generator': 7.28.3
|
||||
'@babel/generator': 7.28.5
|
||||
'@babel/template': 7.27.2
|
||||
'@babel/traverse': 7.28.4
|
||||
flow-enums-runtime: 0.0.6
|
||||
@@ -22755,7 +22783,7 @@ snapshots:
|
||||
metro-transform-worker@0.83.3:
|
||||
dependencies:
|
||||
'@babel/core': 7.28.4
|
||||
'@babel/generator': 7.28.3
|
||||
'@babel/generator': 7.28.5
|
||||
'@babel/parser': 7.28.5
|
||||
'@babel/types': 7.28.5
|
||||
flow-enums-runtime: 0.0.6
|
||||
@@ -24019,6 +24047,13 @@ snapshots:
|
||||
|
||||
react-is@19.2.0: {}
|
||||
|
||||
react-native-blob-util@0.23.2(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||
dependencies:
|
||||
base-64: 0.1.0
|
||||
glob: 10.4.5
|
||||
react: 19.1.0
|
||||
react-native: 0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0)
|
||||
|
||||
react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||
dependencies:
|
||||
'@egjs/hammerjs': 2.0.17
|
||||
@@ -24032,6 +24067,14 @@ snapshots:
|
||||
react: 19.1.0
|
||||
react-native: 0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0)
|
||||
|
||||
react-native-pdf@7.0.3(react-native-blob-util@0.23.2(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||
dependencies:
|
||||
crypto-js: 4.2.0
|
||||
deprecated-react-native-prop-types: 2.3.0
|
||||
react: 19.1.0
|
||||
react-native: 0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0)
|
||||
react-native-blob-util: 0.23.2(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||
|
||||
react-native-reanimated@4.1.5(@babel/core@7.28.4)(react-native-worklets@0.5.1(@babel/core@7.28.4)(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.4)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||
dependencies:
|
||||
'@babel/core': 7.28.4
|
||||
@@ -24522,7 +24565,7 @@ snapshots:
|
||||
|
||||
rolldown-plugin-dts@0.15.6(rolldown@1.0.0-beta.31)(typescript@5.9.3):
|
||||
dependencies:
|
||||
'@babel/generator': 7.28.3
|
||||
'@babel/generator': 7.28.5
|
||||
'@babel/parser': 7.28.5
|
||||
'@babel/types': 7.28.5
|
||||
ast-kit: 2.1.1
|
||||
@@ -25563,13 +25606,6 @@ snapshots:
|
||||
|
||||
tslib@2.8.1: {}
|
||||
|
||||
tsx@4.20.3:
|
||||
dependencies:
|
||||
esbuild: 0.25.10
|
||||
get-tsconfig: 4.10.1
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
tsx@4.20.6:
|
||||
dependencies:
|
||||
esbuild: 0.25.10
|
||||
|
||||
Reference in New Issue
Block a user