109 lines
3.9 KiB
Swift
109 lines
3.9 KiB
Swift
import SwiftUI
|
|
|
|
struct SettingsView: View {
|
|
@EnvironmentObject private var model: AppModel
|
|
@Environment(\.dismiss) private var dismiss
|
|
@State private var showDeleteConfirm = false
|
|
|
|
private let currencies = ["USD", "MYR", "JPY"]
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(alignment: .leading, spacing: 18) {
|
|
ScreenHeader(title: "Settings", subtitle: "Security and device options", onBack: { dismiss() })
|
|
|
|
Card {
|
|
VStack(alignment: .leading, spacing: 10) {
|
|
Text("Currency")
|
|
.font(.system(size: 13, weight: .semibold))
|
|
.foregroundStyle(Theme.muted)
|
|
|
|
LazyVGrid(columns: [GridItem(.adaptive(minimum: 64), spacing: 8)], spacing: 8) {
|
|
ForEach(currencies, id: \.self) { currency in
|
|
let selected = model.fiatCurrency == currency
|
|
Button {
|
|
model.fiatCurrency = currency
|
|
} label: {
|
|
Text(currency)
|
|
.font(.system(size: 13, weight: .medium))
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.vertical, 8)
|
|
.background(selected ? Theme.accent : Theme.surfaceAlt)
|
|
.foregroundStyle(selected ? Color.black : Theme.text)
|
|
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
|
|
}
|
|
}
|
|
}
|
|
|
|
Text("Prices come from CoinGecko (with a Kraken fallback for USD and EUR) and refresh about once a minute.")
|
|
.font(.system(size: 11))
|
|
.foregroundStyle(Theme.muted)
|
|
.padding(.top, 4)
|
|
}
|
|
}
|
|
|
|
Card {
|
|
Toggle(isOn: Binding(get: { model.faceIDEnabled },
|
|
set: { model.faceIDEnabled = $0 })) {
|
|
VStack(alignment: .leading, spacing: 3) {
|
|
Text("Unlock with \(Biometrics.label)")
|
|
.font(.system(size: 15, weight: .semibold))
|
|
.foregroundStyle(Theme.text)
|
|
Text("Require \(Biometrics.label) to open the app, reveal the recovery phrase, and send payments.")
|
|
.font(.system(size: 11))
|
|
.foregroundStyle(Theme.muted)
|
|
}
|
|
}
|
|
.tint(Theme.accent)
|
|
.disabled(!Biometrics.isAvailable)
|
|
|
|
if !Biometrics.isAvailable {
|
|
Text("This device has no biometric sensor configured.")
|
|
.font(.system(size: 11))
|
|
.foregroundStyle(Theme.muted)
|
|
}
|
|
}
|
|
|
|
Card {
|
|
VStack(alignment: .leading, spacing: 10) {
|
|
Text("Danger zone")
|
|
.font(.system(size: 13, weight: .semibold))
|
|
.foregroundStyle(Theme.muted)
|
|
Button {
|
|
showDeleteConfirm = true
|
|
} label: {
|
|
Text("Delete this wallet")
|
|
.font(.system(size: 15, weight: .semibold))
|
|
.foregroundStyle(Theme.danger)
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.vertical, 14)
|
|
.background(Theme.danger.opacity(0.12))
|
|
.clipShape(RoundedRectangle(cornerRadius: 14, style: .continuous))
|
|
}
|
|
Text("Removes the wallet from this device. Your recovery phrase is the only way to get it back.")
|
|
.font(.system(size: 11))
|
|
.foregroundStyle(Theme.muted)
|
|
}
|
|
}
|
|
|
|
Spacer(minLength: 0)
|
|
}
|
|
.padding(.horizontal, 20)
|
|
.padding(.top, 12)
|
|
}
|
|
.preferredColorScheme(.dark)
|
|
.confirmationDialog("Delete this wallet?",
|
|
isPresented: $showDeleteConfirm,
|
|
titleVisibility: .visible) {
|
|
Button("Delete wallet", role: .destructive) {
|
|
Task {
|
|
await model.deleteWallet()
|
|
dismiss()
|
|
}
|
|
}
|
|
Button("Cancel", role: .cancel) {}
|
|
} message: {
|
|
Text("The keys stored on this device are removed. Make sure your recovery phrase is backed up.")
|
|
}
|
|
}
|
|
} |