Skip to content

Commit d47c77e

Browse files
Merge pull request #17309 from nextcloud/fix/upload-marked-as-skip-instead-completed
fix(upload-list): distinguish between skip and complete
2 parents 3f2a7c9 + 0792241 commit d47c77e

8 files changed

Lines changed: 78 additions & 42 deletions

File tree

app/src/main/java/com/nextcloud/client/jobs/autoUpload/AutoUploadWorker.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,10 +411,9 @@ class AutoUploadWorker(
411411
}
412412

413413
// only valid for skip collision policy other scenarios will be handled in UploadFileOperation.java
414-
if (upload.lastResult == UploadResult.UPLOADED &&
415-
syncedFolder.nameCollisionPolicy == NameCollisionPolicy.SKIP
416-
) {
417-
Log_OC.d(TAG, "no need to create and process this entity file is already uploaded")
414+
val alreadyHandled = upload.lastResult == UploadResult.UPLOADED || upload.lastResult == UploadResult.SKIPPED
415+
if (alreadyHandled && syncedFolder.nameCollisionPolicy == NameCollisionPolicy.SKIP) {
416+
Log_OC.d(TAG, "no need to create and process this entity file is already uploaded or skipped")
418417
return AutoUploadEntityResult.Uploaded
419418
}
420419

app/src/main/java/com/nextcloud/utils/extensions/OCUploadExtensions.kt

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,13 @@
88
package com.nextcloud.utils.extensions
99

1010
import android.content.Context
11-
import com.nextcloud.client.preferences.AppPreferences
1211
import com.owncloud.android.R
1312
import com.owncloud.android.datamodel.UploadsStorageManager
1413
import com.owncloud.android.db.OCUpload
1514
import com.owncloud.android.db.UploadResult
16-
import com.owncloud.android.files.services.NameCollisionPolicy
1715

1816
fun List<OCUpload>.getUploadIds(): LongArray = map { it.uploadId }.toLongArray()
1917

20-
fun Array<OCUpload>.getUploadIds(): LongArray = map { it.uploadId }.toLongArray()
21-
2218
fun List<OCUpload>.sortedByUploadOrder(): List<OCUpload> = sortedWith(
2319
compareBy<OCUpload> { it.fixedUploadStatus }
2420
.thenByDescending { it.isFixedUploadingNow }
@@ -41,14 +37,22 @@ fun OCUpload.getStatusText(activity: Context, isGlobalUploadPaused: Boolean, isU
4137
}
4238

4339
UploadsStorageManager.UploadStatus.UPLOAD_SUCCEEDED -> {
44-
status = if (lastResult == UploadResult.SAME_FILE_CONFLICT) {
45-
res.getString(R.string.uploads_view_upload_status_succeeded_same_file)
46-
} else if (lastResult == UploadResult.FILE_NOT_FOUND) {
47-
lastResult.getFailedStatusText(activity)
48-
} else if (nameCollisionPolicy == NameCollisionPolicy.SKIP) {
49-
res.getString(R.string.uploads_view_upload_status_skip_reason)
50-
} else {
51-
res.getString(R.string.uploads_view_upload_status_succeeded)
40+
status = when (lastResult) {
41+
UploadResult.SAME_FILE_CONFLICT -> {
42+
res.getString(R.string.uploads_view_upload_status_succeeded_same_file)
43+
}
44+
45+
UploadResult.FILE_NOT_FOUND -> {
46+
lastResult.getFailedStatusText(activity)
47+
}
48+
49+
UploadResult.SKIPPED -> {
50+
res.getString(R.string.uploads_view_upload_status_skip_reason)
51+
}
52+
53+
else -> {
54+
res.getString(R.string.uploads_view_upload_status_succeeded)
55+
}
5256
}
5357
}
5458

app/src/main/java/com/owncloud/android/datamodel/UploadsStorageManager.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,10 @@ class UploadsStorageManager(
421421
val deleted = contentResolver.delete(
422422
ProviderTableMeta.CONTENT_URI_UPLOADS,
423423
ProviderTableMeta.UPLOADS_STATUS + EQUAL + UploadStatus.UPLOAD_FAILED.value +
424-
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + ANGLE_BRACKETS + UploadResult.LOCK_FAILED.value +
425-
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + ANGLE_BRACKETS + UploadResult.DELAYED_FOR_WIFI.value +
426-
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + ANGLE_BRACKETS + UploadResult.DELAYED_FOR_CHARGING.value +
427-
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + ANGLE_BRACKETS +
424+
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + NOT_EQUAL + UploadResult.LOCK_FAILED.value +
425+
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + NOT_EQUAL + UploadResult.DELAYED_FOR_WIFI.value +
426+
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + NOT_EQUAL + UploadResult.DELAYED_FOR_CHARGING.value +
427+
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + NOT_EQUAL +
428428
UploadResult.DELAYED_IN_POWER_SAVE_MODE.value +
429429
AND + ProviderTableMeta.UPLOADS_ACCOUNT_NAME + IS_EQUAL,
430430
arrayOf(user.accountName)
@@ -452,6 +452,7 @@ class UploadsStorageManager(
452452
val deleted = contentResolver.delete(
453453
ProviderTableMeta.CONTENT_URI_UPLOADS,
454454
ProviderTableMeta.UPLOADS_STATUS + EQUAL + UploadStatus.UPLOAD_SUCCEEDED.value +
455+
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + NOT_EQUAL + UploadResult.SKIPPED.value +
455456
AND + ProviderTableMeta.UPLOADS_ACCOUNT_NAME + IS_EQUAL,
456457
arrayOf(user.accountName)
457458
)
@@ -464,7 +465,7 @@ class UploadsStorageManager(
464465
val deleted = contentResolver.delete(
465466
ProviderTableMeta.CONTENT_URI_UPLOADS,
466467
ProviderTableMeta.UPLOADS_STATUS + EQUAL + UploadStatus.UPLOAD_SUCCEEDED.value +
467-
AND + ProviderTableMeta.UPLOADS_NAME_COLLISION_POLICY + EQUAL + NameCollisionPolicy.SKIP.serialize() +
468+
AND + ProviderTableMeta.UPLOADS_LAST_RESULT + EQUAL + UploadResult.SKIPPED.value +
468469
AND + ProviderTableMeta.UPLOADS_ACCOUNT_NAME + IS_EQUAL,
469470
arrayOf(user.accountName)
470471
)
@@ -493,7 +494,7 @@ class UploadsStorageManager(
493494

494495
if (uploadResult.isSuccess) {
495496
status = UploadStatus.UPLOAD_SUCCEEDED
496-
result = UploadResult.UPLOADED
497+
result = if (upload.wasSkipped()) UploadResult.SKIPPED else UploadResult.UPLOADED
497498
} else if (code.isConflict()) {
498499
val isSame = FileUploadHelper().isSameFileOnRemote(
499500
upload.user,
@@ -600,7 +601,7 @@ class UploadsStorageManager(
600601
private const val EQUAL = "=="
601602
private const val OR = " OR "
602603
private const val AND = " AND "
603-
private const val ANGLE_BRACKETS = "<>"
604+
private const val NOT_EQUAL = "<>"
604605
private const val SINGLE_RESULT = 1
605606

606607
private const val QUERY_PAGE_SIZE: Long = 100

app/src/main/java/com/owncloud/android/db/UploadResult.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public enum UploadResult {
4141
CANNOT_CREATE_FILE(20),
4242
LOCAL_STORAGE_NOT_COPIED(21),
4343
QUOTA_EXCEEDED(22),
44-
SAME_FILE_CONFLICT(23);
44+
SAME_FILE_CONFLICT(23),
45+
SKIPPED(24);
4546

4647
private final int value;
4748

@@ -81,7 +82,8 @@ public int getValue() {
8182
Map.entry(20, CANNOT_CREATE_FILE),
8283
Map.entry(21, LOCAL_STORAGE_NOT_COPIED),
8384
Map.entry(22, QUOTA_EXCEEDED),
84-
Map.entry(23, SAME_FILE_CONFLICT)
85+
Map.entry(23, SAME_FILE_CONFLICT),
86+
Map.entry(24, SKIPPED)
8587
);
8688
public static UploadResult fromValue(int value) {
8789
return valueMap.getOrDefault(value, UNKNOWN);

app/src/main/java/com/owncloud/android/operations/UploadFileOperation.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,17 @@ public class UploadFileOperation extends SyncOperation {
135135
private OCFile mOldFile;
136136
private String mRemotePath;
137137
private String mFolderUnlockToken;
138-
private boolean mRemoteFolderToBeCreated;
138+
private volatile boolean mRemoteFolderToBeCreated;
139139
private NameCollisionPolicy mNameCollisionPolicy;
140140
private int mLocalBehaviour;
141-
private int mCreatedBy;
141+
private volatile int mCreatedBy;
142142
private boolean mOnWifiOnly;
143143
private boolean mWhileChargingOnly;
144144
private boolean mIgnoringPowerSaveMode;
145145
private final boolean mDisableRetries;
146146

147-
private boolean mWasRenamed;
147+
private volatile boolean mWasRenamed;
148+
private volatile boolean mWasSkipped;
148149
private long mOCUploadId;
149150
/**
150151
* Local path to file which is to be uploaded (before any possible renaming or moving).
@@ -168,7 +169,7 @@ public class UploadFileOperation extends SyncOperation {
168169
private final ConnectivityService connectivityService;
169170
private final PowerManagementService powerManagementService;
170171

171-
private boolean encryptedAncestor;
172+
private volatile boolean encryptedAncestor;
172173
private OCFile duplicatedEncryptedFile;
173174
private AtomicBoolean missingPermissionThrown = new AtomicBoolean(false);
174175

@@ -345,6 +346,10 @@ public boolean wasRenamed() {
345346
return mWasRenamed;
346347
}
347348

349+
public boolean wasSkipped() {
350+
return mWasSkipped;
351+
}
352+
348353
public void setCreatedBy(int createdBy) {
349354
mCreatedBy = createdBy;
350355
if (createdBy < CREATED_BY_USER || CREATED_AS_INSTANT_VIDEO < createdBy) {
@@ -1268,6 +1273,7 @@ private RemoteOperationResult checkNameCollision(OCFile parentFile,
12681273
switch (mNameCollisionPolicy) {
12691274
case SKIP:
12701275
Log_OC.d(TAG, "user choose to skip upload if same file exists");
1276+
mWasSkipped = true;
12711277
return new RemoteOperationResult<>(ResultCode.OK);
12721278
case RENAME:
12731279
mRemotePath = getNewAvailableRemotePath(client, mRemotePath, fileNames, encrypted);

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -635,13 +635,18 @@ class UploadListAdapter(
635635
val capabilities = optionalCapabilities.get()
636636

637637
activity.lifecycleScope.launch(Dispatchers.IO) {
638+
val succeededUploads = uploadHelper.getUploadsByStatus(
639+
accountName,
640+
UploadsStorageManager.UploadStatus.UPLOAD_SUCCEEDED,
641+
capabilities
642+
)
643+
638644
val updatedSections = uploadListSections.map { sec ->
639-
val uploads = uploadHelper.getUploadsByStatus(
640-
accountName,
641-
sec.status,
642-
capabilities,
643-
sec.collisionPolicy
644-
)
645+
val uploads = when (sec.type) {
646+
UploadListType.COMPLETED -> succeededUploads.filter { it.lastResult != UploadResult.SKIPPED }
647+
UploadListType.SKIPPED -> succeededUploads.filter { it.lastResult == UploadResult.SKIPPED }
648+
else -> uploadHelper.getUploadsByStatus(accountName, sec.status, capabilities)
649+
}
645650
uploads.forEach { it.setDataFixed(uploadHelper) }
646651
sec.withItems(uploads.sortedByUploadOrder())
647652
}

app/src/main/java/com/owncloud/android/ui/adapter/uploadList/model/UploadListSection.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@ package com.owncloud.android.ui.adapter.uploadList.model
1010
import com.owncloud.android.R
1111
import com.owncloud.android.datamodel.UploadsStorageManager
1212
import com.owncloud.android.db.OCUpload
13-
import com.owncloud.android.files.services.NameCollisionPolicy
1413

1514
data class UploadListSection(
1615
val type: UploadListType?,
1716
val titleRes: Int,
1817
val status: UploadsStorageManager.UploadStatus,
19-
val collisionPolicy: NameCollisionPolicy?,
2018
val items: List<OCUpload>
2119
) {
2220
fun withItems(newItems: List<OCUpload>) = copy(items = newItems)
@@ -27,35 +25,30 @@ data class UploadListSection(
2725
UploadListType.CURRENT,
2826
R.string.uploads_view_group_current_uploads,
2927
UploadsStorageManager.UploadStatus.UPLOAD_IN_PROGRESS,
30-
null,
3128
listOf()
3229
),
3330
UploadListSection(
3431
UploadListType.FAILED,
3532
R.string.uploads_view_group_failed_uploads,
3633
UploadsStorageManager.UploadStatus.UPLOAD_FAILED,
37-
null,
3834
listOf()
3935
),
4036
UploadListSection(
4137
UploadListType.CANCELLED,
4238
R.string.uploads_view_group_manually_cancelled_uploads,
4339
UploadsStorageManager.UploadStatus.UPLOAD_CANCELLED,
44-
null,
4540
listOf()
4641
),
4742
UploadListSection(
4843
UploadListType.COMPLETED,
4944
R.string.uploads_view_group_completed_uploads,
5045
UploadsStorageManager.UploadStatus.UPLOAD_SUCCEEDED,
51-
NameCollisionPolicy.ASK_USER,
5246
listOf()
5347
),
5448
UploadListSection(
5549
UploadListType.SKIPPED,
5650
R.string.uploads_view_upload_status_skip,
5751
UploadsStorageManager.UploadStatus.UPLOAD_SUCCEEDED,
58-
NameCollisionPolicy.SKIP,
5952
listOf()
6053
)
6154
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Nextcloud - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
package com.owncloud.android.db
8+
9+
import org.junit.Assert.assertEquals
10+
import org.junit.Assert.assertNotEquals
11+
import org.junit.Test
12+
13+
class UploadResultTest {
14+
15+
@Test
16+
fun skippedRoundTripsThroughStoredValue() {
17+
val stored = UploadResult.SKIPPED.value
18+
assertEquals(UploadResult.SKIPPED, UploadResult.fromValue(stored))
19+
}
20+
21+
@Test
22+
fun skippedIsDistinctFromUploaded() {
23+
assertNotEquals(UploadResult.SKIPPED.value, UploadResult.UPLOADED.value)
24+
assertEquals(UploadResult.UPLOADED, UploadResult.fromValue(UploadResult.UPLOADED.value))
25+
}
26+
}

0 commit comments

Comments
 (0)