Das Grün, das überall auftauchte, war die System-Akzentfarbe: `.tint` und `.accentColor` werden ohne eigene Angabe dorthin durchgereicht, und das betraf alle Popovers und das ganze Einstellungsfenster. Die Notch-Widgets dagegen benutzten Onyx' eigenes Blau. Zwei Farben, ungewollt. Jetzt eine, und die ist einstellbar. Ein neuer Reiter „Farben": Akzentfarbe mit sechs Vorschlägen und einem Knopf, der die Systemfarbe übernimmt, dazu das Paar für Herunter- und Hochladen samt Tauschknopf. Die Signalfarben bleiben fest und stehen nur zur Ansicht dort. Gelb heißt Warnung, Rot heißt kritisch, Grün heißt in Ordnung — bei Temperatur, Akku, Lüfter und Fehlern. Wer sie umstellen kann, kann ihre Bedeutung zerstören; ein rotes „alles gut" liest niemand richtig. Sichtbar sind sie trotzdem, sonst sucht man die Warnfarbe im Reiter und findet sie nirgends. Umgesetzt über die Tokens statt über vierzig Fundstellen: `Onyx.Color.accent` ist keine Konstante mehr, sondern liest bei jedem Zugriff aus `OnyxTheme`. Damit merkt SwiftUI die Abhängigkeit und zeichnet neu, sobald die Farbe sich ändert. Dazu ein `.tint` an den vier Wurzeln — Panel, Popovers, Einstellungen, Einrichtung —, damit auch Haken, Regler und Auswahlfelder mitziehen. Nebenbei die Beschriftung: „Je Programm" heißt jetzt „Programme". Großgesetzt las sich das als englisches „J-E". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
77 lines
2.5 KiB
Swift
77 lines
2.5 KiB
Swift
import Testing
|
|
import SwiftUI
|
|
@testable import OnyxDesign
|
|
|
|
@Suite("Farbwahl")
|
|
@MainActor
|
|
struct OnyxThemeTests {
|
|
|
|
private func freshDefaults(_ name: String) -> UserDefaults {
|
|
let suite = "onyx.theme.test.\(name)"
|
|
let defaults = UserDefaults(suiteName: suite)!
|
|
defaults.removePersistentDomain(forName: suite)
|
|
return defaults
|
|
}
|
|
|
|
@Test("Ohne Einstellung stehen die Werkswerte")
|
|
func defaultsAreTheFactoryColours() {
|
|
let theme = OnyxTheme(defaults: freshDefaults(#function))
|
|
#expect(theme.accent.onyxHex == OnyxTheme.defaultAccent.onyxHex)
|
|
#expect(theme.isDefault)
|
|
}
|
|
|
|
@Test("Eine gewählte Farbe übersteht den Neustart")
|
|
func choiceSurvivesRestart() {
|
|
let defaults = freshDefaults(#function)
|
|
let theme = OnyxTheme(defaults: defaults)
|
|
theme.accent = Color(onyxHex: "#FF8800")!
|
|
|
|
let restarted = OnyxTheme(defaults: defaults)
|
|
#expect(restarted.accent.onyxHex == "#FF8800")
|
|
#expect(!restarted.isDefault)
|
|
}
|
|
|
|
@Test("Herunter und Hoch sind getrennt einstellbar")
|
|
func directionsAreIndependent() {
|
|
let theme = OnyxTheme(defaults: freshDefaults(#function))
|
|
theme.download = Color(onyxHex: "#112233")!
|
|
#expect(theme.download.onyxHex == "#112233")
|
|
#expect(theme.upload.onyxHex == OnyxTheme.defaultUpload.onyxHex)
|
|
}
|
|
|
|
@Test("Zurücksetzen stellt alles wieder her")
|
|
func resetRestoresEverything() {
|
|
let theme = OnyxTheme(defaults: freshDefaults(#function))
|
|
theme.accent = Color(onyxHex: "#000000")!
|
|
theme.download = Color(onyxHex: "#000000")!
|
|
theme.upload = Color(onyxHex: "#000000")!
|
|
theme.reset()
|
|
#expect(theme.isDefault)
|
|
}
|
|
}
|
|
|
|
@Suite("Farben als Text")
|
|
struct ColourHexTests {
|
|
|
|
@Test("Hin und zurück ergibt denselben Wert")
|
|
func roundTrip() {
|
|
for hex in ["#000000", "#FFFFFF", "#7FA8FF", "#6FCF97", "#EF6D9C"] {
|
|
#expect(Color(onyxHex: hex)?.onyxHex == hex)
|
|
}
|
|
}
|
|
|
|
@Test("Ohne Doppelkreuz geht es auch")
|
|
func hashIsOptional() {
|
|
#expect(Color(onyxHex: "7FA8FF")?.onyxHex == "#7FA8FF")
|
|
}
|
|
|
|
@Test("Unsinn ergibt keine Farbe")
|
|
func garbageIsRejected() {
|
|
// Sonst stünde nach einer verkorksten Einstellung Schwarz auf Schwarz.
|
|
#expect(Color(onyxHex: nil) == nil)
|
|
#expect(Color(onyxHex: "") == nil)
|
|
#expect(Color(onyxHex: "#12345") == nil)
|
|
#expect(Color(onyxHex: "#GGGGGG") == nil)
|
|
}
|
|
}
|