From 64d0c87013464d89dc589cc2b42a0c2df85f9cc2 Mon Sep 17 00:00:00 2001 From: Steve Soltys Date: Sat, 27 Jan 2024 21:27:59 +0000 Subject: [PATCH] Add support for RoundSync as a storage provider --- app/development/scripts/install_app.sh | 2 + app/src/debug/res/values/config.xml | 1 + .../seedvault/ui/storage/SafStorageOptions.kt | 53 ++++++++++++++++++- .../ui/storage/StorageRootFetcher.kt | 1 + .../ui/storage/StorageRootResolver.kt | 4 ++ app/src/main/res/drawable/round_sync.xml | 5 ++ .../res/drawable/round_sync_foreground.xml | 18 +++++++ app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/config.xml | 1 + app/src/main/res/values/strings.xml | 1 + 10 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/drawable/round_sync.xml create mode 100644 app/src/main/res/drawable/round_sync_foreground.xml diff --git a/app/development/scripts/install_app.sh b/app/development/scripts/install_app.sh index 930c7a1f3..93180f4ab 100755 --- a/app/development/scripts/install_app.sh +++ b/app/development/scripts/install_app.sh @@ -30,6 +30,8 @@ $ADB push $ROOT_PROJECT_DIR/app/build/outputs/apk/release/app-release.apk /syste echo "Installing Seedvault permissions..." $ADB push $ROOT_PROJECT_DIR/permissions_com.stevesoltys.seedvault.xml /system/etc/permissions/privapp-permissions-seedvault.xml $ADB push $ROOT_PROJECT_DIR/allowlist_com.stevesoltys.seedvault.xml /system/etc/sysconfig/allowlist-seedvault.xml +$ADB shell am force-stop com.stevesoltys.seedvault +$ADB shell am broadcast -a android.intent.action.BOOT_COMPLETED echo "Setting Seedvault transport..." $ADB shell bmgr transport com.stevesoltys.seedvault.transport.ConfigurableBackupTransport diff --git a/app/src/debug/res/values/config.xml b/app/src/debug/res/values/config.xml index 50bc22f89..a814cb633 100644 --- a/app/src/debug/res/values/config.xml +++ b/app/src/debug/res/values/config.xml @@ -7,5 +7,6 @@ org.nextcloud.documents org.nextcloud.beta.documents at.bitfire.davdroid.webdav + de.felixnuesse.extract.vcp diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/SafStorageOptions.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/SafStorageOptions.kt index f3e9ba6b7..6d86e8608 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/SafStorageOptions.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/SafStorageOptions.kt @@ -5,6 +5,9 @@ import android.content.Intent import android.content.Intent.ACTION_VIEW import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.net.Uri +import android.provider.DocumentsContract +import android.provider.DocumentsContract.Document.COLUMN_DISPLAY_NAME +import android.provider.DocumentsContract.Document.COLUMN_DOCUMENT_ID import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.ui.storage.StorageOption.SafOption import com.stevesoltys.seedvault.ui.storage.StorageRootResolver.getIcon @@ -30,6 +33,7 @@ internal class SafStorageOptions( checkOrAddUsbRoot(roots) checkOrAddDavX5Root(roots) checkOrAddNextCloudRoot(roots) + checkOrAddRoundSyncRoots(roots) } private fun checkOrAddUsbRoot(roots: ArrayList) { @@ -50,6 +54,49 @@ internal class SafStorageOptions( roots.add(root) } + /** + * Add a storage root for each child directory at the RoundSync root, if it exists. + */ + private fun checkOrAddRoundSyncRoots(roots: ArrayList) { + + val roundSyncRoot = roots.firstOrNull { + it.authority == AUTHORITY_ROUND_SYNC + } ?: return + + roots.remove(roundSyncRoot) + + val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree( + roundSyncRoot.uri, roundSyncRoot.documentId + ) + val projection = arrayOf(COLUMN_DISPLAY_NAME, COLUMN_DOCUMENT_ID) + val cursor = context.contentResolver.query(childrenUri, projection, null, null, null) + + cursor?.use { + val nameIndex = cursor.getColumnIndex(COLUMN_DISPLAY_NAME) + val documentIdIndex = cursor.getColumnIndex(COLUMN_DOCUMENT_ID) + + while (cursor.moveToNext()) { + val name = cursor.getString(nameIndex) + val documentId = cursor.getString(documentIdIndex) + + val childRoot = SafOption( + authority = AUTHORITY_ROUND_SYNC, + rootId = name, + documentId = documentId, + icon = getIcon(context, AUTHORITY_ROUND_SYNC, name, 0), + title = name, + summary = context.getString(R.string.storage_round_sync_summary_prefix) + name, + availableBytes = null, + isUsb = false, + requiresNetwork = true, + enabled = true + ) + + roots.add(childRoot) + } + } + } + /** * This adds a fake Dav X5 entry if no real one was found. * @@ -136,8 +183,10 @@ internal class SafStorageOptions( rootId = "fake", documentId = "fake", icon = getIcon(context, AUTHORITY_NEXTCLOUD, "fake", 0), - title = context.getString(R.string.storage_not_recommended, - context.getString(R.string.storage_fake_nextcloud_title)), + title = context.getString( + R.string.storage_not_recommended, + context.getString(R.string.storage_fake_nextcloud_title) + ), summary = context.getString(summaryRes), availableBytes = null, isUsb = false, diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt index 96c27d0ef..1357f2999 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt @@ -24,6 +24,7 @@ const val ROOT_ID_HOME = "home" const val AUTHORITY_DOWNLOADS = "com.android.providers.downloads.documents" const val AUTHORITY_NEXTCLOUD = "org.nextcloud.documents" const val AUTHORITY_DAVX5 = "at.bitfire.davdroid.webdav" +const val AUTHORITY_ROUND_SYNC = "de.felixnuesse.extract.vcp" internal interface RemovableStorageListener { fun onStorageChanged() diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootResolver.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootResolver.kt index 5a48e2e77..9b9c95bb8 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootResolver.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootResolver.kt @@ -141,6 +141,10 @@ internal object StorageRootResolver { context.getDrawable(R.drawable.davx5) } + authority == AUTHORITY_ROUND_SYNC -> { + context.getDrawable(R.drawable.round_sync) + } + else -> null } } diff --git a/app/src/main/res/drawable/round_sync.xml b/app/src/main/res/drawable/round_sync.xml new file mode 100644 index 000000000..ae9c19466 --- /dev/null +++ b/app/src/main/res/drawable/round_sync.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/round_sync_foreground.xml b/app/src/main/res/drawable/round_sync_foreground.xml new file mode 100644 index 000000000..0fdb74675 --- /dev/null +++ b/app/src/main/res/drawable/round_sync_foreground.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index bab25339e..41257d635 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -24,4 +24,5 @@ #558B2F #F9A825 #7cb342 + #4bae4f diff --git a/app/src/main/res/values/config.xml b/app/src/main/res/values/config.xml index fe2f35e1a..af80093aa 100644 --- a/app/src/main/res/values/config.xml +++ b/app/src/main/res/values/config.xml @@ -18,6 +18,7 @@ com.android.externalstorage.documents org.nextcloud.documents at.bitfire.davdroid.webdav + de.felixnuesse.extract.vcp