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..f27dbe409932 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 @@ -987,8 +987,10 @@ 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; + this.sharees = (sharees == null) ? new ArrayList<>() : new ArrayList<>(sharees); } public void setRichWorkspace(String richWorkspace) { 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..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 @@ -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 @@ -50,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; @@ -75,7 +74,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,28 +592,22 @@ private void handleListMode(ListGridItemViewHolder holder, } private void bindSharedAvatars(ListItemViewHolder holder, OCFile file) { - if (!(file.isSharedWithMe() || file.isSharedWithSharee()) || isMultiSelect() || gridView || hideItemOptions) { - holder.getSharedAvatars().setVisibility(View.GONE); - holder.getSharedAvatars().removeAllViews(); - return; - } - - final var sharees = new ArrayList<>(file.getSharees()); + final var sharedAvatars = holder.getSharedAvatars(); - 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); + if (!(file.isSharedWithMe() || file.isSharedWithSharee()) || isMultiSelect() || gridView || hideItemOptions) { + sharedAvatars.setVisibility(View.GONE); + if (sharedAvatars.getChildCount() > 0) { + sharedAvatars.removeAllViews(); } + return; } - Collections.reverse(sharees); - - final var sharedAvatars = holder.getSharedAvatars(); sharedAvatars.setVisibility(View.VISIBLE); - sharedAvatars.removeAllViews(); - sharedAvatars.setAvatars(user, sharees, viewThemeUtils); + if (sharedAvatars.getChildCount() > 0) { + sharedAvatars.removeAllViews(); + } + final var avatars = helper.getAvatarSharees(file, userId); + sharedAvatars.setAvatars(user, avatars, viewThemeUtils); sharedAvatars.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(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..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 @@ -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, 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..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,17 +1,41 @@ /* * 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 */ 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("/")