From 0cfa52de56138c52587e76caa2b5f825a4e6f3c4 Mon Sep 17 00:00:00 2001 From: Terry Yiu Date: Thu, 10 Sep 2026 15:16:27 +0300 Subject: [PATCH] Split the currency picker's browsable list into Priced/Unpriced The "Currencies" section (not-yet-added currencies) is now two: "Priced Currencies" and "Unpriced Currencies", partitioned by whether the active source quotes a rate for each one. "Current Currency" and "Selected Currencies" are unaffected. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01FXcrACM5sok3M1KQJ8kByy --- iosApp/iosApp/CurrencyPickerSheet.swift | 17 ++++++++-- .../xyz/tyiu/satsprice/ui/PriceScreen.kt | 32 ++++++++++++++++--- .../moko-resources/base/strings.xml | 2 ++ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/iosApp/iosApp/CurrencyPickerSheet.swift b/iosApp/iosApp/CurrencyPickerSheet.swift index 995b61e..92de1f9 100644 --- a/iosApp/iosApp/CurrencyPickerSheet.swift +++ b/iosApp/iosApp/CurrencyPickerSheet.swift @@ -36,9 +36,20 @@ struct CurrencyPickerSheet: View { } let matchingUnselected = unselectedCurrencies.filter(matches) - if !matchingUnselected.isEmpty { - Section(IosLocalizationKt.localizedString(resource: MR.strings.shared.currencies_section_title)) { - ForEach(matchingUnselected, id: \.code) { info in + let unselectedPriced = matchingUnselected.filter { pricedCurrencyCodes.contains($0.code) } + let unselectedUnpriced = matchingUnselected.filter { !pricedCurrencyCodes.contains($0.code) } + + if !unselectedPriced.isEmpty { + Section(IosLocalizationKt.localizedString(resource: MR.strings.shared.priced_currencies_section_title)) { + ForEach(unselectedPriced, id: \.code) { info in + currencyRow(for: info, isSelected: false, onTap: { onToggle(info.code) }) + } + } + } + + if !unselectedUnpriced.isEmpty { + Section(IosLocalizationKt.localizedString(resource: MR.strings.shared.unpriced_currencies_section_title)) { + ForEach(unselectedUnpriced, id: \.code) { info in currencyRow(for: info, isSelected: false, onTap: { onToggle(info.code) }) } } diff --git a/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/PriceScreen.kt b/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/PriceScreen.kt index 036ae9e..d52c34c 100644 --- a/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/PriceScreen.kt +++ b/shared/src/commonMain/kotlin/xyz/tyiu/satsprice/ui/PriceScreen.kt @@ -591,19 +591,43 @@ private fun CurrencyPickerScreen( } } - if (unselected.isNotEmpty()) { + val (unselectedPriced, unselectedUnpriced) = unselected.partition { state.isPriced(it.code) } + + if (unselectedPriced.isNotEmpty()) { Column { Text( - stringResource(MR.strings.currencies_section_title).uppercase(), + stringResource(MR.strings.priced_currencies_section_title).uppercase(), style = SectionHeaderStyle, modifier = Modifier.padding(bottom = 4.dp), ) - unselected.forEach { info -> + unselectedPriced.forEach { info -> key(info.code) { CurrencyRow( info = info, isSelected = false, - isPriced = state.isPriced(info.code), + isPriced = true, + sourceName = state.sourceName, + localeCurrencyCode = state.localeCurrencyCode, + onClick = { onToggle(info.code) }, + ) + } + } + } + } + + if (unselectedUnpriced.isNotEmpty()) { + Column { + Text( + stringResource(MR.strings.unpriced_currencies_section_title).uppercase(), + style = SectionHeaderStyle, + modifier = Modifier.padding(bottom = 4.dp), + ) + unselectedUnpriced.forEach { info -> + key(info.code) { + CurrencyRow( + info = info, + isSelected = false, + isPriced = false, sourceName = state.sourceName, localeCurrencyCode = state.localeCurrencyCode, onClick = { onToggle(info.code) }, diff --git a/shared/src/commonMain/moko-resources/base/strings.xml b/shared/src/commonMain/moko-resources/base/strings.xml index 4943d5f..bb6fbb8 100644 --- a/shared/src/commonMain/moko-resources/base/strings.xml +++ b/shared/src/commonMain/moko-resources/base/strings.xml @@ -19,10 +19,12 @@ Move to top Move up Price Source + Priced Currencies Refresh Remove Retry Sats Search currencies Selected Currencies + Unpriced Currencies