Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.jobs.utils.UploadErrorNotificationManager
import com.nextcloud.client.network.ConnectivityService
import com.nextcloud.utils.extensions.getLog
import com.nextcloud.utils.extensions.isConflict
import com.nextcloud.utils.extensions.isNonRetryable
import com.nextcloud.utils.extensions.updateStatus
import com.owncloud.android.R
Expand Down Expand Up @@ -319,7 +320,7 @@ class AutoUploadWorker(
)

// Mark CONFLICT files as handled to prevent retries
if (result.code == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {
if (result.code.isConflict()) {
repository.markFileAsHandled(localPath, syncedFolder)
Log_OC.w(TAG, "Marked CONFLICT file as handled: $localPath")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.nextcloud.client.network.ConnectivityService
import com.nextcloud.client.notifications.AppWideNotificationManager
import com.nextcloud.utils.extensions.checkWCFRestrictions
import com.nextcloud.utils.extensions.getUploadIds
import com.nextcloud.utils.extensions.isLastResultConflictError
import com.owncloud.android.MainApp
import com.owncloud.android.R
import com.owncloud.android.datamodel.FileDataStorageManager
Expand Down Expand Up @@ -180,7 +181,7 @@ class FileUploadHelper {
val uploadsToRetry = mutableListOf<Long>()

for (upload in uploads) {
if (upload.lastResult == UploadResult.SYNC_CONFLICT) {
if (upload.isLastResultConflictError()) {
Log_OC.d(TAG, "retry upload skipped, sync conflict: ${upload.remotePath}")
showSyncConflictNotification = true
continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.core.app.NotificationCompat
import com.nextcloud.client.jobs.notification.WorkerNotificationManager
import com.nextcloud.client.jobs.upload.FileUploadHelper
import com.nextcloud.client.jobs.upload.UploadBroadcastAction
import com.nextcloud.utils.extensions.isConflict
import com.nextcloud.utils.extensions.isFileSpecificError
import com.owncloud.android.R
import com.owncloud.android.authentication.AuthenticatorActivity
Expand All @@ -33,11 +34,11 @@ object UploadErrorNotificationManager {

/**
* Processes the result of an upload operation and manages error notifications.
* * It filters out successful or silent results and handles [ResultCode.SYNC_CONFLICT]
* * It filters out successful or silent results and handles [ResultCode.SYNC_CONFLICT], [ResultCode.CONFLICT]
* by checking if the remote file is identical. If it's a "real" conflict or error,
* it displays a notification with relevant actions (e.g., Resolve Conflict, Pause, Cancel).
*
* @param onSameFileConflict Triggered only if result code is SYNC_CONFLICT and files are identical.
* @param onSameFileConflict Triggered only if result code is CONFLICT or SYNC_CONFLICT and files are identical.
*/
@Suppress("ReturnCount")
suspend fun handleResult(
Expand Down Expand Up @@ -70,7 +71,7 @@ object UploadErrorNotificationManager {
}

// do not show an error notification when uploading the same file again
if (result.code == ResultCode.SYNC_CONFLICT) {
if (result.code.isConflict()) {
val isSameFile = withContext(Dispatchers.IO) {
FileUploadHelper.instance().isSameFileOnRemote(
operation.user,
Expand Down Expand Up @@ -135,7 +136,7 @@ object UploadErrorNotificationManager {
// actions for all error types
addAction(UploadBroadcastAction.PauseAndCancel(operation).cancelAction(context))

if (result.code == ResultCode.SYNC_CONFLICT) {
if (result.code.isConflict()) {
addAction(
R.drawable.ic_cloud_upload,
context.getString(R.string.upload_list_resolve_conflict),
Expand All @@ -152,6 +153,7 @@ object UploadErrorNotificationManager {
private fun ResultCode.toFailedResultTitleId(): Int = when (this) {
ResultCode.UNAUTHORIZED -> R.string.uploader_upload_failed_credentials_error
ResultCode.SYNC_CONFLICT -> R.string.uploader_upload_failed_sync_conflict_error
ResultCode.CONFLICT -> R.string.uploader_upload_failed_sync_conflict_error
else -> R.string.uploader_upload_failed_ticker
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,5 @@ fun OCUpload.getStatusText(activity: Context, isGlobalUploadPaused: Boolean, isU

return status
}

fun OCUpload.isLastResultConflictError(): Boolean = lastResult in UploadResult.CONFLICT_ERRORS
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,12 @@ fun ResultCode.isFileSpecificError(): Boolean {

return !errorCodes.contains(this)
}

fun ResultCode.isConflict(): Boolean {
val errorCodes = listOf(
ResultCode.SYNC_CONFLICT,
ResultCode.CONFLICT
)

return errorCodes.contains(this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ fun UploadResult.isNonRetryable(): Boolean = when (this) {
UploadResult.FOLDER_ERROR,
UploadResult.CANNOT_CREATE_FILE,
UploadResult.SYNC_CONFLICT,
UploadResult.CONFLICT_ERROR,
UploadResult.SAME_FILE_CONFLICT,
UploadResult.LOCAL_STORAGE_NOT_COPIED,
UploadResult.VIRUS_DETECTED,
UploadResult.QUOTA_EXCEEDED,
UploadResult.SAME_FILE_CONFLICT,
UploadResult.PRIVILEGES_ERROR,
UploadResult.CREDENTIAL_ERROR,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.nextcloud.client.jobs.upload.FileUploadHelper;
import com.nextcloud.client.jobs.upload.FileUploadWorker;
import com.nextcloud.utils.autoRename.AutoRename;
import com.nextcloud.utils.extensions.RemoteOperationResultExtensionsKt;
import com.owncloud.android.MainApp;
import com.owncloud.android.db.OCUpload;
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
Expand Down Expand Up @@ -577,7 +578,7 @@ public void updateDatabaseUploadResult(RemoteOperationResult uploadResult, Uploa
if (uploadResult.isSuccess()) {
status = UploadStatus.UPLOAD_SUCCEEDED;
result = UploadResult.UPLOADED;
} else if (code == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {
} else if (RemoteOperationResultExtensionsKt.isConflict(code)) {
boolean isSame = new FileUploadHelper().isSameFileOnRemote(
upload.getUser(), new File(upload.getStoragePath()), upload.getRemotePath(), upload.getContext());

Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/owncloud/android/db/UploadResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

import com.owncloud.android.lib.common.operations.RemoteOperationResult;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public enum UploadResult {
Expand Down Expand Up @@ -51,6 +53,10 @@ public int getValue() {
return value;
}

public static final List<UploadResult> CONFLICT_ERRORS = List.of(
UploadResult.CONFLICT_ERROR,
UploadResult.SYNC_CONFLICT);

private static final Map<Integer, UploadResult> valueMap = Map.ofEntries(
Map.entry(0, UPLOADED),
Map.entry(1, NETWORK_CONNECTION),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.nextcloud.client.network.ConnectivityService;
import com.nextcloud.utils.autoRename.AutoRename;
import com.nextcloud.utils.e2ee.E2EVersionHelper;
import com.nextcloud.utils.extensions.RemoteOperationResultExtensionsKt;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
import com.owncloud.android.datamodel.FileDataStorageManager;
Expand Down Expand Up @@ -913,7 +914,7 @@ private void updateMetadataForV2(DecryptedFolderMetadataFile metadata, Encryptio
private void completeE2EUpload(RemoteOperationResult result, E2EFiles e2eFiles, OwnCloudClient client) {
if (result.isSuccess()) {
handleLocalBehaviour(e2eFiles.getTemporalFile(), e2eFiles.getExpectedFile(), e2eFiles.getOriginalFile(), client);
} else if (result.getCode() == ResultCode.SYNC_CONFLICT) {
} else if (RemoteOperationResultExtensionsKt.isConflict(result.getCode())) {
getStorageManager().saveConflict(mFile, mFile.getEtagInConflict());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.nextcloud.client.jobs.upload.FileUploadHelper
import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.network.ConnectivityService
import com.nextcloud.utils.extensions.getStatusText
import com.nextcloud.utils.extensions.isLastResultConflictError
import com.nextcloud.utils.extensions.setVisibleIf
import com.nextcloud.utils.extensions.sortedByUploadOrder
import com.nextcloud.utils.extensions.toFile
Expand Down Expand Up @@ -418,7 +419,7 @@ class UploadListAdapter(

UploadsStorageManager.UploadStatus.UPLOAD_FAILED -> {
uploadRightButton.run {
if (item.lastResult == UploadResult.SYNC_CONFLICT) {
if (item.isLastResultConflictError()) {
setImageResource(R.drawable.ic_dots_vertical)
setOnClickListener { view ->
optionalUser.ifPresent { user ->
Expand Down Expand Up @@ -466,18 +467,20 @@ class UploadListAdapter(
holder: ItemViewHolder,
status: String
) {
when (item.lastResult) {
UploadResult.CREDENTIAL_ERROR -> {
val user = optionalUser.orElseThrow { RuntimeException() }
activity.fileOperationsHelper.checkCurrentCredentials(user)
}
if (optionalUser.isEmpty) {
return
}
val user = optionalUser.get()

UploadResult.SYNC_CONFLICT if optionalUser.isPresent -> {
if (checkAndOpenConflictResolutionDialog(optionalUser.get(), holder, item, status)) return
retryOrShowError(item)
if (item.lastResult == UploadResult.CREDENTIAL_ERROR) {
activity.fileOperationsHelper.checkCurrentCredentials(user)
} else if (item.isLastResultConflictError()) {
if (checkAndOpenConflictResolutionDialog(user, holder, item, status)) {
return
}

else -> retryOrShowError(item)
retryOrShowError(item)
} else {
retryOrShowError(item)
}
}

Expand Down
Loading