diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe42c1b3d78..fbec3fac663 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,7 @@ ownCloud admins and users.
## Summary
* Bugfix - Shares in non-root are updated correctly: [#4432](https://github.com/owncloud/android/issues/4432)
+* Enhancement - Improved "Remove from original folder" option in auto-upload: [#4357](https://github.com/owncloud/android/issues/4357)
* Enhancement - Improved accessibility of information and relationships: [#4362](https://github.com/owncloud/android/issues/4362)
* Enhancement - Changed the color of some elements to improve accessibility: [#4364](https://github.com/owncloud/android/issues/4364)
* Enhancement - Improved SearchView accessibility: [#4365](https://github.com/owncloud/android/issues/4365)
@@ -48,6 +49,14 @@ ownCloud admins and users.
https://github.com/owncloud/android/issues/4432
https://github.com/owncloud/android/pull/4435
+* Enhancement - Improved "Remove from original folder" option in auto-upload: [#4357](https://github.com/owncloud/android/issues/4357)
+
+ The file will be deleted locally after it has been uploaded to the server,
+ avoiding the loss of the file if an error happens during the upload.
+
+ https://github.com/owncloud/android/issues/4357
+ https://github.com/owncloud/android/pull/4437
+
* Enhancement - Improved accessibility of information and relationships: [#4362](https://github.com/owncloud/android/issues/4362)
Headings have been added to the following views: Share, Edit/Create Share Link,
diff --git a/changelog/unreleased/4437 b/changelog/unreleased/4437
new file mode 100644
index 00000000000..e259e7c374b
--- /dev/null
+++ b/changelog/unreleased/4437
@@ -0,0 +1,6 @@
+Enhancement: Improved "Remove from original folder" option in auto-upload
+
+The file will be deleted locally after it has been uploaded to the server, avoiding the loss of the file if an error happens during the upload.
+
+https://github.com/owncloud/android/issues/4357
+https://github.com/owncloud/android/pull/4437
diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromSystemUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromSystemUseCase.kt
index 6b6fd06bcaa..b1dbd61b904 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromSystemUseCase.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromSystemUseCase.kt
@@ -25,7 +25,6 @@ package com.owncloud.android.usecases.transfers.uploads
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.owncloud.android.domain.BaseUseCase
-import com.owncloud.android.domain.camerauploads.model.UploadBehavior
import com.owncloud.android.domain.transfers.TransferRepository
import com.owncloud.android.extensions.getWorkInfoByTags
import com.owncloud.android.workers.UploadFileFromFileSystemWorker
@@ -58,8 +57,9 @@ class RetryUploadFromSystemUseCase(
accountName = uploadToRetry.accountName,
localPath = uploadToRetry.localPath,
lastModifiedInSeconds = (uploadToRetry.transferEndTimestamp?.div(1000)).toString(),
- behavior = UploadBehavior.MOVE.name,
+ behavior = uploadToRetry.localBehaviour.name,
uploadPath = uploadToRetry.remotePath,
+ sourcePath = uploadToRetry.sourcePath,
uploadIdInStorageManager = params.uploadIdInStorageManager
)
)
diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileFromContentUriUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileFromContentUriUseCase.kt
index 3d27c62a756..ab4a0475000 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileFromContentUriUseCase.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileFromContentUriUseCase.kt
@@ -3,8 +3,9 @@
*
* @author Abel García de Prada
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2022 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -28,6 +29,8 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.workDataOf
import com.owncloud.android.domain.BaseUseCase
+import com.owncloud.android.domain.camerauploads.model.UploadBehavior
+import com.owncloud.android.workers.RemoveSourceFileWorker
import com.owncloud.android.workers.UploadFileFromContentUriWorker
import timber.log.Timber
@@ -36,7 +39,7 @@ class UploadFileFromContentUriUseCase(
) : BaseUseCase() {
override fun run(params: Params) {
- val inputData = workDataOf(
+ val inputDataUploadFileFromContentUriWorker = workDataOf(
UploadFileFromContentUriWorker.KEY_PARAM_ACCOUNT_NAME to params.accountName,
UploadFileFromContentUriWorker.KEY_PARAM_BEHAVIOR to params.behavior,
UploadFileFromContentUriWorker.KEY_PARAM_CONTENT_URI to params.contentUri.toString(),
@@ -44,6 +47,9 @@ class UploadFileFromContentUriUseCase(
UploadFileFromContentUriWorker.KEY_PARAM_UPLOAD_PATH to params.uploadPath,
UploadFileFromContentUriWorker.KEY_PARAM_UPLOAD_ID to params.uploadIdInStorageManager
)
+ val inputDataRemoveSourceFileWorker = workDataOf(
+ UploadFileFromContentUriWorker.KEY_PARAM_CONTENT_URI to params.contentUri.toString(),
+ )
val networkRequired = if (params.wifiOnly) NetworkType.UNMETERED else NetworkType.CONNECTED
val constraints = Constraints.Builder()
@@ -52,13 +58,24 @@ class UploadFileFromContentUriUseCase(
.build()
val uploadFileFromContentUriWorker = OneTimeWorkRequestBuilder()
- .setInputData(inputData)
+ .setInputData(inputDataUploadFileFromContentUriWorker)
.setConstraints(constraints)
.addTag(params.accountName)
.addTag(params.uploadIdInStorageManager.toString())
.build()
- workManager.enqueue(uploadFileFromContentUriWorker)
+ val behavior = UploadBehavior.fromString(params.behavior)
+ if (behavior == UploadBehavior.MOVE) {
+ val removeSourceFileWorker = OneTimeWorkRequestBuilder()
+ .setInputData(inputDataRemoveSourceFileWorker)
+ .build()
+ workManager.beginWith(uploadFileFromContentUriWorker)
+ .then(removeSourceFileWorker) // File is already uploaded, so the original one can be removed if the behaviour is MOVE
+ .enqueue()
+ } else {
+ workManager.enqueue(uploadFileFromContentUriWorker)
+ }
+
Timber.i("Plain upload of ${params.contentUri.path} has been enqueued.")
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileFromSystemUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileFromSystemUseCase.kt
index 6560b44b713..6a219462de0 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileFromSystemUseCase.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileFromSystemUseCase.kt
@@ -2,8 +2,9 @@
* ownCloud Android client application
*
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2022 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -26,6 +27,9 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.workDataOf
import com.owncloud.android.domain.BaseUseCase
+import com.owncloud.android.domain.camerauploads.model.UploadBehavior
+import com.owncloud.android.workers.RemoveSourceFileWorker
+import com.owncloud.android.workers.UploadFileFromContentUriWorker
import com.owncloud.android.workers.UploadFileFromFileSystemWorker
import timber.log.Timber
@@ -34,7 +38,7 @@ class UploadFileFromSystemUseCase(
) : BaseUseCase() {
override fun run(params: Params) {
- val inputData = workDataOf(
+ val inputDataUploadFileFromFileSystemWorker = workDataOf(
UploadFileFromFileSystemWorker.KEY_PARAM_ACCOUNT_NAME to params.accountName,
UploadFileFromFileSystemWorker.KEY_PARAM_BEHAVIOR to params.behavior,
UploadFileFromFileSystemWorker.KEY_PARAM_LOCAL_PATH to params.localPath,
@@ -42,19 +46,33 @@ class UploadFileFromSystemUseCase(
UploadFileFromFileSystemWorker.KEY_PARAM_UPLOAD_PATH to params.uploadPath,
UploadFileFromFileSystemWorker.KEY_PARAM_UPLOAD_ID to params.uploadIdInStorageManager
)
+ val inputDataRemoveSourceFileWorker = workDataOf(
+ UploadFileFromContentUriWorker.KEY_PARAM_CONTENT_URI to params.sourcePath,
+ )
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val uploadFileFromSystemWorker = OneTimeWorkRequestBuilder()
- .setInputData(inputData)
+ .setInputData(inputDataUploadFileFromFileSystemWorker)
.setConstraints(constraints)
.addTag(params.accountName)
.addTag(params.uploadIdInStorageManager.toString())
.build()
- workManager.enqueue(uploadFileFromSystemWorker)
+ val behavior = UploadBehavior.fromString(params.behavior)
+ if (behavior == UploadBehavior.MOVE) {
+ val removeSourceFileWorker = OneTimeWorkRequestBuilder()
+ .setInputData(inputDataRemoveSourceFileWorker)
+ .build()
+ workManager.beginWith(uploadFileFromSystemWorker)
+ .then(removeSourceFileWorker) // File is already uploaded, so the original one can be removed if the behaviour is MOVE
+ .enqueue()
+ } else {
+ workManager.enqueue(uploadFileFromSystemWorker)
+ }
+
Timber.i("Plain upload of ${params.localPath} has been enqueued.")
}
@@ -65,5 +83,6 @@ class UploadFileFromSystemUseCase(
val behavior: String,
val uploadPath: String,
val uploadIdInStorageManager: Long,
+ val sourcePath: String? = null,
)
}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/workers/DownloadFileWorker.kt b/owncloudApp/src/main/java/com/owncloud/android/workers/DownloadFileWorker.kt
index 585f8aaee5e..3d004608257 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/workers/DownloadFileWorker.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/workers/DownloadFileWorker.kt
@@ -76,7 +76,7 @@ class DownloadFileWorker(
private val workerParameters: WorkerParameters
) : CoroutineWorker(
appContext,
- workerParameters
+ workerParameters,
), KoinComponent, OnDatatransferProgressListener {
private val getFileByIdUseCase: GetFileByIdUseCase by inject()
diff --git a/owncloudApp/src/main/java/com/owncloud/android/workers/RemoveSourceFileWorker.kt b/owncloudApp/src/main/java/com/owncloud/android/workers/RemoveSourceFileWorker.kt
new file mode 100644
index 00000000000..c16b5b0f54e
--- /dev/null
+++ b/owncloudApp/src/main/java/com/owncloud/android/workers/RemoveSourceFileWorker.kt
@@ -0,0 +1,62 @@
+/**
+ * ownCloud Android client application
+ *
+ * @author Aitor Ballesteros Pavón
+ *
+ * Copyright (C) 2024 ownCloud GmbH.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.owncloud.android.workers
+
+import android.content.Context
+import android.net.Uri
+import androidx.core.net.toUri
+import androidx.documentfile.provider.DocumentFile
+import androidx.work.CoroutineWorker
+import androidx.work.WorkerParameters
+import com.owncloud.android.workers.UploadFileFromContentUriWorker.Companion.KEY_PARAM_CONTENT_URI
+import org.koin.core.component.KoinComponent
+import timber.log.Timber
+
+class RemoveSourceFileWorker(
+ private val appContext: Context,
+ private val workerParameters: WorkerParameters
+) : CoroutineWorker(
+ appContext,
+ workerParameters
+), KoinComponent {
+
+ private lateinit var contentUri: Uri
+
+ override suspend fun doWork(): Result {
+ if (!areParametersValid()) return Result.failure()
+ return try {
+ val documentFile = DocumentFile.fromSingleUri(appContext, contentUri)
+ documentFile?.delete()
+ Result.success()
+ } catch (throwable: Throwable) {
+ Timber.e(throwable)
+ Result.failure()
+ }
+ }
+
+ private fun areParametersValid(): Boolean {
+ val paramContentUri = workerParameters.inputData.getString(KEY_PARAM_CONTENT_URI)
+
+ contentUri = paramContentUri?.toUri() ?: return false
+
+ return true
+ }
+}
diff --git a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt
index 8e9dc12c5ce..120fc336caf 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt
@@ -3,8 +3,9 @@
*
* @author Abel García de Prada
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2023 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -30,7 +31,6 @@ import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.owncloud.android.R
-import com.owncloud.android.presentation.authentication.AccountUtils
import com.owncloud.android.data.executeRemoteOperation
import com.owncloud.android.data.providers.LocalStorageProvider
import com.owncloud.android.domain.camerauploads.model.UploadBehavior
@@ -57,6 +57,7 @@ import com.owncloud.android.lib.resources.files.UploadFileFromFileSystemOperatio
import com.owncloud.android.lib.resources.files.chunks.ChunkedUploadFromFileSystemOperation
import com.owncloud.android.lib.resources.files.chunks.ChunkedUploadFromFileSystemOperation.Companion.CHUNK_SIZE
import com.owncloud.android.lib.resources.files.services.implementation.OCChunkService
+import com.owncloud.android.presentation.authentication.AccountUtils
import com.owncloud.android.utils.NotificationUtils
import com.owncloud.android.utils.RemoteFileUtils.Companion.getAvailableRemotePath
import com.owncloud.android.utils.SecurityUtils
@@ -194,17 +195,8 @@ class UploadFileFromContentUriWorker(
inputStream?.close()
outputStream.close()
+ transferRepository.updateTransferSourcePath(uploadIdInStorageManager, contentUri.toString())
transferRepository.updateTransferLocalPath(uploadIdInStorageManager, cachePath)
-
- // File is already in cache, so the original one can be removed if the behaviour is MOVE
- if (behavior == UploadBehavior.MOVE) {
- removeLocalFile()
- }
- }
-
- private fun removeLocalFile() {
- val documentFile = DocumentFile.fromSingleUri(appContext, contentUri)
- documentFile?.delete()
}
private fun getClientForThisUpload(): OwnCloudClient =
diff --git a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromFileSystemWorker.kt b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromFileSystemWorker.kt
index c0b4180ea24..1942d2674be 100644
--- a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromFileSystemWorker.kt
+++ b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromFileSystemWorker.kt
@@ -27,7 +27,6 @@ import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.owncloud.android.R
-import com.owncloud.android.presentation.authentication.AccountUtils
import com.owncloud.android.data.executeRemoteOperation
import com.owncloud.android.domain.camerauploads.model.UploadBehavior
import com.owncloud.android.domain.capabilities.usecases.GetStoredCapabilitiesUseCase
@@ -55,6 +54,7 @@ import com.owncloud.android.lib.resources.files.UploadFileFromFileSystemOperatio
import com.owncloud.android.lib.resources.files.chunks.ChunkedUploadFromFileSystemOperation
import com.owncloud.android.lib.resources.files.chunks.ChunkedUploadFromFileSystemOperation.Companion.CHUNK_SIZE
import com.owncloud.android.lib.resources.files.services.implementation.OCChunkService
+import com.owncloud.android.presentation.authentication.AccountUtils
import com.owncloud.android.utils.NotificationUtils
import com.owncloud.android.utils.RemoteFileUtils.Companion.getAvailableRemotePath
import com.owncloud.android.utils.SecurityUtils
@@ -250,8 +250,8 @@ class UploadFileFromFileSystemWorker(
val result = executeRemoteOperation { uploadFileOperation.execute(client) }
- if (result == Unit && behavior == UploadBehavior.MOVE) {
- removeLocalFile()
+ if (result == Unit) {
+ removeLocalFile() // Removed file from tmp folder
}
}
@@ -288,8 +288,8 @@ class UploadFileFromFileSystemWorker(
fileLength = fileSize
)
- // Step 4: Remove local file after uploading
- if (result == Unit && behavior == UploadBehavior.MOVE) {
+ // Step 4: Remove tmp file folder after uploading
+ if (result == Unit) {
removeLocalFile()
}
}
diff --git a/owncloudData/schemas/com.owncloud.android.data.OwncloudDatabase/45.json b/owncloudData/schemas/com.owncloud.android.data.OwncloudDatabase/45.json
new file mode 100644
index 00000000000..4aca004c8b6
--- /dev/null
+++ b/owncloudData/schemas/com.owncloud.android.data.OwncloudDatabase/45.json
@@ -0,0 +1,1128 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 45,
+ "identityHash": "c31966355395e44a297570c614cd97d1",
+ "entities": [
+ {
+ "tableName": "app_registry",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`account_name` TEXT NOT NULL, `mime_type` TEXT NOT NULL, `ext` TEXT, `app_providers` TEXT NOT NULL, `name` TEXT, `icon` TEXT, `description` TEXT, `allow_creation` INTEGER, `default_application` TEXT, PRIMARY KEY(`account_name`, `mime_type`))",
+ "fields": [
+ {
+ "fieldPath": "accountName",
+ "columnName": "account_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mimeType",
+ "columnName": "mime_type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "ext",
+ "columnName": "ext",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "appProviders",
+ "columnName": "app_providers",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "icon",
+ "columnName": "icon",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "allowCreation",
+ "columnName": "allow_creation",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "defaultApplication",
+ "columnName": "default_application",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "account_name",
+ "mime_type"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "folder_backup",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountName` TEXT NOT NULL, `behavior` TEXT NOT NULL, `sourcePath` TEXT NOT NULL, `uploadPath` TEXT NOT NULL, `wifiOnly` INTEGER NOT NULL, `chargingOnly` INTEGER NOT NULL, `name` TEXT NOT NULL, `lastSyncTimestamp` INTEGER NOT NULL, `spaceId` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "accountName",
+ "columnName": "accountName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "behavior",
+ "columnName": "behavior",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "sourcePath",
+ "columnName": "sourcePath",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "uploadPath",
+ "columnName": "uploadPath",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "wifiOnly",
+ "columnName": "wifiOnly",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "chargingOnly",
+ "columnName": "chargingOnly",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lastSyncTimestamp",
+ "columnName": "lastSyncTimestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "spaceId",
+ "columnName": "spaceId",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "capabilities",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`account` TEXT, `version_major` INTEGER NOT NULL, `version_minor` INTEGER NOT NULL, `version_micro` INTEGER NOT NULL, `version_string` TEXT, `version_edition` TEXT, `core_pollinterval` INTEGER NOT NULL, `dav_chunking_version` TEXT NOT NULL, `sharing_api_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_write` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_public_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_days` INTEGER NOT NULL, `sharing_public_expire_date_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_upload` INTEGER NOT NULL DEFAULT -1, `sharing_public_multiple` INTEGER NOT NULL DEFAULT -1, `supports_upload_only` INTEGER NOT NULL DEFAULT -1, `sharing_resharing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_outgoing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_incoming` INTEGER NOT NULL DEFAULT -1, `sharing_user_profile_picture` INTEGER NOT NULL DEFAULT -1, `files_bigfilechunking` INTEGER NOT NULL DEFAULT -1, `files_undelete` INTEGER NOT NULL DEFAULT -1, `files_versioning` INTEGER NOT NULL DEFAULT -1, `files_private_links` INTEGER NOT NULL DEFAULT -1, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `app_providers_enabled` INTEGER, `app_providers_version` TEXT, `app_providers_appsUrl` TEXT, `app_providers_openUrl` TEXT, `app_providers_openWebUrl` TEXT, `app_providers_newUrl` TEXT, `spaces_enabled` INTEGER, `spaces_projects` INTEGER, `spaces_shareJail` INTEGER, `password_policy_maxCharacters` INTEGER, `password_policy_minCharacters` INTEGER, `password_policy_minDigits` INTEGER, `password_policy_minLowercaseCharacters` INTEGER, `password_policy_minSpecialCharacters` INTEGER, `password_policy_minUppercaseCharacters` INTEGER)",
+ "fields": [
+ {
+ "fieldPath": "accountName",
+ "columnName": "account",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "versionMajor",
+ "columnName": "version_major",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "versionMinor",
+ "columnName": "version_minor",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "versionMicro",
+ "columnName": "version_micro",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "versionString",
+ "columnName": "version_string",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "versionEdition",
+ "columnName": "version_edition",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "corePollInterval",
+ "columnName": "core_pollinterval",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "davChunkingVersion",
+ "columnName": "dav_chunking_version",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "filesSharingApiEnabled",
+ "columnName": "sharing_api_enabled",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicEnabled",
+ "columnName": "sharing_public_enabled",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicPasswordEnforced",
+ "columnName": "sharing_public_password_enforced",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicPasswordEnforcedReadOnly",
+ "columnName": "sharing_public_password_enforced_read_only",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicPasswordEnforcedReadWrite",
+ "columnName": "sharing_public_password_enforced_read_write",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicPasswordEnforcedUploadOnly",
+ "columnName": "sharing_public_password_enforced_public_only",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicExpireDateEnabled",
+ "columnName": "sharing_public_expire_date_enabled",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicExpireDateDays",
+ "columnName": "sharing_public_expire_date_days",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "filesSharingPublicExpireDateEnforced",
+ "columnName": "sharing_public_expire_date_enforced",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicUpload",
+ "columnName": "sharing_public_upload",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicMultiple",
+ "columnName": "sharing_public_multiple",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingPublicSupportsUploadOnly",
+ "columnName": "supports_upload_only",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingResharing",
+ "columnName": "sharing_resharing",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingFederationOutgoing",
+ "columnName": "sharing_federation_outgoing",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingFederationIncoming",
+ "columnName": "sharing_federation_incoming",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesSharingUserProfilePicture",
+ "columnName": "sharing_user_profile_picture",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesBigFileChunking",
+ "columnName": "files_bigfilechunking",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesUndelete",
+ "columnName": "files_undelete",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesVersioning",
+ "columnName": "files_versioning",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "filesPrivateLinks",
+ "columnName": "files_private_links",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "-1"
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "appProviders.enabled",
+ "columnName": "app_providers_enabled",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "appProviders.version",
+ "columnName": "app_providers_version",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "appProviders.appsUrl",
+ "columnName": "app_providers_appsUrl",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "appProviders.openUrl",
+ "columnName": "app_providers_openUrl",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "appProviders.openWebUrl",
+ "columnName": "app_providers_openWebUrl",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "appProviders.newUrl",
+ "columnName": "app_providers_newUrl",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "spaces.enabled",
+ "columnName": "spaces_enabled",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "spaces.projects",
+ "columnName": "spaces_projects",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "spaces.shareJail",
+ "columnName": "spaces_shareJail",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "passwordPolicy.maxCharacters",
+ "columnName": "password_policy_maxCharacters",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "passwordPolicy.minCharacters",
+ "columnName": "password_policy_minCharacters",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "passwordPolicy.minDigits",
+ "columnName": "password_policy_minDigits",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "passwordPolicy.minLowercaseCharacters",
+ "columnName": "password_policy_minLowercaseCharacters",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "passwordPolicy.minSpecialCharacters",
+ "columnName": "password_policy_minSpecialCharacters",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "passwordPolicy.minUppercaseCharacters",
+ "columnName": "password_policy_minUppercaseCharacters",
+ "affinity": "INTEGER",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "files",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`parentId` INTEGER, `owner` TEXT NOT NULL, `remotePath` TEXT NOT NULL, `remoteId` TEXT, `length` INTEGER NOT NULL, `creationTimestamp` INTEGER, `modificationTimestamp` INTEGER NOT NULL, `mimeType` TEXT NOT NULL, `etag` TEXT, `permissions` TEXT, `privateLink` TEXT, `storagePath` TEXT, `name` TEXT, `treeEtag` TEXT, `keepInSync` INTEGER, `lastSyncDateForData` INTEGER, `lastUsage` INTEGER, `fileShareViaLink` INTEGER, `needsToUpdateThumbnail` INTEGER NOT NULL, `modifiedAtLastSyncForData` INTEGER, `etagInConflict` TEXT, `fileIsDownloading` INTEGER, `sharedWithSharee` INTEGER, `sharedByLink` INTEGER NOT NULL, `spaceId` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, FOREIGN KEY(`owner`, `spaceId`) REFERENCES `spaces`(`account_name`, `space_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "parentId",
+ "columnName": "parentId",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "owner",
+ "columnName": "owner",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "remotePath",
+ "columnName": "remotePath",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "remoteId",
+ "columnName": "remoteId",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "length",
+ "columnName": "length",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "creationTimestamp",
+ "columnName": "creationTimestamp",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "modificationTimestamp",
+ "columnName": "modificationTimestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mimeType",
+ "columnName": "mimeType",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "etag",
+ "columnName": "etag",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "permissions",
+ "columnName": "permissions",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "privateLink",
+ "columnName": "privateLink",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "storagePath",
+ "columnName": "storagePath",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "treeEtag",
+ "columnName": "treeEtag",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "availableOfflineStatus",
+ "columnName": "keepInSync",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "lastSyncDateForData",
+ "columnName": "lastSyncDateForData",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "lastUsage",
+ "columnName": "lastUsage",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "fileShareViaLink",
+ "columnName": "fileShareViaLink",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "needsToUpdateThumbnail",
+ "columnName": "needsToUpdateThumbnail",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "modifiedAtLastSyncForData",
+ "columnName": "modifiedAtLastSyncForData",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "etagInConflict",
+ "columnName": "etagInConflict",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "fileIsDownloading",
+ "columnName": "fileIsDownloading",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "sharedWithSharee",
+ "columnName": "sharedWithSharee",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "sharedByLink",
+ "columnName": "sharedByLink",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "spaceId",
+ "columnName": "spaceId",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "spaces",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "owner",
+ "spaceId"
+ ],
+ "referencedColumns": [
+ "account_name",
+ "space_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "files_sync",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`fileId` INTEGER NOT NULL, `uploadWorkerUuid` BLOB, `downloadWorkerUuid` BLOB, `isSynchronizing` INTEGER NOT NULL, PRIMARY KEY(`fileId`), FOREIGN KEY(`fileId`) REFERENCES `files`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "fileId",
+ "columnName": "fileId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "uploadWorkerUuid",
+ "columnName": "uploadWorkerUuid",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "downloadWorkerUuid",
+ "columnName": "downloadWorkerUuid",
+ "affinity": "BLOB",
+ "notNull": false
+ },
+ {
+ "fieldPath": "isSynchronizing",
+ "columnName": "isSynchronizing",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "fileId"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "files",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "fileId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "ocshares",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`share_type` INTEGER NOT NULL, `share_with` TEXT, `path` TEXT NOT NULL, `permissions` INTEGER NOT NULL, `shared_date` INTEGER NOT NULL, `expiration_date` INTEGER NOT NULL, `token` TEXT, `shared_with_display_name` TEXT, `share_with_additional_info` TEXT, `is_directory` INTEGER NOT NULL, `id_remote_shared` TEXT NOT NULL, `owner_share` TEXT NOT NULL, `name` TEXT, `url` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "shareType",
+ "columnName": "share_type",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shareWith",
+ "columnName": "share_with",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "path",
+ "columnName": "path",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "permissions",
+ "columnName": "permissions",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "sharedDate",
+ "columnName": "shared_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "expirationDate",
+ "columnName": "expiration_date",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "token",
+ "columnName": "token",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "sharedWithDisplayName",
+ "columnName": "shared_with_display_name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "sharedWithAdditionalInfo",
+ "columnName": "share_with_additional_info",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "isFolder",
+ "columnName": "is_directory",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "remoteId",
+ "columnName": "id_remote_shared",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "accountOwner",
+ "columnName": "owner_share",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "shareLink",
+ "columnName": "url",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "transfers",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localPath` TEXT NOT NULL, `remotePath` TEXT NOT NULL, `accountName` TEXT NOT NULL, `fileSize` INTEGER NOT NULL, `status` INTEGER NOT NULL, `localBehaviour` INTEGER NOT NULL, `forceOverwrite` INTEGER NOT NULL, `transferEndTimestamp` INTEGER, `lastResult` INTEGER, `createdBy` INTEGER NOT NULL, `transferId` TEXT, `spaceId` TEXT, `sourcePath` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "localPath",
+ "columnName": "localPath",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "remotePath",
+ "columnName": "remotePath",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "accountName",
+ "columnName": "accountName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "fileSize",
+ "columnName": "fileSize",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "status",
+ "columnName": "status",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "localBehaviour",
+ "columnName": "localBehaviour",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "forceOverwrite",
+ "columnName": "forceOverwrite",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "transferEndTimestamp",
+ "columnName": "transferEndTimestamp",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "lastResult",
+ "columnName": "lastResult",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "createdBy",
+ "columnName": "createdBy",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "transferId",
+ "columnName": "transferId",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "spaceId",
+ "columnName": "spaceId",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "sourcePath",
+ "columnName": "sourcePath",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "spaces",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`account_name` TEXT NOT NULL, `drive_alias` TEXT NOT NULL, `drive_type` TEXT NOT NULL, `space_id` TEXT NOT NULL, `last_modified_date_time` TEXT, `name` TEXT NOT NULL, `owner_id` TEXT, `web_url` TEXT NOT NULL, `description` TEXT, `quota_remaining` INTEGER, `quota_state` TEXT, `quota_total` INTEGER, `quota_used` INTEGER, `root_etag` TEXT, `root_id` TEXT NOT NULL, `root_web_dav_url` TEXT NOT NULL, `root_deleted_state` TEXT, PRIMARY KEY(`account_name`, `space_id`))",
+ "fields": [
+ {
+ "fieldPath": "accountName",
+ "columnName": "account_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "driveAlias",
+ "columnName": "drive_alias",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "driveType",
+ "columnName": "drive_type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "space_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lastModifiedDateTime",
+ "columnName": "last_modified_date_time",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "ownerId",
+ "columnName": "owner_id",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "webUrl",
+ "columnName": "web_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "description",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "quota.remaining",
+ "columnName": "quota_remaining",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "quota.state",
+ "columnName": "quota_state",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "quota.total",
+ "columnName": "quota_total",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "quota.used",
+ "columnName": "quota_used",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "root.eTag",
+ "columnName": "root_etag",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "root.id",
+ "columnName": "root_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "root.webDavUrl",
+ "columnName": "root_web_dav_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "root.deleteState",
+ "columnName": "root_deleted_state",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "account_name",
+ "space_id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "spaces_special",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`spaces_special_account_name` TEXT NOT NULL, `spaces_special_space_id` TEXT NOT NULL, `spaces_special_etag` TEXT NOT NULL, `file_mime_type` TEXT NOT NULL, `special_id` TEXT NOT NULL, `last_modified_date_time` TEXT NOT NULL, `name` TEXT NOT NULL, `size` INTEGER NOT NULL, `special_folder_name` TEXT NOT NULL, `special_web_dav_url` TEXT NOT NULL, PRIMARY KEY(`spaces_special_space_id`, `special_id`), FOREIGN KEY(`spaces_special_account_name`, `spaces_special_space_id`) REFERENCES `spaces`(`account_name`, `space_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "accountName",
+ "columnName": "spaces_special_account_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "spaceId",
+ "columnName": "spaces_special_space_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "eTag",
+ "columnName": "spaces_special_etag",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "fileMimeType",
+ "columnName": "file_mime_type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "id",
+ "columnName": "special_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lastModifiedDateTime",
+ "columnName": "last_modified_date_time",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "size",
+ "columnName": "size",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "specialFolderName",
+ "columnName": "special_folder_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "webDavUrl",
+ "columnName": "special_web_dav_url",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "spaces_special_space_id",
+ "special_id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "spaces",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "spaces_special_account_name",
+ "spaces_special_space_id"
+ ],
+ "referencedColumns": [
+ "account_name",
+ "space_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "user_quotas",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountName` TEXT NOT NULL, `used` INTEGER NOT NULL, `available` INTEGER NOT NULL, PRIMARY KEY(`accountName`))",
+ "fields": [
+ {
+ "fieldPath": "accountName",
+ "columnName": "accountName",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "used",
+ "columnName": "used",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "available",
+ "columnName": "available",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "accountName"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c31966355395e44a297570c614cd97d1')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/OwncloudDatabase.kt b/owncloudData/src/main/java/com/owncloud/android/data/OwncloudDatabase.kt
index 6613a7f20f7..b923e56a772 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/OwncloudDatabase.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/OwncloudDatabase.kt
@@ -79,6 +79,7 @@ import com.owncloud.android.data.user.db.UserQuotaEntity
AutoMigration(from = 39, to = 40, spec = AutoMigration39To40::class),
AutoMigration(from = 40, to = 41),
AutoMigration(from = 43, to = 44),
+ AutoMigration(from = 44, to = 45),
],
version = ProviderMeta.DB_VERSION,
exportSchema = true
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/ProviderMeta.java b/owncloudData/src/main/java/com/owncloud/android/data/ProviderMeta.java
index ace813be3e2..71f09044d5f 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/ProviderMeta.java
+++ b/owncloudData/src/main/java/com/owncloud/android/data/ProviderMeta.java
@@ -31,7 +31,7 @@ public class ProviderMeta {
public static final String DB_NAME = "filelist";
public static final String NEW_DB_NAME = "owncloud_database";
- public static final int DB_VERSION = 44;
+ public static final int DB_VERSION = 45;
private ProviderMeta() {
}
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/LocalTransferDataSource.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/LocalTransferDataSource.kt
index 4662bb6c452..f46bcdaae49 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/LocalTransferDataSource.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/LocalTransferDataSource.kt
@@ -2,8 +2,9 @@
* ownCloud Android client application
*
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2022 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -38,6 +39,7 @@ interface LocalTransferDataSource {
)
fun updateTransferLocalPath(id: Long, localPath: String)
+ fun updateTransferSourcePath(id: Long, sourcePath: String)
fun updateTransferStorageDirectoryInLocalPath(
id: Long,
oldDirectory: String,
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSource.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSource.kt
index dfde793f7db..e149545590a 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSource.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSource.kt
@@ -2,8 +2,9 @@
* ownCloud Android client application
*
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2023 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -64,6 +65,10 @@ class OCLocalTransferDataSource(
transferDao.updateTransferLocalPath(id, localPath)
}
+ override fun updateTransferSourcePath(id: Long, sourcePath: String) {
+ transferDao.updateTransferSourcePath(id, sourcePath)
+ }
+
override fun updateTransferStorageDirectoryInLocalPath(
id: Long,
oldDirectory: String,
@@ -163,6 +168,7 @@ class OCLocalTransferDataSource(
createdBy = UploadEnqueuedBy.values()[createdBy],
transferId = transferId,
spaceId = spaceId,
+ sourcePath = sourcePath,
)
@VisibleForTesting
fun OCTransfer.toEntity() = OCTransferEntity(
@@ -178,6 +184,7 @@ class OCLocalTransferDataSource(
createdBy = createdBy.ordinal,
transferId = transferId,
spaceId = spaceId,
+ sourcePath = sourcePath,
).apply { this@toEntity.id?.let { this.id = it } }
}
}
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/OCTransferEntity.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/OCTransferEntity.kt
index 32d3da8f56e..96d9813e772 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/OCTransferEntity.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/OCTransferEntity.kt
@@ -2,8 +2,9 @@
* ownCloud Android client application
*
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2023 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -54,6 +55,7 @@ data class OCTransferEntity(
val createdBy: Int,
val transferId: String? = null,
val spaceId: String? = null,
+ val sourcePath: String? = null,
) {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/TransferDao.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/TransferDao.kt
index ce4b17e8bdc..56f358626ff 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/TransferDao.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/TransferDao.kt
@@ -2,8 +2,9 @@
* ownCloud Android client application
*
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2022 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -56,6 +57,9 @@ interface TransferDao {
@Query(UPDATE_TRANSFER_LOCAL_PATH_WITH_ID)
fun updateTransferLocalPath(id: Long, localPath: String)
+ @Query(UPDATE_TRANSFER_SOURCE_PATH_WITH_ID)
+ fun updateTransferSourcePath(id: Long, sourcePath: String)
+
@Query(UPDATE_TRANSFER_STORAGE_DIRECTORY)
fun updateTransferStorageDirectoryInLocalPath(id: Long, oldDirectory: String, newDirectory: String)
@@ -111,7 +115,11 @@ interface TransferDao {
SET localPath = :localPath
WHERE id = :id
"""
-
+ private const val UPDATE_TRANSFER_SOURCE_PATH_WITH_ID = """
+ UPDATE $TRANSFERS_TABLE_NAME
+ SET sourcePath = :sourcePath
+ WHERE id = :id
+ """
private const val UPDATE_TRANSFER_STORAGE_DIRECTORY = """
UPDATE $TRANSFERS_TABLE_NAME
SET localPath = `REPLACE`(localPath, :oldDirectory, :newDirectory)
diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/repository/OCTransferRepository.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/repository/OCTransferRepository.kt
index 00f5e196fdc..7f3c07a9499 100644
--- a/owncloudData/src/main/java/com/owncloud/android/data/transfers/repository/OCTransferRepository.kt
+++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/repository/OCTransferRepository.kt
@@ -2,8 +2,9 @@
* ownCloud Android client application
*
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2022 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -48,6 +49,10 @@ class OCTransferRepository(
localTransferDataSource.updateTransferLocalPath(id = id, localPath = localPath)
}
+ override fun updateTransferSourcePath(id: Long, sourcePath: String) {
+ localTransferDataSource.updateTransferSourcePath(id = id, sourcePath = sourcePath)
+ }
+
override fun updateTransferWhenFinished(
id: Long,
status: TransferStatus,
diff --git a/owncloudData/src/test/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSourceTest.kt b/owncloudData/src/test/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSourceTest.kt
index ba092c8c330..df3bcca4496 100644
--- a/owncloudData/src/test/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSourceTest.kt
+++ b/owncloudData/src/test/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSourceTest.kt
@@ -122,6 +122,16 @@ class OCLocalTransferDataSourceTest {
}
}
+ @Test
+ fun `updateTransferSourcePath changes transfer source path correctly`() {
+
+ ocLocalTransferDataSource.updateTransferSourcePath(OC_TRANSFER.id!!, OC_TRANSFER.sourcePath!!)
+
+ verify(exactly = 1) {
+ transferDao.updateTransferSourcePath(OC_TRANSFER.id!!, OC_TRANSFER.sourcePath!!)
+ }
+ }
+
@Test
fun `updateTransferStorageDirectoryInLocalPath changes directory correctly`() {
val oldDirectory = "oldDirectory"
diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/TransferRepository.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/TransferRepository.kt
index 23855a3a93c..5eea7df2daf 100644
--- a/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/TransferRepository.kt
+++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/TransferRepository.kt
@@ -2,8 +2,9 @@
* ownCloud Android client application
*
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2022 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -31,6 +32,7 @@ interface TransferRepository {
fun updateTransferStatusToInProgressById(id: Long)
fun updateTransferStatusToEnqueuedById(id: Long)
fun updateTransferLocalPath(id: Long, localPath: String)
+ fun updateTransferSourcePath(id: Long, sourcePath: String)
fun updateTransferWhenFinished(
id: Long,
status: TransferStatus,
diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/OCTransfer.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/OCTransfer.kt
index b757d45c9e8..aa4733f6d8d 100644
--- a/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/OCTransfer.kt
+++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/OCTransfer.kt
@@ -2,8 +2,9 @@
* ownCloud Android client application
*
* @author Juan Carlos Garrote Gascón
+ * @author Aitor Ballesteros Pavón
*
- * Copyright (C) 2023 ownCloud GmbH.
+ * Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -40,6 +41,7 @@ data class OCTransfer(
val createdBy: UploadEnqueuedBy,
val transferId: String? = null,
val spaceId: String? = null,
+ val sourcePath: String? = null,
) : Parcelable {
init {
if (!remotePath.startsWith(File.separator)) throw IllegalArgumentException("Remote path must be an absolute path in the local file system")
diff --git a/owncloudTestUtil/src/main/java/com/owncloud/android/testutil/OCTransfer.kt b/owncloudTestUtil/src/main/java/com/owncloud/android/testutil/OCTransfer.kt
index 8ed70060c45..e66031b5a78 100644
--- a/owncloudTestUtil/src/main/java/com/owncloud/android/testutil/OCTransfer.kt
+++ b/owncloudTestUtil/src/main/java/com/owncloud/android/testutil/OCTransfer.kt
@@ -34,5 +34,6 @@ val OC_TRANSFER = OCTransfer(
status = TransferStatus.TRANSFER_IN_PROGRESS,
localBehaviour = UploadBehavior.MOVE,
forceOverwrite = true,
- createdBy = UploadEnqueuedBy.ENQUEUED_BY_USER
+ createdBy = UploadEnqueuedBy.ENQUEUED_BY_USER,
+ sourcePath = "/source/path",
)