termux / termux-app

Termux - a terminal emulator application for Android OS extendible by variety of packages.
https://f-droid.org/en/packages/com.termux
Other
33.44k stars 3.53k forks source link

[Feature]: pass to URI to `termux-file-editor` which enables file saving #2658

Open knyipab opened 2 years ago

knyipab commented 2 years ago

Feature description

IIRC, the current termux-file-editor only performs on a copy of the shared file.

Recently, Termux:API has provided SAF API for programs to handle URI. It would be great if TermuxFileReceiverActivity.java could send URI to termux-file-editor so that it could save the file back to URI through the new SAF API. That way, Termux could really edit and save file in external storage (even on GDrive, if it is opened from com.android.documentsui.files.FilesActivity instead of official GDrive App).

And this should somehow solve #766 .

Additional information

I could think of some backward-compatible implementations.

  1. use second argument $2. It is easy to implement (add dataUri in the EXTRA_ARGUMENTS line and change argument specification of promptNameAndSave)
  2. environment variable. This require to change buildEnvironment across a few java files. But this may be more consistent if one day Termux implements another version of file editor for multiple files.

If you don't mind me to make a pull request. I could help as well. Thanks a lot!

twaik commented 2 years ago

It is not possible. C/C++ programs can not use Android's URI.

knyipab commented 2 years ago

It is not possible. C/C++ programs can not use Android's URI.

This is where the bash script comes in (termux-file-editor). It will be responsible for detecting any changes in the local mirror file done by C/C++ program (based on timestamp or tools like inotifywait) and uploading back to the Android URI (with the use of the new SAF API).

Then it is defacto a temporary one-way sync (to let say Gdrive) and allows editing a single file with linux programs.

cunlem commented 1 year ago
  1. use second argument $2. It is easy to implement (add dataUri in the EXTRA_ARGUMENTS line and change argument specification of promptNameAndSave)

Please don't: #2285 The editing feature should not be limited to single file. There are programs like cat that are able to operate on multiple files (!)

It will be responsible for detecting any changes in the local mirror file done by C/C++ program (based on timestamp or tools like inotifywait) and uploading back to the Android URI (with the use of the new SAF API).

I might be missing something but assuming the storage has been setup (termux-setup-storage) every program can access external files directly through symlinks in ~/storage. So why even bother with a copy?

tareksander commented 1 year ago

I might be missing something but assuming the storage has been setup (termux-setup-storage) every program can access external files directly through symlinks in ~/storage. So why even bother with a copy?

The symlinks only cover files in the shared folders for all apps, but you can share a file from e.g. Google Drive, which doesn't even exist on the device. Using URIs you could operate on these non-local files, and files in app-private directories if shared.

I don't know if that would currently work though. When sharing, the Termux app gets the permission to access the URI, but the SAF API is in Termux:API. I don't know if the URI permission is shared when the user id is shared.

cunlem commented 1 year ago

The symlinks only cover files in the shared folders for all apps, but you can share a file from e.g. Google Drive, which doesn't even exist on the device. Using URIs you could operate on these non-local files, and files in app-private directories if shared.

Ah yes this makes sense. But I still feel that for local files that are directly accessible there needs to be a way to avoid copying. An example use case could be: changing metadata of Matroska file that is 40 GB in length.

twaik commented 1 year ago

Is it possible to open ParcelFileDescriptor sent in Intent? We can extract regular fd but usually applications open files by path, not from fd.

agnostic-apollo commented 1 year ago

A toggle can be added in edit screen for No Copy and original path is passed. The script can then check if file is readable or not, like if on public storage. If it is, then script can directly do what it wants. If path is a uri for SAF, can use termux-api-saf apis. If path is on public storage, can just convert original uri to an absolute path and pass that so that script doesn't have to convert.

twaik commented 1 year ago

I think it is possiblle to open files directly from another application (without caching) in the case if we have ParcelFileDescriptor. We can wrap open/fopen/etc. calls using LD_PRELOAD feature to use file descriptor we got from ContentResolver. And it will work in both termux and proot. In the case if file has read-only flag editor will simply show save dialog when user try to save edited file. But it will require some termux-api modifications.

agnostic-apollo commented 1 year ago

It "may" be possible to implement something like that, but would have performance penalty for all open calls. One could check if a content uri is being opened but since Context won't be available, would have use termux-api like api to get file descriptor back. Also LD_PRELOAD isn't set for termux-file-editor so new shell would have to be started, unless exported by app, not sure why that isn't done. Also there are different sources for content uris, so not sure how things will behave for all.

twaik commented 1 year ago

It "may" be possible to implement something like that, but would have performance penalty for all open calls

Also LD_PRELOAD isn't set for termux-file-editor so new shell would have to be started

Anyway termux opens new shell when it creates new file, isn't it? It will not touch other shell sessions.

agnostic-apollo commented 1 year ago

LD_PRELOAD is set by login script and available for all session shells. Unless you want separate shared lib than libtermux-exec.so only available for termux-file-editor api by default. There might be other cases where its useful as well, but I guess users can export in shell profiles files or wherever needed.

fieldlab commented 1 year ago

I don't know if this helps but I was surprised this workaround works perfectly to save a screenshot in jpg vs png format (not an option on my oldish pixel). It doesn't even leave the png file anymore. I take a normal screenshot in Android but tap "share" and find the Termux app. I did a chmod 775 on the "termux-file-editor" which is just a text file, and used the shebang since I don't think I can add a .bash, but might be redundant. Safe redundancy though. Of course you could check file type and create a huge bash script to do all kinds of fancy functions on various files "shared" to the Termux app from Android.

The dumb ironic thing is that Facebook doesn't accept PNG images though sometimes they are smaller than jpg.

~/bin$ cat termux-file-editor
#!/data/data/com.termux/files/usr/bin/bash
convert $1 "/data/data/com.termux/files/home/storage/shared/Pictures/Screenshots/"$(date +%F\-%T).jpg