feat(mac): show relay attention badge without dimming paused state

main
Peter Steinberger 2025-12-06 23:54:56 +01:00
parent c9f5edbc1d
commit ff36375581
1 changed files with 64 additions and 36 deletions

View File

@ -592,9 +592,9 @@ enum ShellRunner {
struct ClawdisApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) private var delegate
@StateObject private var state: AppState
@StateObject private var relayManager = RelayProcessManager.shared
@State private var statusItem: NSStatusItem?
@State private var isMenuPresented = false
private let relayManager = RelayProcessManager.shared
init() {
_state = StateObject(wrappedValue: AppStateStore.shared)
@ -605,7 +605,8 @@ struct ClawdisApp: App {
CritterStatusLabel(
isPaused: self.state.isPaused,
isWorking: self.state.isWorking,
earBoostActive: self.state.earBoostActive)
earBoostActive: self.state.earBoostActive,
relayStatus: self.relayManager.status)
}
.menuBarExtraStyle(.menu)
.menuBarExtraAccess(isPresented: self.$isMenuPresented) { item in
@ -708,6 +709,7 @@ private struct CritterStatusLabel: View {
var isPaused: Bool
var isWorking: Bool
var earBoostActive: Bool
var relayStatus: RelayProcessManager.Status
@State private var blinkAmount: CGFloat = 0
@State private var nextBlink = Date().addingTimeInterval(Double.random(in: 3.5...8.5))
@ -721,6 +723,7 @@ private struct CritterStatusLabel: View {
private let ticker = Timer.publish(every: 0.35, on: .main, in: .common).autoconnect()
var body: some View {
ZStack(alignment: .bottomTrailing) {
Group {
if self.isPaused {
Image(nsImage: CritterIconRenderer.makeIcon(blink: 0))
@ -762,6 +765,14 @@ private struct CritterStatusLabel: View {
.onChange(of: self.isPaused) { _, _ in self.resetMotion() }
}
}
if self.relayNeedsAttention {
Circle()
.fill(self.relayBadgeColor)
.frame(width: 8, height: 8)
.offset(x: 4, y: 4)
}
}
}
private func resetMotion() {
@ -827,6 +838,23 @@ private struct CritterStatusLabel: View {
withAnimation(.interpolatingSpring(stiffness: 260, damping: 19)) { self.earWiggle = 0 }
}
}
private var relayNeedsAttention: Bool {
switch self.relayStatus {
case .failed, .stopped:
return !self.isPaused
case .starting, .restarting, .running:
return false
}
}
private var relayBadgeColor: Color {
switch self.relayStatus {
case .failed: return .red
case .stopped: return .orange
default: return .clear
}
}
}
enum CritterIconRenderer {