Beim ersten Start fuehrt kein Weg an einer sechsstelligen PIN vorbei. Danach sperrt die App beim Kaltstart und beim Wegschalten; kommt man binnen einer Minute zurueck, geht sie ohne Nachfrage wieder auf. Face ID zuerst, die PIN als Rueckfallweg und als einziger Weg ohne Biometrie. Nach fuenf falschen PINs meldet die App ab. Gesperrt wird schon bei inactive, nicht erst im Hintergrund - sonst stuenden die Kontostaende im App-Umschalter. Von der PIN liegt nur ein gesalzener SHA-256 im Schluesselbund. Die Gerätemarke selbst bleibt wie bisher abgelegt: Die Sperre verdeckt die Oberflaeche, sie verschluesselt nichts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
78 lines
2.7 KiB
Swift
78 lines
2.7 KiB
Swift
import SwiftUI
|
||
|
||
/// Welcher Bildschirm zu sehen ist, entscheidet allein `AppZustand.lage`.
|
||
/// Jede Ansicht darunter darf davon ausgehen, dass es einen angemeldeten
|
||
/// Client gibt.
|
||
struct RootAnsicht: View {
|
||
@Environment(AppZustand.self) private var zustand
|
||
|
||
var body: some View {
|
||
switch zustand.lage {
|
||
case .startet:
|
||
ProgressView()
|
||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||
|
||
case .brauchtServer:
|
||
ServerAnsicht()
|
||
|
||
case .brauchtAnmeldung:
|
||
AnmeldeAnsicht()
|
||
|
||
case .brauchtZweitenFaktor:
|
||
ZweiFaktorAnsicht()
|
||
|
||
case .brauchtPasswortwechsel:
|
||
PasswortWechselAnsicht()
|
||
|
||
case .brauchtZweitenFaktorEinrichtung:
|
||
ZweitenFaktorEinrichtenHinweis()
|
||
|
||
case .bereit:
|
||
// Reihenfolge mit Absicht: Ohne PIN kommt niemand an die Zahlen,
|
||
// und der Sperrbildschirm liegt vor allem anderen.
|
||
if !zustand.hatPIN {
|
||
PINEinrichtenAnsicht()
|
||
} else if zustand.gesperrt {
|
||
SperrAnsicht()
|
||
} else {
|
||
Hauptnavigation()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Die Reiter. Auf dem iPhone unten, auf dem iPad als Seitenleiste – das
|
||
/// erledigt `.sidebarAdaptable` von selbst.
|
||
///
|
||
/// Reihenfolge nach Häufigkeit, nicht nach Umfang: Das Dashboard beantwortet
|
||
/// die Frage, wegen der man die App öffnet. Konten und Einstellungen stehen
|
||
/// hinten, weil man sie selten braucht.
|
||
struct Hauptnavigation: View {
|
||
var body: some View {
|
||
TabView {
|
||
Tab(String(localized: "reiter.dashboard"), systemImage: "square.grid.2x2") {
|
||
NavigationStack { DashboardAnsicht() }
|
||
}
|
||
Tab(String(localized: "reiter.budget"), systemImage: "chart.pie") {
|
||
NavigationStack { BudgetAnsicht() }
|
||
}
|
||
Tab(String(localized: "reiter.buchungen"), systemImage: "list.bullet.rectangle") {
|
||
NavigationStack { BuchungsListe() }
|
||
}
|
||
Tab(String(localized: "reiter.arbeitsliste"), systemImage: "tray") {
|
||
NavigationStack { ArbeitslisteAnsicht() }
|
||
}
|
||
Tab(String(localized: "reiter.abos"), systemImage: "arrow.triangle.2.circlepath") {
|
||
NavigationStack { AboListe() }
|
||
}
|
||
Tab(String(localized: "reiter.konten"), systemImage: "wallet.bifold") {
|
||
NavigationStack { KontenListe() }
|
||
}
|
||
Tab(String(localized: "reiter.einstellungen"), systemImage: "gearshape") {
|
||
NavigationStack { EinstellungenAnsicht() }
|
||
}
|
||
}
|
||
.tabViewStyle(.sidebarAdaptable)
|
||
}
|
||
}
|