Add manual currency sorting and improve currency categorization
This commit is contained in:
@@ -15,6 +15,15 @@ struct ContentView: View {
|
||||
}
|
||||
}
|
||||
.navigationTitle("SatsPrice")
|
||||
#if os(iOS)
|
||||
// macOS Lists support drag-to-reorder directly; iOS only shows reorder handles
|
||||
// once edit mode is active, which this toggles.
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
EditButton()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +111,7 @@ struct ContentView: View {
|
||||
|
||||
Section(IosLocalizationKt.localizedString(resource: MR.strings.shared.currencies_section_title)) {
|
||||
Button(
|
||||
state.selectedCurrencyCodes.isEmpty
|
||||
state.selectedCurrencyCodes.count <= 1
|
||||
? IosLocalizationKt.localizedString(resource: MR.strings.shared.add_currency)
|
||||
: IosLocalizationKt.localizedFormattedString(
|
||||
resource: MR.strings.shared.currencies_selected_count,
|
||||
@@ -112,14 +121,30 @@ struct ContentView: View {
|
||||
showCurrencyPicker = true
|
||||
}
|
||||
|
||||
ForEach(state.fiatRows, id: \.code) { row in
|
||||
ForEach(Array(state.fiatRows.enumerated()), id: \.element.code) { index, row in
|
||||
amountRow(
|
||||
label: row.code,
|
||||
value: row.amount,
|
||||
keyboardType: .decimalPad,
|
||||
sanitize: sanitizeDecimalInput,
|
||||
onChange: { viewModel.onFiatAmountChanged(code: row.code, value: $0) }
|
||||
onChange: { viewModel.onFiatAmountChanged(code: row.code, value: $0) },
|
||||
onMoveUp: index > 0 ? {
|
||||
var codes = state.fiatRows.map(\.code)
|
||||
codes.move(fromOffsets: [index], toOffset: index - 1)
|
||||
viewModel.onFiatCurrenciesReordered(codes)
|
||||
} : nil,
|
||||
onMoveDown: index < state.fiatRows.count - 1 ? {
|
||||
var codes = state.fiatRows.map(\.code)
|
||||
codes.move(fromOffsets: [index], toOffset: index + 2)
|
||||
viewModel.onFiatCurrenciesReordered(codes)
|
||||
} : nil
|
||||
)
|
||||
.deleteDisabled(row.code == state.defaultCurrencyCode)
|
||||
}
|
||||
.onMove { indices, newOffset in
|
||||
var codes = state.fiatRows.map(\.code)
|
||||
codes.move(fromOffsets: indices, toOffset: newOffset)
|
||||
viewModel.onFiatCurrenciesReordered(codes)
|
||||
}
|
||||
#if os(iOS)
|
||||
.onDelete { indexSet in
|
||||
@@ -135,8 +160,9 @@ struct ContentView: View {
|
||||
#endif
|
||||
.sheet(isPresented: $showCurrencyPicker) {
|
||||
CurrencyPickerSheet(
|
||||
currencies: state.availableCurrencies,
|
||||
selectedCodes: state.selectedCurrencyCodes,
|
||||
currentCurrency: state.currentCurrency,
|
||||
selectedOtherCurrencies: state.selectedOtherCurrencies,
|
||||
unselectedCurrencies: state.unselectedCurrencies,
|
||||
localeCurrencyCode: state.localeCurrencyCode,
|
||||
onToggle: { viewModel.onFiatCurrencyToggled($0) }
|
||||
)
|
||||
@@ -149,9 +175,31 @@ struct ContentView: View {
|
||||
value: String,
|
||||
keyboardType: NumericFieldKeyboard,
|
||||
sanitize: @escaping (String) -> String,
|
||||
onChange: @escaping (String) -> Void
|
||||
onChange: @escaping (String) -> Void,
|
||||
onMoveUp: (() -> Void)? = nil,
|
||||
onMoveDown: (() -> Void)? = nil
|
||||
) -> some View {
|
||||
HStack {
|
||||
#if os(macOS)
|
||||
// macOS's Form isn't List-backed, so .onMove's drag-to-reorder has no effect here;
|
||||
// these buttons are macOS's equivalent of iOS's Edit-mode drag handles.
|
||||
if onMoveUp != nil || onMoveDown != nil {
|
||||
VStack(spacing: 2) {
|
||||
Button(action: { onMoveUp?() }) {
|
||||
Image(systemName: "chevron.up")
|
||||
.frame(width: 16, height: 10)
|
||||
}
|
||||
.disabled(onMoveUp == nil)
|
||||
Button(action: { onMoveDown?() }) {
|
||||
Image(systemName: "chevron.down")
|
||||
.frame(width: 16, height: 10)
|
||||
}
|
||||
.disabled(onMoveDown == nil)
|
||||
}
|
||||
.font(.system(size: 10))
|
||||
.buttonStyle(.borderless)
|
||||
}
|
||||
#endif
|
||||
Text(label)
|
||||
Spacer()
|
||||
NumericField(
|
||||
|
||||
@@ -35,6 +35,10 @@ final class ConverterViewModel: ObservableObject {
|
||||
bridge.onFiatCurrencyToggled(code: code)
|
||||
}
|
||||
|
||||
func onFiatCurrenciesReordered(_ newOrder: [String]) {
|
||||
bridge.onFiatCurrenciesReordered(newOrder: newOrder)
|
||||
}
|
||||
|
||||
func onSourceSelected(_ name: String) {
|
||||
bridge.onSourceSelected(name: name)
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ import Shared
|
||||
import SwiftUI
|
||||
|
||||
struct CurrencyPickerSheet: View {
|
||||
let currencies: [CurrencyInfo]
|
||||
let selectedCodes: [String]
|
||||
let currentCurrency: CurrencyInfo
|
||||
let selectedOtherCurrencies: [CurrencyInfo]
|
||||
let unselectedCurrencies: [CurrencyInfo]
|
||||
let localeCurrencyCode: String?
|
||||
let onToggle: (String) -> Void
|
||||
|
||||
@@ -11,20 +12,24 @@ struct CurrencyPickerSheet: View {
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
List(currencies, id: \.code) { info in
|
||||
Button {
|
||||
onToggle(info.code)
|
||||
} label: {
|
||||
HStack {
|
||||
Text(currencyLabel(for: info))
|
||||
.foregroundColor(.primary)
|
||||
Spacer()
|
||||
if selectedCodes.contains(info.code) {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.accentColor)
|
||||
List {
|
||||
Section(IosLocalizationKt.localizedString(resource: MR.strings.shared.current_currency_section_title)) {
|
||||
currencyRow(for: currentCurrency, isSelected: true, onTap: nil)
|
||||
}
|
||||
|
||||
if !selectedOtherCurrencies.isEmpty {
|
||||
Section(IosLocalizationKt.localizedString(resource: MR.strings.shared.selected_currencies_section_title)) {
|
||||
ForEach(selectedOtherCurrencies, id: \.code) { info in
|
||||
currencyRow(for: info, isSelected: true, onTap: { onToggle(info.code) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Section(IosLocalizationKt.localizedString(resource: MR.strings.shared.currencies_section_title)) {
|
||||
ForEach(unselectedCurrencies, id: \.code) { info in
|
||||
currencyRow(for: info, isSelected: false, onTap: { onToggle(info.code) })
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle(IosLocalizationKt.localizedString(resource: MR.strings.shared.currencies_section_title))
|
||||
#if os(iOS)
|
||||
@@ -44,6 +49,24 @@ struct CurrencyPickerSheet: View {
|
||||
#endif
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func currencyRow(for info: CurrencyInfo, isSelected: Bool, onTap: (() -> Void)?) -> some View {
|
||||
let content = HStack {
|
||||
Text(currencyLabel(for: info))
|
||||
.foregroundColor(.primary)
|
||||
Spacer()
|
||||
if isSelected {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
}
|
||||
if let onTap {
|
||||
Button(action: onTap) { content }
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
|
||||
private func currencyLabel(for info: CurrencyInfo) -> String {
|
||||
if info.code == localeCurrencyCode {
|
||||
return IosLocalizationKt.localizedFormattedString(
|
||||
|
||||
Reference in New Issue
Block a user