diff --git a/packages/app-mobile/utils/fs-driver-rn.ts b/packages/app-mobile/utils/fs-driver-rn.ts index a3e46bdb3..8d409d26c 100644 --- a/packages/app-mobile/utils/fs-driver-rn.ts +++ b/packages/app-mobile/utils/fs-driver-rn.ts @@ -107,10 +107,8 @@ export default class FsDriverRN extends FsDriverBase { } public async move(source: string, dest: string) { - if (isScopedUri(source) && isScopedUri(dest)) { + if (isScopedUri(source) || isScopedUri(dest)) { await RNSAF.moveFile(source, dest, { replaceIfDestinationExists: true }); - } else if (isScopedUri(source) || isScopedUri(dest)) { - throw new Error('Move between different storage types not supported'); } return RNFS.moveFile(source, dest); } @@ -191,11 +189,9 @@ export default class FsDriverRN extends FsDriverBase { public async copy(source: string, dest: string) { let retry = false; try { - if (isScopedUri(source) && isScopedUri(dest)) { + if (isScopedUri(source) || isScopedUri(dest)) { await RNSAF.copyFile(source, dest, { replaceIfDestinationExists: true }); return; - } else if (isScopedUri(source) || isScopedUri(dest)) { - throw new Error('Move between different storage types not supported'); } await RNFS.copyFile(source, dest); } catch (error) { @@ -204,7 +200,13 @@ export default class FsDriverRN extends FsDriverBase { await this.unlink(dest); } - if (retry) await RNFS.copyFile(source, dest); + if (retry) { + if (isScopedUri(source) || isScopedUri(dest)) { + await RNSAF.copyFile(source, dest, { replaceIfDestinationExists: true }); + } else { + await RNFS.copyFile(source, dest); + } + } } public async unlink(path: string) { diff --git a/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/SafXModule.java b/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/SafXModule.java index 01674d3e3..5f8f61948 100644 --- a/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/SafXModule.java +++ b/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/SafXModule.java @@ -169,7 +169,10 @@ public class SafXModule extends ReactContextBaseJavaModule { try { DocumentFile doc = this.documentHelper.goToDocument(uriString, false, true); boolean result = doc.delete(); - promise.resolve(result); + if (!result) { + throw new Exception("Failed to unlink file. Unknown error."); + } + promise.resolve(true); } catch (FileNotFoundException e) { promise.reject("ENOENT", e.getLocalizedMessage()); } catch (SecurityException e) { diff --git a/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/utils/DocumentHelper.java b/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/utils/DocumentHelper.java index 827abea3d..23331d5cb 100644 --- a/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/utils/DocumentHelper.java +++ b/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/utils/DocumentHelper.java @@ -2,6 +2,7 @@ package com.reactnativesafx.utils; import android.annotation.SuppressLint; import android.app.Activity; +import android.content.ContentResolver; import android.content.Intent; import android.content.UriPermission; import android.net.Uri; @@ -18,6 +19,7 @@ import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; +import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -378,6 +380,9 @@ public class DocumentHelper { public DocumentFile goToDocument( String unknownUriString, boolean createIfDirectoryNotExist, boolean includeLastSegment) throws SecurityException, IOException { + if (unknownUriString.startsWith(ContentResolver.SCHEME_FILE)) { + return DocumentFile.fromFile(new File(Uri.parse(unknownUriString).getPath())); + } String uriString = UriHelper.normalize(unknownUriString); String baseUri = ""; String appendUri; @@ -454,7 +459,7 @@ public class DocumentHelper { public void transferFile( String srcUri, String destUri, boolean replaceIfDestExists, boolean copy, Promise promise) { try { - DocumentFile srcDoc = this.goToDocument(srcUri, false, true); + DocumentFile srcDoc = this.goToDocument(UriHelper.getUnifiedUri(srcUri), false, true); if (srcDoc.isDirectory()) { throw new IllegalArgumentException("Cannot move directories"); @@ -462,7 +467,7 @@ public class DocumentHelper { DocumentFile destDoc; try { - destDoc = this.goToDocument(destUri, false, true); + destDoc = this.goToDocument(UriHelper.getUnifiedUri(destUri), false, true); if (!replaceIfDestExists) { throw new IOException("a document with the same name already exists in destination"); } diff --git a/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/utils/UriHelper.java b/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/utils/UriHelper.java index 5fe21a034..cae2a4aac 100644 --- a/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/utils/UriHelper.java +++ b/packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/utils/UriHelper.java @@ -1,5 +1,6 @@ package com.reactnativesafx.utils; +import android.content.ContentResolver; import android.net.Uri; import android.os.Build.VERSION_CODES; import androidx.annotation.RequiresApi; @@ -33,4 +34,19 @@ public class UriHelper { return Uri.decode(normalize(uriString)); } + + public static String getUnifiedUri(String uriString) throws Exception { + Uri uri = Uri.parse(uriString); + if (uri.getScheme() == null) { + uri = Uri.parse(ContentResolver.SCHEME_FILE+"://"+uriString); + } else if (!(uri.getScheme().equals(ContentResolver.SCHEME_FILE) || uri.getScheme().equals(ContentResolver.SCHEME_CONTENT))) { + throw new Exception("Scheme not supported"); + } + + if (uri.getScheme() == null) { + throw new Exception("Invalid Uri: Cannot determine scheme"); + } + + return uri.toString(); + } }