Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: chenxiaolong/RSAF
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v2.4
Choose a base ref
...
head repository: chenxiaolong/RSAF
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Dec 20, 2024

  1. Add support for DocumentsProvider.openDocumentThumbnail()

    This will return a pipe and then spawn a background task to generate a
    thumbnail and write it to the pipe. Cancellation is supported in between
    logical operations (eg. parse headers, load frame, etc.). Android has no
    way to interrupt the parsers in MediaMetadataRetriever and ImageDecoder
    though, so there will be a delay before cancellation takes effect. This
    can be noticeable when scrolling quickly, for example through a list of
    videos, since there is a hard concurrency limit equal to the number of
    logical cores.
    
    Note that only audio, image, and video formats natively supported by
    Android can be thumbnailed. We don't bundle any decoders.
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Dec 20, 2024
    Copy the full SHA
    1b41b95 View commit details
  2. CHANGELOG.md: Add entry for PR #113

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Dec 20, 2024
    Copy the full SHA
    3701006 View commit details
  3. Version 2.5

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Dec 20, 2024
    Copy the full SHA
    38d4a94 View commit details

Commits on Jan 12, 2025

  1. Add support for resuming VFS cache writeback

    Previously, if the VFS cache writeback was interrupted, it would
    effectively not be resumable, especially if the files were big. After
    the interruption, the first file operation on remotes with pending
    uploads would block until the uploads completed. However, there would be
    no foreground service to keep the process alive. The only way to get out
    of the situation would be to leave the RSAF settings screen open until
    the uploads invisibly complete.
    
    With this commit, BackgroundUploadMonitorService is now also started on
    boot or when the user first opens the app after it crashes or is killed.
    It will scan through the VFS cache directory and initialize the VFS
    instances for remotes with pending uploads. The service now exits on its
    own after a period of time with no VFS cache files open.
    
    For this to work well, the rclone VFS is configured so that writebacks
    are asynchronous. This is necessary to prevent VFS initialization from
    blocking until uploads are complete, but unfortunately also makes the
    close() operation asynchronous. RSAF is no longer able to show a
    notification if a background upload fails.
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 12, 2025
    Copy the full SHA
    c63e7f4 View commit details
  2. CHANGELOG.md: Add entry for PR #114

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 12, 2025
    Copy the full SHA
    c63d934 View commit details
  3. Remove support for POSIX-like semantics

    This turned out to be not such a great idea. Applications expect
    document providers to behave like Android's builtin FileSystemProvider
    for local files. POSIX-like semantics differed significantly from that
    and there are no known applications that explicitly try to make use of
    this functionality. Let's get rid of this feature and simplify the code.
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 12, 2025
    Copy the full SHA
    d33e9ea View commit details
  4. CHANGELOG.md: Add entry for PR #115

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 12, 2025
    Copy the full SHA
    ece4835 View commit details
  5. Fix broken golang dependency caching in Github Actions CI build

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 12, 2025
    Copy the full SHA
    f97ca78 View commit details
  6. CHANGELOG.md: Add entry for PR #116

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 12, 2025
    Copy the full SHA
    b285043 View commit details
  7. Update rclone to 1.69.0

    Nothing special this time besides the addition of the `vfs.ELOOP` error
    code.
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 12, 2025
    Copy the full SHA
    276c95d View commit details
  8. CHANGELOG.md: Add entry for PR #117

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 12, 2025
    Copy the full SHA
    d439b7a View commit details

Commits on Jan 13, 2025

  1. Update dependencies

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 13, 2025
    Copy the full SHA
    8d0e36c View commit details
  2. CHANGELOG.md: Add entry for PR #118

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 13, 2025
    Copy the full SHA
    66281a9 View commit details
  3. Version 3.0

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 13, 2025
    Copy the full SHA
    e91b8ea View commit details

Commits on Jan 14, 2025

  1. Add proper support for Android's CA trust stores

    golang does not support Android's various trust stores well. The CA
    certificates in /system/etc/security/cacerts are the only ones that are
    properly read. The updatable apex trust store in Android 14+ and the
    user trust store are ignored. System CA certificates that the user
    disables are still permitted to be used.
    
    This commit implements our own certificate loading mechanism that loads
    from all of Android's trust stores and respects disabled certificates.
    We generate a combined PEM file in a temp file and feed that to rclone's
    CaCert option.
    
    While live reloading is supported, the user experience is not that
    great. Due to rclone's caching, when certificates are reloaded, they
    only take effect in new remotes. The user will need to delete and
    recreate the remote, export and reimport, or force close RSAF.
    
    Fixes: #119
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 14, 2025
    Copy the full SHA
    bff18e6 View commit details
  2. CHANGELOG.md: Add entry for PR #120

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 14, 2025
    Copy the full SHA
    6c88320 View commit details
  3. Make file close operations synchronous again

    In c63e7f4, file close operations were
    made asynchronous to prevent vfs.New() from blocking due to it opening
    and closing every cached file to trigger pending uploads. This broke the
    in-use file tracker in RcloneProvider and made it impossible for RSAF to
    report upload errors in most cases.
    
    This commit fixes the problem by keeping the file close operation
    asynchronous initially and then making it synchronous after the VFS
    instance is created.
    
    Fixes: #81 (again)
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 14, 2025
    Copy the full SHA
    4c97113 View commit details
  4. CHANGELOG.md: Add entry for PR #121

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 14, 2025
    Copy the full SHA
    e3d3897 View commit details

Commits on Jan 15, 2025

  1. Prompt before actions that delete the VFS cache

    Previously, when deleting a remote, renaming (copy + delete) a remote,
    or importing a configuration, we'd wait up to 1 minute for pending VFS
    writeback operations to complete and then delete the remote and VFS
    cache. This was a terrible user experience because:
    
    * the user does not have the choice to wait for file operations to
      complete if they weren't already aware of them
    * the UI would appear as if nothing was happening
    * the user would have to wait for no reason if they don't care about
      pending uploads
    
    With this commit, we'll show a prompt before destructive operations that
    delete the VFS cache. If the user chooses to proceed, the deletion
    occurs immediately. This is not perfect though--a VFS writeback thread
    cannot be cancelled and will likely throw a checksum validation error
    when it completes.
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 15, 2025
    Copy the full SHA
    ac029e8 View commit details
  2. CHANGELOG.md: Add entry for PR #123

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 15, 2025
    Copy the full SHA
    46c8cd4 View commit details

Commits on Jan 16, 2025

  1. Add support for automatically reloading CA certificates

    The initial implementation of loading Android's CA trust stores wrote
    the certificates to a temporary file and then passed them to rclone via
    the CaCert config option. This would only get loaded when a new backend
    Fs instance was created. If the backend was already created, the user
    would need to delete and recreate the remote or force quit RSAF, which
    is a terrible user experience.
    
    Unfortunately, reloading by recreating the Fs and VFS instances would
    not provide a good experience either. The VFS would need to be shut
    down, interrupting VFS writeback, and we need to wait for the garbage
    collector to clean up the VFS instance so that the corresponding Fs
    instance would be unpinned from the cache. This precludes the CA
    reloading process from being automatic.
    
    Instead, this commit makes use of a per-request hook to set the trusted
    CA certificates on every connection. This requires a soft-fork of rclone
    to add a hook point to fshttp.(*Transport).RoundTrip(). The patch is
    extremely simple and is easy to port to future versions of rclone. No
    other patches will be added to the fork and I plan to switch back to the
    upstream version if another good solution is found, even if hacky.
    
    Some other approaches I tried or considered:
    
    * Replace fshttp.isCertificateExpired() using go:linkname and in the
      replacement, update the tls.Config.RootCAs in addition to executing a
      copy of the original code. This function would be called during each
      RoundTrip() invocation. This approach does not work with how gomobile
      builds rcbridge as a library and causes duplicate symbol errors during
      linking.
    * Add the code as is done in this commit, except via a -toolexec program
      that preprocesses the AST of the go sources. This approach does not
      work because -toolexec is not invoked at the necessary points when
      compiling with gomobile.
    * Patch fshttp.isCertificateExpired() at runtime by inserting a jump
      call to our own implementation. This is error prone, requires specific
      assembly code for each CPU architecture, and does not work if the
      function we want to patch was inlined.
    
    This commit also fixes a bug where a remote's Fs instance is not
    properly removed from rclone's cache when deleting the remote.
    
    Issue: #119
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 16, 2025
    Copy the full SHA
    7b4b5f6 View commit details
  2. CHANGELOG.md: Add entry for PR #125

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 16, 2025
    Copy the full SHA
    6233904 View commit details

Commits on Jan 18, 2025

  1. Only allow copy/move via rclone when it can be done server-side

    If copyDocument() and moveDocument() are slow, the binder transaction
    will time out and Android will kill RSAF. If we can't perform the
    operation quickly via server-side operations, let's just tell the client
    that the operation is unsupported. Android's DocumentsUI specifically
    handles this scenario and will do the copy/move operation itself, which
    isn't subject to this problem.
    
    Fixes: #124
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 18, 2025
    Copy the full SHA
    21b3251 View commit details
  2. CHANGELOG.md: Add entry for PR #126

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 18, 2025
    Copy the full SHA
    9556d2c View commit details
  3. Improve logic for revoking grants when moving and removing documents

    The DocumentsProvider base class already has a method for doing this.
    The previous revokeGrants() method did not properly revoke grants for
    tree URIs. This also fixes grants being revoked twice when a client app
    calls deleteDocument().
    
    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 18, 2025
    Copy the full SHA
    b21d1b7 View commit details
  4. CHANGELOG.md: Add entry for PR #129

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 18, 2025
    Copy the full SHA
    b67e1ae View commit details
  5. Version 3.1

    Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
    chenxiaolong committed Jan 18, 2025
    Copy the full SHA
    02c922e View commit details
Showing with 1,891 additions and 1,242 deletions.
  1. +3 −2 .github/workflows/ci.yml
  2. +1 −1 .github/workflows/release.yml
  3. +42 −0 CHANGELOG.md
  4. +4 −12 README.md
  5. +4 −0 UPDATES.md
  6. +21 −7 app/build.gradle.kts
  7. BIN app/images/dark.png
  8. BIN app/images/light.png
  9. +73 −321 app/src/androidTest/java/com/chiller3/rsaf/RcloneProviderTest.kt
  10. +11 −1 app/src/main/AndroidManifest.xml
  11. +11 −13 app/src/main/java/com/chiller3/rsaf/Notifications.kt
  12. +1 −7 app/src/main/java/com/chiller3/rsaf/Preferences.kt
  13. +54 −0 app/src/main/java/com/chiller3/rsaf/dialog/VfsCacheDeletionDialogFragment.kt
  14. +20 −0 app/src/main/java/com/chiller3/rsaf/rclone/BackgroundUploadMonitorReceiver.kt
  15. +94 −98 app/src/main/java/com/chiller3/rsaf/rclone/BackgroundUploadMonitorService.kt
  16. +164 −80 app/src/main/java/com/chiller3/rsaf/rclone/RcloneProvider.kt
  17. +320 −0 app/src/main/java/com/chiller3/rsaf/rclone/Thumbnailer.kt
  18. +133 −0 app/src/main/java/com/chiller3/rsaf/rclone/VfsCache.kt
  19. +54 −23 app/src/main/java/com/chiller3/rsaf/settings/EditRemoteFragment.kt
  20. +41 −29 app/src/main/java/com/chiller3/rsaf/settings/EditRemoteViewModel.kt
  21. +26 −4 app/src/main/java/com/chiller3/rsaf/settings/SettingsFragment.kt
  22. +5 −0 app/src/main/java/com/chiller3/rsaf/settings/SettingsViewModel.kt
  23. +6 −6 app/src/main/res/values/strings.xml
  24. +1 −8 app/src/main/res/xml/preferences_root.xml
  25. +3 −1 gradle/libs.versions.toml
  26. +368 −376 gradle/verification-metadata.xml
  27. +2 −2 gradle/wrapper/gradle-wrapper.properties
  28. +1 −2 gradlew
  29. +75 −72 rcbridge/go.mod
  30. +166 −162 rcbridge/go.sum
  31. +187 −15 rcbridge/rcbridge.go
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -16,10 +16,10 @@ jobs:
submodules: true

- name: Validate gradle wrapper checksum
uses: gradle/actions/wrapper-validation@cc4fc85e6b35bafd578d5ffbc76a5518407e1af0 # v4.2.1
uses: gradle/actions/wrapper-validation@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2

- name: Set up JDK 21
uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0
uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
with:
distribution: 'temurin'
java-version: 21
@@ -28,6 +28,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
cache-dependency-path: rcbridge/go.sum
go-version-file: rcbridge/go.mod

- name: Install gomobile
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Create release
uses: softprops/action-gh-release@7b4da11513bf3f43f9999e90eabced41ab8bb048 # v2.2.0
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag_name: v${{ steps.get_version.outputs.version }}
42 changes: 42 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -7,6 +7,35 @@
to update the actual links at the bottom of the file.
-->

### Version 3.1

* Add support for user CA certificate trust store and Android 14+'s apex trust store ([Issue #119], [PR #120], [PR #125])
* Make file close operations synchronous after VFS initialization ([PR #121])
* This fixes a regression caused by [PR #114] in version 3.0 that reintroduced [Issue #81].
* This allows RSAF to report upload errors in most cases again.
* Ask for confirmation before performing destructive operations on a remote that has pending uploads ([PR #123])
* This includes deleting a remote, renaming a remote, or importing a config file.
* Only perform copy and move operations via rclone if they can be done server-side ([PR #126])
* Android does not allow file copy/move operations to be slow and will kill RSAF if they are.
* For non-server-side copies/moves, RSAF will report that the operation is unsupported and the file manager will handle it itself instead.
* Fix revoking access to the original path when a directory is moved or deleted ([PR #129])

### Version 3.0

* Add support for resuming background uploads if RSAF crashes or is killed by Android ([PR #114])
* This process is automatically triggered after the device boots or when RSAF is opened.
* This also fixes an issue where after a crash, the first file operation on a remote will hang until all leftover pending uploads for that remote have completed.
* **NOTE**: Due to limitations with how rclone reports errors for asynchronous uploads, RSAF is no longer able to show a notification if a file upload fails. rclone automatically retries failed uploads and the files remain in the VFS cache until the upload succeeds.
* Remove support for POSIX-like file operation semantics ([PR #115])
* Android is generally not designed to behave this way and applications expect document providers, like RSAF, to behave like Android's builtin document provider for local files. There are no known client applications that explicitly made use of this feature.
* Fix caching of golang dependencies in Github Actions CI builds ([PR #116])
* Update rclone to 1.69.0 ([PR #117])
* Update dependencies ([PR #118])

### Version 2.5

* Add support for generating thumbnails for audio, image, and video files ([PR #113])

### Version 2.4

* Make inactivity timeout duration for the app lock configurable and add a button for locking immediately ([PR #109])
@@ -212,6 +241,7 @@
[Issue #81]: https://github.com/chenxiaolong/RSAF/issues/81
[Issue #93]: https://github.com/chenxiaolong/RSAF/issues/93
[Issue #106]: https://github.com/chenxiaolong/RSAF/issues/106
[Issue #119]: https://github.com/chenxiaolong/RSAF/issues/119
[PR #1]: https://github.com/chenxiaolong/RSAF/pull/1
[PR #2]: https://github.com/chenxiaolong/RSAF/pull/2
[PR #3]: https://github.com/chenxiaolong/RSAF/pull/3
@@ -293,3 +323,15 @@
[PR #109]: https://github.com/chenxiaolong/RSAF/pull/109
[PR #110]: https://github.com/chenxiaolong/RSAF/pull/110
[PR #111]: https://github.com/chenxiaolong/RSAF/pull/111
[PR #113]: https://github.com/chenxiaolong/RSAF/pull/113
[PR #114]: https://github.com/chenxiaolong/RSAF/pull/114
[PR #115]: https://github.com/chenxiaolong/RSAF/pull/115
[PR #116]: https://github.com/chenxiaolong/RSAF/pull/116
[PR #117]: https://github.com/chenxiaolong/RSAF/pull/117
[PR #118]: https://github.com/chenxiaolong/RSAF/pull/118
[PR #120]: https://github.com/chenxiaolong/RSAF/pull/120
[PR #121]: https://github.com/chenxiaolong/RSAF/pull/121
[PR #123]: https://github.com/chenxiaolong/RSAF/pull/123
[PR #125]: https://github.com/chenxiaolong/RSAF/pull/125
[PR #126]: https://github.com/chenxiaolong/RSAF/pull/126
[PR #129]: https://github.com/chenxiaolong/RSAF/pull/129
16 changes: 4 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -21,7 +21,6 @@ RSAF is not itself a file manager, but any file manager supporting SAF, includin
* Supports client applications that request access to a file descriptor
* Supports client applications that open entire directories with `ACTION_OPEN_DOCUMENT_TREE`
* Supports pretending to be local storage for apps that block remote SAF roots
* Supports both [Android-like and POSIX-like file operation semantics](#file-operation-semantics)
* [No required permissions besides network access](#permissions)

## Limitations
@@ -57,16 +56,7 @@ RSAF is not itself a file manager, but any file manager supporting SAF, includin

## File operation semantics

RSAF supports operating with either Android-like (default) or POSIX-like semantics.

With Android-like semantics, when creating, renaming, copying, or moving a file/directory, RSAF will add a counter to the filename to try and avoid conflicts (eg. `file(1).txt`) if the target path already exists. This matches the Storage Access Framework's behavior for local files, though RSAF extends this to copying/moving instead of just file creation/renaming. However, this feature cannot be implemented in a completely foolproof way. If two client applications try to create files with the same name at the same time, they still might end up clobbering each other's data, even with the added counter.

With POSIX-like semantics, RSAF follows the behavior of the underlying filesystem calls. It'll behave more like common CLI utilities, such as `mv`, `cp`, or even `rclone` itself.

* Creating a new file/directory behaves like `touch`/`mkdir -p`. If the path already exists and is the same type, the operation will succeed.
* Renaming a file on top of an existing file will overwrite the existing file. Otherwise, if the target path already exists, the operation will fail.
* Copying files/directories behaves like `cp -rT`. Files with the same name in the target will be overwritten. Directories will be merged (but conflicting files within directories are still overwritten).
* Moving paths behaves like copying paths, except that the source is gone once the operation succeeds.
When creating, renaming, copying, or moving a file/directory, RSAF will add a counter to the filename to try and avoid conflicts (eg. `file(1).txt`) if the target path already exists. This matches the Storage Access Framework's behavior for local files, though RSAF extends this to copying/moving instead of just file creation/renaming. However, this feature cannot be implemented in a completely foolproof way. If two client applications try to create files with the same name at the same time, they still might end up clobbering each other's data, even with the added counter.

## Usage

@@ -78,7 +68,9 @@ With POSIX-like semantics, RSAF follows the behavior of the underlying filesyste

## Permissions

The only permission RSAF requires is the `INTERNET` permission. It is used only to allow rclone to access the configured remotes. RSAF does not and will never have ads or telemetry.
The main permission RSAF requires is the `INTERNET` permission. It is used only to allow rclone to access the configured remotes. RSAF does not and will never have ads or telemetry.

The `RECEIVE_BOOT_COMPLETED` permission is used to automatically resume pending uploads if they were interrupted due to a crash or reboot.

Allowing notifications and disabling battery optimizations are optional, but strongly recommended. These are needed to allow RSAF to reliably run in the background after a client app closes a file, which is when file uploads actually begin.

4 changes: 4 additions & 0 deletions UPDATES.md
Original file line number Diff line number Diff line change
@@ -20,6 +20,10 @@ Hopefully, most issues can be found just by trying to compile rcbridge with `./g

If librclone gained new functionality that can replace current uses of internal APIs, then that new functionality should be used. librclone RPC-related tasks should be done purely on the Android side in [`RcloneRpc`](./app/src/main/java/com/chiller3/rsaf/rclone/RcloneRpc.kt), not in go.

### Certificate reloading

Check if there's any way hook into `fshttp.(*Transport).RoundTrip()`. The hook to update `tls.Config.RootCAs` is the only reason we need to fork rclone.

### `RbDocMkdir`

Check the `vfs.Dir.Mkdir()` implementation to see if it fails with EEXIST when the path already exists. If so, `RcloneProvider` can be updated to avoid an unnecessary stat when creating directories with Android semantics.
28 changes: 21 additions & 7 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Andrew Gunnerson
* SPDX-FileCopyrightText: 2023-2025 Andrew Gunnerson
* SPDX-License-Identifier: GPL-3.0-only
*/

@@ -196,6 +196,7 @@ dependencies {
implementation(libs.appcompat)
implementation(libs.biometric)
implementation(libs.core.ktx)
implementation(libs.exifinterface)
implementation(libs.fragment.ktx)
implementation(libs.preference.ktx)
implementation(libs.security.crypto)
@@ -238,6 +239,14 @@ interface InjectedExecOps {
@get:Inject val execOps: ExecOperations
}

// https://github.com/gradle/gradle/issues/12247
class LazyString(private val source: Lazy<String>) : java.io.Serializable {
constructor(source: () -> String) : this(lazy(source))
constructor(source: Provider<String>) : this(source::get)

override fun toString() = source.value
}

val rcbridge = tasks.register<Exec>("rcbridge") {
val rcbridgeSrcDir = File(rootDir, "rcbridge")
val tempDir = rcbridgeDir.map { it.dir("temp") }
@@ -251,27 +260,32 @@ val rcbridge = tasks.register<Exec>("rcbridge") {
inputs.properties(
"android.defaultConfig.minSdk" to android.defaultConfig.minSdk,
"android.namespace" to android.namespace,
"android.ndkDirectory" to android.ndkDirectory,
"androidComponents.sdkComponents.ndkDirectory" to
androidComponents.sdkComponents.ndkDirectory.map { it.asFile.absolutePath },
"androidComponents.sdkComponents.sdkDirectory" to
androidComponents.sdkComponents.sdkDirectory.map { it.asFile.absolutePath },
)
outputs.files(
rcbridgeDir.map { it.file("rcbridge.aar") },
rcbridgeDir.map { it.file("rcbridge-sources.jar") },
)

executable = "gomobile"
args = listOf(
args(
"bind",
"-v",
"-o", rcbridgeAar.get().asFile.absolutePath,
"-o", LazyString(rcbridgeAar.map { it.asFile.absolutePath }),
"-target=android",
"-androidapi=${android.defaultConfig.minSdk}",
"-javapkg=${android.namespace}.binding",
".",
)
environment(
"ANDROID_HOME" to android.sdkDirectory,
"ANDROID_NDK_HOME" to android.ndkDirectory,
"TMPDIR" to tempDir.get().asFile.absolutePath,
"ANDROID_HOME" to LazyString(androidComponents.sdkComponents.sdkDirectory
.map { it.asFile.absolutePath }),
"ANDROID_NDK_HOME" to LazyString(androidComponents.sdkComponents.ndkDirectory
.map { it.asFile.absolutePath }),
"TMPDIR" to LazyString(tempDir.map { it.asFile.absolutePath }),
)

if (!environment.containsKey("GOPROXY")) {
Binary file modified app/images/dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/images/light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading