Kacheln und Fenster sprechen dieselbe Sprache
Alle Kacheln, Popovers und Fenster auf die Designschicht umgestellt: rund hundert gesetzte Schriftgrößen und 159 gesetzte Abstände und Radien sind jetzt Token. Übrig bleibt `spacing: 0` — das ist eine Aussage, keine geratene Zahl. Die Einstellungen bekommen eine Seitenleiste statt sieben Reitern, deren deutsche Beschriftungen zusammen 880 Punkte brauchten. Panel-Token stehen nicht mehr in Fenstern: dort gilt Systemsemantik, damit der Hellmodus nicht schwarz auf schwarz endet. Neu ist ein Schaufenster, das alle Bauteile nebeneinander zeigt — ohne das lässt sich eine Änderung an einem Token nur prüfen, indem man die App bedient, bis jede Kachel einmal zu sehen war. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9b600de9a9
commit
edb327cabe
@@ -8,7 +8,7 @@ struct NetworkPopoverContent: View {
|
||||
let model: NetworkModel
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
VStack(alignment: .leading, spacing: Onyx.Space.lg) {
|
||||
HStack(alignment: .top) {
|
||||
rate(model.snapshot.downloadRate, "network.download", Onyx.Color.download)
|
||||
Spacer()
|
||||
@@ -43,17 +43,17 @@ struct NetworkPopoverContent: View {
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
section("network.addresses")
|
||||
OnyxPopoverTitle(String(localized: "network.addresses", bundle: .module))
|
||||
field("network.field.interface", model.snapshot.interfaceName)
|
||||
field("network.field.ipv4", model.snapshot.ipv4)
|
||||
field("network.field.ipv6", model.snapshot.ipv6)
|
||||
field("network.field.router", model.snapshot.router)
|
||||
|
||||
section("network.transferred")
|
||||
OnyxPopoverTitle(String(localized: "network.transferred", bundle: .module))
|
||||
field("network.total.received", bytes(model.snapshot.totalReceived))
|
||||
field("network.total.sent", bytes(model.snapshot.totalSent))
|
||||
|
||||
section("network.public")
|
||||
OnyxPopoverTitle(String(localized: "network.public", bundle: .module))
|
||||
if model.showsPublicAddress {
|
||||
HStack {
|
||||
if model.publicAddress.isLoading {
|
||||
@@ -86,7 +86,7 @@ struct NetworkPopoverContent: View {
|
||||
}
|
||||
|
||||
if !model.processes.isEmpty {
|
||||
section("network.processes")
|
||||
OnyxPopoverTitle(String(localized: "network.processes", bundle: .module))
|
||||
ForEach(model.processes) { process in
|
||||
HStack {
|
||||
Text(process.name).font(.callout).lineLimit(1)
|
||||
@@ -101,7 +101,7 @@ struct NetworkPopoverContent: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(14)
|
||||
.padding(Onyx.Space.xl)
|
||||
.frame(width: 300)
|
||||
.onAppear { model.addDetailConsumer() }
|
||||
.onDisappear { model.removeDetailConsumer() }
|
||||
@@ -117,10 +117,10 @@ struct NetworkPopoverContent: View {
|
||||
}
|
||||
|
||||
private func rate(_ value: Double, _ key: LocalizedStringKey, _ tint: Color) -> some View {
|
||||
VStack(alignment: .leading, spacing: 1) {
|
||||
VStack(alignment: .leading, spacing: Onyx.Space.xxs) {
|
||||
Text(Throughput.formatted(value))
|
||||
.font(.system(size: 18, weight: .medium).monospacedDigit())
|
||||
HStack(spacing: 4) {
|
||||
.font(Onyx.Font.display.monospacedDigit())
|
||||
HStack(spacing: Onyx.Space.xs) {
|
||||
Circle().fill(tint).frame(width: 6, height: 6)
|
||||
Text(key, bundle: .module).font(.caption).foregroundStyle(.secondary)
|
||||
}
|
||||
@@ -128,19 +128,12 @@ struct NetworkPopoverContent: View {
|
||||
}
|
||||
|
||||
private func peak(_ value: Double, _ key: LocalizedStringKey) -> some View {
|
||||
HStack(spacing: 4) {
|
||||
HStack(spacing: Onyx.Space.xs) {
|
||||
Text(key, bundle: .module).font(.caption2).foregroundStyle(.secondary)
|
||||
Text(Throughput.formatted(value)).font(.caption2.monospacedDigit())
|
||||
}
|
||||
}
|
||||
|
||||
private func section(_ key: LocalizedStringKey) -> some View {
|
||||
Text(key, bundle: .module)
|
||||
.font(.caption.weight(.semibold))
|
||||
.foregroundStyle(Onyx.Color.accent)
|
||||
.textCase(.uppercase)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func field(_ key: LocalizedStringKey, _ value: String?) -> some View {
|
||||
if let value {
|
||||
@@ -175,16 +168,16 @@ private struct TrafficChart: View {
|
||||
// Fünftel je Balken, und mit jedem weiteren wurden sie schmaler.
|
||||
// Frisch gestartet sah das Diagramm dadurch aus wie ein Ausschlag.
|
||||
let width = GraphLayout.barWidth(capacity: NetworkModel.historyLength,
|
||||
totalWidth: geometry.size.width, spacing: 1)
|
||||
totalWidth: geometry.size.width, spacing: Onyx.Space.xxs)
|
||||
let half = geometry.size.height / 2
|
||||
|
||||
HStack(alignment: .center, spacing: 1) {
|
||||
HStack(alignment: .center, spacing: Onyx.Space.xxs) {
|
||||
// Fehlende Messwerte bleiben als freie Fläche links stehen; der
|
||||
// Verlauf wächst nach links weg, wie bei jedem Zeitdiagramm.
|
||||
Spacer(minLength: 0)
|
||||
|
||||
ForEach(Array(points.enumerated()), id: \.offset) { _, snapshot in
|
||||
VStack(spacing: 1) {
|
||||
VStack(spacing: Onyx.Space.xxs) {
|
||||
Rectangle()
|
||||
.fill(Onyx.Color.upload)
|
||||
.frame(height: max(half * CGFloat(snapshot.uploadRate / peak), 0.5))
|
||||
|
||||
Reference in New Issue
Block a user