diff --git a/common/src/commonMain/composeResources/values/strings.xml b/common/src/commonMain/composeResources/values/strings.xml index 23e9a87b..e090bc04 100644 --- a/common/src/commonMain/composeResources/values/strings.xml +++ b/common/src/commonMain/composeResources/values/strings.xml @@ -307,6 +307,7 @@ View parent item Always show keyboard + Remember sorting method Sync vault Lock vault Rename folder diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListStateProducer.kt index d13c9c09..7de490e7 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/home/vault/screen/VaultListStateProducer.kt @@ -137,6 +137,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json import org.kodein.di.DirectDI import org.kodein.di.compose.localDI import org.kodein.di.direct @@ -165,6 +166,16 @@ data class ComparatorHolder( favourites = map["favourites"].toString() == "true", ) } + + fun deserialize( + json: Json, + value: Map, + ): ComparatorHolder = of(value) + + fun serialize( + json: Json, + value: ComparatorHolder, + ): Map = value.toMap() } fun toMap() = mapOf( @@ -369,16 +380,18 @@ fun vaultListScreenState( } .launchIn(this) - val showKeyboardSink = if (args.canAlwaysShowKeyboard) { - mutablePersistedFlow( - key = "keyboard", - storage = storage, - ) { false } - } else { - mutablePersistedFlow( - key = "keyboard", - ) { false } - } + val showKeyboardSink = mutablePersistedFlow( + key = "keyboard", + storage = if (args.canAlwaysShowKeyboard) { + storage + } else PersistedStorage.InMemory, + ) { false } + val rememberSortSink = mutablePersistedFlow( + key = "sort_persistent_enabled", + storage = if (args.canAlwaysShowKeyboard) { + storage + } else PersistedStorage.InMemory, + ) { false } val syncFlow = syncSupervisor .get(AccountTask.SYNC) .map { accounts -> @@ -389,23 +402,41 @@ fun vaultListScreenState( comparator = AlphabeticalSort, favourites = true, ) + // Alternative sort sink that is stored on the + // disk storage. Mirrored from the in-memory sink. + val sortPersistentSink = mutablePersistedFlow( + key = "sort_persistent", + storage = storage, + serialize = ComparatorHolder::serialize, + deserialize = ComparatorHolder::deserialize, + ) { + sortDefault + } val sortSink = mutablePersistedFlow( key = "sort", - serialize = { json, value -> - value.toMap() - }, - deserialize = { json, value -> - ComparatorHolder.of(value) - }, + serialize = ComparatorHolder::serialize, + deserialize = ComparatorHolder::deserialize, ) { if (args.sort != null) { ComparatorHolder( comparator = args.sort, ) } else { - sortDefault + if (rememberSortSink.value) { + sortPersistentSink.value + } else { + sortDefault + } } } + // Copy the in-memory sorting method into + // the persistent storage. We need it for + // 'Remember sorting method' option to work. + sortSink + .onEach { value -> + sortPersistentSink.value = value + } + .launchIn(screenScope) var scrollPositionKey: Any? = null val scrollPositionSink = mutablePersistedFlow("scroll_state") { OhOhOh() } @@ -488,8 +519,28 @@ fun vaultListScreenState( onClick = showKeyboardSink::value::set.partially1(!showKeyboard), ) } + val actionRememberSortingFlow = rememberSortSink + .map { rememberSorting -> + FlatItemAction( + leading = { + Icon( + Icons.Outlined.SortByAlpha, + null, + ) + }, + trailing = { + Switch( + checked = rememberSorting, + onCheckedChange = rememberSortSink::value::set, + ) + }, + title = Res.string.vault_action_remember_sorting_title.wrap(), + onClick = rememberSortSink::value::set.partially1(!rememberSorting), + ) + } val actionGroup2Flow = combine( actionAlwaysShowKeyboardFlow, + actionRememberSortingFlow, ) { array -> buildContextItems { section {