Skip to content

Commit b513b43

Browse files
Merge pull request #16735 from nextcloud/fix/upload-pause
fix(file-upload-worker): pausing upload
2 parents 70ba60c + f28695e commit b513b43

8 files changed

Lines changed: 52 additions & 43 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class FileUploadBroadcastReceiver : BroadcastReceiver() {
5757

5858
val remove = intent.getBooleanExtra(REMOVE, false)
5959

60-
FileUploadWorker.cancelCurrentUpload(remotePath, accountName, onCompleted = {})
60+
FileUploadWorker.cancelUpload(remotePath, accountName)
6161

6262
if (remove) {
6363
uploadsStorageManager.removeUpload(uploadId)

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import com.nextcloud.client.database.entity.toUploadEntity
1919
import com.nextcloud.client.device.BatteryStatus
2020
import com.nextcloud.client.device.PowerManagementService
2121
import com.nextcloud.client.jobs.BackgroundJobManager
22-
import com.nextcloud.client.jobs.upload.FileUploadWorker.Companion.currentUploadFileOperation
2322
import com.nextcloud.client.network.Connectivity
2423
import com.nextcloud.client.network.ConnectivityService
2524
import com.nextcloud.client.notifications.AppWideNotificationManager
@@ -440,7 +439,7 @@ class FileUploadHelper {
440439

441440
@Suppress("ReturnCount")
442441
fun isUploadingNow(upload: OCUpload?): Boolean {
443-
val currentUploadFileOperation = currentUploadFileOperation
442+
val currentUploadFileOperation = FileUploadWorker.getCurrentUpload(upload?.uploadId)
444443
if (currentUploadFileOperation == null || currentUploadFileOperation.user == null) return false
445444
if (upload == null || upload.accountName != currentUploadFileOperation.user.accountName) return false
446445

@@ -610,7 +609,7 @@ class FileUploadHelper {
610609
return
611610
}
612611

613-
FileUploadWorker.cancelCurrentUpload(remotePath, accountName, onCompleted = {
612+
FileUploadWorker.cancelUpload(remotePath, accountName, onCompleted = {
614613
instance().updateUploadStatus(remotePath, accountName, UploadStatus.UPLOAD_CANCELLED)
615614
})
616615
}

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

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import kotlinx.coroutines.Dispatchers
5050
import kotlinx.coroutines.ensureActive
5151
import kotlinx.coroutines.withContext
5252
import java.io.File
53+
import java.util.concurrent.ConcurrentHashMap
5354
import kotlin.random.Random
5455

5556
@Suppress("LongParameterList", "TooGenericExceptionCaught")
@@ -80,8 +81,6 @@ class FileUploadWorker(
8081
const val TOTAL_UPLOAD_SIZE = "total_upload_size"
8182
const val SHOW_SAME_FILE_ALREADY_EXISTS_NOTIFICATION = "show_same_file_already_exists_notification"
8283

83-
var currentUploadFileOperation: UploadFileOperation? = null
84-
8584
private const val BATCH_SIZE = 100
8685

8786
const val EXTRA_ACCOUNT_NAME = "ACCOUNT_NAME"
@@ -91,21 +90,26 @@ class FileUploadWorker(
9190
const val LOCAL_BEHAVIOUR_FORGET = 2
9291
const val LOCAL_BEHAVIOUR_DELETE = 3
9392

94-
fun cancelCurrentUpload(remotePath: String, accountName: String, onCompleted: () -> Unit) {
95-
currentUploadFileOperation?.let {
96-
if (it.remotePath == remotePath && it.user.accountName == accountName) {
97-
it.cancel(ResultCode.USER_CANCELLED)
98-
onCompleted()
99-
}
93+
private val activeOperations = ConcurrentHashMap<Long, UploadFileOperation>()
94+
95+
@JvmOverloads
96+
fun cancelUpload(remotePath: String?, accountName: String?, onCompleted: () -> Unit = {}) {
97+
val operation =
98+
activeOperations.values.find { it.remotePath == remotePath && it.user.accountName == accountName }
99+
100+
operation?.let {
101+
Log_OC.d(TAG, "upload operation is cancelled: $remotePath")
102+
operation.cancel(ResultCode.USER_CANCELLED)
103+
activeOperations.remove(operation.ocUploadId)
100104
}
105+
106+
onCompleted()
101107
}
102108

103-
fun isUploading(remotePath: String?, accountName: String?): Boolean {
104-
currentUploadFileOperation?.let {
105-
return it.remotePath == remotePath && it.user.accountName == accountName
106-
}
109+
fun getCurrentUpload(id: Long?): UploadFileOperation? = activeOperations[id]
107110

108-
return false
111+
fun isUploading(remotePath: String?, accountName: String?): Boolean = activeOperations.values.any {
112+
it.remotePath == remotePath && it.user.accountName == accountName
109113
}
110114

111115
fun getUploadAction(action: String): Int = when (action) {
@@ -135,7 +139,8 @@ class FileUploadWorker(
135139
result
136140
} catch (t: Throwable) {
137141
Log_OC.e(TAG, "exception $t")
138-
currentUploadFileOperation?.cancel(null)
142+
activeOperations.values.forEach { it.cancel(null) }
143+
activeOperations.clear()
139144
Result.failure()
140145
} finally {
141146
// Ensure all database operations are complete before signaling completion
@@ -256,7 +261,7 @@ class FileUploadWorker(
256261

257262
fileUploadEventBroadcaster.sendUploadEnqueued(context)
258263
val operation = createUploadFileOperation(upload, user)
259-
currentUploadFileOperation = operation
264+
activeOperations[upload.uploadId] = operation
260265

261266
val currentIndex = (index + 1)
262267
val currentUploadIndex = (currentIndex + previouslyUploadedFileSize)
@@ -270,7 +275,7 @@ class FileUploadWorker(
270275
val result = withContext(Dispatchers.IO) {
271276
upload(upload, operation, user, client)
272277
}
273-
currentUploadFileOperation = null
278+
activeOperations.remove(upload.uploadId)
274279

275280
if (result.code == ResultCode.QUOTA_EXCEEDED) {
276281
Log_OC.w(TAG, "Quota exceeded, stopping uploads")
@@ -379,24 +384,24 @@ class FileUploadWorker(
379384
}
380385
}
381386
result = RemoteOperationResult(e)
382-
} finally {
383-
if (!isStopped) {
384-
UploadErrorNotificationManager.handleResult(
385-
context,
386-
notificationManager,
387-
operation,
388-
result,
389-
onSameFileConflict = {
390-
withContext(Dispatchers.Main) {
391-
val showSameFileAlreadyExistsNotification =
392-
inputData.getBoolean(SHOW_SAME_FILE_ALREADY_EXISTS_NOTIFICATION, false)
393-
if (showSameFileAlreadyExistsNotification) {
394-
notificationManager.showSameFileAlreadyExistsNotification(operation.fileName)
395-
}
387+
}
388+
389+
if (!isStopped) {
390+
UploadErrorNotificationManager.handleResult(
391+
context,
392+
notificationManager,
393+
operation,
394+
result,
395+
onSameFileConflict = {
396+
withContext(Dispatchers.Main) {
397+
val showSameFileAlreadyExistsNotification =
398+
inputData.getBoolean(SHOW_SAME_FILE_ALREADY_EXISTS_NOTIFICATION, false)
399+
if (showSameFileAlreadyExistsNotification) {
400+
notificationManager.showSameFileAlreadyExistsNotification(operation.fileName)
396401
}
397402
}
398-
)
399-
}
403+
}
404+
)
400405
}
401406

402407
return@withContext result
@@ -421,6 +426,9 @@ class FileUploadWorker(
421426

422427
if (percent != lastPercent && (currentTime - lastUpdateTime) >= minProgressUpdateInterval) {
423428
notificationManager.run {
429+
val currentUploadFileOperation =
430+
activeOperations.values.find { it.originalStoragePath == fileAbsoluteName }
431+
424432
val accountName = currentUploadFileOperation?.user?.accountName
425433
val remotePath = currentUploadFileOperation?.remotePath
426434

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ sealed class UploadBroadcastAction {
5454
context,
5555
requestCode,
5656
intent,
57-
PendingIntent.FLAG_IMMUTABLE
57+
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
5858
)
5959
}
6060
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi
106106
notificationManager.cancel(getId())
107107

108108
notificationBuilder.run {
109+
clearActions()
109110
setContentTitle(context.getString(R.string.file_upload_worker_error_notification_title))
110111
setContentText("")
111112
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ object UploadErrorNotificationManager {
4949
) {
5050
Log_OC.d(TAG, "handle upload result with result code: " + result.code)
5151

52-
if (result.isSuccess || result.isCancelled || operation.isMissingPermissionThrown) {
52+
if (result.isSuccess || operation.isMissingPermissionThrown) {
5353
Log_OC.d(TAG, "operation is successful, cancelled or lack of storage permission, notification skipped")
5454
return
5555
}
@@ -59,7 +59,9 @@ object UploadErrorNotificationManager {
5959
ResultCode.DELAYED_FOR_CHARGING,
6060
ResultCode.DELAYED_IN_POWER_SAVE_MODE,
6161
ResultCode.LOCAL_FILE_NOT_FOUND,
62-
ResultCode.LOCK_FAILED
62+
ResultCode.LOCK_FAILED,
63+
ResultCode.CANCELLED,
64+
ResultCode.USER_CANCELLED
6365
)
6466

6567
if (result.code in silentCodes) {
@@ -131,7 +133,6 @@ object UploadErrorNotificationManager {
131133
)
132134

133135
// actions for all error types
134-
addAction(UploadBroadcastAction.PauseAndCancel(operation).pauseAction(context))
135136
addAction(UploadBroadcastAction.PauseAndCancel(operation).cancelAction(context))
136137

137138
if (result.code == ResultCode.SYNC_CONFLICT) {

app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ public void onBindHeaderViewHolder(SectionedViewHolder holder, int section, bool
186186
uploadHelper.updateUploadStatus(upload.getRemotePath(), accountName, UploadStatus.UPLOAD_CANCELLED, new Function0<Unit>() {
187187
@Override
188188
public Unit invoke() {
189-
FileUploadWorker.Companion.cancelCurrentUpload(upload.getRemotePath(), accountName, new Function0<Unit>() {
189+
FileUploadWorker.Companion.cancelUpload(upload.getRemotePath(), accountName, new Function0<Unit>() {
190190
@Override
191191
public Unit invoke() {
192192
completedCount[0]++;
@@ -428,7 +428,7 @@ public void onBindViewHolder(SectionedViewHolder holder, int section, int relati
428428
itemViewHolder.binding.uploadRightButton.setVisibility(View.VISIBLE);
429429
itemViewHolder.binding.uploadRightButton.setOnClickListener(v -> {
430430
uploadHelper.updateUploadStatus(item.getRemotePath(), item.getAccountName(), UploadStatus.UPLOAD_CANCELLED, () -> {
431-
FileUploadWorker.Companion.cancelCurrentUpload(item.getRemotePath(), item.getAccountName(), () -> {
431+
FileUploadWorker.Companion.cancelUpload(item.getRemotePath(), item.getAccountName(), () -> {
432432
loadUploadItemsFromDb(() -> {});
433433
return Unit.INSTANCE;
434434
});

app/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1043,7 +1043,7 @@ public void cancelTransference(OCFile file) {
10431043

10441044
final var fileUploadHelper = FileUploadHelper.Companion.instance();
10451045
if (fileUploadHelper.isUploading(file.getRemotePath(), currentUser.getAccountName())) {
1046-
FileUploadWorker.Companion.cancelCurrentUpload(file.getRemotePath(), currentUser.getAccountName(), () -> {
1046+
FileUploadWorker.Companion.cancelUpload(file.getRemotePath(), currentUser.getAccountName(), () -> {
10471047
fileUploadHelper.updateUploadStatus(file.getRemotePath(), currentUser.getAccountName(), UploadsStorageManager.UploadStatus.UPLOAD_CANCELLED);
10481048
return Unit.INSTANCE;
10491049
});

0 commit comments

Comments
 (0)