Skip to content

Commit 134cd4a

Browse files
committed
fix(auto-upload): simplify error notification logic
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
1 parent 3909b9f commit 134cd4a

File tree

2 files changed

+62
-69
lines changed

2 files changed

+62
-69
lines changed

app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ class FileUploadWorker(
380380
notificationManager,
381381
operation,
382382
result,
383-
showSameFileAlreadyExistsNotification = {
383+
onSameFileConflict = {
384384
withContext(Dispatchers.Main) {
385385
val showSameFileAlreadyExistsNotification =
386386
inputData.getBoolean(SHOW_SAME_FILE_ALREADY_EXISTS_NOTIFICATION, false)

app/src/main/java/com/nextcloud/client/jobs/utils/UploadErrorNotificationManager.kt

Lines changed: 61 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -31,35 +31,67 @@ import java.io.File
3131
object UploadErrorNotificationManager {
3232
private const val TAG = "UploadErrorNotificationManager"
3333

34+
/**
35+
* Processes the result of an upload operation and manages error notifications.
36+
* * It filters out successful or silent results and handles [ResultCode.SYNC_CONFLICT]
37+
* by checking if the remote file is identical. If it's a "real" conflict or error,
38+
* it displays a notification with relevant actions (e.g., Resolve Conflict, Pause, Cancel).
39+
*
40+
* @param onSameFileConflict Triggered only if a 409 Conflict occurs but files are identical.
41+
*/
42+
@Suppress("ReturnCount")
3443
suspend fun handleResult(
3544
context: Context,
3645
notificationManager: WorkerNotificationManager,
3746
operation: UploadFileOperation,
3847
result: RemoteOperationResult<Any?>,
39-
showSameFileAlreadyExistsNotification: suspend () -> Unit = {}
48+
onSameFileConflict: suspend () -> Unit = {}
4049
) {
4150
Log_OC.d(TAG, "handle upload result with result code: " + result.code)
4251

43-
val notification = withContext(Dispatchers.IO) {
44-
val isSameFileOnRemote = FileUploadHelper.instance().isSameFileOnRemote(
45-
operation.user,
46-
File(operation.storagePath),
47-
operation.remotePath,
48-
context
49-
)
52+
if (result.isSuccess || result.isCancelled || operation.isMissingPermissionThrown) {
53+
Log_OC.d(TAG, "operation is successful, cancelled or lack of storage permission, notification skipped")
54+
return
55+
}
5056

51-
getNotification(
52-
isSameFileOnRemote,
53-
context,
54-
notificationManager.notificationBuilder,
55-
operation,
56-
result,
57-
notifyOnSameFileExists = {
58-
showSameFileAlreadyExistsNotification()
59-
operation.handleLocalBehaviour()
60-
}
61-
)
62-
} ?: return
57+
val silentCodes = setOf(
58+
ResultCode.DELAYED_FOR_WIFI,
59+
ResultCode.DELAYED_FOR_CHARGING,
60+
ResultCode.DELAYED_IN_POWER_SAVE_MODE,
61+
ResultCode.LOCAL_FILE_NOT_FOUND,
62+
ResultCode.LOCK_FAILED
63+
)
64+
65+
if (result.code in silentCodes) {
66+
Log_OC.d(TAG, "silent error code, notification skipped")
67+
return
68+
}
69+
70+
// Do not show an error notification when uploading the same file again (manual uploads only).
71+
if (result.code == ResultCode.SYNC_CONFLICT) {
72+
val isSameFile = withContext(Dispatchers.IO) {
73+
FileUploadHelper.instance().isSameFileOnRemote(
74+
operation.user,
75+
File(operation.storagePath),
76+
operation.remotePath,
77+
context
78+
)
79+
}
80+
81+
if (isSameFile) {
82+
Log_OC.w(TAG, "exact same file already exists on remote, error notification skipped")
83+
onSameFileConflict()
84+
return
85+
}
86+
}
87+
88+
// now we can show error notification
89+
val notification = getNotification(
90+
context,
91+
notificationManager.notificationBuilder,
92+
operation,
93+
result
94+
)
6395

6496
Log_OC.d(TAG, "🔔" + "notification created")
6597

@@ -72,19 +104,12 @@ object UploadErrorNotificationManager {
72104
}
73105
}
74106

75-
private suspend fun getNotification(
76-
isSameFileOnRemote: Boolean,
107+
private fun getNotification(
77108
context: Context,
78109
builder: NotificationCompat.Builder,
79110
operation: UploadFileOperation,
80-
result: RemoteOperationResult<Any?>,
81-
notifyOnSameFileExists: suspend () -> Unit
82-
): Notification? {
83-
if (!shouldShowConflictDialog(isSameFileOnRemote, operation, result, notifyOnSameFileExists)) {
84-
Log_OC.d(TAG, "no need to show conflict resolve notification")
85-
return null
86-
}
87-
111+
result: RemoteOperationResult<Any?>
112+
): Notification {
88113
val textId = result.code.toFailedResultTitleId()
89114
val errorMessage = ErrorMessageAdapter.getErrorCauseMessage(result, operation, context.resources)
90115

@@ -97,19 +122,19 @@ object UploadErrorNotificationManager {
97122
setProgress(0, 0, false)
98123
clearActions()
99124

100-
result.code.takeIf { it == ResultCode.SYNC_CONFLICT }?.let {
125+
// actions for all error types
126+
addAction(UploadBroadcastAction.PauseAndCancel(operation).pauseAction(context))
127+
addAction(UploadBroadcastAction.PauseAndCancel(operation).cancelAction(context))
128+
129+
if (result.code == ResultCode.SYNC_CONFLICT) {
101130
addAction(
102131
R.drawable.ic_cloud_upload,
103132
context.getString(R.string.upload_list_resolve_conflict),
104133
conflictResolvePendingIntent(context, operation)
105134
)
106135
}
107136

108-
addAction(UploadBroadcastAction.PauseAndCancel(operation).pauseAction(context))
109-
110-
addAction(UploadBroadcastAction.PauseAndCancel(operation).cancelAction(context))
111-
112-
result.code.takeIf { it == ResultCode.UNAUTHORIZED }?.let {
137+
if (result.code == ResultCode.UNAUTHORIZED) {
113138
setContentIntent(credentialPendingIntent(context, operation))
114139
}
115140
}.build()
@@ -162,36 +187,4 @@ object UploadErrorNotificationManager {
162187
PendingIntent.FLAG_IMMUTABLE
163188
)
164189
}
165-
166-
@Suppress("ReturnCount", "ComplexCondition")
167-
private suspend fun shouldShowConflictDialog(
168-
isSameFileOnRemote: Boolean,
169-
operation: UploadFileOperation,
170-
result: RemoteOperationResult<Any?>,
171-
notifyOnSameFileExists: suspend () -> Unit
172-
): Boolean {
173-
if (result.isSuccess ||
174-
result.isCancelled ||
175-
result.code == ResultCode.USER_CANCELLED ||
176-
operation.isMissingPermissionThrown
177-
) {
178-
Log_OC.w(TAG, "operation is successful, cancelled or lack of storage permission")
179-
return false
180-
}
181-
182-
if (result.code == ResultCode.SYNC_CONFLICT) {
183-
if (isSameFileOnRemote) {
184-
Log_OC.w(TAG, "same file exists on remote")
185-
notifyOnSameFileExists()
186-
}
187-
188-
return false
189-
}
190-
191-
val delayedCodes =
192-
setOf(ResultCode.DELAYED_FOR_WIFI, ResultCode.DELAYED_FOR_CHARGING, ResultCode.DELAYED_IN_POWER_SAVE_MODE)
193-
val invalidCodes = setOf(ResultCode.LOCAL_FILE_NOT_FOUND, ResultCode.LOCK_FAILED)
194-
195-
return result.code !in delayedCodes && result.code !in invalidCodes
196-
}
197190
}

0 commit comments

Comments
 (0)