FIX: FIle picker was double closing modal

This commit is contained in:
Marcos Rodriguez Velez 2024-12-15 01:12:31 -04:00
parent 5e2e0b58c2
commit 9ce4188a72

View file

@ -1,7 +1,7 @@
import { Alert, Linking, Platform } from 'react-native'; import { Alert, Linking, Platform } from 'react-native';
import DocumentPicker from 'react-native-document-picker'; import DocumentPicker from 'react-native-document-picker';
import RNFS from 'react-native-fs'; import RNFS from 'react-native-fs';
import { launchImageLibrary } from 'react-native-image-picker'; import { launchImageLibrary, ImagePickerResponse } from 'react-native-image-picker';
import Share from 'react-native-share'; import Share from 'react-native-share';
import { request, PERMISSIONS } from 'react-native-permissions'; import { request, PERMISSIONS } from 'react-native-permissions';
import presentAlert from '../components/Alert'; import presentAlert from '../components/Alert';
@ -16,23 +16,23 @@ const _sanitizeFileName = (fileName: string) => {
}; };
const _shareOpen = async (filePath: string, showShareDialog: boolean = false) => { const _shareOpen = async (filePath: string, showShareDialog: boolean = false) => {
return await Share.open({ try {
url: 'file://' + filePath, await Share.open({
saveToFiles: isDesktop || !showShareDialog, url: 'file://' + filePath,
// @ts-ignore: Website claims this propertie exists, but TS cant find it. Send anyways. saveToFiles: isDesktop || !showShareDialog,
useInternalStorage: Platform.OS === 'android', // @ts-ignore: Website claims this propertie exists, but TS cant find it. Send anyways.
failOnCancel: false, useInternalStorage: Platform.OS === 'android',
}) failOnCancel: false,
.catch(error => {
console.log(error);
// If user cancels sharing, we dont want to show an error. for some reason we get 'CANCELLED' string as error
if (error.message !== 'CANCELLED') {
presentAlert({ message: error.message });
}
})
.finally(() => {
RNFS.unlink(filePath);
}); });
} catch (error: any) {
console.log(error);
// If user cancels sharing, we dont want to show an error. for some reason we get 'CANCELLED' string as error
if (error.message !== 'CANCELLED') {
presentAlert({ message: error.message });
}
} finally {
await RNFS.unlink(filePath);
}
}; };
/** /**
@ -42,16 +42,18 @@ const _shareOpen = async (filePath: string, showShareDialog: boolean = false) =>
export const writeFileAndExport = async function (fileName: string, contents: string, showShareDialog: boolean = true) { export const writeFileAndExport = async function (fileName: string, contents: string, showShareDialog: boolean = true) {
const sanitizedFileName = _sanitizeFileName(fileName); const sanitizedFileName = _sanitizeFileName(fileName);
if (Platform.OS === 'ios') { try {
const filePath = RNFS.TemporaryDirectoryPath + `/${sanitizedFileName}`; if (Platform.OS === 'ios') {
await RNFS.writeFile(filePath, contents); const filePath = `${RNFS.TemporaryDirectoryPath}/${sanitizedFileName}`;
await _shareOpen(filePath, showShareDialog); await RNFS.writeFile(filePath, contents);
} else if (Platform.OS === 'android') { await _shareOpen(filePath, showShareDialog);
const isAndroidVersion33OrAbove = Platform.Version >= 33; } else if (Platform.OS === 'android') {
const permissionType = isAndroidVersion33OrAbove ? PERMISSIONS.ANDROID.READ_MEDIA_IMAGES : PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE; const isAndroidVersion33OrAbove = Platform.Version >= 33;
request(permissionType).then(async result => { const permissionType = isAndroidVersion33OrAbove ? PERMISSIONS.ANDROID.READ_MEDIA_IMAGES : PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE;
const result = await request(permissionType);
if (result === 'granted') { if (result === 'granted') {
const filePath = RNFS.ExternalDirectoryPath + `/${sanitizedFileName}`; const filePath = `${RNFS.ExternalDirectoryPath}/${sanitizedFileName}`;
try { try {
await RNFS.writeFile(filePath, contents); await RNFS.writeFile(filePath, contents);
if (showShareDialog) { if (showShareDialog) {
@ -74,7 +76,9 @@ export const writeFileAndExport = async function (fileName: string, contents: st
{ text: loc._.cancel, onPress: () => {}, style: 'cancel' }, { text: loc._.cancel, onPress: () => {}, style: 'cancel' },
]); ]);
} }
}); }
} catch (error: any) {
presentAlert({ message: error.message });
} }
}; };
@ -115,36 +119,34 @@ const _readPsbtFileIntoBase64 = async function (uri: string): Promise<string> {
} }
}; };
export const showImagePickerAndReadImage = (): Promise<string | undefined> => { export const showImagePickerAndReadImage = async (): Promise<string | undefined> => {
return new Promise((resolve, reject) => try {
launchImageLibrary( const response: ImagePickerResponse = await launchImageLibrary({
{ mediaType: 'photo',
mediaType: 'photo', maxHeight: 800,
maxHeight: 800, maxWidth: 600,
maxWidth: 600, selectionLimit: 1,
selectionLimit: 1, });
},
response => { if (response.didCancel) {
if (!response.didCancel) { return undefined;
const asset = response.assets?.[0] ?? {}; } else if (response.errorCode) {
if (asset.uri) { throw new Error(response.errorMessage);
RNQRGenerator.detect({ } else if (response.assets?.[0]?.uri) {
uri: decodeURI(asset.uri.toString()), try {
}) const result = await RNQRGenerator.detect({ uri: decodeURI(response.assets[0].uri.toString()) });
.then(result => { return result?.values[0];
if (result) { } catch (error) {
resolve(result.values[0]); console.error(error);
} throw new Error(loc.send.qr_error_no_qrcode);
}) }
.catch(error => { }
console.error(error);
reject(new Error(loc.send.qr_error_no_qrcode)); return undefined;
}); } catch (error: any) {
} console.error(error);
} throw error;
}, }
),
);
}; };
export const showFilePickerAndReadFile = async function (): Promise<{ data: string | false; uri: string | false }> { export const showFilePickerAndReadFile = async function (): Promise<{ data: string | false; uri: string | false }> {
@ -165,45 +167,34 @@ export const showFilePickerAndReadFile = async function (): Promise<{ data: stri
}); });
if (!res.fileCopyUri) { if (!res.fileCopyUri) {
// to make ts happy, should not need this check here
presentAlert({ message: 'Picking and caching a file failed' }); presentAlert({ message: 'Picking and caching a file failed' });
return { data: false, uri: false }; return { data: false, uri: false };
} }
const fileCopyUri = decodeURI(res.fileCopyUri); const fileCopyUri = decodeURI(res.fileCopyUri);
let file;
if (res.fileCopyUri.toLowerCase().endsWith('.psbt')) { if (res.fileCopyUri.toLowerCase().endsWith('.psbt')) {
// this is either binary file from ElectrumDesktop OR string file with base64 string in there // this is either binary file from ElectrumDesktop OR string file with base64 string in there
file = await _readPsbtFileIntoBase64(fileCopyUri); const file = await _readPsbtFileIntoBase64(fileCopyUri);
return { data: file, uri: decodeURI(res.fileCopyUri) }; return { data: file, uri: decodeURI(res.fileCopyUri) };
} }
if (res.type === DocumentPicker.types.images || res.type?.startsWith('image/')) { if (res.type === DocumentPicker.types.images || res.type?.startsWith('image/')) {
return new Promise(resolve => { try {
if (!res.fileCopyUri) {
// to make ts happy, should not need this check here
presentAlert({ message: 'Picking and caching a file failed' });
resolve({ data: false, uri: false });
return;
}
const uri2 = res.fileCopyUri.replace('file://', ''); const uri2 = res.fileCopyUri.replace('file://', '');
const result = await RNQRGenerator.detect({ uri: decodeURI(uri2) });
RNQRGenerator.detect({ if (result) {
uri: decodeURI(uri2), return { data: result.values[0], uri: fileCopyUri };
}) }
.then(result => { return { data: false, uri: false };
if (result) { } catch (error) {
resolve({ data: result.values[0], uri: fileCopyUri }); console.error(error);
} return { data: false, uri: false };
}) }
.catch(error => {
console.error(error);
resolve({ data: false, uri: false });
});
});
} }
file = await RNFS.readFile(fileCopyUri); const file = await RNFS.readFile(fileCopyUri);
return { data: file, uri: fileCopyUri }; return { data: file, uri: fileCopyUri };
} catch (err: any) { } catch (err: any) {
if (!DocumentPicker.isCancel(err)) { if (!DocumentPicker.isCancel(err)) {