feat: Enhance document management with a first draft of upload and download functionalities (needs revision)
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import { Download, FileText, MapPin, Plus, Search, CalendarIcon } from 'lucide-react-native';
|
||||
import { ArrowLeft, Download, FileText, MapPin, Plus, Search, CalendarIcon } from 'lucide-react-native';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useRouter } from 'expo-router';
|
||||
import { RangePickerModal } from '@/components/RangePickerModal';
|
||||
import { Alert, RefreshControl, ScrollView, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
||||
import { DocumentItem } from '@/types/types';
|
||||
@ -8,8 +9,10 @@ import dayjs from 'dayjs';
|
||||
import LoadingScreen from '@/components/LoadingScreen';
|
||||
import { formatTimestamp, parseTimestamp } from '@/utils/dateTime';
|
||||
import AddDocumentModal from '@/components/AddDocumentModal';
|
||||
import { downloadAndShareDocument, downloadDocumentByUrl, downloadDocumentLegacy, uploadDocument } from '@/utils/documentUtils';
|
||||
|
||||
export default function DocumentsScreen() {
|
||||
const router = useRouter();
|
||||
const [documents, setDocuments] = useState<DocumentItem[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
@ -77,25 +80,9 @@ export default function DocumentsScreen() {
|
||||
|
||||
// Gestione Caricamento Documento
|
||||
const handleUploadDocument = async (file: any, customTitle?: string) => {
|
||||
console.log('Caricamento documento:', file, 'con titolo personalizzato:', customTitle);
|
||||
setIsUploading(true);
|
||||
try {
|
||||
// const formData = new FormData();
|
||||
// formData.append('file', {
|
||||
// uri: file.uri,
|
||||
// name: file.name,
|
||||
// type: file.mimeType || 'application/octet-stream',
|
||||
// } as any);
|
||||
// if (customTitle) {
|
||||
// formData.append('title', customTitle);
|
||||
// }
|
||||
|
||||
// const response = await api.post('/attachment/upload', formData, {
|
||||
// headers: {
|
||||
// 'Content-Type': 'multipart/form-data',
|
||||
// },
|
||||
// });
|
||||
|
||||
const response = await uploadDocument(file, null, customTitle);
|
||||
// console.log('Risposta caricamento:', response.data);
|
||||
// Alert.alert('Successo', 'Documento caricato con successo!');
|
||||
// setShowUploadModal(false);
|
||||
@ -108,6 +95,16 @@ export default function DocumentsScreen() {
|
||||
}
|
||||
}
|
||||
|
||||
// Gestione Download e Condivisione Documento
|
||||
const handleDownloadAndShare = async (mimetype: string, fileName: string, fileUrl: string) => {
|
||||
try {
|
||||
await downloadAndShareDocument(mimetype, fileName, fileUrl);
|
||||
} catch (error) {
|
||||
console.error('Errore nel download/condivisione del documento:', error);
|
||||
Alert.alert('Errore', 'Impossibile scaricare/condividere il documento. Riprova più tardi.');
|
||||
}
|
||||
};
|
||||
|
||||
if (isLoading && !refreshing) {
|
||||
return (
|
||||
<LoadingScreen />
|
||||
@ -117,11 +114,15 @@ export default function DocumentsScreen() {
|
||||
return (
|
||||
<View className="flex-1 bg-gray-50">
|
||||
{/* Header */}
|
||||
{/* TODO: Aggiungi torna indietro */}
|
||||
<View className="bg-white p-6 pt-16 shadow-sm border-b border-gray-100">
|
||||
<Text className="text-3xl font-bold text-gray-800 mb-1">Documenti</Text>
|
||||
<View className="flex-row items-center gap-4 bg-white p-6 pt-16 shadow-sm border-b border-gray-100">
|
||||
<TouchableOpacity onPress={() => router.back()} className="p-2 -ml-2 rounded-full active:bg-gray-100">
|
||||
<ArrowLeft size={24} color="#374151" />
|
||||
</TouchableOpacity>
|
||||
<View className="flex-1">
|
||||
<Text className="text-3xl font-bold text-gray-800">Documenti</Text>
|
||||
<Text className="text-base text-gray-500">Gestisci i tuoi documenti</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className="p-5 gap-6 flex-1">
|
||||
{/* Search + Date Row */}
|
||||
@ -179,7 +180,9 @@ export default function DocumentsScreen() {
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableOpacity className="p-4 bg-gray-50 rounded-2xl active:bg-gray-100">
|
||||
<TouchableOpacity
|
||||
onPress={() => downloadDocumentLegacy(doc.mimetype, doc.title, doc.url)} // downloadDocumentByUrl(doc.url, doc.title) handleDownloadAndShare(doc.mimetype, doc.title, doc.url)
|
||||
className="p-4 bg-gray-50 rounded-2xl active:bg-gray-100">
|
||||
<Download size={24} color="#6b7280" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
@ -8,6 +8,8 @@ import LoadingScreen from '@/components/LoadingScreen';
|
||||
import api from '@/utils/api';
|
||||
import dayjs from 'dayjs';
|
||||
import { formatTimestamp, parseTimestamp } from '@/utils/dateTime';
|
||||
import { downloadAndShareDocument, uploadDocument } from '@/utils/documentUtils';
|
||||
import AddDocumentModal from '@/components/AddDocumentModal';
|
||||
|
||||
export default function SiteDocumentsScreen() {
|
||||
const router = useRouter();
|
||||
@ -17,6 +19,9 @@ export default function SiteDocumentsScreen() {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
|
||||
const [showUploadModal, setShowUploadModal] = useState(false);
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
|
||||
// Fetch dei documenti del cantiere
|
||||
const fetchSiteDocuments = useCallback(async (siteId: number, isRefreshing = false) => {
|
||||
try {
|
||||
@ -88,6 +93,33 @@ export default function SiteDocumentsScreen() {
|
||||
return true;
|
||||
});
|
||||
|
||||
// Gestione Download e Condivisione Documento
|
||||
const handleDownloadAndShare = async (mimetype: string, fileName: string, fileUrl: string) => {
|
||||
try {
|
||||
await downloadAndShareDocument(mimetype, fileName, fileUrl);
|
||||
} catch (error) {
|
||||
console.error('Errore nel download/condivisione del documento:', error);
|
||||
Alert.alert('Errore', 'Impossibile scaricare il documento. Riprova più tardi.');
|
||||
}
|
||||
};
|
||||
|
||||
// Gestione Caricamento Documento
|
||||
const handleUploadDocument = async (file: any, customTitle?: string) => {
|
||||
setIsUploading(true);
|
||||
try {
|
||||
const response = await uploadDocument(file, Number(params.id), customTitle);
|
||||
// console.log('Risposta caricamento:', response.data);
|
||||
// Alert.alert('Successo', 'Documento caricato con successo!');
|
||||
// setShowUploadModal(false);
|
||||
// fetchSiteDocuments(Number(params.id)); // Ricarica la lista dei documenti
|
||||
} catch (error) {
|
||||
console.error('Errore nel caricamento del documento:', error);
|
||||
Alert.alert('Errore', 'Impossibile caricare il documento. Riprova più tardi.');
|
||||
} finally {
|
||||
setIsUploading(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!site || (isLoading && !refreshing)) {
|
||||
return (
|
||||
<LoadingScreen />
|
||||
@ -175,7 +207,9 @@ export default function SiteDocumentsScreen() {
|
||||
<Text className="text-sm text-gray-400 font-medium">{formatTimestamp(doc.updated_at)}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableOpacity className="p-4 bg-gray-50 rounded-2xl active:bg-gray-100">
|
||||
<TouchableOpacity
|
||||
onPress={() => handleDownloadAndShare(doc.mimetype, doc.title, doc.url)}
|
||||
className="p-4 bg-gray-50 rounded-2xl active:bg-gray-100">
|
||||
<Download size={24} color="#6b7280" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
@ -189,11 +223,19 @@ export default function SiteDocumentsScreen() {
|
||||
|
||||
{/* FAB (Spostato qui) */}
|
||||
<TouchableOpacity
|
||||
onPress={() => alert(`Aggiungi doc a ${site.name}`)}
|
||||
onPress={() => setShowUploadModal(true)}
|
||||
className="absolute bottom-8 right-6 w-16 h-16 bg-[#099499] rounded-full shadow-lg items-center justify-center active:scale-90"
|
||||
>
|
||||
<Plus size={32} color="white" />
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* Modale Caricamento Documento */}
|
||||
<AddDocumentModal
|
||||
visible={showUploadModal}
|
||||
onClose={() => setShowUploadModal(false)}
|
||||
onUpload={handleUploadDocument}
|
||||
isUploading={isUploading}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@ -22,6 +22,7 @@ export default function AddDocumentModal({ visible, onClose, onUpload, isUploadi
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
// TODO: Considerare selezione multipla?
|
||||
const pickDocument = async () => {
|
||||
try {
|
||||
const result = await DocumentPicker.getDocumentAsync({
|
||||
@ -34,7 +35,7 @@ export default function AddDocumentModal({ visible, onClose, onUpload, isUploadi
|
||||
const asset = result.assets[0];
|
||||
setSelectedFile(asset);
|
||||
|
||||
// Pre-compila il titolo con il nome del file (senza estensione se vuoi essere fancy, qui lo lascio intero)
|
||||
// Pre-compila il titolo con il nome del file
|
||||
setCustomTitle(asset.name);
|
||||
|
||||
} catch (err) {
|
||||
@ -54,6 +55,7 @@ export default function AddDocumentModal({ visible, onClose, onUpload, isUploadi
|
||||
};
|
||||
|
||||
// Formatta dimensione file
|
||||
// TODO: Spostare in utils?
|
||||
const formatSize = (size?: number) => {
|
||||
if (!size) return '0 B';
|
||||
const k = 1024;
|
||||
@ -102,10 +104,10 @@ export default function AddDocumentModal({ visible, onClose, onUpload, isUploadi
|
||||
<FileText size={24} color="#099499" />
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Text className="text-gray-800 font-bold text-sm" numberOfLines={1}>
|
||||
<Text className="text-gray-800 font-bold text-base" numberOfLines={1}>
|
||||
{selectedFile.name}
|
||||
</Text>
|
||||
<Text className="text-gray-500 text-xs">
|
||||
<Text className="text-gray-500 text-sm">
|
||||
{formatSize(selectedFile.size)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
72
package-lock.json
generated
72
package-lock.json
generated
@ -17,12 +17,14 @@
|
||||
"expo": "~54.0.25",
|
||||
"expo-constants": "~18.0.10",
|
||||
"expo-document-picker": "~14.0.8",
|
||||
"expo-file-system": "~19.0.21",
|
||||
"expo-font": "~14.0.9",
|
||||
"expo-haptics": "~15.0.7",
|
||||
"expo-image": "~3.0.10",
|
||||
"expo-linking": "~8.0.9",
|
||||
"expo-linking": "~8.0.11",
|
||||
"expo-router": "~6.0.15",
|
||||
"expo-secure-store": "~15.0.8",
|
||||
"expo-sharing": "~14.0.8",
|
||||
"expo-splash-screen": "~31.0.11",
|
||||
"expo-status-bar": "~3.0.8",
|
||||
"expo-symbols": "~1.0.7",
|
||||
@ -1756,15 +1758,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/config": {
|
||||
"version": "12.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@expo/config/-/config-12.0.11.tgz",
|
||||
"integrity": "sha512-bGKNCbHirwgFlcOJHXpsAStQvM0nU3cmiobK0o07UkTfcUxl9q9lOQQh2eoMGqpm6Vs1IcwBpYye6thC3Nri/w==",
|
||||
"version": "12.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@expo/config/-/config-12.0.13.tgz",
|
||||
"integrity": "sha512-Cu52arBa4vSaupIWsF0h7F/Cg//N374nYb7HAxV0I4KceKA7x2UXpYaHOL7EEYYvp7tZdThBjvGpVmr8ScIvaQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "~7.10.4",
|
||||
"@expo/config-plugins": "~54.0.3",
|
||||
"@expo/config-types": "^54.0.9",
|
||||
"@expo/json-file": "^10.0.7",
|
||||
"@expo/config-plugins": "~54.0.4",
|
||||
"@expo/config-types": "^54.0.10",
|
||||
"@expo/json-file": "^10.0.8",
|
||||
"deepmerge": "^4.3.1",
|
||||
"getenv": "^2.0.0",
|
||||
"glob": "^13.0.0",
|
||||
@ -1777,14 +1779,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/config-plugins": {
|
||||
"version": "54.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-54.0.3.tgz",
|
||||
"integrity": "sha512-tBIUZIxLQfCu5jmqTO+UOeeDUGIB0BbK6xTMkPRObAXRQeTLPPfokZRCo818d2owd+Bcmq1wBaDz0VY3g+glfw==",
|
||||
"version": "54.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-54.0.4.tgz",
|
||||
"integrity": "sha512-g2yXGICdoOw5i3LkQSDxl2Q5AlQCrG7oniu0pCPPO+UxGb7He4AFqSvPSy8HpRUj55io17hT62FTjYRD+d6j3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@expo/config-types": "^54.0.9",
|
||||
"@expo/json-file": "~10.0.7",
|
||||
"@expo/plist": "^0.4.7",
|
||||
"@expo/config-types": "^54.0.10",
|
||||
"@expo/json-file": "~10.0.8",
|
||||
"@expo/plist": "^0.4.8",
|
||||
"@expo/sdk-runtime-versions": "^1.0.0",
|
||||
"chalk": "^4.1.2",
|
||||
"debug": "^4.3.5",
|
||||
@ -1811,9 +1813,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/config-types": {
|
||||
"version": "54.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-54.0.9.tgz",
|
||||
"integrity": "sha512-Llf4jwcrAnrxgE5WCdAOxtMf8FGwS4Sk0SSgI0NnIaSyCnmOCAm80GPFvsK778Oj19Ub4tSyzdqufPyeQPksWw==",
|
||||
"version": "54.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-54.0.10.tgz",
|
||||
"integrity": "sha512-/J16SC2an1LdtCZ67xhSkGXpALYUVUNyZws7v+PVsFZxClYehDSoKLqyRaGkpHlYrCc08bS0RF5E0JV6g50psA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@expo/config/node_modules/@babel/code-frame": {
|
||||
@ -6453,9 +6455,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/expo-file-system": {
|
||||
"version": "19.0.20",
|
||||
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-19.0.20.tgz",
|
||||
"integrity": "sha512-Jr/nNvJmUlptS3cHLKVBNyTyGMHNyxYBKRph1KRe0Nb3RzZza1gZLZXMG5Ky//sO2azTn+OaT0dv/lAyL0vJNA==",
|
||||
"version": "19.0.21",
|
||||
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-19.0.21.tgz",
|
||||
"integrity": "sha512-s3DlrDdiscBHtab/6W1osrjGL+C2bvoInPJD7sOwmxfJ5Woynv2oc+Fz1/xVXaE/V7HE/+xrHC/H45tu6lZzzg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"expo": "*",
|
||||
@ -6514,13 +6516,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/expo-linking": {
|
||||
"version": "8.0.10",
|
||||
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.10.tgz",
|
||||
"integrity": "sha512-0EKtn4Sk6OYmb/5ZqK8riO0k1Ic+wyT3xExbmDvUYhT7p/cKqlVUExMuOIAt3Cx3KUUU1WCgGmdd493W/D5XjA==",
|
||||
"version": "8.0.11",
|
||||
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.11.tgz",
|
||||
"integrity": "sha512-+VSaNL5om3kOp/SSKO5qe6cFgfSIWnnQDSbA7XLs3ECkYzXRquk5unxNS3pg7eK5kNUmQ4kgLI7MhTggAEUBLA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"expo-constants": "~18.0.11",
|
||||
"expo-constants": "~18.0.12",
|
||||
"invariant": "^2.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@ -6528,6 +6529,20 @@
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-linking/node_modules/expo-constants": {
|
||||
"version": "18.0.13",
|
||||
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.13.tgz",
|
||||
"integrity": "sha512-FnZn12E1dRYKDHlAdIyNFhBurKTS3F9CrfrBDJI5m3D7U17KBHMQ6JEfYlSj7LG7t+Ulr+IKaj58L1k5gBwTcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@expo/config": "~12.0.13",
|
||||
"@expo/env": "~2.0.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"expo": "*",
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-modules-autolinking": {
|
||||
"version": "3.0.23",
|
||||
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-3.0.23.tgz",
|
||||
@ -6828,6 +6843,15 @@
|
||||
"node": ">=20.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-sharing": {
|
||||
"version": "14.0.8",
|
||||
"resolved": "https://registry.npmjs.org/expo-sharing/-/expo-sharing-14.0.8.tgz",
|
||||
"integrity": "sha512-A1pPr2iBrxypFDCWVAESk532HK+db7MFXbvO2sCV9ienaFXAk7lIBm6bkqgE6vzRd9O3RGdEGzYx80cYlc089Q==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-splash-screen": {
|
||||
"version": "31.0.12",
|
||||
"resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-31.0.12.tgz",
|
||||
|
||||
@ -20,12 +20,14 @@
|
||||
"expo": "~54.0.25",
|
||||
"expo-constants": "~18.0.10",
|
||||
"expo-document-picker": "~14.0.8",
|
||||
"expo-file-system": "~19.0.21",
|
||||
"expo-font": "~14.0.9",
|
||||
"expo-haptics": "~15.0.7",
|
||||
"expo-image": "~3.0.10",
|
||||
"expo-linking": "~8.0.9",
|
||||
"expo-linking": "~8.0.11",
|
||||
"expo-router": "~6.0.15",
|
||||
"expo-secure-store": "~15.0.8",
|
||||
"expo-sharing": "~14.0.8",
|
||||
"expo-splash-screen": "~31.0.11",
|
||||
"expo-status-bar": "~3.0.8",
|
||||
"expo-symbols": "~1.0.7",
|
||||
|
||||
@ -22,6 +22,7 @@ export interface AttendanceRecord {
|
||||
|
||||
export interface DocumentItem {
|
||||
id: number;
|
||||
mimetype: string;
|
||||
title: string;
|
||||
url: string;
|
||||
updated_at: string;
|
||||
|
||||
149
utils/documentUtils.tsx
Normal file
149
utils/documentUtils.tsx
Normal file
@ -0,0 +1,149 @@
|
||||
import api from '@/utils/api';
|
||||
import { Directory, File, Paths } from 'expo-file-system';
|
||||
import * as FileSystem from 'expo-file-system/legacy';
|
||||
import { StorageAccessFramework } from 'expo-file-system/legacy';
|
||||
import * as Sharing from 'expo-sharing';
|
||||
import * as Linking from 'expo-linking';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
/**
|
||||
* Gestisce l'upload di un documento verso il server usando Expo FileSystem
|
||||
* @param file File da caricare (deve avere almeno la proprietà 'uri')
|
||||
* @param siteId ID del sito a cui associare il documento (null per registro generale)
|
||||
* @param customTitle Titolo personalizzato per il documento (opzionale)
|
||||
*/
|
||||
export const uploadDocument = async (
|
||||
file: any,
|
||||
siteId: number | null,
|
||||
customTitle?: string
|
||||
): Promise<void> => {
|
||||
if (!file || !file.uri) {
|
||||
throw new Error("File non valido per l'upload.");
|
||||
}
|
||||
|
||||
if (siteId === null) {
|
||||
console.log("Uploading document:", file, "to registry with title:", customTitle);
|
||||
} else {
|
||||
console.log("Uploading document:", file, "to site:", siteId, "with title:", customTitle);
|
||||
}
|
||||
|
||||
// TODO: Funzione di upload (manca lato backend)
|
||||
};
|
||||
|
||||
/**
|
||||
* Scarica un documento e offre di aprirlo/condividerlo (expo-sharing)
|
||||
* @param attachmentId ID o URL relativo del documento
|
||||
* @param fileName Nome con cui salvare il file
|
||||
* @param fileUrl URL completo del file da scaricare
|
||||
*/
|
||||
export const downloadAndShareDocument = async (
|
||||
mimetype: string,
|
||||
fileName: string,
|
||||
fileUrl: string
|
||||
): Promise<void> => {
|
||||
try {
|
||||
// TODO: Gestire meglio il download (attualmente si basa su expo-sharing)
|
||||
if (!fileUrl || !fileName) {
|
||||
throw new Error("Parametri mancanti per il download del documento.");
|
||||
}
|
||||
|
||||
const destination = new Directory(Paths.cache, 'documents');
|
||||
destination.exists ? destination.delete() : null;
|
||||
destination.create({ overwrite: true });
|
||||
|
||||
const tmpFile = await File.downloadFileAsync(fileUrl, destination);
|
||||
console.log("File temporaneo scaricato in:", tmpFile.uri);
|
||||
|
||||
const outFile = new File(destination, fileName);
|
||||
await tmpFile.move(outFile);
|
||||
console.log("File spostato in:", outFile.uri);
|
||||
console.log("File type:", mimetype);
|
||||
|
||||
if (await Sharing.isAvailableAsync()) {
|
||||
await Sharing.shareAsync(outFile.uri, {
|
||||
mimeType: mimetype,
|
||||
dialogTitle: `Scarica ${fileName}`,
|
||||
UTI: 'public.item'
|
||||
});
|
||||
} else {
|
||||
throw new Error("Condivisione non supportata su questo dispositivo.");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("Download Error:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Test con versione legacy di FileSystem e SAF
|
||||
export const downloadDocumentLegacy = async (
|
||||
mimetype: string,
|
||||
fileName: string,
|
||||
fileUrl: string
|
||||
): Promise<void> => {
|
||||
try {
|
||||
if (!fileUrl || !fileName) {
|
||||
throw new Error("Parametri mancanti per il download del documento.");
|
||||
}
|
||||
|
||||
const path = FileSystem.cacheDirectory + 'documents/';
|
||||
// Download del file nella directory selezionata
|
||||
const tmpFile = await FileSystem.downloadAsync(fileUrl, path + fileName);
|
||||
console.log("File temporaneo scaricato in:", tmpFile.uri);
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
const permission = await StorageAccessFramework.requestDirectoryPermissionsAsync();
|
||||
if (permission.granted) {
|
||||
// Gets SAF URI from response
|
||||
const safUri = permission.directoryUri;
|
||||
console.log("Selected Directory URI:", safUri);
|
||||
|
||||
const fileContent = await FileSystem.readAsStringAsync(tmpFile.uri, { encoding: FileSystem.EncodingType.Base64 });
|
||||
console.log("File letto in Base64, dimensione:", fileContent.length);
|
||||
|
||||
// Copia il file nella directory SAF selezionata
|
||||
const destUri = await StorageAccessFramework.createFileAsync(
|
||||
safUri,
|
||||
fileName,
|
||||
mimetype
|
||||
);
|
||||
console.log("Destinazione SAF URI:", destUri);
|
||||
|
||||
await FileSystem.writeAsStringAsync(destUri, fileContent, { encoding: FileSystem.EncodingType.Base64 });
|
||||
console.log("File riscritto in SAF.");
|
||||
}
|
||||
} else if (Platform.OS === 'ios') {
|
||||
if (await Sharing.isAvailableAsync()) {
|
||||
await Sharing.shareAsync(tmpFile.uri, {
|
||||
mimeType: mimetype,
|
||||
dialogTitle: `Scarica ${fileName}`,
|
||||
UTI: 'public.item'
|
||||
});
|
||||
} else {
|
||||
throw new Error("Condivisione non supportata su questo dispositivo.");
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("Download Error:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Test con Linking standard
|
||||
export const downloadDocumentByUrl = async (
|
||||
fileUrl: string,
|
||||
fileName: string
|
||||
): Promise<void> => {
|
||||
try {
|
||||
if (!fileUrl || !fileName) {
|
||||
throw new Error("Parametri mancanti per il download del documento.");
|
||||
}
|
||||
|
||||
Linking.openURL(fileUrl);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Download Error:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user