From 737f9fc92fa730c2c9d21709f60f021e13c0890e Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 6 May 2026 16:03:19 +0200 Subject: [PATCH 1/7] fix(oc-search-task): data consistency Signed-off-by: alperozturk96 --- .../android/ui/adapter/OCFileListAdapter.java | 2 +- .../android/ui/adapter/OCFileListDelegate.kt | 23 ++++++++----- .../ui/fragment/OCFileListSearchTask.kt | 33 ++++++++++++++++++- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java index a7566c809d19..3ec39ea43e66 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java @@ -496,7 +496,7 @@ public void bindRecommendedFilesHolder(OCFileListRecommendedItemViewHolder holde } private void bindHolder(@NonNull RecyclerView.ViewHolder holder, ListViewHolder viewHolder, OCFile file) { - ocFileListDelegate.bindViewHolder(viewHolder, file, currentDirectory, searchType, overlayManager); + ocFileListDelegate.bindViewHolder(viewHolder, file, currentDirectory, overlayManager); if (holder instanceof ListItemViewHolder itemViewHolder) { bindListItemViewHolder(itemViewHolder, file); diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt index 65bc90380aaf..c509f2881b36 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt @@ -32,7 +32,6 @@ import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.ui.activity.ComponentsGetter import com.owncloud.android.ui.activity.FolderPickerActivity import com.owncloud.android.ui.fragment.GalleryFragment -import com.owncloud.android.ui.fragment.SearchType import com.owncloud.android.ui.interfaces.OCFileListFragmentInterface import com.owncloud.android.utils.DisplayUtils import com.owncloud.android.utils.EncryptionUtils @@ -207,7 +206,6 @@ class OCFileListDelegate( viewHolder: ListViewHolder, file: OCFile, currentDirectory: OCFile?, - searchType: SearchType?, overlayManager: OverlayManager ) { // thumbnail @@ -243,13 +241,12 @@ class OCFileListDelegate( file.isEncrypted && !EncryptionUtils.supportsSecureFiledrop(file, user) ) || - (searchType == SearchType.FAVORITE_SEARCH) || ( file.isFolder && (currentDirectory?.isEncrypted ?: false) ) ) - ) // sharing an encrypted subfolder is not possible + ) if (shouldHideShare) { viewHolder.shared.visibility = View.GONE } else { @@ -405,18 +402,28 @@ class OCFileListDelegate( return null } - if (file.isOfflineOperation) return null + if (file.isOfflineOperation) { + return null + } - if (holder !is OCFileListItemViewHolder && file.unreadCommentsCount != 0) return null + if (holder !is OCFileListItemViewHolder && file.unreadCommentsCount != 0) { + return null + } return when { file.isSharedWithSharee || file.isSharedWithMe -> { - if (showShareAvatar) null else R.drawable.shared_via_users to R.string.shared_icon_shared + if (showShareAvatar) { + null + } else { + R.drawable.shared_via_users to R.string.shared_icon_shared + } } file.isSharedViaLink -> R.drawable.shared_via_link to R.string.shared_icon_shared_via_link - else -> R.drawable.ic_unshared to R.string.shared_icon_share + else -> { + R.drawable.ic_unshared to R.string.shared_icon_share + } } } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index 6788110f67cf..eb547eaec930 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -203,7 +203,14 @@ class OCFileListSearchTask( for (obj in data) { try { val remoteFile = obj as? RemoteFile ?: continue - var ocFile = FileStorageUtils.fillOCFile(remoteFile) + val newFile = FileStorageUtils.fillOCFile(remoteFile) + + val existingFile = storageManager.getFileByPath(newFile.remotePath) + if (existingFile != null) { + preserveLocalFieldsOverEmptyRemoteFile(newFile, existingFile) + } + + var ocFile = newFile FileStorageUtils.searchForLocalFileInDefaultPath(ocFile, currentUser.accountName) resolveLocalFileId(ocFile) ocFile = storageManager.saveFileWithParent(ocFile, activity) @@ -238,6 +245,30 @@ class OCFileListSearchTask( return@withContext resultFiles } + /** + * Needed to prevent overwriting the valid local fields. + */ + private fun preserveLocalFieldsOverEmptyRemoteFile(newFile: OCFile, existingFile: OCFile) { + if (newFile.sharees.isNullOrEmpty()) { + newFile.sharees = existingFile.sharees + } + if (!newFile.isSharedViaLink) { + newFile.isSharedViaLink = existingFile.isSharedViaLink + } + if (!newFile.isSharedWithSharee) { + newFile.isSharedWithSharee = existingFile.isSharedWithSharee + } + if (newFile.firstShareTimestamp == 0L) { + newFile.firstShareTimestamp = existingFile.firstShareTimestamp + } + if (newFile.tags.isNullOrEmpty()) { + newFile.tags = existingFile.tags + } + if (newFile.imageDimension == null) { + newFile.imageDimension = existingFile.imageDimension + } + } + @Suppress("DEPRECATION") private fun handleEncryptionIfNeeded( ocFile: OCFile, From b410b2fb760653ae95e4de12303fc3a39456713f Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 6 May 2026 16:04:15 +0200 Subject: [PATCH 2/7] fix(oc-search-task): data consistency Signed-off-by: alperozturk96 --- .../android/ui/adapter/OCFileListAdapter.java | 2 +- .../android/ui/adapter/OCFileListDelegate.kt | 23 +++++++------------ 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java index 3ec39ea43e66..a7566c809d19 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java @@ -496,7 +496,7 @@ public void bindRecommendedFilesHolder(OCFileListRecommendedItemViewHolder holde } private void bindHolder(@NonNull RecyclerView.ViewHolder holder, ListViewHolder viewHolder, OCFile file) { - ocFileListDelegate.bindViewHolder(viewHolder, file, currentDirectory, overlayManager); + ocFileListDelegate.bindViewHolder(viewHolder, file, currentDirectory, searchType, overlayManager); if (holder instanceof ListItemViewHolder itemViewHolder) { bindListItemViewHolder(itemViewHolder, file); diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt index c509f2881b36..65bc90380aaf 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt @@ -32,6 +32,7 @@ import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.ui.activity.ComponentsGetter import com.owncloud.android.ui.activity.FolderPickerActivity import com.owncloud.android.ui.fragment.GalleryFragment +import com.owncloud.android.ui.fragment.SearchType import com.owncloud.android.ui.interfaces.OCFileListFragmentInterface import com.owncloud.android.utils.DisplayUtils import com.owncloud.android.utils.EncryptionUtils @@ -206,6 +207,7 @@ class OCFileListDelegate( viewHolder: ListViewHolder, file: OCFile, currentDirectory: OCFile?, + searchType: SearchType?, overlayManager: OverlayManager ) { // thumbnail @@ -241,12 +243,13 @@ class OCFileListDelegate( file.isEncrypted && !EncryptionUtils.supportsSecureFiledrop(file, user) ) || + (searchType == SearchType.FAVORITE_SEARCH) || ( file.isFolder && (currentDirectory?.isEncrypted ?: false) ) ) - ) + ) // sharing an encrypted subfolder is not possible if (shouldHideShare) { viewHolder.shared.visibility = View.GONE } else { @@ -402,28 +405,18 @@ class OCFileListDelegate( return null } - if (file.isOfflineOperation) { - return null - } + if (file.isOfflineOperation) return null - if (holder !is OCFileListItemViewHolder && file.unreadCommentsCount != 0) { - return null - } + if (holder !is OCFileListItemViewHolder && file.unreadCommentsCount != 0) return null return when { file.isSharedWithSharee || file.isSharedWithMe -> { - if (showShareAvatar) { - null - } else { - R.drawable.shared_via_users to R.string.shared_icon_shared - } + if (showShareAvatar) null else R.drawable.shared_via_users to R.string.shared_icon_shared } file.isSharedViaLink -> R.drawable.shared_via_link to R.string.shared_icon_shared_via_link - else -> { - R.drawable.ic_unshared to R.string.shared_icon_share - } + else -> R.drawable.ic_unshared to R.string.shared_icon_share } } From 4e4dddc63f41ff3b16b06c6b6efd47548da89188 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 8 May 2026 11:47:20 +0200 Subject: [PATCH 3/7] fetch result from search directly Signed-off-by: alperozturk96 # Conflicts: # app/src/main/java/com/owncloud/android/ui/asynctasks/GallerySearchTask.kt --- .../android/ui/adapter/OCFileListDelegate.kt | 2 +- .../ui/fragment/OCFileListSearchTask.kt | 35 ++----------------- 2 files changed, 3 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt index 65bc90380aaf..3f607b3e6b0b 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListDelegate.kt @@ -414,7 +414,7 @@ class OCFileListDelegate( if (showShareAvatar) null else R.drawable.shared_via_users to R.string.shared_icon_shared } - file.isSharedViaLink -> R.drawable.shared_via_link to R.string.shared_icon_shared_via_link + file.isShared || file.isSharedViaLink -> R.drawable.shared_via_link to R.string.shared_icon_shared_via_link else -> R.drawable.ic_unshared to R.string.shared_icon_share } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index eb547eaec930..e63a6188fd72 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -202,15 +202,8 @@ class OCFileListSearchTask( for (obj in data) { try { - val remoteFile = obj as? RemoteFile ?: continue - val newFile = FileStorageUtils.fillOCFile(remoteFile) - - val existingFile = storageManager.getFileByPath(newFile.remotePath) - if (existingFile != null) { - preserveLocalFieldsOverEmptyRemoteFile(newFile, existingFile) - } - - var ocFile = newFile + val remoteFile = (obj as? RemoteFile) ?: continue + var ocFile = FileStorageUtils.fillOCFile(remoteFile) FileStorageUtils.searchForLocalFileInDefaultPath(ocFile, currentUser.accountName) resolveLocalFileId(ocFile) ocFile = storageManager.saveFileWithParent(ocFile, activity) @@ -245,30 +238,6 @@ class OCFileListSearchTask( return@withContext resultFiles } - /** - * Needed to prevent overwriting the valid local fields. - */ - private fun preserveLocalFieldsOverEmptyRemoteFile(newFile: OCFile, existingFile: OCFile) { - if (newFile.sharees.isNullOrEmpty()) { - newFile.sharees = existingFile.sharees - } - if (!newFile.isSharedViaLink) { - newFile.isSharedViaLink = existingFile.isSharedViaLink - } - if (!newFile.isSharedWithSharee) { - newFile.isSharedWithSharee = existingFile.isSharedWithSharee - } - if (newFile.firstShareTimestamp == 0L) { - newFile.firstShareTimestamp = existingFile.firstShareTimestamp - } - if (newFile.tags.isNullOrEmpty()) { - newFile.tags = existingFile.tags - } - if (newFile.imageDimension == null) { - newFile.imageDimension = existingFile.imageDimension - } - } - @Suppress("DEPRECATION") private fun handleEncryptionIfNeeded( ocFile: OCFile, From 5a9f21e32ad08d04eab419e1f8b0945aba997436 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 27 May 2026 10:08:44 +0300 Subject: [PATCH 4/7] fix user file selection order Signed-off-by: alperozturk96 # Conflicts: # gradle/libs.versions.toml --- gradle/verification-metadata.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 07e384abe004..0eb104438acd 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -21688,6 +21688,14 @@ + + + + + + + + From 4956c990f8aa1b10098910af8ea770f75f531f32 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 2 Jun 2026 13:58:18 +0300 Subject: [PATCH 5/7] wip Signed-off-by: alperozturk96 --- .../owncloud/android/ui/fragment/SharedListFragment.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt b/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt index 5e7b26a3b019..56e11a40c360 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt @@ -83,16 +83,18 @@ class SharedListFragment : etag = it } } - val file = FileStorageUtils.fillOCFile(remoteFile) - FileStorageUtils.searchForLocalFileInDefaultPath(file, user.accountName) - val savedFile = mContainerActivity.storageManager.saveFileWithParent(file, context) - savedFile.apply { + // todo: ideally remote operation must return valid values via webdav entry + val file = FileStorageUtils.fillOCFile(remoteFile).apply { + fileId = partialFile.fileId + parentId = partialFile.parentId ownerId = partialFile.ownerId ownerDisplayName = partialFile.ownerDisplayName isSharedViaLink = partialFile.isSharedViaLink isSharedWithSharee = partialFile.isSharedWithSharee sharees = partialFile.sharees } + FileStorageUtils.searchForLocalFileInDefaultPath(file, user.accountName) + val savedFile = mContainerActivity.storageManager.saveFileWithParent(file, context) savedFile } else { logger.e(SHARED_TAG, "Error fetching file") From e592cbb0cdd3e2d1dc004fd5f812041c8f592d1f Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 2 Jun 2026 15:30:08 +0300 Subject: [PATCH 6/7] add missing fields Signed-off-by: alperozturk96 --- .../utils/extensions/RemoteFileExtensions.kt | 11 +++++++++++ .../android/ui/fragment/SharedListFragment.kt | 6 ------ .../com/owncloud/android/utils/FileStorageUtils.java | 11 +++++++++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/nextcloud/utils/extensions/RemoteFileExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/RemoteFileExtensions.kt index 114849b5a831..2b0eabc011d4 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/RemoteFileExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/RemoteFileExtensions.kt @@ -9,6 +9,8 @@ package com.nextcloud.utils.extensions import com.nextcloud.utils.TimeConstants import com.owncloud.android.lib.resources.files.model.RemoteFile +import com.owncloud.android.lib.resources.shares.ShareeUser +import com.owncloud.android.lib.resources.tags.Tag import com.owncloud.android.utils.FileUtil import com.owncloud.android.utils.MimeTypeUtil @@ -27,6 +29,15 @@ fun RemoteFile.isSame(path: String?): Boolean { this.areImageDimensionsSame(path) } +fun RemoteFile.sharedViaLink(): Boolean = sharees?.any { it.shareType?.isLink == true } ?: false + +fun RemoteFile.sharedWithSharee(): Boolean = sharees?.isNotEmpty() ?: false + +fun RemoteFile.getShareeList(): List = sharees?.toList() ?: emptyList() + +fun RemoteFile.tags(): List = + tags?.mapNotNull { it } ?: emptyList() + @Suppress("ReturnCount") private fun RemoteFile.areImageDimensionsSame(path: String): Boolean { if (!MimeTypeUtil.isImage(mimeType)) { diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt b/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt index 56e11a40c360..30857c9665eb 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt @@ -83,15 +83,9 @@ class SharedListFragment : etag = it } } - // todo: ideally remote operation must return valid values via webdav entry val file = FileStorageUtils.fillOCFile(remoteFile).apply { fileId = partialFile.fileId parentId = partialFile.parentId - ownerId = partialFile.ownerId - ownerDisplayName = partialFile.ownerDisplayName - isSharedViaLink = partialFile.isSharedViaLink - isSharedWithSharee = partialFile.isSharedWithSharee - sharees = partialFile.sharees } FileStorageUtils.searchForLocalFileInDefaultPath(file, user.accountName) val savedFile = mContainerActivity.storageManager.saveFileWithParent(file, context) diff --git a/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java b/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java index 1068358b9bcd..014f4e12d64e 100644 --- a/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java +++ b/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java @@ -21,6 +21,7 @@ import android.webkit.MimeTypeMap; import com.nextcloud.client.preferences.SubFolderRule; +import com.nextcloud.utils.extensions.RemoteFileExtensionsKt; import com.nextcloud.utils.extensions.StringConstants; import com.owncloud.android.MainApp; import com.owncloud.android.R; @@ -28,6 +29,8 @@ import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.files.model.RemoteFile; +import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.lib.resources.shares.ShareeUser; import com.owncloud.android.ui.helpers.FileOperationsHelper; import org.apache.commons.io.FilenameUtils; @@ -349,7 +352,11 @@ public static OCFile fillOCFile(RemoteFile remote) { file.setOwnerId(remote.getOwnerId()); file.setOwnerDisplayName(remote.getOwnerDisplayName()); file.setNote(remote.getNote()); - file.setSharees(new ArrayList<>(Arrays.asList(remote.getSharees()))); + + file.setSharees(RemoteFileExtensionsKt.getShareeList(remote)); + file.setSharedWithSharee(RemoteFileExtensionsKt.sharedWithSharee(remote)); + file.setSharedViaLink(RemoteFileExtensionsKt.sharedViaLink(remote)); + file.setRichWorkspace(remote.getRichWorkspace()); file.setLocked(remote.isLocked()); file.setLockType(remote.getLockType()); @@ -359,7 +366,7 @@ public static OCFile fillOCFile(RemoteFile remote) { file.setLockTimestamp(remote.getLockTimestamp()); file.setLockTimeout(remote.getLockTimeout()); file.setLockToken(remote.getLockToken()); - file.setTags(new ArrayList<>(Arrays.asList(remote.getTags()))); + file.setTags(RemoteFileExtensionsKt.tags(remote)); file.setImageDimension(remote.getImageDimension()); file.setGeoLocation(remote.getGeoLocation()); file.setLivePhoto(remote.getLivePhoto()); From 25c5af3b5a6a6b3364d9031c16c6e602ee53065a Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 2 Jun 2026 15:40:31 +0300 Subject: [PATCH 7/7] add missing fields Signed-off-by: alperozturk96 --- .../nextcloud/utils/extensions/RemoteFileExtensions.kt | 9 ++++----- gradle/verification-metadata.xml | 8 ++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/nextcloud/utils/extensions/RemoteFileExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/RemoteFileExtensions.kt index 2b0eabc011d4..22758d6140a2 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/RemoteFileExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/RemoteFileExtensions.kt @@ -29,14 +29,13 @@ fun RemoteFile.isSame(path: String?): Boolean { this.areImageDimensionsSame(path) } -fun RemoteFile.sharedViaLink(): Boolean = sharees?.any { it.shareType?.isLink == true } ?: false +fun RemoteFile.sharedViaLink(): Boolean = sharees?.any { it.shareType?.isLink == true } ?: false -fun RemoteFile.sharedWithSharee(): Boolean = sharees?.isNotEmpty() ?: false +fun RemoteFile.sharedWithSharee(): Boolean = sharees?.isNotEmpty() ?: false -fun RemoteFile.getShareeList(): List = sharees?.toList() ?: emptyList() +fun RemoteFile.getShareeList(): List = sharees?.toList() ?: emptyList() -fun RemoteFile.tags(): List = - tags?.mapNotNull { it } ?: emptyList() +fun RemoteFile.tags(): List = tags?.mapNotNull { it } ?: emptyList() @Suppress("ReturnCount") private fun RemoteFile.areImageDimensionsSame(path: String): Boolean { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 0eb104438acd..0a754c411505 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -21168,6 +21168,14 @@ + + + + + + + +