Kameraaufnahme, Anlernen über drei Posen, Fenster je Bildschirm auf Bildschirmschoner-Ebene, Passwortrückfall. **Das Anmeldepasswort wird nicht gespeichert.** Ein Spike hat den Weg freigeräumt: `ODRecord.verifyPassword` ist öffentliche API, die Eingabe geht direkt hinein, das Ergebnis ist ein `Bool`, danach ist die Zeichenkette wieder weg. Damit fällt der Grund weg, aus dem vergleichbare Programme sich das Passwort geben lassen und in die Keychain legen. Angelernt wird über drei Posen mit je fünf Aufnahmen. Der Merkmalsvektor ist ein allgemeiner Bildmerkmalsvektor und kein Gesichtsmerkmal — er reagiert auf Kopfhaltung und Beleuchtung mit. Eine einzige Aufnahme beschreibt genau eine Haltung bei genau einem Licht. Die Vektoren liegen in der Keychain, nicht in einer Datei: aus ihnen lässt sich kein Bild zurückgewinnen, aber wer sie hat, kann prüfen, ob eine bestimmte Person vor der Kamera stand. Die Einschränkung steht auf dem Sperrbildschirm selbst und nicht im Kleingedruckten: Bequemlichkeit, keine Sicherheitsgrenze; der Vergleich läuft über die Webcam und lässt sich mit einem Foto täuschen. Wer sich darauf verlässt, tut es dort. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
74 lines
2.8 KiB
Swift
74 lines
2.8 KiB
Swift
import SwiftUI
|
|
|
|
/// Die Bereiche des Einstellungsfensters.
|
|
///
|
|
/// **Seitenleiste statt Reiterband.** Sieben deutsche Reiterbeschriftungen
|
|
/// brauchten rund 880 Punkte nebeneinander — das Fenster hatte deshalb eine
|
|
/// Mindestbreite, die nichts mit seinem Inhalt zu tun hatte, sondern nur damit,
|
|
/// dass sonst der erste und der letzte Reiter über die Kante hinausragten. Eine
|
|
/// Seitenleiste wächst nach unten, und dort ist Platz.
|
|
///
|
|
/// **Keine leeren Einträge auf Vorrat.** Sperrbildschirm, Zwischenablage und
|
|
/// Notizen kommen mit ihren Phasen. Ein Eintrag, der sich öffnen lässt und
|
|
/// nichts enthält, ist ein Versprechen, das die App nicht hält.
|
|
enum SettingsSection: String, CaseIterable, Identifiable, Hashable {
|
|
case general
|
|
case widgets
|
|
case widgetOptions
|
|
case notch
|
|
case appearance
|
|
case menubar
|
|
case fans
|
|
case lockScreen
|
|
case permissions
|
|
|
|
var id: Self { self }
|
|
|
|
var title: String {
|
|
switch self {
|
|
case .general: String(localized: "settings.general")
|
|
case .widgets: String(localized: "settings.tab.widgets")
|
|
case .widgetOptions: String(localized: "settings.tab.options")
|
|
case .notch: String(localized: "settings.section.notch")
|
|
case .appearance: String(localized: "settings.section.appearance")
|
|
case .menubar: String(localized: "settings.tab.menubar")
|
|
case .fans: String(localized: "settings.tab.fans")
|
|
case .lockScreen: String(localized: "settings.section.lock")
|
|
case .permissions: String(localized: "settings.tab.permissions")
|
|
}
|
|
}
|
|
|
|
var symbol: String {
|
|
switch self {
|
|
case .general: "gearshape.fill"
|
|
case .widgets: "square.grid.2x2.fill"
|
|
case .widgetOptions: "wrench.adjustable.fill"
|
|
case .notch: "macbook"
|
|
case .appearance: "paintpalette.fill"
|
|
case .menubar: "menubar.rectangle"
|
|
case .fans: "fan.fill"
|
|
case .lockScreen: "faceid"
|
|
case .permissions: "lock.fill"
|
|
}
|
|
}
|
|
|
|
/// Die Farbe des Plättchens.
|
|
///
|
|
/// Fest und **nicht** die Akzentfarbe: acht Einträge in derselben Farbe
|
|
/// wären wieder acht gleich aussehende Zeilen. Die Farbe unterscheidet
|
|
/// hier, sie schmückt nicht.
|
|
var tint: Color {
|
|
switch self {
|
|
case .general: Color(red: 0.44, green: 0.47, blue: 0.51)
|
|
case .widgets: Color(red: 0.31, green: 0.53, blue: 0.93)
|
|
case .widgetOptions: Color(red: 0.29, green: 0.68, blue: 0.66)
|
|
case .notch: Color(red: 0.55, green: 0.44, blue: 0.85)
|
|
case .appearance: Color(red: 0.90, green: 0.60, blue: 0.28)
|
|
case .menubar: Color(red: 0.85, green: 0.45, blue: 0.66)
|
|
case .fans: Color(red: 0.33, green: 0.68, blue: 0.85)
|
|
case .lockScreen: Color(red: 0.45, green: 0.44, blue: 0.80)
|
|
case .permissions: Color(red: 0.82, green: 0.37, blue: 0.35)
|
|
}
|
|
}
|
|
}
|