Eine Designschicht statt hundertfach gesetzter Zahlen
Token für Schrift, Symbolgröße, Abstand, Radius und Bewegung, dazu sieben Bauteile, die vorher in jeder Kachel neu gebaut wurden — Karte, Abschnittstitel, Hinweis, Pillenknopf, Regler, Ablegefläche, Haarlinie. Symbole bekommen eine **eigene** Staffel und nicht die der Schrift: ein 9-Punkt-Symbol neben 9-Punkt-Text wirkt kleiner, nicht gleich groß. Beide in eine Staffel zu zwingen hieße, an jeder Stelle gegen sie zu arbeiten. Das Flächenrezept — Tint, Bänderung, Kante — stand zweimal da, einmal für das Panel und einmal für Fenster. Es ist jetzt `OnyxStone`, generisch über die Form, damit auch die animierende Notch-Silhouette es benutzen kann. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
49a3ff0548
commit
ecb39fbe5f
@@ -1,7 +1,8 @@
|
||||
import SwiftUI
|
||||
import AppKit
|
||||
|
||||
/// Die einstellbaren Farben.
|
||||
/// Was am Aussehen von Onyx einstellbar ist: die Farben und das
|
||||
/// Bewegungsprofil.
|
||||
///
|
||||
/// **Nicht alle Farben sind einstellbar, und das ist Absicht.** Gelb heißt
|
||||
/// Warnung, Rot heißt kritisch, Grün heißt in Ordnung — bei Temperatur, Akku,
|
||||
@@ -20,8 +21,17 @@ public final class OnyxTheme {
|
||||
/// Kühl und entsättigt — Farbe ist in Onyx ein Signal, keine Dekoration.
|
||||
public static let defaultAccent = Color(red: 0.498, green: 0.659, blue: 1.0)
|
||||
/// Herunterladen grün, Hochladen rosa: die Zuordnung ist reine Gewohnheit,
|
||||
/// aber eine verbreitete. Wer sie anders kennt, dreht sie um.
|
||||
public static let defaultDownload = Color(red: 0.435, green: 0.812, blue: 0.592)
|
||||
/// aber eine verbreitete.
|
||||
///
|
||||
/// **Wärmer als das Signalgrün, und das ist der Punkt.** Vorher war dieser
|
||||
/// Wert Zeichen für Zeichen `Onyx.Color.positive` — derselbe grüne Balken
|
||||
/// hieß im Netzwerk „lädt herunter" und in den Messwerten „alles in
|
||||
/// Ordnung". Zwei Bedeutungen in einer Farbe sind eine zu viel.
|
||||
///
|
||||
/// Wärmer und nicht kühler, weil das Gegenstück rosa bis cyan sein darf:
|
||||
/// ein Grün, das ins Türkise zieht, wäre vom Hochladen kaum noch zu
|
||||
/// unterscheiden. Nach Gelb hin ist von beidem Abstand.
|
||||
public static let defaultDownload = Color(red: 0.561, green: 0.835, blue: 0.408)
|
||||
public static let defaultUpload = Color(red: 0.937, green: 0.427, blue: 0.612)
|
||||
|
||||
public var accent: Color {
|
||||
@@ -34,12 +44,31 @@ public final class OnyxTheme {
|
||||
didSet { store(upload, as: Keys.upload) }
|
||||
}
|
||||
|
||||
/// Wie sich das Panel bewegt.
|
||||
///
|
||||
/// Getrennt von den Farben gespeichert und **nicht** von `reset()` erfasst:
|
||||
/// der Knopf dort heißt „Farben zurücksetzen", und ein Knopf, der nebenbei
|
||||
/// die Animationen umstellt, ist eine Falle.
|
||||
public var motion: MotionProfile = .snappy {
|
||||
didSet { defaults.set(motion.rawValue, forKey: Keys.motion) }
|
||||
}
|
||||
|
||||
/// Woraus die Panelfläche gemacht ist.
|
||||
///
|
||||
/// Wie `motion` von den Farben getrennt und **nicht** von `reset()`
|
||||
/// erfasst: „Farben zurücksetzen" soll Farben zurücksetzen.
|
||||
public var material: NotchMaterial = .stone {
|
||||
didSet { defaults.set(material.rawValue, forKey: Keys.material) }
|
||||
}
|
||||
|
||||
private let defaults: UserDefaults
|
||||
|
||||
private enum Keys {
|
||||
static let accent = "onyx.theme.accent"
|
||||
static let download = "onyx.theme.download"
|
||||
static let upload = "onyx.theme.upload"
|
||||
static let motion = "onyx.theme.motion"
|
||||
static let material = "onyx.theme.material"
|
||||
}
|
||||
|
||||
public init(defaults: UserDefaults = .standard) {
|
||||
@@ -47,10 +76,17 @@ public final class OnyxTheme {
|
||||
accent = Color(onyxHex: defaults.string(forKey: Keys.accent)) ?? Self.defaultAccent
|
||||
download = Color(onyxHex: defaults.string(forKey: Keys.download)) ?? Self.defaultDownload
|
||||
upload = Color(onyxHex: defaults.string(forKey: Keys.upload)) ?? Self.defaultUpload
|
||||
// Unbekannte Profilnamen fallen auf die Voreinstellung zurück, statt die
|
||||
// Bewegung ganz ausfallen zu lassen — eine App ohne Animation sieht aus,
|
||||
// als hinge sie.
|
||||
motion = MotionProfile(rawValue: defaults.string(forKey: Keys.motion) ?? "") ?? .snappy
|
||||
material = NotchMaterial(rawValue: defaults.string(forKey: Keys.material) ?? "") ?? .stone
|
||||
}
|
||||
|
||||
/// Ob alles auf den Werkseinstellungen steht — für den Zurücksetzen-Knopf,
|
||||
/// der sonst auch dann anböte, etwas zu tun, wenn es nichts zu tun gibt.
|
||||
/// Ob **die Farben** auf den Werkseinstellungen stehen — für den
|
||||
/// Zurücksetzen-Knopf, der sonst auch dann anböte, etwas zu tun, wenn es
|
||||
/// nichts zu tun gibt. Das Bewegungsprofil zählt bewusst nicht mit; siehe
|
||||
/// `motion`.
|
||||
public var isDefault: Bool {
|
||||
accent.onyxHex == Self.defaultAccent.onyxHex
|
||||
&& download.onyxHex == Self.defaultDownload.onyxHex
|
||||
|
||||
Reference in New Issue
Block a user