mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 08:35:05 -06:00
[PM-25394] Sort default user collections by Organization name (#5819)
This commit is contained in:
parent
9adc25471e
commit
1c4e4dcaf4
@ -82,7 +82,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.UpdateSendResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultUnlockResult
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.sortAlphabetically
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.sortAlphabeticallyByType
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.sortAlphabeticallyByTypeAndOrganization
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.toDomainsData
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedNetworkFolder
|
||||
import com.x8bit.bitwarden.data.vault.repository.util.toEncryptedNetworkSend
|
||||
@ -1168,7 +1168,11 @@ class VaultRepositoryImpl(
|
||||
.fold(
|
||||
onSuccess = { collections ->
|
||||
DataState.Loaded(
|
||||
collections.sortAlphabeticallyByType(),
|
||||
collections.sortAlphabeticallyByTypeAndOrganization(
|
||||
userOrganizations = authDiskSource
|
||||
.getOrganizations(userId = userId)
|
||||
.orEmpty(),
|
||||
),
|
||||
)
|
||||
},
|
||||
onFailure = { throwable -> DataState.Error(throwable) },
|
||||
|
||||
@ -32,21 +32,45 @@ fun List<SyncResponseJson.Collection>.toEncryptedSdkCollectionList(): List<Colle
|
||||
map { it.toEncryptedSdkCollection() }
|
||||
|
||||
/**
|
||||
* Sorts the collections, grouping them by type, with `DEFAULT_USER_COLLECTION` types displayed
|
||||
* first. Within each group, collections are sorted alphabetically by name.
|
||||
* Sorts a list of [CollectionView] objects based on a multi-level sorting logic.
|
||||
*
|
||||
* The sorting criteria are as follows, in order of precedence:
|
||||
* 1. Collections of type `DEFAULT_USER_COLLECTION` are placed first.
|
||||
* 2. All other collections are grouped by their `CollectionType`.
|
||||
* 3. Within each group, collections are sorted alphabetically by name. For collections of
|
||||
* type `DEFAULT_USER_COLLECTION`, the corresponding organization's name is used for sorting
|
||||
* instead of the collection's own name.
|
||||
*
|
||||
* This function uses a [SpecialCharWithPrecedenceComparator] for the alphabetical sort.
|
||||
*
|
||||
* @param userOrganizations A list of the user's organizations, used to find the name for
|
||||
* `DEFAULT_USER_COLLECTION` types.
|
||||
* @return A new list containing the sorted [CollectionView] objects.
|
||||
*/
|
||||
@JvmName("toAlphabeticallySortedCollectionList")
|
||||
fun List<CollectionView>.sortAlphabeticallyByType(): List<CollectionView> {
|
||||
fun List<CollectionView>.sortAlphabeticallyByTypeAndOrganization(
|
||||
userOrganizations: List<SyncResponseJson.Profile.Organization>,
|
||||
): List<CollectionView> {
|
||||
return this.sortedWith(
|
||||
// DEFAULT_USER_COLLECTION come first
|
||||
comparator = compareBy<CollectionView> { it.type != CollectionType.DEFAULT_USER_COLLECTION }
|
||||
// Then sort by other CollectionType ordinals
|
||||
.thenBy { it.type }
|
||||
// Finally, sort by name within each group
|
||||
.thenComparing(
|
||||
CollectionView::name,
|
||||
SpecialCharWithPrecedenceComparator,
|
||||
),
|
||||
// Finally, sort within each group. For default collections, use the
|
||||
// organization's name; for others, use the collection's name.
|
||||
.thenBy(SpecialCharWithPrecedenceComparator) {
|
||||
if (it.type == CollectionType.DEFAULT_USER_COLLECTION) {
|
||||
// For default collections, sort by the organization's name
|
||||
userOrganizations
|
||||
.find { org -> org.id == it.organizationId }
|
||||
?.name
|
||||
?: it.name
|
||||
} else {
|
||||
// For other collections, sort by the collection's name
|
||||
it.name
|
||||
}
|
||||
}
|
||||
// As a final fallback if names are identical, sort by ID to ensure a stable order
|
||||
.thenBy { it.id },
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import com.bitwarden.collections.Collection
|
||||
import com.bitwarden.collections.CollectionType
|
||||
import com.bitwarden.network.model.CollectionTypeJson
|
||||
import com.bitwarden.network.model.SyncResponseJson
|
||||
import com.bitwarden.network.model.createMockOrganization
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCollectionView
|
||||
import org.junit.Test
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
@ -103,7 +104,7 @@ class VaultSdkCollectionExtensionsTest {
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `toSortAlphabetically should sort collections by type and name`() {
|
||||
fun `toSortAlphabeticallyByTypeAndOrganization should sort collections by type and name`() {
|
||||
val list = listOf(
|
||||
createMockCollectionView(1).copy(name = "c"),
|
||||
createMockCollectionView(1).copy(name = "B"),
|
||||
@ -111,16 +112,28 @@ class VaultSdkCollectionExtensionsTest {
|
||||
createMockCollectionView(1).copy(name = "4"),
|
||||
createMockCollectionView(1).copy(name = "A"),
|
||||
createMockCollectionView(1).copy(name = "#"),
|
||||
createMockCollectionView(1).copy(
|
||||
name = "D",
|
||||
createMockCollectionView(2).copy(
|
||||
name = "Org2 items",
|
||||
type = CollectionType.DEFAULT_USER_COLLECTION,
|
||||
organizationId = "mockId-2",
|
||||
),
|
||||
createMockCollectionView(1).copy(
|
||||
name = "Org1 items",
|
||||
type = CollectionType.DEFAULT_USER_COLLECTION,
|
||||
organizationId = "mockId-1",
|
||||
),
|
||||
)
|
||||
|
||||
val expected = listOf(
|
||||
createMockCollectionView(1).copy(
|
||||
name = "D",
|
||||
name = "Org1 items",
|
||||
type = CollectionType.DEFAULT_USER_COLLECTION,
|
||||
organizationId = "mockId-1",
|
||||
),
|
||||
createMockCollectionView(2).copy(
|
||||
name = "Org2 items",
|
||||
type = CollectionType.DEFAULT_USER_COLLECTION,
|
||||
organizationId = "mockId-2",
|
||||
),
|
||||
createMockCollectionView(1).copy(name = "#"),
|
||||
createMockCollectionView(1).copy(name = "4"),
|
||||
@ -132,7 +145,12 @@ class VaultSdkCollectionExtensionsTest {
|
||||
|
||||
assertEquals(
|
||||
expected,
|
||||
list.sortAlphabeticallyByType(),
|
||||
list.sortAlphabeticallyByTypeAndOrganization(
|
||||
userOrganizations = listOf(
|
||||
createMockOrganization(number = 1),
|
||||
createMockOrganization(number = 2),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user