Add FileOperationHelper

Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2024-08-21 15:22:34 +02:00
parent 98bab61143
commit 153fd9b049
No known key found for this signature in database
GPG key ID: 4E577DC593B59BDF
4 changed files with 104 additions and 28 deletions

View file

@ -28,6 +28,7 @@ import com.nextcloud.client.core.ClockImpl;
import com.nextcloud.client.core.ThreadPoolAsyncRunner;
import com.nextcloud.client.database.dao.ArbitraryDataDao;
import com.nextcloud.client.device.DeviceInfo;
import com.nextcloud.client.jobs.operation.FileOperationHelper;
import com.nextcloud.client.logger.FileLogHandler;
import com.nextcloud.client.logger.Logger;
import com.nextcloud.client.logger.LoggerImpl;
@ -250,6 +251,11 @@ class AppModule {
return new PassCodeManager(preferences, clock);
}
@Provides
FileOperationHelper fileOperationHelper(CurrentAccountProvider currentAccountProvider, Context context) {
return new FileOperationHelper(currentAccountProvider.getUser(), context, fileDataStorageManager(currentAccountProvider, context));
}
@Provides
@Singleton
UsersAndGroupsSearchConfig userAndGroupSearchConfig() {

View file

@ -0,0 +1,52 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.client.jobs.operation
import android.content.Context
import com.nextcloud.client.account.User
import com.nextcloud.client.network.ClientFactoryImpl
import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.operations.RemoveFileOperation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
class FileOperationHelper(
private val user: User,
private val context: Context,
private val fileDataStorageManager: FileDataStorageManager
) {
companion object {
private val TAG = FileOperationHelper::class.java.simpleName
}
private val clientFactory = ClientFactoryImpl(context)
private val client = clientFactory.create(user)
@Suppress("TooGenericExceptionCaught", "Deprecation")
suspend fun removeFile(file: OCFile, onlyLocalCopy: Boolean, inBackground: Boolean): Boolean = coroutineScope {
try {
async(Dispatchers.IO) {
RemoveFileOperation(
file,
onlyLocalCopy,
user,
inBackground,
context,
fileDataStorageManager
)
}.await().execute(client).isSuccess
} catch (e: Exception) {
Log_OC.e(TAG, "Error occurred while removing file: $e")
false
}
}
}

View file

@ -17,8 +17,10 @@ import android.widget.Toast
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.lifecycleScope
import com.nextcloud.client.account.User
import com.nextcloud.client.database.entity.OfflineOperationEntity
import com.nextcloud.client.jobs.download.FileDownloadHelper
import com.nextcloud.client.jobs.offlineOperations.OfflineOperationsNotificationManager
import com.nextcloud.client.jobs.operation.FileOperationHelper
import com.nextcloud.client.jobs.upload.FileUploadHelper
import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.jobs.upload.UploadNotificationManager
@ -36,6 +38,7 @@ import com.owncloud.android.lib.resources.files.model.RemoteFile
import com.owncloud.android.ui.dialog.ConflictsResolveDialog
import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Decision
import com.owncloud.android.ui.dialog.ConflictsResolveDialog.OnConflictDecisionMadeListener
import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.FileStorageUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -48,6 +51,9 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
@Inject
lateinit var uploadsStorageManager: UploadsStorageManager
@Inject
lateinit var fileOperationHelper: FileOperationHelper
private var conflictUploadId: Long = 0
private var offlineOperationPath: String? = null
private var existingFile: OCFile? = null
@ -97,15 +103,19 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
// version
val user = user.orElseThrow { RuntimeException() }
val offlineOperation = if (offlineOperationPath != null) {
fileDataStorageManager.offlineOperationDao.getByPath(offlineOperationPath!!)
} else {
null
}
when (decision) {
Decision.KEEP_LOCAL -> keepLocal(file, upload, user)
Decision.KEEP_BOTH -> keepBoth(file, upload, user)
Decision.KEEP_SERVER -> keepServer(file, upload)
Decision.KEEP_OFFLINE_FOLDER,
Decision.KEEP_SERVER_FOLDER,
Decision.KEEP_BOTH_FOLDER -> handleFolderConflict(decision)
Decision.KEEP_OFFLINE_FOLDER -> keepOfflineFolder(newFile, offlineOperation)
Decision.KEEP_SERVER_FOLDER -> keepServerFile(offlineOperation)
Decision.KEEP_BOTH_FOLDER -> keepBothFolder(offlineOperation)
Decision.CANCEL -> Unit
else -> Unit
}
@ -114,32 +124,39 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
}
}
private fun handleFolderConflict(decision: Decision) {
val path = offlineOperationPath ?: return
val serverFile = newFile ?: return
val offlineOperation = fileDataStorageManager.offlineOperationDao.getByPath(path) ?: return
when(decision) {
Decision.KEEP_OFFLINE_FOLDER -> {
fileOperationsHelper?.removeFiles(listOf(serverFile), false, false)
backgroundJobManager.startOfflineOperations()
}
Decision.KEEP_SERVER_FOLDER -> {
fileDataStorageManager.offlineOperationDao.deleteByPath(path)
}
Decision.KEEP_BOTH_FOLDER -> {
fileDataStorageManager.keepOfflineOperationAndServerFile(offlineOperation)
backgroundJobManager.startOfflineOperations()
}
else -> Unit
}
private fun keepBothFolder(offlineOperation: OfflineOperationEntity?) {
offlineOperation ?: return
fileDataStorageManager.keepOfflineOperationAndServerFile(offlineOperation)
backgroundJobManager.startOfflineOperations()
offlineOperationNotificationManager.dismissNotification(offlineOperation.id)
}
private fun keepServerFile(offlineOperation: OfflineOperationEntity?) {
val path = offlineOperation?.path ?: return
fileDataStorageManager.offlineOperationDao.deleteByPath(path)
val id = offlineOperation.id ?: return
offlineOperationNotificationManager.dismissNotification(id)
}
private fun keepOfflineFolder(serverFile: OCFile?, offlineOperation: OfflineOperationEntity?) {
serverFile ?: return
offlineOperation ?: return
lifecycleScope.launch {
val success = fileOperationHelper.removeFile(serverFile, false, false)
if (success) {
backgroundJobManager.startOfflineOperations()
offlineOperationNotificationManager.dismissNotification(offlineOperation.id)
} else {
DisplayUtils.showSnackMessage(
this@ConflictsResolveActivity,
R.string.conflict_resolver_activity_keep_offline_folder_error_message
)
}
}
}
private fun keepLocal(file: OCFile?, upload: OCUpload?, user: User) {
upload?.let {
FileUploadHelper.instance().removeFileUpload(it.remotePath, it.accountName)

View file

@ -1030,6 +1030,7 @@
<string name="sync_not_enough_space_dialog_title">Not enough space</string>
<string name="conflict_file_headline">Conflicting file %1$s</string>
<string name="conflict_folder_headline">Folder Conflict</string>
<string name="conflict_resolver_activity_keep_offline_folder_error_message">Error occurred during deleting the remote file</string>
<string name="conflict_message_description_for_folder">If you select both versions, the local folder will have a number appended to its name.</string>
<string name="conflict_message_description">If you select both versions, the local file will have a number appended to its name.</string>
<string name="conflict_local_file">Local file</string>