Giter Club home page Giter Club logo

ark-navigator's Issues

"Open with" button in gallery mode

There should be "open with" button displayed on top of preview in GalleryFragment. Similar to "edit" and "delete" buttons.

The action to trigger by this button is opening the resource in an external app. E.g. video might be opened in video player or html file might be opened in web browser.

Persisted sorting preferences

Sorting preferences must be saved between runs. E.g. if a user chooses "sort by size, descending", this choice must be still enabled even after the user left the app, or the app crashed and restarted.

Full-Screen mode in GalleryFragment

In current state, when a user lists resources' previews in GalleryFragment, he can tap on a free space and this will hide controls.
It would be great to also switch picture into full-screen mode, hiding titlebar, bottom tabs switch and system topbar.

Fragments must be restorable

Right now, if a user leaves the app on, e.g. GalleryFragment, and switches to another app, and OS kills our app — after Android attempts to restore our app, it will crash. The reason is that Android can restore only fragments with empty constructors.

Fragments should be reworked to gain this capability, particularly GalleryFragment and ResourcesFragment.

"Share" button in gallery mode

There should be "share" button displayed on top of preview in GalleryFragment. Similar to "edit" and "delete" buttons.

The action to trigger by this button is sharing the resource via external app like messengers.

Huge images loading

When we load preview for an image, we should create hint for a user about size of it. Spinner animation also would not hurt. We should also verify later that even 100mb images load successfully.

Remember tags on/off state

The tag on/off state is not remembered when returning back after viewing media

As you see in the video, tags were turned ON before viewing media. When returning back to the view, the button shows as OFF again

tag_button_state.mp4

Resources grid details widget

Another improvement. It would be great if the user had the option to see the full path to the opened folder. There isn't enough space to display the full path on the header, so maybe we could show it somewhere in the white section? The header could just show the name of the current folder or something?

image

"Edit resource" button

In gallery screen, a resource must be capable of edition. The "edit tags" button should be moved into tags list so its place could be used by new "edit resource" button.

Previews for video files

Some random frame from the video would be enough.
It can be useful to overlay also duration of the video and quality.

Remember expanded and collapsed folders

This is more of an improvement than a bug.
It is a few extra steps each time to open the root folders again after pressing the compass button and returning back to the Manage Folders tab.

Ideally, the app remembers the expanded and collapsed folders and displays it when the user returns back to the view

collapsing_folders.mp4

Tags editing and bulk operations

It must be possible to edit tags, i.e. rename or delete them.

Renaming a tag from A to B walks through all resources labeled with A, removes A from them and sets B instead. Deletion of a tag X just removes it from all resources labeled with X.

Boosting priority of folders in indexing queue, basing on type and access frequency

When a user opens the app, she sees folders screen. Indexing of resources should start immediately in background. All "favorites" should be placed first in the queue, "roots" follow after. Every folder must have score which is incremented every time the user opens the folder. If types of 2 folders are the same, their scores are used to order them in the queue.

ResourcesFragment: "tags off" gets stucked

How to reproduce:

  1. open a folder
  2. click "tags off" button (picture of crossed-out cloud)
  3. undo by clicking "tags on"
  4. open any resource
  5. go back (using system navigation button)

Expected:

  • all resources in the folder displayed

Actual:

  • only resources without tags displayed (the same as after step 2)

Previews for PDF files

In gallery mode PDF files should be depicted by it's first page.
If possible, number of pages should be depicted on top of preview.

In resources grid PDF files should be depicted by special PDF icon.
If possible, number of pages should be overlayed on top the icon.

"Shuffle" button in resources grid

The button must shuffle current selection every time (it isn't "as-is" ordering).

Lazy shuffling could be implemented for usage with big collections: select random N resources, where N is amount of visible items in the grid; select next ones only when a user scrolls the grid or the gallery. Similar to #73.

Filesystem monitoring and reactive updates

Ideally, we should react to changes in filesystem.

E.g. if some path P maps to id A, after an external app modified P it needs to be updated to id B.
This change also must be propagated to the tags storage since id changed.

But there are some unclear moments like if an external app, in fact, moved original file untouched to another path S and put new content to the original path P. In this case, id A is still in our collection, it just was moved from P to S, so we shouldn't change tags storage regarding A but only bind A to new path S in the resources index and bind P to new resource B.

There might be other corner cases. This feature requires to be discussed before approaching.

Background indexing

It would be great, if a user could switch to other activities with the app while huge folders are being indexed.
E.g. trigger indexing of other folders or tag resources. It can happen that the user tags a resource, which is still not indexed.
Then we need to postpone modification of the storage, since we don't know the resource's id.
This means, beside of indexing queue we also need to create tagging queue.

Tags storage access in coroutine

D/item-container: item 8 clicked
D/gallery-screen: preview at 8 clicked, switching controls on/off
E/: [ZeroHung]zrhung_get_config: Get config failed for wp[0x0102]
D/gallery-screen: tag todo on resource 1771473116 long-clicked
D/gallery-screen: closing dialog in GalleryFragment
D/gallery-screen: displaying tags of resource 1771473116 for preview
D/gallery-screen: displaying tags resource 1771473116 for edit
D/OpenGLRenderer:   HWUI Binary is  enabled
E/: [ZeroHung]zrhung_get_config: Get config failed for wp[0x0102]
D/gallery-screen: tags [ark] added to 1771473116
D/mali_winsys: EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
D/OpenGLRenderer:   HWUI Binary is  enabled
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: space.taran.arknavigator, PID: 13324
    java.lang.AssertionError: Storage isn't aware about this resource id
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage$setTags$2.invokeSuspend(PlainTagsStorage.kt:62)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

Resource versions tracking

Related to #27

Every time a resource has changed, we can represent this change as a transition from id1 to id2. This transition we can store in replicated state (or send to another app instance, but it will complicate implementation and should be avoided if possible). Afterwards, it should ease conflicts resolution.

"Focus on tag" capability in tags selector

Right now, the following actions can be applied to a chip (tag) in tags selector:

  1. Tap for selecting the tag. Tap again for unselecting.
  2. Long-tap for negating the tag. This means that all resources marked with the tag, will be filtered out of current selection.

The desired feature is third possible action:
3. Double-tap for "focus on" the tag. After this, the tag becomes selected. Then, all tags from available set become negated. Previously selected or negated tags must not be affected.

Icons for various types of files

Right now, we only have predefined previews (icons) for "file" and "folder" types.
It is necessary to add icons for html, txt, doc and other types of files.

Faster id calculation

Right now, CRC-32 hash is used for resource identification.
Calculation of hash of some file's content can take the same time as reading the file from disk.

This should be improved. Maybe with native library.

Boosting priority of resources in indexing queue

Asynchronous indexing (#23) will allow a user to continue working while she has some resources in indexing queue. This means, that some of resources can have modified tags and unknown (yet) id. Such resources should gain priority of indexing.

Resources grid forgets sorting after tags changed in the selector

  1. Open a folder.
  2. [optionally] select some tags
  3. Choose sorting type. Now resources are sorted correctly.
  4. Select different tags so another resources are presented.

Expected: resources are sorted with ordering type specified before.
Actual: resources are not sorted. Sorting menu displays ordering type chosen before.

Access denied in SD card

How to reproduce:
add a tag to the resource on the SD card

It looks like this bug does not affect Android 11

Log:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: space.taran.arknavigator, PID: 8596
    java.nio.file.AccessDeniedException: /storage/1B0C-2304/DCIM/.ark-tags
        at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
        at java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:434)
        at java.nio.file.Files.newOutputStream(Files.java:216)
        at java.nio.file.Files.write(Files.java:3351)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage$writeStorage$2.invokeSuspend(PlainTagsStorage.kt:174)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage$writeStorage$2.invoke(Unknown Source:8)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage$writeStorage$2.invoke(Unknown Source:4)
        at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
        at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:161)
        at kotlinx.coroutines.BuildersKt.withContext(Unknown Source:1)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage.writeStorage(PlainTagsStorage.kt:165)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage.access$writeStorage(PlainTagsStorage.kt:22)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage$persist$2.invokeSuspend(PlainTagsStorage.kt:136)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage$persist$2.invoke(Unknown Source:8)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage$persist$2.invoke(Unknown Source:4)
        at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
        at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:161)
        at kotlinx.coroutines.BuildersKt.withContext(Unknown Source:1)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage.persist(PlainTagsStorage.kt:90)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage.access$persist(PlainTagsStorage.kt:22)
        at space.taran.arknavigator.mvp.model.repo.PlainTagsStorage$setTags$2.invokeSuspend(PlainTagsStorage.kt:68)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

Global resources counter and occupied disk space info

This feature is conceptually simple, but requires some smart structure in fact.
Architecturally, we should modify the counter every time we index a resource.

Visually, these counters should be placed on the folders screen.

"Reset preferences" button

Such button would be useful for testing (quickly reset sorting or chosen apps to open certain types of resources).

"Pick" button stucks in "favorite" state

  1. Open folder picker.
  2. Walk into some known root — "add root" button grays out.
  3. Descend further into some folder — "add root" becomes "favorite".
  4. Go back with "back" button — "favorite" must change back to grayed-out "add root".
  5. Go back again — the button must change to active "add root".

During steps 4 and 5 the "pick" button still has label "favorite".
During step 4 the "pick" button is still active.

Incremental sorting

Right now, sorting of resources causes small delays on huge collections (e.g. 5000 of pictures). After addition of persistence of sorting preferences, this delay is imposed after frequent actions: opening a folder and going back from gallery mode to resources grid.

It may be possible to perform sorting in a smarter way:

  1. find top T resources and put K of them into visible frame;
  2. spawn sorting of the rest of resources in background;
  3. allow the user to do his stuff.

Implementation can be non-trivial, but performance would be better:
blocking phase: T * N operations to find top T resources (where N is number of all resources)
background phase: normal sorting of N - T elements

Syncthing folder as a device

There is a software called Syncthing: https://syncthing.net/

Our app's focus is on easy replication of data — we don't involve our own syncing mechanism, but we assume that a user can replicate his files to other devices. That's why we store tags in files inside of user-chosen folders. These storage files will be automatically replicated (whether it is by USB drive, or by syncing software like Syncthing).

But Syncthing on Android versions allows writing only into folders inside of Synthing's folder.
This makes a user to choose long paths, so we can ease this by creating a virtual device for Syncthing in our app.

Removal from resources index fails on huge collections

This SQL query

    @Query("DELETE FROM Resource where path in (:paths)")
    suspend fun deletePaths(paths: List<StringPath>)

fails when there are too much elements in paths:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: space.taran.arknavigator, PID: 27089
E/AndroidRuntime: android.database.sqlite.SQLiteException: too many SQL variables (Sqlite code 1 SQLITE_ERROR): , while compiling: DELETE FROM Resource where path in (?,?,...,?), (OS error - 0:Success)
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:948)
        at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:559)
        at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:603)
        at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:63)
        at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
        at android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1166)
        at androidx.sqlite.db.framework.FrameworkSQLiteDatabase.compileStatement(FrameworkSQLiteDatabase.java:64)
        at androidx.room.RoomDatabase.compileStatement(RoomDatabase.java:459)
        at space.taran.arknavigator.mvp.model.dao.ResourceDao_Impl$4.call(ResourceDao_Impl.java:138)
        at space.taran.arknavigator.mvp.model.dao.ResourceDao_Impl$4.call(ResourceDao_Impl.java:129)
        at androidx.room.CoroutinesRoom$Companion$execute$2.invokeSuspend(CoroutinesRoom.kt:61)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at androidx.room.TransactionExecutor$1.run(TransactionExecutor.java:47)
        at java.util.concurrent.ThreadPoolExecutor.processTask(ThreadPoolExecutor.java:1187)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:784)

Display progress spinner when resources are being sorted

Huge folders can cause ResourcesFragment freeze during sorting — sorting of 5000 resources freezes for 5 seconds on my Huawei P10. We should inform user about operation in progress. Also would be great to attach short label to any spinner animation: like "indexing" and "sorting" to provide a user with clue about what exactly takes time (so she can disable sorting for instance).

Bulk resources operations

It should be possible to apply some operations to selections, e.g. to move all selected resources to some folder (favorite or root) with all their tags.

Storage file format upgrades

When the app reads a tags storage file, it checks the format version. If the version is lower than the current one, the file must be upgraded before using.

The app must contain code for upgrades between any two adjacent versions. Backup of the file should be done before upgrade.

Tags editing dialog: focus on the input

When tags editing dialog is spawned, focus must be on the text input and keyboard must be displayed.
This reduces amount of time necessary to input a tag.

Fix warnings

This issue will be updated with various debt about warnings.

MainActivity.kt: (55, 27): 'setOnNavigationItemSelectedListener(BottomNavigationView.OnNavigationItemSelectedListener?): Unit' is deprecated. Deprecated in Java

MainActivity.kt: (168, 15): 'onActivityResult(Int, Int, Intent?): Unit' is deprecated. Overrides deprecated member in 'androidx.activity.ComponentActivity'. Deprecated in Java

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.