diff --git a/android/app/build.gradle b/android/app/build.gradle
index 06689b63c..b43bcda91 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
android {
+
+ namespace 'com.twohundredok.organice'
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "com.twohundredok.organice"
@@ -21,6 +23,11 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ testOptions {
+ unitTests {
+ includeAndroidResources = true
+ }
+ }
}
repositories {
@@ -34,8 +41,11 @@ dependencies {
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
+ implementation 'androidx.documentfile:documentfile:1.0.1'
implementation project(':capacitor-android')
testImplementation "junit:junit:$junitVersion"
+ testImplementation 'org.robolectric:robolectric:4.9'
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
implementation project(':capacitor-cordova-android-plugins')
diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle
index 5f94affb4..ec71b6492 100644
--- a/android/app/capacitor.build.gradle
+++ b/android/app/capacitor.build.gradle
@@ -10,7 +10,6 @@ android {
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {
implementation project(':capacitor-app')
- implementation project(':send-intent')
}
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 8b95ab90e..4d143bf0c 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,6 +1,5 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+ * Will save permissions to the directory.
+ *
+ * @param call
+ * @param result
+ */
+ @SuppressLint("WrongConstant")
+ @ActivityCallback
+ public void pickDirectoryResult(PluginCall call, ActivityResult result) {
+ if (call == null) {
+ return;
+ }
+
+ Intent intent = result.getData();
+
+ if (intent != null) {
+ Uri uri = intent.getData();
+ JSObject ret = new JSObject();
+
+ // Persist permissions
+ // https://developer.android.com/training/data-storage/shared/documents-files#grant-access-directory
+ final int takeFlags = intent.getFlags()
+ & (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ // Check for the freshest data.
+ getActivity().getContentResolver().takePersistableUriPermission(uri, takeFlags);
+
+ var d = DocumentFile.fromTreeUri(getContext(), uri);
+
+ ret.put("uri", uri);
+ ret.put("path", d.getUri().getEncodedPath());
+ call.resolve(ret);
+ } else {
+ JSObject ret = new JSObject();
+ ret.put("intent", result.getData());
+ ret.put("resultCode", result.getResultCode());
+ ret.put("uri", null);
+ call.reject("Failed with intent code " + result.getResultCode(), ret);
+ }
+ }
+
+ /**
+ * List files in a directory.
+ *
+ * @param call Expect a "uri" string parameter.
+ */
+ @PluginMethod
+ public void listFiles(PluginCall call) {
+ String uriStr = call.getString("uri");
+ String path = call.getString("path");
+ if (uriStr != null && path != null) {
+ try {
+ final Uri base = Uri.parse(uriStr);
+ final Uri uri = pathToUri(base, path);
+ var d = DocumentFile.fromTreeUri(getContext(), uri);
+ if (d.exists() && d.isDirectory()) {
+ JSObject ret = new JSObject();
+ var files = d.listFiles();
+ // convert DocumentFile to a json object structure for use in organice
+ var listing = Arrays.stream(files)
+ .map(OrganiceSync::asFileMetaData)
+ .collect(Collectors.toList());
+ ret.put("files", new JSArray(listing));
+ call.resolve(ret);
+ } else {
+ JSObject ret = new JSObject();
+ ret.put("error", true);
+ ret.put("uri", base);
+ ret.put("errorMessage", "Usi is not a directory ");
+ call.reject("Usi is not a directory " + uri);
+ }
+ } catch (Exception e) {
+ JSObject o = new JSObject();
+ o.put("error", true);
+ o.put("uriStr", uriStr);
+// o.put("uri", uri.toString());
+ o.put("path", path);
+ o.put("errorMessage", e.getLocalizedMessage());
+ call.reject("Exception writing uri" + uriStr, o);
+ }
+ } else {
+ call.reject("Uri or path is null");
+ }
+ }
+
+ public void writeFile(ContentResolver resolver, Uri uri, String data) throws Exception {
+ try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "w");
+ FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor())) {
+ fileOutputStream.write(data.getBytes(StandardCharsets.UTF_8));
+ }
+ }
+
+ /**
+ * Update / write to a file.
+ * Perform a full file write.
+ *
+ * @param call Expect a "uri" string parameter.
+ */
+ @PluginMethod
+ public void putFileContents(PluginCall call) {
+ String uriStr = call.getString("uri");
+ String data = call.getString("contents");
+ String path = call.getString("path");
+ if (uriStr != null && path != null) {
+ Uri base = Uri.parse(uriStr);
+ Uri uri = pathToUri(base, path);
+ try {
+ ContentResolver resolver = getActivity().getContentResolver();
+ writeFile(resolver, uri, data);
+ } catch (Exception e) {
+ JSObject o = new JSObject();
+ o.put("error", true);
+ o.put("uri", uri);
+ o.put("errorMessage", e.getLocalizedMessage());
+ call.reject("Exception writing uri" + uri, o);
+ }
+ } else {
+ call.reject("Uri is null");
+ }
+ }
+
+ /**
+ * @param call
+ */
+ @PluginMethod
+ public void getFileContentsAndMetadata(PluginCall call) {
+ String uriStr = call.getString("uri");
+ String path = call.getString("path");
+ if (uriStr != null && path != null) {
+ var uri = Uri.parse(uriStr).buildUpon().encodedPath(path).build();
+ try {
+ ContentResolver resolver = getContext().getContentResolver();
+ var contents = readTextFromUri(resolver, uri);
+ var d = DocumentFile.fromSingleUri(getContext(), uri);
+ LocalDateTime date = toLocalDateTime(d.lastModified());
+ JSObject r = asFileMetaData(d);
+ r.put("contents", contents);
+ r.put("lastModifiedAt", date.format(DateTimeFormatter.ISO_DATE_TIME));
+ call.resolve(r);
+ } catch (Exception e) {
+ JSObject o = new JSObject();
+ o.put("error", true);
+ o.put("uriStr", uriStr);
+ o.put("uri", uri.toString());
+ o.put("path", path);
+ o.put("errorMessage", e.getLocalizedMessage());
+ call.reject("Exception writing uri" + uriStr, o);
+ }
+ } else {
+ JSObject o = new JSObject();
+ o.put("error", true);
+ o.put("message", "Uri or path is null");
+ call.reject("Uri or path is null", o);
+ }
+ }
+
+ /**
+ * https://developer.android.com/training/data-storage/shared/documents-files#create-file
+ *
+ * @param call
+ */
+ @PluginMethod
+ public void createFile(PluginCall call) {
+ String uriStr = call.getString("uri");
+ String path = call.getString("path");
+ String content = call.getString("content");
+ if (uriStr == null || path == null) {
+ JSObject o = new JSObject();
+ o.put("error", true);
+ o.put("message", "Uri or path is null");
+ call.reject("Uri or path is null", o);
+ }
+
+ var base = Uri.parse(uriStr);
+ var uri = pathToUri(base, path);
+ var fileParent = removeLastPathSegment(uri);
+ try {
+ // https://www.reddit.com/r/androiddev/comments/mz2j9s/comment/gw1uddt/?utm_source=share&utm_medium=web2x&context=3
+ var dir = DocumentFile.fromTreeUri(getContext(), fileParent);
+ ContentResolver resolver = getContext().getContentResolver();
+ Uri document = DocumentsContract.createDocument(resolver, uri, "application/octet-stream",
+ uri.getLastPathSegment());
+ var file = DocumentFile.fromSingleUri(getContext(), document);
+ writeFile(resolver, file.getUri(), content);
+ JSObject r = asFileMetaData(dir);
+ call.resolve(r);
+ } catch (Exception e) {
+ JSObject o = new JSObject();
+ o.put("error", true);
+ o.put("uriStr", uriStr);
+ o.put("uri", uri.toString());
+ o.put("path", path);
+ o.put("parentFile", fileParent);
+ o.put("errorMessage", e.getLocalizedMessage());
+ call.reject("Exception writing uri" + uriStr, o);
+ }
+ }
+
+ private Uri removeLastPathSegment(Uri uri) {
+ var segments = uri.getPathSegments();
+ segments = segments.subList(0, segments.size() - 1);
+ var u = uri.buildUpon();
+ segments.forEach(s -> u.appendPath(s));
+ return u.build();
+ }
+
+ /**
+ * @param call
+ */
+ @PluginMethod
+ public void deleteFile(PluginCall call) {
+ String uriStr = call.getString("uri");
+ String path = call.getString("path");
+ if (uriStr != null && path != null) {
+ Uri base = Uri.parse(uriStr);
+ Uri uri = pathToUri(base, path);
+ var f = DocumentFile.fromSingleUri(getContext(), uri);
+ var deleted = f.delete();
+ if (deleted) {
+ call.resolve();
+ } else {
+ call.reject("File was not deleted");
+ }
+ } else {
+ call.reject("Uri is null");
+ }
+ }
+
+}
diff --git a/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index c7bd21dbd..000000000
--- a/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/android/app/src/main/res/drawable/ic_launcher_background.xml b/android/app/src/main/res/drawable/ic_launcher_background.xml
index d5fccc538..e55387b67 100644
--- a/android/app/src/main/res/drawable/ic_launcher_background.xml
+++ b/android/app/src/main/res/drawable/ic_launcher_background.xml
@@ -2,169 +2,77 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
index 036d09bc5..c4a603d4c 100644
--- a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index 036d09bc5..c4a603d4c 100644
--- a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
index c023e5059..c7eb273a7 100644
Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
index 2127973b2..48557d23a 100644
Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
index b441f37d6..9dafa41b1 100644
Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
index 72905b854..f750f94c3 100644
Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
index 8ed0605c2..019356997 100644
Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
index 9502e47a2..e933b6271 100644
Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index 4d1e07710..9371d9885 100644
Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
index df0f15880..9519ef60f 100644
Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
index 853db043d..e1884070d 100644
Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 6cdf97c11..bec298f48 100644
Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
index 2960cbb61..17e272b9d 100644
Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
index 8e3093a86..3c3ae9c3a 100644
Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index 46de6e255..1f12870ef 100644
Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
index d2ea9abed..000ff8012 100644
Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
index a40d73e9c..dff68140f 100644
Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/android/app/src/test/java/com/twohundredok/organice/OrganiceSyncTest.java b/android/app/src/test/java/com/twohundredok/organice/OrganiceSyncTest.java
new file mode 100644
index 000000000..c383a65b4
--- /dev/null
+++ b/android/app/src/test/java/com/twohundredok/organice/OrganiceSyncTest.java
@@ -0,0 +1,38 @@
+package com.twohundredok.organice;
+
+import static org.junit.Assert.*;
+
+import android.net.Uri;
+
+import androidx.documentfile.provider.DocumentFile;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.io.File;
+
+@RunWith(RobolectricTestRunner.class)
+public class OrganiceSyncTest {
+
+
+ @Test
+ public void uriTest(){
+ var base = Uri.parse("content://com.android.externalstorage.documents/tree/1413-3A04%3Aorg");
+ var document = Uri.parse("content://com.android.externalstorage.documents/tree/1413-3A04%3Aorg/document/1413-3A04%3Aorg%2Fmanual.org");
+ var encodedPath = "/document/1413-3A04%3Aorg%2Fmanual.org";
+
+ var uri2 = base.buildUpon().appendPath("path").build();
+ var uri3 = uri2.buildUpon().appendPath("localPath").build();
+
+ var uri4 = OrganiceSync.pathToUri(base,"local3");
+
+
+ DocumentFile.fromFile(new File("local"));
+
+ System.out.println("" + base.getPath());
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/android/build.gradle b/android/build.gradle
index 637f81f06..5c1acd510 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.2.1'
+ classpath 'com.android.tools.build:gradle:7.3.1'
classpath 'com.google.gms:google-services:4.3.13'
// NOTE: Do not place your application dependencies here; they belong
diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle
index 7030d8533..2085c8639 100644
--- a/android/capacitor.settings.gradle
+++ b/android/capacitor.settings.gradle
@@ -4,6 +4,3 @@ project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/
include ':capacitor-app'
project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android')
-
-include ':send-intent'
-project(':send-intent').projectDir = new File('../node_modules/send-intent/android')
diff --git a/android/variables.gradle b/android/variables.gradle
index 2dbd75af6..14edf659a 100644
--- a/android/variables.gradle
+++ b/android/variables.gradle
@@ -1,5 +1,5 @@
ext {
- minSdkVersion = 22
+ minSdkVersion = 26
compileSdkVersion = 32
targetSdkVersion = 32
androidxActivityVersion = '1.4.0'
diff --git a/package.json b/package.json
index 1b1201dc5..6451f2dd3 100644
--- a/package.json
+++ b/package.json
@@ -8,9 +8,9 @@
"dependencies": {
"@babel/helper-environment-visitor": "^7.18.2",
"@bity/oauth2-auth-code-pkce": "^2.13.0",
- "@capacitor/android": "^4.0.0",
- "@capacitor/app": "^4.0.0",
- "@capacitor/core": "^4.0.0",
+ "@capacitor/android": "^4.6.1",
+ "@capacitor/app": "^4.1.1",
+ "@capacitor/core": "^4.6.1",
"aos": "^2.3.4",
"bowser": "^2.11.0",
"classnames": "^2.2.6",
@@ -34,7 +34,6 @@
"redux": "^4.1.0",
"redux-thunk": "^2.3.0",
"redux-undo": "1.0.1",
- "send-intent": "^3.0.11",
"webdav": "^3.3.0"
},
"scripts": {
diff --git a/src/App.js b/src/App.js
index 4bd5035bf..70516cc85 100644
--- a/src/App.js
+++ b/src/App.js
@@ -23,6 +23,7 @@ import { setDisappearingLoadingMessage, restoreStaticFile } from './actions/base
import createDropboxSyncBackendClient from './sync_backend_clients/dropbox_sync_backend_client';
import createWebDAVSyncBackendClient from './sync_backend_clients/webdav_sync_backend_client';
+import createAndroidSyncBackendClient from './sync_backend_clients/android_sync_backend_client';
import createGitLabSyncBackendClient, {
createGitlabOAuth,
} from './sync_backend_clients/gitlab_sync_backend_client';
@@ -44,28 +45,28 @@ import AppUrlListener from './AppUrlListener';
import { configure } from 'react-hotkeys';
-import { SendIntent } from 'send-intent';
+// import { SendIntent } from 'send-intent';
// do handle hotkeys even if they come from within 'input', 'select' or 'textarea'
configure({ ignoreTags: [] });
-SendIntent.checkSendIntentReceived()
- .then((result) => {
- if (result) {
- console.log('SendIntent received');
- console.log(JSON.stringify(result));
- }
- if (result.url) {
- let resultUrl = decodeURIComponent(result.url);
- console.log(resultUrl);
- // Filesystem.readFile({path: resultUrl})
- // .then((content) => {
- // console.log(content.data);
- // })
- // .catch((err) => console.error(err));
- }
- })
- .catch((err) => console.error(err));
+// SendIntent.checkSendIntentReceived()
+// .then((result) => {
+// if (result) {
+// console.log('SendIntent received');
+// console.log(JSON.stringify(result));
+// }
+// if (result.url) {
+// let resultUrl = decodeURIComponent(result.url);
+// console.log(resultUrl);
+// // Filesystem.readFile({path: resultUrl})
+// // .then((content) => {
+// // console.log(content.data);
+// // })
+// // .catch((err) => console.error(err));
+// }
+// })
+// .catch((err) => console.error(err));
const handleGitLabAuthResponse = async (oauthClient) => {
let success = false;
@@ -144,6 +145,16 @@ export function handleAuthenticatedSyncService(initialState) {
client,
});
break;
+ case 'AndroidStorage':
+ client = createAndroidSyncBackendClient(
+ getPersistedField('orgDirectory'),
+ getPersistedField('orgDirectoryPath')
+ );
+ initialState.syncBackend = Map({
+ isAuthenticated: true,
+ client,
+ });
+ break;
default:
}
}
diff --git a/src/actions/sync_backend.js b/src/actions/sync_backend.js
index aa69449fd..2ab6e0a4f 100644
--- a/src/actions/sync_backend.js
+++ b/src/actions/sync_backend.js
@@ -25,6 +25,9 @@ export const signOut = () => (dispatch, getState) => {
persistField('gitLabProject', null);
createGitlabOAuth().reset();
break;
+ case 'AndroidStorage':
+ persistField('orgDirectory', null);
+ break;
default:
}
diff --git a/src/components/FileBrowser/index.js b/src/components/FileBrowser/index.js
index a71635445..36dc2f8b8 100644
--- a/src/components/FileBrowser/index.js
+++ b/src/components/FileBrowser/index.js
@@ -31,6 +31,7 @@ const FileBrowser = ({
switch (syncBackendType) {
case 'Dropbox':
case 'GitLab':
+ case 'AndroidStorage':
case 'WebDAV':
const pathParts = path.split('/');
return pathParts.slice(0, pathParts.length - 1).join('/');
diff --git a/src/components/SyncServiceSignIn/index.js b/src/components/SyncServiceSignIn/index.js
index fa32a6520..3e4e94bb2 100644
--- a/src/components/SyncServiceSignIn/index.js
+++ b/src/components/SyncServiceSignIn/index.js
@@ -1,3 +1,4 @@
+import { Capacitor } from '@capacitor/core';
import React, { PureComponent, useState } from 'react';
import './stylesheet.css';
@@ -5,12 +6,14 @@ import './stylesheet.css';
import DropboxLogo from './dropbox.svg';
import GitLabLogo from './gitlab.svg';
-import { persistField } from '../../util/settings_persister';
+import { getPersistedField, persistField } from '../../util/settings_persister';
import {
createGitlabOAuth,
gitLabProjectIdFromURL,
} from '../../sync_backend_clients/gitlab_sync_backend_client';
+import { pickDirectory } from '../../sync_backend_clients/android_sync_backend_client';
+
import { Dropbox } from 'dropbox';
import _ from 'lodash';
@@ -149,6 +152,70 @@ function GitLab() {
);
}
+const isNative = Capacitor.isNativePlatform();
+
+function AndroidStorage() {
+ const [isVisible, setIsVisible] = useState(false);
+ const toggleVisible = () => setIsVisible(!isVisible);
+
+ const defaultOrgDirectory = getPersistedField('orgDirectory');
+ const defaultOrgDirectoryPath = getPersistedField('orgDirectoryPath');
+ const [orgDirectory, setOrgDirectory] = useState(defaultOrgDirectory);
+ const [orgDirectoryPath, setOrgDirectoryPath] = useState(defaultOrgDirectoryPath);
+
+ return (
+
+
+ {isVisible && (
+ <>
+
+
+
+
+
+
+
+
+ >
+ )}
+
+ );
+}
+
export default class SyncServiceSignIn extends PureComponent {
constructor(props) {
super(props);
@@ -175,20 +242,28 @@ export default class SyncServiceSignIn extends PureComponent {
organice syncs your files with Dropbox, GitLab, and WebDAV.
Click to sign in with:
+ {!isNative && (
+ <>
+
-
-
-
-
-
+
+
+
-
-
-
+
+
+
+ >
+ )}
+ {isNative && (
+
+ )}