import SwiftUI import ActivityProvider import MetricsProvider import OnyxDesign /// Was am Strom geschieht — Netzteil dran, ab, Limit erreicht, Akku fast leer. /// /// **Nicht bei jedem Messwert, sondern bei jedem Wechsel.** Der Ladestand /// ändert sich ständig; eine Notch, die das begleitet, wäre eine Leuchtreklame. /// Angemeldet wird nur, wenn sich der *Zustand* ändert. struct PowerActivity: NotchActivity { /// Was gemeldet wird. enum Kind: Equatable { case charging case plugged case unplugged case atLimit(Int) case low var text: String { switch self { case .charging: String(localized: "activity.power.charging") case .plugged: String(localized: "activity.power.plugged") case .unplugged: String(localized: "activity.power.unplugged") case .atLimit: String(localized: "activity.power.atLimit") case .low: String(localized: "activity.power.low") } } /// „Fast leer" ist das eine, das man nicht verpassen darf. var rank: Int { self == .low ? ActivityRank.alert : ActivityRank.notice } /// Eine Warnung darf länger stehen als eine Beiläufigkeit. var duration: TimeInterval { self == .low ? 4 : 2.2 } } let id = "power" let kind: Kind let charge: Double let isCharging: Bool let isPluggedIn: Bool var rank: Int { kind.rank } var duration: TimeInterval? { kind.duration } var size: CGSize { CGSize(width: 232, height: 34) } func makeContent() -> AnyView { AnyView( HStack(spacing: Onyx.Space.lg) { BatteryGlyphView(charge: charge, isCharging: isCharging, isPluggedIn: isPluggedIn, height: 13) Text(kind.text) .font(Onyx.Font.footnote) .foregroundStyle(Onyx.Color.textPrimary) .lineLimit(1) Spacer(minLength: Onyx.Space.sm) Text("\(Int((min(max(charge, 0), 1) * 100).rounded())) %") .font(Onyx.Font.metricSmall) .foregroundStyle(kind == .low ? Onyx.Color.critical : Onyx.Color.textSecondary) } .padding(.horizontal, Onyx.Space.xl) .frame(maxWidth: .infinity, maxHeight: .infinity) ) } } /// Was gerade spielt — beim Wechsel des Titels. /// /// Ohne Fortschritt und ohne Knöpfe: das steht im Panel. Hier geht es um die /// eine Frage, die man beim Wechsel hat — was ist das jetzt? struct MediaActivity: NotchActivity { let id = "media" let rank = ActivityRank.notice let duration: TimeInterval? = 3 var size: CGSize { CGSize(width: 264, height: 40) } let title: String let artist: String let artwork: Data? func makeContent() -> AnyView { AnyView( HStack(spacing: Onyx.Space.lg) { Group { if let artwork, let image = NSImage(data: artwork) { Image(nsImage: image).resizable() } else { // Kein Cover ist kein Fehler — Radiostreams haben keins. Onyx.Color.elevated .overlay { Image(systemName: "music.note") .font(Onyx.Font.micro) .foregroundStyle(Onyx.Color.textTertiary) } } } .frame(width: 26, height: 26) .clipShape(RoundedRectangle(cornerRadius: Onyx.Radius.chip, style: .continuous)) VStack(alignment: .leading, spacing: Onyx.Space.xxs) { Text(title) .font(Onyx.Font.micro) .foregroundStyle(Onyx.Color.textPrimary) .lineLimit(1) if !artist.isEmpty { Text(artist) .font(Onyx.Font.micro) .foregroundStyle(Onyx.Color.textTertiary) .lineLimit(1) } } Spacer(minLength: 0) } .padding(.horizontal, Onyx.Space.xl) .frame(maxWidth: .infinity, maxHeight: .infinity) ) } }