orgzly-revived / orgzly-android-revived

Outliner for taking notes and managing to-do lists
https://www.orgzlyrevived.com
GNU General Public License v3.0
669 stars 42 forks source link

Support subfolders for Sync locations #312

Closed amberin closed 2 months ago

amberin commented 2 months ago

This resolves #175, which was originally https://github.com/orgzly/orgzly-android/issues/225 (the most "liked" issue). See especially this comment for background: https://github.com/orgzly-revived/orgzly-android-revived/issues/175#issuecomment-2128058037

amberin commented 2 months ago

Would especially love to get some feedback from @NatKarmios on the change to ExternalAccessReceiver (f91b4074954dcf70844e4d00060aac682c10a3d5). I don't use that myself, so I don't know how to test it.

credmp commented 2 months ago

Great work! If there is some way to contribute to testing this feature, please let me know, will happily do some bughunting on the functionality.

amberin commented 2 months ago

Great work! If there is some way to contribute to testing this feature, please let me know, will happily do some bughunting on the functionality.

@credmp Yes, if you could try out the latest beta build, that would be highly valuable!

credmp commented 2 months ago

I installed the beta (v1.8.27-beta.2), created a webdav share with subfolders and top level files. All files are synced correctly and the overview shows from which subfolder they come, this is great.

I performed various editing operations, both client and server side, introduced conflicts etc. The functionality holds well, no issues found so far. Interestingly if I refresh a note from within the note (open note, pull down) it will retrieve the server version, but it will not update the server version. Update only happens in the notes list view.

New files go to the top level directory.

Things that might be improved:

I think the above should be actual tickets for future work, but perhaps you already have some sort of roadmap, if not I will happily create the tickets.

Great work!

sethidden commented 2 months ago

@amberin I'm using v1.8.27-beta.2 with external storage provider (DavX5 webdav mount hosted on mailbox.org): https://github.com/orgzly-revived/orgzly-android-revived/discussions/304

When trying to sync, I'm getting the following error notification:

Sync failed Unsupported book file name content://at.bitfire.davdroid.webdav/tree/36/document/38

content://at.bitfire.davdroid.webdav/tree/36 is the folder that I have mounted through Davx5, I don't know what document/38 is. Is there any way I can open a content URI directly from termux to see what document/38 is?

The file structure of the tree/36 folder is:

- Documents
  - Templates (empty folder)
- Music (empty folder)
- Pictures (empty folder)
- Videos (empty folder)
- myorgfile.org
- myorgfile1.org
- ... 21 more .org files (in root of folder)

Ofc using external content providers isn't exactly officially supported, but just putting it out here

amberin commented 2 months ago

@credmp Thank you for testing!

Interestingly if I refresh a note from within the note (open note, pull down) it will retrieve the server version, but it will not update the server version. Update only happens in the notes list view.

Could you please double check and help me reproduce, because this sounds very curious. There is only one sync workflow, no matter where you trigger it from (which bothers me, since I'd love to be able to sync a single notebook).

  • Allow sorting on the directory name first before the note names, now it is sorted on the title
  • In the left slide out pane, show a tree of the directory structure, allow folding
  • In the overview, allow folding on directory level

Yes, this seems to be what @nevenz had in mind when discussing subfolders in previous issues. I'm afraid it's out of my reach, since it would require quite some database and UI changes. I saw this as low-hanging fruit to achieve some rudimentary support, although it's quite an ugly hack. The only thing Orgzly is now aware of is that notebook names or file paths may contain a "/", but there is no other contract between repos and the rest of the app. So endowing the app with a proper "directory" concept is quite some more work. (This is why you can't e.g. sort on directory, because there is only a notebook name with a slash in it.)

It would be great if you'd file tickets about these things.

Thanks again for testing and reporting any findings.

sethidden commented 2 months ago

I just checked again and it turns out that content://at.bitfire.davdroid.webdav/tree/36/document/38 appears as a .org file in the root of the dav folder mount from davx5

I checked by connecting phone to computer and running adb shell, then `am start -p me.zhanghai.android.files -d content://at.bitfire.davdroid.webdav/tree/36/document/38 - I can't see the text content of the .org file in Material files once I open it, so perhaps it's some meta-file? 🤔

EDIT: Response to below @amberin yes the webdav worked fine for me on 1.26.x

amberin commented 2 months ago

Ofc using external content providers isn't exactly officially supported, but just putting it out here

@sethidden Interesting! Did this webdav mount work for you before this version?

There could be some assumptions about what content:// URLs usually look like which are causing trouble. It's very bad practice to draw conclusions from those URLs, as every ContentProvider works differently, but it seemed like a working primitive solution within my reach to cram regular directories into our SyncRepo interface.

If this type of setup worked for you before, this is of course very unwelcome and must be reconsidered.

sethidden commented 2 months ago

Some further attempts to access the mysterious content:// uri over adb (without Orgzly Revived in the picture):

$ adb shell content query --uri content://at.bitfire.davdroid.webdav/tree/36/document/38         
Error while accessing provider:at.bitfire.davdroid.webdav
java.lang.SecurityException: Permission Denial: opening provider at.bitfire.davdroid.webdav.DavDocumentsProvider from (null) (pid=22820, uid=2000) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
    at android.os.Parcel.createExceptionOrNull(Parcel.java:3183)
    at android.os.Parcel.createException(Parcel.java:3167)
    at android.os.Parcel.readException(Parcel.java:3150)
    at android.os.Parcel.readException(Parcel.java:3092)
    at android.app.IActivityManager$Stub$Proxy.getContentProviderExternal(IActivityManager.java:7921)
    at com.android.commands.content.Content$Command.execute(Content.java:516)
    at com.android.commands.content.Content.main(Content.java:735)
    at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
    at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:369)
Caused by: android.os.RemoteException: Remote stack trace:
    at com.android.server.am.ContentProviderHelper.checkAssociationAndPermissionLocked(ContentProviderHelper.java:709)
    at com.android.server.am.ContentProviderHelper.getContentProviderImpl(ContentProviderHelper.java:307)
    at com.android.server.am.ContentProviderHelper.getContentProviderExternalUnchecked(ContentProviderHelper.java:167)
    at com.android.server.am.ContentProviderHelper.getContentProviderExternal(ContentProviderHelper.java:161)
    at com.android.server.am.ActivityManagerService.getContentProviderExternal(ActivityManagerService.java:6989)
credmp commented 2 months ago

Interestingly if I refresh a note from within the note (open note, pull down) it will retrieve the server version, but it will not update the server version. Update only happens in the notes list view.

Could you please double check and help me reproduce, because this sounds very curious. There is only one sync workflow, no matter where you trigger it from (which bothers me, since I'd love to be able to sync a single notebook).

Double checked, it seems to rather be an issue with my WebDav host, the sync occured but during my testing the webdav host did not trigger sync to my desktop host. On the server it was updated.

So, false alarm, it works correctly!

amberin commented 2 months ago

Some further attempts to access the mysterious content:// uri over adb (without Orgzly Revived in the picture):

@sethidden Thanks. Yes, this makes sense, because only an app which has requested permission via the file picker is allowed to access that URL. Which of course is really frustrating when trying to debug and test these things.

sethidden commented 2 months ago

@amberin Ah sorry, I assumed the permission error was the culprit. I thought about it and remembered I can start adb in root mode:

$ adb shell content query --uri content://at.bitfire.davdroid.webdav/tree/36/document/38      
Row: 0 document_id=38, _display_name=chores.org, mime_type=application/vnd.lotus-organizer, flags=454, _size=1385, last_modified=1719560201000, icon=NULL, summary=chores.org

So just to fully confirm (as I mentioned it in previous comment as well) - it's just a regular chores.org file in the DAV folder root.

amberin commented 2 months ago

Let's continue exploring this in #304.