From 107bfadb3517e465110a77583fa1c597b787a7fa Mon Sep 17 00:00:00 2001 From: Eugen Stan Date: Sat, 14 Jan 2023 11:31:52 +0200 Subject: [PATCH] [#932] Fixed file loading bug + cleanup --- android/app/src/main/AndroidManifest.xml | 2 - .../twohundredok/organice/OrganiceSync.java | 92 ++++++++++--------- src/App.js | 4 +- src/actions/sync_backend.js | 4 +- src/components/SyncServiceSignIn/index.js | 73 ++++++++------- src/organice_android_sync/index.js | 2 +- .../android_sync_backend_client.js | 71 ++++++-------- 7 files changed, 119 insertions(+), 129 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 4c4ea060..4d143bf0 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -45,6 +45,4 @@ - - diff --git a/android/app/src/main/java/com/twohundredok/organice/OrganiceSync.java b/android/app/src/main/java/com/twohundredok/organice/OrganiceSync.java index d5946912..435f9348 100644 --- a/android/app/src/main/java/com/twohundredok/organice/OrganiceSync.java +++ b/android/app/src/main/java/com/twohundredok/organice/OrganiceSync.java @@ -47,6 +47,48 @@ public static Uri pathToUri(Uri base, String path) { } } + public static JSObject asFileMetaData(DocumentFile d) { + if (d == null) { + throw new IllegalArgumentException("DocumentFile is null"); + } + if (!d.exists()) { + throw new IllegalStateException("DocumentFile does not exist:" + d); + } + LocalDateTime date = toLocalDateTime(d.lastModified()); + var o = new JSObject(); + o.put("id", d.getUri().toString()); + o.put("path", d.getUri().getEncodedPath()); + o.put("lastModified", date.format(DateTimeFormatter.ISO_DATE_TIME)); + o.put("length", d.length()); + o.put("name", d.getName()); + o.put("type", d.getType()); + o.put("isDirectory", d.isDirectory()); + o.put("isFile", d.isFile()); + return o; + } + + /** + * Read a document to a string. + * https://developer.android.com/training/data-storage/shared/documents-files#input_stream + * + * @param uri + * @return + * @throws IOException + */ + public static String readTextFromUri(ContentResolver resolver, Uri uri) throws IOException { + try (InputStream fis = resolver.openInputStream(uri); + BufferedReader reader = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8))) { + return reader.lines() + .collect(Collectors.joining("\n")); + } + } + + static LocalDateTime toLocalDateTime(long lastModified) { + Instant i = Instant.ofEpochMilli(lastModified); + LocalDateTime date = i.atZone(ZoneId.systemDefault()).toLocalDateTime(); + return date; + } + /** * API available in JS to open the org root directory. * @@ -97,7 +139,7 @@ public void pickDirectoryResult(PluginCall call, ActivityResult result) { // Check for the freshest data. getActivity().getContentResolver().takePersistableUriPermission(uri, takeFlags); - var d = DocumentFile.fromTreeUri(getContext(),uri); + var d = DocumentFile.fromTreeUri(getContext(), uri); ret.put("uri", uri); ret.put("path", d.getUri().getEncodedPath()); @@ -111,25 +153,6 @@ public void pickDirectoryResult(PluginCall call, ActivityResult result) { } } - public static JSObject asFileMetaData(DocumentFile d) { - if (d == null) { - throw new IllegalArgumentException("DocumentFile is null"); - } - if (!d.exists()) { - throw new IllegalStateException("DocumentFile does not exist:" + d); - } - var o = new JSObject(); - o.put("id", d.getUri().toString()); - o.put("path", d.getUri().getEncodedPath()); - o.put("lastModified", d.lastModified()); - o.put("length", d.length()); - o.put("name", d.getName()); - o.put("type", d.getType()); - o.put("isDirectory", d.isDirectory()); - o.put("isFile", d.isFile()); - return o; - } - /** * List files in a directory. * @@ -210,26 +233,6 @@ public void putFileContents(PluginCall call) { } } - /** - * Read a document to a string. - * https://developer.android.com/training/data-storage/shared/documents-files#input_stream - * - * @param uri - * @return - * @throws IOException - */ - public static String readTextFromUri(ContentResolver resolver, Uri uri) throws IOException { - StringBuilder stringBuilder = new StringBuilder(); - try (InputStream fis = resolver.openInputStream(uri); - BufferedReader reader = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8))) { - String line; - while ((line = reader.readLine()) != null) { - stringBuilder.append(line); - } - } - return stringBuilder.toString(); - } - /** * @param call */ @@ -243,8 +246,7 @@ public void getFileContentsAndMetadata(PluginCall call) { ContentResolver resolver = getContext().getContentResolver(); var contents = readTextFromUri(resolver, uri); var d = DocumentFile.fromSingleUri(getContext(), uri); - Instant i = Instant.ofEpochMilli(d.lastModified()); - LocalDateTime date = i.atZone(ZoneId.systemDefault()).toLocalDateTime(); + LocalDateTime date = toLocalDateTime(d.lastModified()); JSObject r = asFileMetaData(d); r.put("contents", contents); r.put("lastModifiedAt", date.format(DateTimeFormatter.ISO_DATE_TIME)); @@ -290,9 +292,9 @@ public void createFile(PluginCall call) { // 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 document = DocumentsContract.createDocument(resolver, uri, "application/octet-stream", uri.getLastPathSegment()); - var file = DocumentFile.fromSingleUri(getContext(),document); + var file = DocumentFile.fromSingleUri(getContext(), document); writeFile(resolver, file.getUri(), content); JSObject r = asFileMetaData(dir); call.resolve(r); @@ -310,7 +312,7 @@ public void createFile(PluginCall call) { private Uri removeLastPathSegment(Uri uri) { var segments = uri.getPathSegments(); - segments = segments.subList(0,segments.size()-1); + segments = segments.subList(0, segments.size() - 1); var u = uri.buildUpon(); segments.forEach(s -> u.appendPath(s)); return u.build(); diff --git a/src/App.js b/src/App.js index 35bee9a3..70516cc8 100644 --- a/src/App.js +++ b/src/App.js @@ -147,8 +147,8 @@ export function handleAuthenticatedSyncService(initialState) { break; case 'AndroidStorage': client = createAndroidSyncBackendClient( - getPersistedField("orgDirectory"), - getPersistedField("orgDirectoryPath") + getPersistedField('orgDirectory'), + getPersistedField('orgDirectoryPath') ); initialState.syncBackend = Map({ isAuthenticated: true, diff --git a/src/actions/sync_backend.js b/src/actions/sync_backend.js index 2eabe270..2ab6e0a4 100644 --- a/src/actions/sync_backend.js +++ b/src/actions/sync_backend.js @@ -26,8 +26,8 @@ export const signOut = () => (dispatch, getState) => { createGitlabOAuth().reset(); break; case 'AndroidStorage': - persistField('orgDirectory', null); - break; + persistField('orgDirectory', null); + break; default: } diff --git a/src/components/SyncServiceSignIn/index.js b/src/components/SyncServiceSignIn/index.js index 3707153b..3e4e94bb 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'; @@ -11,9 +12,7 @@ import { gitLabProjectIdFromURL, } from '../../sync_backend_clients/gitlab_sync_backend_client'; -import { - pickDirectory, -} from '../../sync_backend_clients/android_sync_backend_client'; +import { pickDirectory } from '../../sync_backend_clients/android_sync_backend_client'; import { Dropbox } from 'dropbox'; import _ from 'lodash'; @@ -153,6 +152,8 @@ function GitLab() { ); } +const isNative = Capacitor.isNativePlatform(); + function AndroidStorage() { const [isVisible, setIsVisible] = useState(false); const toggleVisible = () => setIsVisible(!isVisible); @@ -171,7 +172,7 @@ function AndroidStorage() { {isVisible && ( <> -
+

-
+ id="org-pick-directory" + name="orgDir" + onClick={(event) => { + event.preventDefault(); + pickDirectory().then((result) => { + const { uri, path } = result; + setOrgDirectory(uri); + setOrgDirectoryPath(path); + }); + }} + > + Choose org dir + +
{ event.preventDefault(); persistField('authenticatedSyncService', 'AndroidStorage'); persistField('orgDirectory', orgDirectory); persistField('orgDirectoryPath', orgDirectoryPath); - alert("Location:" + orgDirectoryPath); - window.location = window.location.origin + "/"; + window.location = window.location.origin + '/'; }} > @@ -239,24 +242,28 @@ export default class SyncServiceSignIn extends PureComponent { organice syncs your files with Dropbox, GitLab, and WebDAV.

Click to sign in with:

+ {!isNative && ( + <> +
+ + Dropbox logo + +
-
- - Dropbox logo - -
- -
- -
- -
- -
+
+ +
-
- -
+
+ +
+ + )} + {isNative && ( +
+ +
+ )}