Always sort ignoring word case
This commit is contained in:
parent
61b64ba555
commit
2113847162
|
@ -0,0 +1,26 @@
|
||||||
|
package com.artemchep.keyguard.common.util
|
||||||
|
|
||||||
|
class StringComparatorIgnoreCase<T>(
|
||||||
|
private val descending: Boolean = false,
|
||||||
|
private val getter: (T) -> String?,
|
||||||
|
) : Comparator<T> {
|
||||||
|
override fun compare(aHolder: T, bHolder: T): Int {
|
||||||
|
val a = getter(aHolder)
|
||||||
|
val b = getter(bHolder)
|
||||||
|
|
||||||
|
var r = internalCompare(a, b)
|
||||||
|
// Reverse the comparison result,
|
||||||
|
// if needed.
|
||||||
|
if (descending) {
|
||||||
|
r *= -1
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun internalCompare(a: String?, b: String?): Int {
|
||||||
|
if (a === b) return 0
|
||||||
|
if (a == null) return -1
|
||||||
|
if (b == null) return 1
|
||||||
|
return a.compareTo(b, ignoreCase = true)
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ import com.artemchep.keyguard.common.usecase.GetFolders
|
||||||
import com.artemchep.keyguard.common.usecase.GetOrganizations
|
import com.artemchep.keyguard.common.usecase.GetOrganizations
|
||||||
import com.artemchep.keyguard.common.usecase.GetProfiles
|
import com.artemchep.keyguard.common.usecase.GetProfiles
|
||||||
import com.artemchep.keyguard.common.usecase.RemoveAttachment
|
import com.artemchep.keyguard.common.usecase.RemoveAttachment
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.common.util.flow.foldAsList
|
import com.artemchep.keyguard.common.util.flow.foldAsList
|
||||||
import com.artemchep.keyguard.feature.attachments.model.AttachmentItem
|
import com.artemchep.keyguard.feature.attachments.model.AttachmentItem
|
||||||
import com.artemchep.keyguard.feature.attachments.util.createAttachmentItem
|
import com.artemchep.keyguard.feature.attachments.util.createAttachmentItem
|
||||||
|
@ -239,7 +240,7 @@ fun produceAttachmentsScreenState(
|
||||||
.map { list ->
|
.map { list ->
|
||||||
list
|
list
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
.sortedBy { it.item.name }
|
.sortedWith(StringComparatorIgnoreCase { it.item.name })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.shareInScreenScope()
|
.shareInScreenScope()
|
||||||
|
|
|
@ -9,6 +9,7 @@ import arrow.core.partially1
|
||||||
import com.artemchep.keyguard.common.model.Loadable
|
import com.artemchep.keyguard.common.model.Loadable
|
||||||
import com.artemchep.keyguard.common.usecase.GetFolders
|
import com.artemchep.keyguard.common.usecase.GetFolders
|
||||||
import com.artemchep.keyguard.common.usecase.WindowCoroutineScope
|
import com.artemchep.keyguard.common.usecase.WindowCoroutineScope
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.feature.auth.common.TextFieldModel2
|
import com.artemchep.keyguard.feature.auth.common.TextFieldModel2
|
||||||
import com.artemchep.keyguard.feature.auth.common.Validated
|
import com.artemchep.keyguard.feature.auth.common.Validated
|
||||||
import com.artemchep.keyguard.feature.auth.common.util.validatedTitle
|
import com.artemchep.keyguard.feature.auth.common.util.validatedTitle
|
||||||
|
@ -130,7 +131,7 @@ fun folderConfirmationState(
|
||||||
.map { folders ->
|
.map { folders ->
|
||||||
val items = folders
|
val items = folders
|
||||||
.filter { it.accountId == args.accountId.id }
|
.filter { it.accountId == args.accountId.id }
|
||||||
.sortedBy { it.name }
|
.sortedWith(StringComparatorIgnoreCase { it.name })
|
||||||
.map { folder ->
|
.map { folder ->
|
||||||
val folderEnabled = folder.id !in args.blacklistedFolderIds
|
val folderEnabled = folder.id !in args.blacklistedFolderIds
|
||||||
val folderInfo = FolderVariant.FolderInfo.Id(
|
val folderInfo = FolderVariant.FolderInfo.Id(
|
||||||
|
|
|
@ -21,6 +21,7 @@ import com.artemchep.keyguard.common.usecase.GetFolders
|
||||||
import com.artemchep.keyguard.common.usecase.GetOrganizations
|
import com.artemchep.keyguard.common.usecase.GetOrganizations
|
||||||
import com.artemchep.keyguard.common.usecase.GetProfiles
|
import com.artemchep.keyguard.common.usecase.GetProfiles
|
||||||
import com.artemchep.keyguard.common.usecase.WindowCoroutineScope
|
import com.artemchep.keyguard.common.usecase.WindowCoroutineScope
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.common.util.contains
|
import com.artemchep.keyguard.common.util.contains
|
||||||
import com.artemchep.keyguard.feature.auth.common.TextFieldModel2
|
import com.artemchep.keyguard.feature.auth.common.TextFieldModel2
|
||||||
import com.artemchep.keyguard.feature.auth.common.Validated
|
import com.artemchep.keyguard.feature.auth.common.Validated
|
||||||
|
@ -230,7 +231,7 @@ fun organizationConfirmationState(
|
||||||
accountsFlow,
|
accountsFlow,
|
||||||
) { organizations, accounts ->
|
) { organizations, accounts ->
|
||||||
organizations
|
organizations
|
||||||
.sortedBy { it.name }
|
.sortedWith(StringComparatorIgnoreCase { it.name })
|
||||||
.map { organization ->
|
.map { organization ->
|
||||||
val enabled = organization.id !in args.blacklistedOrganizationIds
|
val enabled = organization.id !in args.blacklistedOrganizationIds
|
||||||
OrganizationVariant(
|
OrganizationVariant(
|
||||||
|
@ -274,7 +275,7 @@ fun organizationConfirmationState(
|
||||||
accountsFlow,
|
accountsFlow,
|
||||||
) { folders, accounts ->
|
) { folders, accounts ->
|
||||||
folders
|
folders
|
||||||
.sortedBy { it.name }
|
.sortedWith(StringComparatorIgnoreCase { it.name })
|
||||||
.map { folder ->
|
.map { folder ->
|
||||||
val enabled = folder.id !in args.blacklistedFolderIds
|
val enabled = folder.id !in args.blacklistedFolderIds
|
||||||
FolderVariant(
|
FolderVariant(
|
||||||
|
|
|
@ -15,6 +15,7 @@ import com.artemchep.keyguard.common.service.relays.api.EmailRelay
|
||||||
import com.artemchep.keyguard.common.usecase.AddEmailRelay
|
import com.artemchep.keyguard.common.usecase.AddEmailRelay
|
||||||
import com.artemchep.keyguard.common.usecase.GetEmailRelays
|
import com.artemchep.keyguard.common.usecase.GetEmailRelays
|
||||||
import com.artemchep.keyguard.common.usecase.RemoveEmailRelayById
|
import com.artemchep.keyguard.common.usecase.RemoveEmailRelayById
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.common.util.flow.persistingStateIn
|
import com.artemchep.keyguard.common.util.flow.persistingStateIn
|
||||||
import com.artemchep.keyguard.feature.attachments.SelectableItemState
|
import com.artemchep.keyguard.feature.attachments.SelectableItemState
|
||||||
import com.artemchep.keyguard.feature.attachments.SelectableItemStateRaw
|
import com.artemchep.keyguard.feature.attachments.SelectableItemStateRaw
|
||||||
|
@ -200,7 +201,7 @@ fun produceEmailRelayListState(
|
||||||
.partially1(emailRelay),
|
.partially1(emailRelay),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.sortedBy { it.title }
|
.sortedWith(StringComparatorIgnoreCase { it.title })
|
||||||
.toImmutableList()
|
.toImmutableList()
|
||||||
|
|
||||||
val itemsRawFlow = getEmailRelays()
|
val itemsRawFlow = getEmailRelays()
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.artemchep.keyguard.common.usecase.QueueSyncById
|
||||||
import com.artemchep.keyguard.common.usecase.RemoveAccountById
|
import com.artemchep.keyguard.common.usecase.RemoveAccountById
|
||||||
import com.artemchep.keyguard.common.usecase.SupervisorRead
|
import com.artemchep.keyguard.common.usecase.SupervisorRead
|
||||||
import com.artemchep.keyguard.common.usecase.WindowCoroutineScope
|
import com.artemchep.keyguard.common.usecase.WindowCoroutineScope
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.common.util.flow.foldAsList
|
import com.artemchep.keyguard.common.util.flow.foldAsList
|
||||||
import com.artemchep.keyguard.feature.auth.AccountViewRoute
|
import com.artemchep.keyguard.feature.auth.AccountViewRoute
|
||||||
import com.artemchep.keyguard.feature.confirmation.createConfirmationDialogIntent
|
import com.artemchep.keyguard.feature.confirmation.createConfirmationDialogIntent
|
||||||
|
@ -287,7 +288,7 @@ fun accountListScreenState(
|
||||||
.foldAsList()
|
.foldAsList()
|
||||||
.map { items ->
|
.map { items ->
|
||||||
items
|
items
|
||||||
.sortedBy { it.text }
|
.sortedWith(StringComparatorIgnoreCase { it.text })
|
||||||
}
|
}
|
||||||
|
|
||||||
combine(
|
combine(
|
||||||
|
|
|
@ -88,6 +88,7 @@ import com.artemchep.keyguard.common.usecase.GetOrganizations
|
||||||
import com.artemchep.keyguard.common.usecase.GetProfiles
|
import com.artemchep.keyguard.common.usecase.GetProfiles
|
||||||
import com.artemchep.keyguard.common.usecase.GetTotpCode
|
import com.artemchep.keyguard.common.usecase.GetTotpCode
|
||||||
import com.artemchep.keyguard.common.usecase.ShowMessage
|
import com.artemchep.keyguard.common.usecase.ShowMessage
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.common.util.flow.EventFlow
|
import com.artemchep.keyguard.common.util.flow.EventFlow
|
||||||
import com.artemchep.keyguard.common.util.flow.combineToList
|
import com.artemchep.keyguard.common.util.flow.combineToList
|
||||||
import com.artemchep.keyguard.common.util.flow.foldAsList
|
import com.artemchep.keyguard.common.util.flow.foldAsList
|
||||||
|
@ -1965,7 +1966,7 @@ private suspend fun RememberStateFlowScope.produceOwnershipFlow(
|
||||||
}
|
}
|
||||||
|
|
||||||
val selectedCollections = collections
|
val selectedCollections = collections
|
||||||
.sortedBy { it.name }
|
.sortedWith(StringComparatorIgnoreCase { it.name })
|
||||||
.filter { it.id in collectionIds }
|
.filter { it.id in collectionIds }
|
||||||
val el = AddState.SaveToElement(
|
val el = AddState.SaveToElement(
|
||||||
readOnly = ro,
|
readOnly = ro,
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.artemchep.keyguard.common.usecase.GetFolders
|
||||||
import com.artemchep.keyguard.common.usecase.MergeFolderById
|
import com.artemchep.keyguard.common.usecase.MergeFolderById
|
||||||
import com.artemchep.keyguard.common.usecase.RemoveFolderById
|
import com.artemchep.keyguard.common.usecase.RemoveFolderById
|
||||||
import com.artemchep.keyguard.common.usecase.RenameFolderById
|
import com.artemchep.keyguard.common.usecase.RenameFolderById
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.core.store.bitwarden.exists
|
import com.artemchep.keyguard.core.store.bitwarden.exists
|
||||||
import com.artemchep.keyguard.feature.confirmation.ConfirmationResult
|
import com.artemchep.keyguard.feature.confirmation.ConfirmationResult
|
||||||
import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute
|
import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute
|
||||||
|
@ -189,7 +190,7 @@ fun foldersScreenState(
|
||||||
translate(Res.strings.folder_action_change_name_title)
|
translate(Res.strings.folder_action_change_name_title)
|
||||||
},
|
},
|
||||||
items = folders
|
items = folders
|
||||||
.sortedBy { it.name }
|
.sortedWith(StringComparatorIgnoreCase { it.name })
|
||||||
.map { folder ->
|
.map { folder ->
|
||||||
ConfirmationRoute.Args.Item.StringItem(
|
ConfirmationRoute.Args.Item.StringItem(
|
||||||
key = folder.id,
|
key = folder.id,
|
||||||
|
|
|
@ -27,6 +27,7 @@ import com.artemchep.keyguard.common.model.DSecret
|
||||||
import com.artemchep.keyguard.common.model.iconImageVector
|
import com.artemchep.keyguard.common.model.iconImageVector
|
||||||
import com.artemchep.keyguard.common.model.titleH
|
import com.artemchep.keyguard.common.model.titleH
|
||||||
import com.artemchep.keyguard.common.usecase.GetFolderTree
|
import com.artemchep.keyguard.common.usecase.GetFolderTree
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.feature.home.vault.component.rememberSecretAccentColor
|
import com.artemchep.keyguard.feature.home.vault.component.rememberSecretAccentColor
|
||||||
import com.artemchep.keyguard.feature.home.vault.model.FilterItem
|
import com.artemchep.keyguard.feature.home.vault.model.FilterItem
|
||||||
import com.artemchep.keyguard.feature.home.vault.search.filter.FilterHolder
|
import com.artemchep.keyguard.feature.home.vault.search.filter.FilterHolder
|
||||||
|
@ -560,7 +561,7 @@ suspend fun <
|
||||||
title = name,
|
title = name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.sortedBy { it.title }
|
.sortedWith(StringComparatorIgnoreCase { it.title })
|
||||||
.toList() +
|
.toList() +
|
||||||
createCollectionFilterAction(
|
createCollectionFilterAction(
|
||||||
collectionIds = setOfNull,
|
collectionIds = setOfNull,
|
||||||
|
@ -602,7 +603,7 @@ suspend fun <
|
||||||
title = name,
|
title = name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.sortedBy { it.title }
|
.sortedWith(StringComparatorIgnoreCase { it.title })
|
||||||
.toList() +
|
.toList() +
|
||||||
createOrganizationFilterAction(
|
createOrganizationFilterAction(
|
||||||
organizationIds = setOfNull,
|
organizationIds = setOfNull,
|
||||||
|
|
|
@ -60,6 +60,7 @@ import com.artemchep.keyguard.common.usecase.PasskeyTargetCheck
|
||||||
import com.artemchep.keyguard.common.usecase.QueueSyncAll
|
import com.artemchep.keyguard.common.usecase.QueueSyncAll
|
||||||
import com.artemchep.keyguard.common.usecase.RenameFolderById
|
import com.artemchep.keyguard.common.usecase.RenameFolderById
|
||||||
import com.artemchep.keyguard.common.usecase.SupervisorRead
|
import com.artemchep.keyguard.common.usecase.SupervisorRead
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.common.util.flow.EventFlow
|
import com.artemchep.keyguard.common.util.flow.EventFlow
|
||||||
import com.artemchep.keyguard.common.util.flow.persistingStateIn
|
import com.artemchep.keyguard.common.util.flow.persistingStateIn
|
||||||
import com.artemchep.keyguard.feature.attachments.AttachmentsRoute
|
import com.artemchep.keyguard.feature.attachments.AttachmentsRoute
|
||||||
|
@ -284,7 +285,7 @@ fun vaultListScreenState(
|
||||||
icon = icon(Icons.Outlined.Edit),
|
icon = icon(Icons.Outlined.Edit),
|
||||||
title = "Change folder name",
|
title = "Change folder name",
|
||||||
items = folders
|
items = folders
|
||||||
.sortedBy { it.name }
|
.sortedWith(StringComparatorIgnoreCase { it.name })
|
||||||
.map { folder ->
|
.map { folder ->
|
||||||
ConfirmationRoute.Args.Item.StringItem(
|
ConfirmationRoute.Args.Item.StringItem(
|
||||||
key = folder.id,
|
key = folder.id,
|
||||||
|
|
|
@ -133,6 +133,7 @@ import com.artemchep.keyguard.common.usecase.RestoreCipherById
|
||||||
import com.artemchep.keyguard.common.usecase.RetryCipher
|
import com.artemchep.keyguard.common.usecase.RetryCipher
|
||||||
import com.artemchep.keyguard.common.usecase.TrashCipherById
|
import com.artemchep.keyguard.common.usecase.TrashCipherById
|
||||||
import com.artemchep.keyguard.common.usecase.WindowCoroutineScope
|
import com.artemchep.keyguard.common.usecase.WindowCoroutineScope
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.common.util.flow.persistingStateIn
|
import com.artemchep.keyguard.common.util.flow.persistingStateIn
|
||||||
import com.artemchep.keyguard.core.store.bitwarden.canRetry
|
import com.artemchep.keyguard.core.store.bitwarden.canRetry
|
||||||
import com.artemchep.keyguard.core.store.bitwarden.expired
|
import com.artemchep.keyguard.core.store.bitwarden.expired
|
||||||
|
@ -421,7 +422,7 @@ fun vaultViewScreenState(
|
||||||
collections
|
collections
|
||||||
.firstOrNull { it.id == collectionId && it.accountId == accountId }
|
.firstOrNull { it.id == collectionId && it.accountId == accountId }
|
||||||
}
|
}
|
||||||
.sortedByDescending { it.name }
|
.sortedWith(StringComparatorIgnoreCase(descending = true) { it.name })
|
||||||
}
|
}
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
val organizationFlow = getOrganizations()
|
val organizationFlow = getOrganizations()
|
||||||
|
|
|
@ -36,6 +36,7 @@ import com.artemchep.keyguard.common.usecase.RePromptCipherById
|
||||||
import com.artemchep.keyguard.common.usecase.RemoveCipherById
|
import com.artemchep.keyguard.common.usecase.RemoveCipherById
|
||||||
import com.artemchep.keyguard.common.usecase.RestoreCipherById
|
import com.artemchep.keyguard.common.usecase.RestoreCipherById
|
||||||
import com.artemchep.keyguard.common.usecase.TrashCipherById
|
import com.artemchep.keyguard.common.usecase.TrashCipherById
|
||||||
|
import com.artemchep.keyguard.common.util.StringComparatorIgnoreCase
|
||||||
import com.artemchep.keyguard.feature.confirmation.ConfirmationResult
|
import com.artemchep.keyguard.feature.confirmation.ConfirmationResult
|
||||||
import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute
|
import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute
|
||||||
import com.artemchep.keyguard.feature.confirmation.folder.FolderConfirmationResult
|
import com.artemchep.keyguard.feature.confirmation.folder.FolderConfirmationResult
|
||||||
|
@ -371,7 +372,7 @@ fun RememberStateFlowScope.cipherChangeNameAction(
|
||||||
before?.invoke()
|
before?.invoke()
|
||||||
|
|
||||||
val items = ciphers
|
val items = ciphers
|
||||||
.sortedBy { it.name }
|
.sortedWith(StringComparatorIgnoreCase { it.name })
|
||||||
.map { cipher ->
|
.map { cipher ->
|
||||||
ConfirmationRoute.Args.Item.StringItem(
|
ConfirmationRoute.Args.Item.StringItem(
|
||||||
key = cipher.id,
|
key = cipher.id,
|
||||||
|
@ -444,7 +445,7 @@ fun RememberStateFlowScope.cipherChangePasswordAction(
|
||||||
|
|
||||||
val items = ciphers
|
val items = ciphers
|
||||||
.filter { it.type == DSecret.Type.Login }
|
.filter { it.type == DSecret.Type.Login }
|
||||||
.sortedBy { it.name }
|
.sortedWith(StringComparatorIgnoreCase { it.name })
|
||||||
.map { cipher ->
|
.map { cipher ->
|
||||||
ConfirmationRoute.Args.Item.StringItem(
|
ConfirmationRoute.Args.Item.StringItem(
|
||||||
key = cipher.id,
|
key = cipher.id,
|
||||||
|
|
Loading…
Reference in New Issue