mirror of
https://github.com/bitwarden/android.git
synced 2025-03-16 03:08:50 +03:00
[PM-9927] Sort order update (#3625)
This commit is contained in:
parent
da3d834a91
commit
8ffd14c2fb
10 changed files with 133 additions and 16 deletions
|
@ -0,0 +1,38 @@
|
|||
package com.x8bit.bitwarden.data.platform.util
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Compare two characters, where a special character is considered with higher precedence over
|
||||
* letters and numbers. If both characters are a letter or a digit use the default
|
||||
* [Char.compareTo].
|
||||
*/
|
||||
private fun compareCharsSpecialCharsWithPrecedence(c1: Char, c2: Char): Int {
|
||||
return when {
|
||||
c1.isLetterOrDigit() && !c2.isLetterOrDigit() -> 1
|
||||
!c1.isLetterOrDigit() && c2.isLetterOrDigit() -> -1
|
||||
else -> c1.compareTo(c2)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String [Comparator] where the characters are compared giving precedence to
|
||||
* special characters.
|
||||
*/
|
||||
object CompareStringSpecialCharWithPrecedence : Comparator<String> {
|
||||
override fun compare(str1: String, str2: String): Int {
|
||||
val uppercaseStr1 = str1.uppercase(Locale.getDefault())
|
||||
val uppercaseStr2 = str2.uppercase(Locale.getDefault())
|
||||
val minLength = minOf(uppercaseStr1.length, uppercaseStr2.length)
|
||||
for (i in 0 until minLength) {
|
||||
val char1 = uppercaseStr1[i]
|
||||
val char2 = uppercaseStr2[i]
|
||||
val compareResult = compareCharsSpecialCharsWithPrecedence(char1, char2)
|
||||
if (compareResult != 0) {
|
||||
return compareResult
|
||||
}
|
||||
}
|
||||
// If all compared chars are the same give precedence to the shorter String.
|
||||
return uppercaseStr1.length - uppercaseStr2.length
|
||||
}
|
||||
}
|
|
@ -1085,7 +1085,7 @@ class VaultRepositoryImpl(
|
|||
sendList = it.toEncryptedSdkSendList(),
|
||||
)
|
||||
.fold(
|
||||
onSuccess = { sends -> DataState.Loaded(sends) },
|
||||
onSuccess = { sends -> DataState.Loaded(sends.sortAlphabetically()) },
|
||||
onFailure = { throwable -> DataState.Error(throwable) },
|
||||
)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.bitwarden.vault.PasswordHistory
|
|||
import com.bitwarden.vault.SecureNote
|
||||
import com.bitwarden.vault.SecureNoteType
|
||||
import com.bitwarden.vault.UriMatchType
|
||||
import com.x8bit.bitwarden.data.platform.util.CompareStringSpecialCharWithPrecedence
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.AttachmentJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherRepromptTypeJson
|
||||
|
@ -29,7 +30,6 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
|||
import com.x8bit.bitwarden.data.vault.datasource.network.model.UriMatchTypeJson
|
||||
import java.time.ZoneOffset
|
||||
import java.time.ZonedDateTime
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [Cipher] object to a corresponding
|
||||
|
@ -553,8 +553,14 @@ fun FieldTypeJson.toSdkFieldType(): FieldType =
|
|||
}
|
||||
|
||||
/**
|
||||
* Sorts the data in alphabetical order by name.
|
||||
* Sorts the data in alphabetical order by name. Using lexicographical sorting but giving
|
||||
* precedence to special characters over letters and digits.
|
||||
*/
|
||||
@JvmName("toAlphabeticallySortedCipherList")
|
||||
fun List<CipherView>.sortAlphabetically(): List<CipherView> =
|
||||
this.sortedBy { it.name.uppercase(Locale.getDefault()) }
|
||||
fun List<CipherView>.sortAlphabetically(): List<CipherView> {
|
||||
return this.sortedWith(
|
||||
comparator = { cipher1, cipher2 ->
|
||||
CompareStringSpecialCharWithPrecedence.compare(cipher1.name, cipher2.name)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ package com.x8bit.bitwarden.data.vault.repository.util
|
|||
|
||||
import com.bitwarden.vault.Collection
|
||||
import com.bitwarden.vault.CollectionView
|
||||
import com.x8bit.bitwarden.data.platform.util.CompareStringSpecialCharWithPrecedence
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Converts a [SyncResponseJson.Collection] object to a corresponding Bitwarden SDK [Collection]
|
||||
|
@ -30,5 +30,10 @@ fun List<SyncResponseJson.Collection>.toEncryptedSdkCollectionList(): List<Colle
|
|||
* Sorts the data in alphabetical order by name.
|
||||
*/
|
||||
@JvmName("toAlphabeticallySortedCollectionList")
|
||||
fun List<CollectionView>.sortAlphabetically(): List<CollectionView> =
|
||||
this.sortedBy { it.name.uppercase(Locale.getDefault()) }
|
||||
fun List<CollectionView>.sortAlphabetically(): List<CollectionView> {
|
||||
return this.sortedWith(
|
||||
comparator = { collection1, collection2 ->
|
||||
CompareStringSpecialCharWithPrecedence.compare(collection1.name, collection2.name)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ package com.x8bit.bitwarden.data.vault.repository.util
|
|||
|
||||
import com.bitwarden.vault.Folder
|
||||
import com.bitwarden.vault.FolderView
|
||||
import com.x8bit.bitwarden.data.platform.util.CompareStringSpecialCharWithPrecedence
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.FolderJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* Converts a list of [SyncResponseJson.Folder] objects to a list of corresponding
|
||||
|
@ -24,16 +24,21 @@ fun SyncResponseJson.Folder.toEncryptedSdkFolder(): Folder =
|
|||
revisionDate = revisionDate.toInstant(),
|
||||
)
|
||||
|
||||
/**
|
||||
* Sorts the data in alphabetical order by name.
|
||||
*/
|
||||
@JvmName("toAlphabeticallySortedFolderList")
|
||||
fun List<FolderView>.sortAlphabetically(): List<FolderView> =
|
||||
this.sortedBy { it.name.uppercase(Locale.getDefault()) }
|
||||
|
||||
/**
|
||||
* Converts a Bitwarden SDK [Folder] objects to a corresponding
|
||||
* [SyncResponseJson.Folder] object.
|
||||
*/
|
||||
fun Folder.toEncryptedNetworkFolder(): FolderJsonRequest =
|
||||
FolderJsonRequest(name = name)
|
||||
|
||||
/**
|
||||
* Sorts the data in alphabetical order by name.
|
||||
*/
|
||||
@JvmName("toAlphabeticallySortedFolderList")
|
||||
fun List<FolderView>.sortAlphabetically(): List<FolderView> {
|
||||
return this.sortedWith(
|
||||
comparator = { folder1, folder2 ->
|
||||
CompareStringSpecialCharWithPrecedence.compare(folder1.name, folder2.name)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import com.bitwarden.send.Send
|
|||
import com.bitwarden.send.SendFile
|
||||
import com.bitwarden.send.SendText
|
||||
import com.bitwarden.send.SendType
|
||||
import com.bitwarden.send.SendView
|
||||
import com.x8bit.bitwarden.data.platform.util.CompareStringSpecialCharWithPrecedence
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendTypeJson
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||
|
@ -123,3 +125,15 @@ private fun SendTypeJson.toSdkSendType(): SendType =
|
|||
SendTypeJson.TEXT -> SendType.TEXT
|
||||
SendTypeJson.FILE -> SendType.FILE
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the data in alphabetical order by name.
|
||||
*/
|
||||
@JvmName("toAlphabeticallySortedSendList")
|
||||
fun List<SendView>.sortAlphabetically(): List<SendView> {
|
||||
return this.sortedWith(
|
||||
comparator = { send1, send2 ->
|
||||
CompareStringSpecialCharWithPrecedence.compare(send1.name, send2.name)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -304,12 +304,23 @@ class VaultSdkCipherExtensionsTest {
|
|||
createMockCipherView(1).copy(name = "c"),
|
||||
createMockCipherView(1).copy(name = "B"),
|
||||
createMockCipherView(1).copy(name = "z"),
|
||||
createMockCipherView(1).copy(name = "8"),
|
||||
createMockCipherView(1).copy(name = "7"),
|
||||
createMockCipherView(1).copy(name = "_"),
|
||||
createMockCipherView(1).copy(name = "A"),
|
||||
createMockCipherView(1).copy(name = "D"),
|
||||
createMockCipherView(1).copy(name = "AbA"),
|
||||
createMockCipherView(1).copy(name = "aAb"),
|
||||
|
||||
)
|
||||
|
||||
val expected = listOf(
|
||||
createMockCipherView(1).copy(name = "_"),
|
||||
createMockCipherView(1).copy(name = "7"),
|
||||
createMockCipherView(1).copy(name = "8"),
|
||||
createMockCipherView(1).copy(name = "A"),
|
||||
createMockCipherView(1).copy(name = "aAb"),
|
||||
createMockCipherView(1).copy(name = "AbA"),
|
||||
createMockCipherView(1).copy(name = "B"),
|
||||
createMockCipherView(1).copy(name = "c"),
|
||||
createMockCipherView(1).copy(name = "D"),
|
||||
|
|
|
@ -65,11 +65,15 @@ class VaultSdkCollectionExtensionsTest {
|
|||
createMockCollectionView(1).copy(name = "c"),
|
||||
createMockCollectionView(1).copy(name = "B"),
|
||||
createMockCollectionView(1).copy(name = "z"),
|
||||
createMockCollectionView(1).copy(name = "4"),
|
||||
createMockCollectionView(1).copy(name = "A"),
|
||||
createMockCollectionView(1).copy(name = "#"),
|
||||
createMockCollectionView(1).copy(name = "D"),
|
||||
)
|
||||
|
||||
val expected = listOf(
|
||||
createMockCollectionView(1).copy(name = "#"),
|
||||
createMockCollectionView(1).copy(name = "4"),
|
||||
createMockCollectionView(1).copy(name = "A"),
|
||||
createMockCollectionView(1).copy(name = "B"),
|
||||
createMockCollectionView(1).copy(name = "c"),
|
||||
|
|
|
@ -41,12 +41,16 @@ class VaultSdkFolderExtensionsTest {
|
|||
val list = listOf(
|
||||
createMockFolderView(1).copy(name = "c"),
|
||||
createMockFolderView(1).copy(name = "D"),
|
||||
createMockFolderView(1).copy(name = "_"),
|
||||
createMockFolderView(1).copy(name = "4"),
|
||||
createMockFolderView(1).copy(name = "B"),
|
||||
createMockFolderView(1).copy(name = "A"),
|
||||
createMockFolderView(1).copy(name = "z"),
|
||||
)
|
||||
|
||||
val expected = listOf(
|
||||
createMockFolderView(1).copy(name = "_"),
|
||||
createMockFolderView(1).copy(name = "4"),
|
||||
createMockFolderView(1).copy(name = "A"),
|
||||
createMockFolderView(1).copy(name = "B"),
|
||||
createMockFolderView(1).copy(name = "c"),
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.vault.repository.util
|
|||
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockSend
|
||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockSendJsonRequest
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSendView
|
||||
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSdkSend
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
@ -50,4 +51,33 @@ class VaultSdkSendExtensionsTest {
|
|||
sdkSends,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `toSortAlphabetically should sort SendView by name`() {
|
||||
val list = listOf(
|
||||
createMockSendView(1).copy(name = "c"),
|
||||
createMockSendView(1).copy(name = "B"),
|
||||
createMockSendView(1).copy(name = "z"),
|
||||
createMockSendView(1).copy(name = "4"),
|
||||
createMockSendView(1).copy(name = "A"),
|
||||
createMockSendView(1).copy(name = "#"),
|
||||
createMockSendView(1).copy(name = "D"),
|
||||
)
|
||||
|
||||
val expected = listOf(
|
||||
createMockSendView(1).copy(name = "#"),
|
||||
createMockSendView(1).copy(name = "4"),
|
||||
createMockSendView(1).copy(name = "A"),
|
||||
createMockSendView(1).copy(name = "B"),
|
||||
createMockSendView(1).copy(name = "c"),
|
||||
createMockSendView(1).copy(name = "D"),
|
||||
createMockSendView(1).copy(name = "z"),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
expected,
|
||||
list.sortAlphabetically(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue