diff --git a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt index 1a8d0df4d2..8cff82456f 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt @@ -24,6 +24,7 @@ import com.nextcloud.client.documentscan.GeneratePdfFromImagesWork import com.nextcloud.client.integrations.deck.DeckApi import com.nextcloud.client.jobs.download.FileDownloadWorker import com.nextcloud.client.jobs.offlineOperations.OfflineOperationsWorker +import com.nextcloud.client.jobs.sync.SyncWorker import com.nextcloud.client.jobs.upload.FileUploadWorker import com.nextcloud.client.logger.Logger import com.nextcloud.client.network.ConnectivityService @@ -98,6 +99,7 @@ class BackgroundJobFactory @Inject constructor( TestJob::class -> createTestJob(context, workerParameters) OfflineOperationsWorker::class -> createOfflineOperationsWorker(context, workerParameters) InternalTwoWaySyncWork::class -> createInternalTwoWaySyncWork(context, workerParameters) + SyncWorker::class -> createSyncWorker(context, workerParameters) else -> null // caller falls back to default factory } } @@ -301,4 +303,12 @@ class BackgroundJobFactory @Inject constructor( preferences ) } + + private fun createSyncWorker(context: Context, params: WorkerParameters): SyncWorker { + return SyncWorker( + accountManager.user, + context, + params + ) + } } diff --git a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManager.kt b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManager.kt index 6201f0439e..fce3cf22a4 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManager.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManager.kt @@ -174,4 +174,5 @@ interface BackgroundJobManager { fun startPeriodicallyOfflineOperation() fun scheduleInternal2WaySync(intervalMinutes: Long) fun cancelAllFilesDownloadJobs() + fun syncFolder(filePaths: List) } diff --git a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt index 7736098433..149018e390 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt @@ -27,6 +27,7 @@ import com.nextcloud.client.di.Injectable import com.nextcloud.client.documentscan.GeneratePdfFromImagesWork import com.nextcloud.client.jobs.download.FileDownloadWorker import com.nextcloud.client.jobs.offlineOperations.OfflineOperationsWorker +import com.nextcloud.client.jobs.sync.SyncWorker import com.nextcloud.client.jobs.upload.FileUploadWorker import com.nextcloud.client.preferences.AppPreferences import com.nextcloud.utils.extensions.isWorkRunning @@ -85,7 +86,7 @@ internal class BackgroundJobManagerImpl( const val JOB_PERIODIC_OFFLINE_OPERATIONS = "periodic_offline_operations" const val JOB_PERIODIC_HEALTH_STATUS = "periodic_health_status" const val JOB_IMMEDIATE_HEALTH_STATUS = "immediate_health_status" - + const val JOB_SYNC_FOLDER = "sync_folder" const val JOB_INTERNAL_TWO_WAY_SYNC = "internal_two_way_sync" const val JOB_TEST = "test_job" @@ -717,4 +718,16 @@ internal class BackgroundJobManagerImpl( workManager.enqueueUniquePeriodicWork(JOB_INTERNAL_TWO_WAY_SYNC, ExistingPeriodicWorkPolicy.UPDATE, request) } + + override fun syncFolder(filePaths: List) { + val data = Data.Builder() + .putStringArray(SyncWorker.FILE_PATHS, filePaths.toTypedArray()) + .build() + + val request = oneTimeRequestBuilder(SyncWorker::class, JOB_SYNC_FOLDER) + .setInputData(data) + .build() + + workManager.enqueueUniqueWork(JOB_SYNC_FOLDER, ExistingWorkPolicy.REPLACE, request) + } } diff --git a/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadHelper.kt b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadHelper.kt index e1ad4662e0..e677b278b8 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadHelper.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/download/FileDownloadHelper.kt @@ -141,4 +141,8 @@ class FileDownloadHelper { conflictUploadId ) } + + fun syncFolder(filePaths: List) { + backgroundJobManager.syncFolder(filePaths) + } } diff --git a/app/src/main/java/com/nextcloud/client/jobs/sync/SyncWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/sync/SyncWorker.kt new file mode 100644 index 0000000000..5d78387ae0 --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/jobs/sync/SyncWorker.kt @@ -0,0 +1,63 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.client.jobs.sync + +import android.content.Context +import androidx.work.CoroutineWorker +import androidx.work.WorkerParameters +import com.nextcloud.client.account.User +import com.owncloud.android.datamodel.FileDataStorageManager +import com.owncloud.android.lib.common.OwnCloudClientManagerFactory +import com.owncloud.android.lib.common.utils.Log_OC +import com.owncloud.android.operations.DownloadFileOperation + +class SyncWorker( + private val user: User, + private val context: Context, + params: WorkerParameters +) : CoroutineWorker(context, params) { + + companion object { + const val FILE_PATHS = "FILE_PATHS" + private const val TAG = "SyncWorker" + } + + @Suppress("DEPRECATION") + override suspend fun doWork(): Result { + Log_OC.d(TAG, "SyncWorker started") + val filePaths = inputData.getStringArray(FILE_PATHS) + + if (filePaths.isNullOrEmpty()) { + return Result.failure() + } + + val fileDataStorageManager = FileDataStorageManager(user, context.contentResolver) + + val account = user.toOwnCloudAccount() + val client = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(account, context) + + var result = true + filePaths.forEach { path -> + fileDataStorageManager.getFileByDecryptedRemotePath(path)?.let { file -> + val operation = DownloadFileOperation(user, file, context).execute(client) + Log_OC.d(TAG, "Syncing file: " + file.decryptedRemotePath) + if (!operation.isSuccess) { + result = false + } + } + } + + return if (result) { + Log_OC.d(TAG, "SyncWorker completed") + Result.success() + } else { + Log_OC.d(TAG, "SyncWorker failed") + Result.failure() + } + } +} diff --git a/app/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java index ee71f0ee60..733293ba49 100644 --- a/app/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -40,6 +40,7 @@ import java.util.List; import java.util.Map; import java.util.Vector; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -500,7 +501,9 @@ public class SynchronizeFolderOperation extends SyncOperation { Log_OC.d(TAG, "Exception caught at startDirectDownloads" + e); } } else { - mFilesForDirectDownload.forEach(file -> fileDownloadHelper.downloadFile(user, file)); + final var filePaths = new ArrayList(); + mFilesForDirectDownload.forEach(file -> filePaths.add(file.getDecryptedRemotePath())); + fileDownloadHelper.syncFolder(filePaths); } }