From 53d44b0c35afba98e5e1944ebc3673bdd8763082 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 27 Jul 2026 14:36:56 +0200 Subject: [PATCH 1/7] make sharees mutable Signed-off-by: alperozturk96 --- .../owncloud/android/datamodel/OCFile.java | 4 ++-- .../owncloud/android/datamodel/OCFileTest.kt | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java index 7aaf0e05924f..18cfa14e9d3d 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java +++ b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java @@ -105,7 +105,7 @@ public class OCFile implements Parcelable, Comparable, ServerFileInterfa private String ownerId; private String ownerDisplayName; String note; - private List sharees; + private List sharees = new ArrayList<>(); private String richWorkspace; private boolean locked; @Nullable @@ -988,7 +988,7 @@ public void setNote(String note) { } public void setSharees(List sharees) { - this.sharees = sharees; + this.sharees = (sharees == null) ? new ArrayList<>() : new ArrayList<>(sharees); } public void setRichWorkspace(String richWorkspace) { diff --git a/app/src/test/java/com/owncloud/android/datamodel/OCFileTest.kt b/app/src/test/java/com/owncloud/android/datamodel/OCFileTest.kt index 030623b04de5..79c910bb4ffc 100644 --- a/app/src/test/java/com/owncloud/android/datamodel/OCFileTest.kt +++ b/app/src/test/java/com/owncloud/android/datamodel/OCFileTest.kt @@ -7,11 +7,34 @@ */ package com.owncloud.android.datamodel +import com.owncloud.android.lib.resources.shares.ShareType +import com.owncloud.android.lib.resources.shares.ShareeUser import org.junit.Assert.assertEquals import org.junit.Assert.assertNotEquals +import org.junit.Assert.assertTrue import org.junit.Test class OCFileTest { + @Test + fun testShareesDefaultsToEmptyMutableList() { + val sut = OCFile("/") + + assertTrue(sut.sharees.isEmpty()) + + sut.sharees.add(ShareeUser("alice", "Alice", ShareType.USER)) + assertEquals(1, sut.sharees.size) + } + + @Test + fun testShareesStayMutableWhenSetFromImmutableList() { + val sut = OCFile("/") + + sut.sharees = listOf(ShareeUser("alice", "Alice", ShareType.USER)) + + sut.sharees.add(ShareeUser("bob", "Bob", ShareType.USER)) + assertEquals(2, sut.sharees.size) + } + @Test fun testLongIds() { val sut = OCFile("/") From 8ec2c7b1bdf9dc3c43adf47932e90f6c78e11a00 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 27 Jul 2026 14:48:14 +0200 Subject: [PATCH 2/7] speed-up bindSharedAvatars Signed-off-by: alperozturk96 --- .../android/ui/adapter/OCFileListAdapter.java | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 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 352bc6472b8d..3edcc558d0ab 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 @@ -75,7 +75,6 @@ import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; @@ -594,29 +593,44 @@ private void handleListMode(ListGridItemViewHolder holder, } private void bindSharedAvatars(ListItemViewHolder holder, OCFile file) { + final var sharedAvatars = holder.getSharedAvatars(); + if (!(file.isSharedWithMe() || file.isSharedWithSharee()) || isMultiSelect() || gridView || hideItemOptions) { - holder.getSharedAvatars().setVisibility(View.GONE); - holder.getSharedAvatars().removeAllViews(); + sharedAvatars.setVisibility(View.GONE); + if (sharedAvatars.getChildCount() > 0) { + sharedAvatars.removeAllViews(); + } return; } - final var sharees = new ArrayList<>(file.getSharees()); + sharedAvatars.setVisibility(View.VISIBLE); + sharedAvatars.setAvatars(user, avatarSharees(file), viewThemeUtils); + sharedAvatars.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(file)); + } + + private List avatarSharees(OCFile file) { + final List sharees = file.getSharees(); + ShareeUser owner = null; final String ownerId = file.getOwnerId(); if (!TextUtils.isEmpty(ownerId) && !ownerId.equals(userId)) { final var ownerSharee = new ShareeUser(ownerId, file.getOwnerDisplayName(), ShareType.USER); if (!sharees.contains(ownerSharee)) { - sharees.add(ownerSharee); + owner = ownerSharee; } } - Collections.reverse(sharees); + final var ordered = new ArrayList(sharees.size() + (owner == null ? 0 : 1)); + if (owner != null) { + ordered.add(owner); + } - final var sharedAvatars = holder.getSharedAvatars(); - sharedAvatars.setVisibility(View.VISIBLE); - sharedAvatars.removeAllViews(); - sharedAvatars.setAvatars(user, sharees, viewThemeUtils); - sharedAvatars.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(file)); + // count from last to first to get desired order + for (int i = sharees.size() - 1; i >= 0; i--) { + ordered.add(sharees.get(i)); + } + + return ordered; } private void bindListItemViewHolder(ListItemViewHolder holder, OCFile file) { From 88b3d95cd73a7fdec8388470903a6a91c737099a Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 27 Jul 2026 14:50:26 +0200 Subject: [PATCH 3/7] speed-up bindSharedAvatars Signed-off-by: alperozturk96 --- app/src/test/java/com/owncloud/android/datamodel/OCFileTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/test/java/com/owncloud/android/datamodel/OCFileTest.kt b/app/src/test/java/com/owncloud/android/datamodel/OCFileTest.kt index 79c910bb4ffc..939e1a3d73f5 100644 --- a/app/src/test/java/com/owncloud/android/datamodel/OCFileTest.kt +++ b/app/src/test/java/com/owncloud/android/datamodel/OCFileTest.kt @@ -1,6 +1,7 @@ /* * Nextcloud - Android Client * + * SPDX-FileCopyrightText: 2026 Alper Ozturk * SPDX-FileCopyrightText: 2022 Tobias Kaminsky * SPDX-FileCopyrightText: 2022 Nextcloud GmbH * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only From 792d5d8d6dfb18c7975327d3e6ad60dd968fddad Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 27 Jul 2026 14:50:43 +0200 Subject: [PATCH 4/7] speed-up bindSharedAvatars Signed-off-by: alperozturk96 --- .../java/com/owncloud/android/ui/adapter/OCFileListAdapter.java | 1 + 1 file changed, 1 insertion(+) 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 3edcc558d0ab..8da468e266ce 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 @@ -1,6 +1,7 @@ /* * Nextcloud - Android Client * + * SPDX-FileCopyrightText: 2026 Alper Ozturk * SPDX-FileCopyrightText: 2023 TSI-mc * SPDX-FileCopyrightText: 2020 Chris Narkiewicz * SPDX-FileCopyrightText: 2018 Tobias Kaminsky From 5784152f66da4aca7ba4a9be2b1c7134ac9df04f Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 5 Aug 2026 08:30:08 +0200 Subject: [PATCH 5/7] fix lint Signed-off-by: alperozturk96 --- app/src/main/java/com/owncloud/android/datamodel/OCFile.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java index 18cfa14e9d3d..f27dbe409932 100644 --- a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java +++ b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java @@ -987,6 +987,8 @@ public void setNote(String note) { this.note = note; } + @SuppressFBWarnings(value = "OCP_OVERLY_CONCRETE_COLLECTION_PARAMETER", + justification = "List keeps the Kotlin synthetic property in sync with getSharees()") public void setSharees(List sharees) { this.sharees = (sharees == null) ? new ArrayList<>() : new ArrayList<>(sharees); } From 2c02a9f614d1c67f9a92d1761ebed919dc6f9ec5 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 5 Aug 2026 08:50:40 +0200 Subject: [PATCH 6/7] use kt helper class Signed-off-by: alperozturk96 --- .../android/ui/adapter/OCFileListAdapter.java | 33 +++---------------- .../adapter/helper/OCFileListAdapterHelper.kt | 15 +++++++++ 2 files changed, 20 insertions(+), 28 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 8da468e266ce..e68ba687ec1f 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 @@ -51,8 +51,6 @@ import com.owncloud.android.datamodel.VirtualFolderType; import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.shares.ShareType; -import com.owncloud.android.lib.resources.shares.ShareeUser; import com.owncloud.android.lib.resources.status.OCCapability; import com.owncloud.android.lib.resources.tags.Tag; import com.owncloud.android.ui.activity.ComponentsGetter; @@ -605,33 +603,12 @@ private void bindSharedAvatars(ListItemViewHolder holder, OCFile file) { } sharedAvatars.setVisibility(View.VISIBLE); - sharedAvatars.setAvatars(user, avatarSharees(file), viewThemeUtils); - sharedAvatars.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(file)); - } - - private List avatarSharees(OCFile file) { - final List sharees = file.getSharees(); - - ShareeUser owner = null; - final String ownerId = file.getOwnerId(); - if (!TextUtils.isEmpty(ownerId) && !ownerId.equals(userId)) { - final var ownerSharee = new ShareeUser(ownerId, file.getOwnerDisplayName(), ShareType.USER); - if (!sharees.contains(ownerSharee)) { - owner = ownerSharee; - } + if (sharedAvatars.getChildCount() > 0) { + sharedAvatars.removeAllViews(); } - - final var ordered = new ArrayList(sharees.size() + (owner == null ? 0 : 1)); - if (owner != null) { - ordered.add(owner); - } - - // count from last to first to get desired order - for (int i = sharees.size() - 1; i >= 0; i--) { - ordered.add(sharees.get(i)); - } - - return ordered; + final var avatars = helper.getAvatarSharees(file, userId); + sharedAvatars.setAvatars(user, avatars, viewThemeUtils); + sharedAvatars.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(file)); } private void bindListItemViewHolder(ListItemViewHolder holder, OCFile file) { diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/helper/OCFileListAdapterHelper.kt b/app/src/main/java/com/owncloud/android/ui/adapter/helper/OCFileListAdapterHelper.kt index af07db366a2c..6e1a8e031f60 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/helper/OCFileListAdapterHelper.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/helper/OCFileListAdapterHelper.kt @@ -13,6 +13,8 @@ import com.nextcloud.utils.extensions.filterFilenames import com.nextcloud.utils.extensions.isTempFile import com.owncloud.android.MainApp import com.owncloud.android.datamodel.OCFile +import com.owncloud.android.lib.resources.shares.ShareType +import com.owncloud.android.lib.resources.shares.ShareeUser import com.owncloud.android.utils.FileSortOrder import com.owncloud.android.utils.MimeTypeUtil import kotlinx.coroutines.CoroutineScope @@ -54,6 +56,19 @@ class OCFileListAdapterHelper { } } + fun getAvatarSharees(file: OCFile, userId: String): List { + val sharees = file.sharees + val ownerId = file.ownerId + + val ownerSharee = if (!ownerId.isNullOrEmpty() && ownerId != userId) { + ShareeUser(ownerId, file.ownerDisplayName, ShareType.USER).takeIf { it !in sharees } + } else { + null + } + + return listOfNotNull(ownerSharee) + sharees.asReversed() + } + suspend fun prepareFileList( directory: OCFile, dataProvider: OCFileListAdapterDataProvider, From 30e5142c9260b3a66c6587f02da6462589a73b91 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Wed, 5 Aug 2026 08:55:14 +0200 Subject: [PATCH 7/7] use kt helper class Signed-off-by: alperozturk96 --- .../android/ui/adapter/helper/OCFileListAdapterHelper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/helper/OCFileListAdapterHelper.kt b/app/src/main/java/com/owncloud/android/ui/adapter/helper/OCFileListAdapterHelper.kt index 6e1a8e031f60..398b2fa30d0d 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/helper/OCFileListAdapterHelper.kt +++ b/app/src/main/java/com/owncloud/android/ui/adapter/helper/OCFileListAdapterHelper.kt @@ -56,7 +56,7 @@ class OCFileListAdapterHelper { } } - fun getAvatarSharees(file: OCFile, userId: String): List { + fun getAvatarSharees(file: OCFile, userId: String?): List { val sharees = file.sharees val ownerId = file.ownerId