Add support for macOS and backport to older OS versions
This commit is contained in:
@@ -6,7 +6,7 @@ struct ContentView: View {
|
||||
@State private var showCurrencyPicker = false
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
NavigationStack {
|
||||
Group {
|
||||
if let state = viewModel.state {
|
||||
form(for: state)
|
||||
@@ -121,13 +121,18 @@ struct ContentView: View {
|
||||
onChange: { viewModel.onFiatAmountChanged(code: row.code, value: $0) }
|
||||
)
|
||||
}
|
||||
#if os(iOS)
|
||||
.onDelete { indexSet in
|
||||
for index in indexSet {
|
||||
viewModel.onFiatCurrencyToggled(state.fiatRows[index].code)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if os(macOS)
|
||||
.formStyle(.grouped)
|
||||
#endif
|
||||
.sheet(isPresented: $showCurrencyPicker) {
|
||||
CurrencyPickerSheet(
|
||||
currencies: state.availableCurrencies,
|
||||
@@ -142,7 +147,7 @@ struct ContentView: View {
|
||||
private func amountRow(
|
||||
label: String,
|
||||
value: String,
|
||||
keyboardType: UIKeyboardType,
|
||||
keyboardType: NumericFieldKeyboard,
|
||||
sanitize: @escaping (String) -> String,
|
||||
onChange: @escaping (String) -> Void
|
||||
) -> some View {
|
||||
@@ -150,7 +155,7 @@ struct ContentView: View {
|
||||
Text(label)
|
||||
Spacer()
|
||||
NumericField(
|
||||
placeholder: label,
|
||||
placeholder: "",
|
||||
value: value,
|
||||
keyboardType: keyboardType,
|
||||
sanitize: sanitize,
|
||||
@@ -170,7 +175,7 @@ struct ContentView: View {
|
||||
private struct NumericField: View {
|
||||
let placeholder: String
|
||||
let value: String
|
||||
let keyboardType: UIKeyboardType
|
||||
let keyboardType: NumericFieldKeyboard
|
||||
let sanitize: (String) -> String
|
||||
let onChange: (String) -> Void
|
||||
var alignment: TextAlignment = .leading
|
||||
@@ -179,10 +184,15 @@ private struct NumericField: View {
|
||||
|
||||
var body: some View {
|
||||
TextField(placeholder, text: $text)
|
||||
.keyboardType(keyboardType)
|
||||
#if os(iOS)
|
||||
.keyboardType(keyboardType.uiKeyboardType)
|
||||
#endif
|
||||
.multilineTextAlignment(alignment)
|
||||
#if os(macOS)
|
||||
.frame(maxWidth: 140)
|
||||
#endif
|
||||
.onAppear { text = value }
|
||||
.onChange(of: text) { _, newValue in
|
||||
.onChange(of: text) { newValue in
|
||||
let sanitized = sanitize(newValue)
|
||||
if sanitized != newValue {
|
||||
text = sanitized
|
||||
@@ -191,7 +201,7 @@ private struct NumericField: View {
|
||||
onChange(sanitized)
|
||||
}
|
||||
}
|
||||
.onChange(of: value) { _, newValue in
|
||||
.onChange(of: value) { newValue in
|
||||
if newValue != text {
|
||||
text = newValue
|
||||
}
|
||||
@@ -216,3 +226,21 @@ private func sanitizeDecimalInput(_ raw: String) -> String {
|
||||
private func sanitizeIntegerInput(_ raw: String) -> String {
|
||||
raw.filter { $0.isNumber }
|
||||
}
|
||||
|
||||
/// `UIKeyboardType` doesn't exist on macOS (no on-screen keyboard), so this stands in for it
|
||||
/// across both platforms; only iOS actually applies it, via `uiKeyboardType` below.
|
||||
private enum NumericFieldKeyboard {
|
||||
case decimalPad
|
||||
case numberPad
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
private extension NumericFieldKeyboard {
|
||||
var uiKeyboardType: UIKeyboardType {
|
||||
switch self {
|
||||
case .decimalPad: return .decimalPad
|
||||
case .numberPad: return .numberPad
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -10,7 +10,7 @@ struct CurrencyPickerSheet: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
NavigationStack {
|
||||
List(currencies, id: \.code) { info in
|
||||
Button {
|
||||
onToggle(info.code)
|
||||
@@ -27,13 +27,21 @@ struct CurrencyPickerSheet: View {
|
||||
}
|
||||
}
|
||||
.navigationTitle(IosLocalizationKt.localizedString(resource: MR.strings.shared.currencies_section_title))
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
#endif
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button(IosLocalizationKt.localizedString(resource: MR.strings.shared.done)) { dismiss() }
|
||||
}
|
||||
}
|
||||
}
|
||||
#if os(macOS)
|
||||
// macOS sizes a .sheet() to its content's ideal size rather than the parent window's
|
||||
// size (unlike iOS, which presents modally full-size); without an explicit frame here,
|
||||
// the List has no size to lay out rows in and renders empty.
|
||||
.frame(minWidth: 420, minHeight: 480)
|
||||
#endif
|
||||
}
|
||||
|
||||
private func currencyLabel(for info: CurrencyInfo) -> String {
|
||||
|
||||
@@ -5,6 +5,9 @@ struct iOSApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
#if os(macOS)
|
||||
.frame(minWidth: 420, minHeight: 500)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
Reference in New Issue
Block a user