Files
koins/apps/ios/Koins/Views/SettingsView.swift
T

121 lines
4.4 KiB
Swift

import SwiftUI
struct SettingsView: View {
@EnvironmentObject private var model: AppModel
@EnvironmentObject private var drawers: DrawerCoordinator
@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: { drawers.settings = false })
Card {
VStack(alignment: .leading, spacing: 10) {
Text("Wallet")
.font(.system(size: 13, weight: .semibold))
.foregroundStyle(Theme.muted)
ChainPicker(selection: Binding(get: { model.chain },
set: { newValue in Task { await model.select(newValue) } }))
}
}
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()
drawers.settings = false
}
}
Button("Cancel", role: .cancel) {}
} message: {
Text("The keys stored on this device are removed. Make sure your recovery phrase is backed up.")
}
}
}