snapdrop-android icon indicating copy to clipboard operation
snapdrop-android copied to clipboard

Improve scoped storage efficiency

Open anggrayudi opened this issue 3 years ago • 15 comments

Previous logic:

  1. Write to temp file
  2. Copy temp file to destination folder
  3. Delete temp file
  4. Post notification

New logic:

  1. Write to media store database directly
  2. Post notification

The advantages of this improvement:

  • It's 2x faster than old logic.
  • It can save physical storage lifetime, just like how SSD works.

Test result:

Screen Shot 2022-05-03 at 08 19 01

anggrayudi avatar May 03 '22 01:05 anggrayudi

Hi, thanks for the PR!

Two questions for clarification:

  • What will happen if someone sends me a file I do not want (e.g. in a public network)?
  • Is it necessary to change the download folder to downloadsFolder + "/Snapdrop"? If not, I would favor to leave it as is...

fm-sys avatar May 03 '22 07:05 fm-sys

Is it necessary to change the download folder to downloadsFolder + "/Snapdrop"?

Nope. I have removed path /Snapdrop on new commit. Reverted.

What will happen if someone sends me a file I do not want (e.g. in a public network)?

Current Snapdrop logic do not have a confirmation JSAPI (@JavascriptInterface), so the flow is as follows:

  1. An anonymous user sends a file in public network.
  2. File is received by Snapdrop app, and write it into temp file.
  3. After the temp file is downloaded 100%, then ask user whether to save or ignore the received file.
  4. If the user wants to save it, then rename and move it to Download folder.
  5. If the user wants to ignore it, then the temp file stays in cache directory for an unknown time. It could make the storage full if users never clean up caches in their devices.

Above logic is not a good approach, the following actions are much better:

  1. An anonymous user sends a file in public network.
  2. JSAPI confirmation is triggered, then file data (name, mime type, size) are received, and ask the user to save or ignore it.
  3. If the user selects ignore, nothing will happen.
  4. If the user selects save, then start downloading the file.
  5. File is received by Snapdrop app, and write it into media store directly.

And the logic of current changes on this PR is:

  1. An anonymous user sends a file in public network.
  2. File is received by Snapdrop app, and write it into media store directly.
  3. After the file is downloaded 100%, then ask user whether to save or ignore the received file.
  4. The only difference of selecting save/ignore is, option "save" will show notification & snackbar. The file still persists in storage, even though the user selects ignore.

Current Snapdrop logic is a bad approach, because it will download the file before asking the user. It will be a redundant if the file is downloaded but the user selects ignore. There should be a JSAPI to ask user whether to save/ignore before downloading files, do you know what is it?

anggrayudi avatar May 03 '22 12:05 anggrayudi

Current Snapdrop logic is a bad approach, because it will download the file before asking the user.

I totally agree that this logic has downsides. One of the good things however is, that snapdrop is able to show e.g. image previews

Unfortunately, we are dependent on https://github.com/RobinLinus/snapdrop and they have decided to go that way...

Oh, and the current Snapdrop logic is even a bit more complicated. Currently, the file is actually stored three times.

  1. As blob content inside the webview
  2. As temp file
  3. Finally a public user-visible file is created out of the temp file

Maybe we can directly stream the blob into a SAF file. We had some trials in #76, but somehow we ended up with the current logic.

fm-sys avatar May 03 '22 14:05 fm-sys

One of the good things however is, that snapdrop is able to show e.g. image previews

Instead of receiving full size of the file, snapdrop server should generate thumbnails to achieve this. So we can avoid redundancy in transferring files.

Our best workaround for now is listening "ignore" option from the dialog. If the user selects ignore, we should remove the downloaded files from media store database. So we can still achieve "2x faster transfer rate" as I pointed above. In the future, we need to make an improvement to start downloading files after the user confirmed "save" on the dialog. Now, how to listen ignore?

anggrayudi avatar May 03 '22 14:05 anggrayudi

Is it really the network transfer rate which will get improved, or rather the delay which is currently necessary for moving the file?

fm-sys avatar May 03 '22 15:05 fm-sys

From users perspective, they see it as single transfer rate. But from our perspective as developer, we see it as download rate + moving file to media store rate. Thus removing "moving file to media store" will make the transfer rate 2x faster from the user perspective.

anggrayudi avatar May 04 '22 02:05 anggrayudi

Our best workaround for now is listening "ignore" option from the dialog. If the user selects ignore, we should remove the downloaded files from media store database.

Yes, probably this is the best way to go.

Furthermore media store allows us to easily rename files and change the MIME type, right? Maybe, we could store the files as snapdrop-data.temp and rename the file as soon as the user selects "download".

Still not perfect, but maybe something to consider. What do you think?

fm-sys avatar May 04 '22 13:05 fm-sys

We can't rename files in media store database, but we can hide/unhide the file from the user with MediaFile.isPending in SimpleStorage. Now back to previous question, how to listen "save/ignore/download"?

anggrayudi avatar May 04 '22 19:05 anggrayudi

We can't rename files in media store database, but we can hide/unhide the file from the user with MediaFile.isPending in SimpleStorage.

That sounds even better 👍

Now back to previous question, how to listen "save/ignore/download"?

We already modify the website quite a bit via JS. See: https://github.com/fm-sys/snapdrop-android/blob/master/app/src/main/assets/init.js

We could just add an OnClickListener to the relevant html button via js and let it call the JavascriptInterface

fm-sys avatar May 04 '22 20:05 fm-sys

I'm not an expert in Javascript. Maybe you can create a new branch that modifies init.js, and I will change this PR's target branch to the newly branch you've created. So you can test this PR with the new JavascriptInterface. How about that?

One more question, can we modify the confirmation dialog in init.js to write files after the user selects save? I wish we can reverse the current logic, to avoid writing unneeded files to the user's storage.

anggrayudi avatar May 05 '22 15:05 anggrayudi

I'm not an expert in Javascript. Maybe you can create a new branch that modifies init.js, and I will change this PR's target branch to the newly branch you've created. So you can test this PR with the new JavascriptInterface. How about that?

Sure 👍 Might take some days though...

One more question, can we modify the confirmation dialog in init.js to write files after the user selects save? I wish we can reverse the current logic, to avoid writing unneeded files to the user's storage.

I fear this will not be possible unfortunately.

fm-sys avatar May 05 '22 18:05 fm-sys

Hi, just want to say that I haven't forgotten your PR. However, I'm quite busy currently... sorry!

fm-sys avatar May 12 '22 22:05 fm-sys

Here we go, I had almost forgotten that I had planned to do something here... https://github.com/fm-sys/snapdrop-android/commit/9d1a09ab3ff2b5fe9f43b5c4c23c0bc3bc3e9a83

fm-sys avatar May 24 '22 19:05 fm-sys

Added new changes to handle ignoreClickedListener. Please check it @fm-sys

anggrayudi avatar Jul 09 '22 12:07 anggrayudi

SimpleStorage v1.4.0 has been released to support this changes.

anggrayudi avatar Jul 12 '22 08:07 anggrayudi

The pipeline is green now. Please help to check it, or merge if you've approved it, @fm-sys. Thanks in advance.

anggrayudi avatar Oct 30 '22 17:10 anggrayudi

Resolved all threads. You can merge it now @fm-sys

anggrayudi avatar Mar 14 '23 08:03 anggrayudi

Thanks for your work (and sorry for the delay) 👍

fm-sys avatar Mar 14 '23 09:03 fm-sys