mirror of
https://github.com/papra-hq/papra.git
synced 2025-12-21 12:09:39 -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": {
|
"expo": {
|
||||||
"name": "mobile",
|
"name": "Papra",
|
||||||
"slug": "mobile",
|
"slug": "papra",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./src/assets/images/icon.png",
|
"icon": "./src/assets/images/icon.png",
|
||||||
@@ -19,7 +19,8 @@
|
|||||||
"monochromeImage": "./src/assets/images/android-icon-monochrome.png"
|
"monochromeImage": "./src/assets/images/android-icon-monochrome.png"
|
||||||
},
|
},
|
||||||
"edgeToEdgeEnabled": true,
|
"edgeToEdgeEnabled": true,
|
||||||
"predictiveBackGestureEnabled": false
|
"predictiveBackGestureEnabled": false,
|
||||||
|
"package": "app.papra.android"
|
||||||
},
|
},
|
||||||
"web": {
|
"web": {
|
||||||
"output": "static",
|
"output": "static",
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ export default function RootLayout() {
|
|||||||
<Stack.Screen name="auth/login" options={{ headerShown: false }} />
|
<Stack.Screen name="auth/login" options={{ headerShown: false }} />
|
||||||
<Stack.Screen name="auth/signup" options={{ headerShown: false }} />
|
<Stack.Screen name="auth/signup" options={{ headerShown: false }} />
|
||||||
<Stack.Screen name="(with-organizations)" 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>
|
</Stack>
|
||||||
<StatusBar style="auto" />
|
<StatusBar style="auto" />
|
||||||
</ApiProvider>
|
</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": {
|
"scripts": {
|
||||||
"dev": "pnpm start",
|
"dev": "pnpm start",
|
||||||
"start": "expo start",
|
"start": "expo start",
|
||||||
"android": "expo start --android",
|
"android": "expo run:android",
|
||||||
"ios": "expo start --ios",
|
"ios": "expo run:ios",
|
||||||
"web": "expo start --web",
|
"web": "expo start --web",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"lint:fix": "eslint . --fix",
|
"lint:fix": "eslint . --fix",
|
||||||
@@ -48,6 +48,7 @@
|
|||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0",
|
||||||
"react-native": "0.81.5",
|
"react-native": "0.81.5",
|
||||||
"react-native-gesture-handler": "~2.28.0",
|
"react-native-gesture-handler": "~2.28.0",
|
||||||
|
"react-native-pdf": "^7.0.3",
|
||||||
"react-native-reanimated": "~4.1.1",
|
"react-native-reanimated": "~4.1.1",
|
||||||
"react-native-safe-area-context": "~5.6.0",
|
"react-native-safe-area-context": "~5.6.0",
|
||||||
"react-native-screens": "~4.16.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 { Document } from '@/modules/documents/documents.types';
|
||||||
import type { ThemeColors } from '@/modules/ui/theme.constants';
|
import type { ThemeColors } from '@/modules/ui/theme.constants';
|
||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
|
import { router } from 'expo-router';
|
||||||
import * as Sharing from 'expo-sharing';
|
import * as Sharing from 'expo-sharing';
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
@@ -21,14 +22,12 @@ type DocumentActionSheetProps = {
|
|||||||
visible: boolean;
|
visible: boolean;
|
||||||
document: CoerceDates<Document> | undefined;
|
document: CoerceDates<Document> | undefined;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onView: () => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function DocumentActionSheet({
|
export function DocumentActionSheet({
|
||||||
visible,
|
visible,
|
||||||
document,
|
document,
|
||||||
onClose,
|
onClose,
|
||||||
onView,
|
|
||||||
}: DocumentActionSheetProps) {
|
}: DocumentActionSheetProps) {
|
||||||
const themeColors = useThemeColor();
|
const themeColors = useThemeColor();
|
||||||
const styles = createStyles({ themeColors });
|
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 handleDownloadAndShare = async () => {
|
||||||
const baseUrl = await configLocalStorage.getApiServerBaseUrl();
|
const baseUrl = await configLocalStorage.getApiServerBaseUrl();
|
||||||
|
|
||||||
@@ -166,9 +176,9 @@ export function DocumentActionSheet({
|
|||||||
{isViewable && (
|
{isViewable && (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.actionButton}
|
style={styles.actionButton}
|
||||||
onPress={() => {
|
onPress={async () => {
|
||||||
onClose();
|
onClose();
|
||||||
onView();
|
await handleView();
|
||||||
}}
|
}}
|
||||||
activeOpacity={0.7}
|
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({
|
export async function fetchDocumentFile({
|
||||||
document,
|
document,
|
||||||
organizationId,
|
organizationId,
|
||||||
|
|||||||
@@ -85,7 +85,6 @@ export function DocumentsListScreen() {
|
|||||||
visible={true}
|
visible={true}
|
||||||
document={onDocumentActionSheet}
|
document={onDocumentActionSheet}
|
||||||
onClose={() => setOnDocumentActionSheet(undefined)}
|
onClose={() => setOnDocumentActionSheet(undefined)}
|
||||||
onView={() => {}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<View style={styles.header}>
|
<View style={styles.header}>
|
||||||
|
|||||||
84
pnpm-lock.yaml
generated
84
pnpm-lock.yaml
generated
@@ -225,6 +225,9 @@ importers:
|
|||||||
react-native-gesture-handler:
|
react-native-gesture-handler:
|
||||||
specifier: ~2.28.0
|
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)
|
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:
|
react-native-reanimated:
|
||||||
specifier: ~4.1.1
|
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)
|
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==}
|
resolution: {integrity: sha512-fB7M1CMOCIUudTRuj7kzxIBTVw2KXnsgbQ6+4cbqSxo8NmRRhA0Ul4ZUzZj3rFd3VznTL4Brmocv1oiN0bWZ8w==}
|
||||||
engines: {node: '>= 20.19.4'}
|
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':
|
'@react-native/normalize-colors@0.74.89':
|
||||||
resolution: {integrity: sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==}
|
resolution: {integrity: sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==}
|
||||||
|
|
||||||
@@ -5874,6 +5880,9 @@ packages:
|
|||||||
bare-events:
|
bare-events:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
base-64@0.1.0:
|
||||||
|
resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==}
|
||||||
|
|
||||||
base-64@1.0.0:
|
base-64@1.0.0:
|
||||||
resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==}
|
resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==}
|
||||||
|
|
||||||
@@ -6403,6 +6412,9 @@ packages:
|
|||||||
crypt@0.0.2:
|
crypt@0.0.2:
|
||||||
resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
|
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:
|
crypto-random-string@2.0.0:
|
||||||
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
|
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -6560,6 +6572,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
deprecated-react-native-prop-types@2.3.0:
|
||||||
|
resolution: {integrity: sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA==}
|
||||||
|
|
||||||
dequal@2.0.3:
|
dequal@2.0.3:
|
||||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -7824,9 +7839,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
|
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
get-tsconfig@4.10.0:
|
|
||||||
resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==}
|
|
||||||
|
|
||||||
get-tsconfig@4.10.1:
|
get-tsconfig@4.10.1:
|
||||||
resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
|
resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
|
||||||
|
|
||||||
@@ -10091,6 +10103,12 @@ packages:
|
|||||||
react-is@19.2.0:
|
react-is@19.2.0:
|
||||||
resolution: {integrity: sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==}
|
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:
|
react-native-gesture-handler@2.28.0:
|
||||||
resolution: {integrity: sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==}
|
resolution: {integrity: sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -10103,6 +10121,13 @@ packages:
|
|||||||
react: '*'
|
react: '*'
|
||||||
react-native: '*'
|
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:
|
react-native-reanimated@4.1.5:
|
||||||
resolution: {integrity: sha512-UA6VUbxwhRjEw2gSNrvhkusUq3upfD3Cv+AnB07V+kC8kpvwRVI+ivwY95ePbWNFkFpP+Y2Sdw1WHpHWEV+P2Q==}
|
resolution: {integrity: sha512-UA6VUbxwhRjEw2gSNrvhkusUq3upfD3Cv+AnB07V+kC8kpvwRVI+ivwY95ePbWNFkFpP+Y2Sdw1WHpHWEV+P2Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -11264,11 +11289,6 @@ packages:
|
|||||||
tslib@2.8.1:
|
tslib@2.8.1:
|
||||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
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:
|
tsx@4.20.6:
|
||||||
resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==}
|
resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -14046,7 +14066,7 @@ snapshots:
|
|||||||
'@esbuild-kit/esm-loader@2.6.5':
|
'@esbuild-kit/esm-loader@2.6.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@esbuild-kit/core-utils': 3.3.2
|
'@esbuild-kit/core-utils': 3.3.2
|
||||||
get-tsconfig: 4.10.0
|
get-tsconfig: 4.10.1
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.19.12':
|
'@esbuild/aix-ppc64@0.19.12':
|
||||||
optional: true
|
optional: true
|
||||||
@@ -16421,6 +16441,8 @@ snapshots:
|
|||||||
|
|
||||||
'@react-native/js-polyfills@0.81.5': {}
|
'@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.74.89': {}
|
||||||
|
|
||||||
'@react-native/normalize-colors@0.76.2': {}
|
'@react-native/normalize-colors@0.76.2': {}
|
||||||
@@ -18705,6 +18727,8 @@ snapshots:
|
|||||||
bare-events: 2.5.4
|
bare-events: 2.5.4
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
base-64@0.1.0: {}
|
||||||
|
|
||||||
base-64@1.0.0: {}
|
base-64@1.0.0: {}
|
||||||
|
|
||||||
base64-js@1.5.1: {}
|
base64-js@1.5.1: {}
|
||||||
@@ -19274,6 +19298,8 @@ snapshots:
|
|||||||
|
|
||||||
crypt@0.0.2: {}
|
crypt@0.0.2: {}
|
||||||
|
|
||||||
|
crypto-js@4.2.0: {}
|
||||||
|
|
||||||
crypto-random-string@2.0.0: {}
|
crypto-random-string@2.0.0: {}
|
||||||
|
|
||||||
css-in-js-utils@3.1.0:
|
css-in-js-utils@3.1.0:
|
||||||
@@ -19406,6 +19432,12 @@ snapshots:
|
|||||||
|
|
||||||
depd@2.0.0: {}
|
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: {}
|
dequal@2.0.3: {}
|
||||||
|
|
||||||
destr@2.0.5: {}
|
destr@2.0.5: {}
|
||||||
@@ -21054,10 +21086,6 @@ snapshots:
|
|||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
get-intrinsic: 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:
|
get-tsconfig@4.10.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
resolve-pkg-maps: 1.0.0
|
resolve-pkg-maps: 1.0.0
|
||||||
@@ -21545,7 +21573,7 @@ snapshots:
|
|||||||
jiti: 2.0.0-beta.3
|
jiti: 2.0.0-beta.3
|
||||||
jiti-v1: jiti@1.21.7
|
jiti-v1: jiti@1.21.7
|
||||||
pathe: 1.1.2
|
pathe: 1.1.2
|
||||||
tsx: 4.20.3
|
tsx: 4.20.6
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -22724,7 +22752,7 @@ snapshots:
|
|||||||
metro-transform-plugins@0.83.3:
|
metro-transform-plugins@0.83.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.4
|
'@babel/core': 7.28.4
|
||||||
'@babel/generator': 7.28.3
|
'@babel/generator': 7.28.5
|
||||||
'@babel/template': 7.27.2
|
'@babel/template': 7.27.2
|
||||||
'@babel/traverse': 7.28.4
|
'@babel/traverse': 7.28.4
|
||||||
flow-enums-runtime: 0.0.6
|
flow-enums-runtime: 0.0.6
|
||||||
@@ -22755,7 +22783,7 @@ snapshots:
|
|||||||
metro-transform-worker@0.83.3:
|
metro-transform-worker@0.83.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.4
|
'@babel/core': 7.28.4
|
||||||
'@babel/generator': 7.28.3
|
'@babel/generator': 7.28.5
|
||||||
'@babel/parser': 7.28.5
|
'@babel/parser': 7.28.5
|
||||||
'@babel/types': 7.28.5
|
'@babel/types': 7.28.5
|
||||||
flow-enums-runtime: 0.0.6
|
flow-enums-runtime: 0.0.6
|
||||||
@@ -24019,6 +24047,13 @@ snapshots:
|
|||||||
|
|
||||||
react-is@19.2.0: {}
|
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):
|
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:
|
dependencies:
|
||||||
'@egjs/hammerjs': 2.0.17
|
'@egjs/hammerjs': 2.0.17
|
||||||
@@ -24032,6 +24067,14 @@ snapshots:
|
|||||||
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-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):
|
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:
|
dependencies:
|
||||||
'@babel/core': 7.28.4
|
'@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):
|
rolldown-plugin-dts@0.15.6(rolldown@1.0.0-beta.31)(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/generator': 7.28.3
|
'@babel/generator': 7.28.5
|
||||||
'@babel/parser': 7.28.5
|
'@babel/parser': 7.28.5
|
||||||
'@babel/types': 7.28.5
|
'@babel/types': 7.28.5
|
||||||
ast-kit: 2.1.1
|
ast-kit: 2.1.1
|
||||||
@@ -25563,13 +25606,6 @@ snapshots:
|
|||||||
|
|
||||||
tslib@2.8.1: {}
|
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:
|
tsx@4.20.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.10
|
esbuild: 0.25.10
|
||||||
|
|||||||
Reference in New Issue
Block a user