From 88d20c54194896780c698c41ce9df5188bf4d155 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 24 Dec 2025 13:51:05 +0100 Subject: [PATCH] perf: gate idle pulse animations --- apps/ios/Sources/Status/StatusPill.swift | 14 +++++++++---- apps/macos/Sources/Clawdis/Onboarding.swift | 22 ++++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/apps/ios/Sources/Status/StatusPill.swift b/apps/ios/Sources/Status/StatusPill.swift index cce2d778e..9d3c6f6d6 100644 --- a/apps/ios/Sources/Status/StatusPill.swift +++ b/apps/ios/Sources/Status/StatusPill.swift @@ -1,6 +1,8 @@ import SwiftUI struct StatusPill: View { + @Environment(\.scenePhase) private var scenePhase + enum BridgeState: Equatable { case connected case connecting @@ -72,14 +74,18 @@ struct StatusPill: View { .buttonStyle(.plain) .accessibilityLabel("Status") .accessibilityValue("\(self.bridge.title), Voice Wake \(self.voiceWakeEnabled ? "enabled" : "disabled")") - .onAppear { self.updatePulse(for: self.bridge) } + .onAppear { self.updatePulse(for: self.bridge, scenePhase: self.scenePhase) } + .onDisappear { self.pulse = false } .onChange(of: self.bridge) { _, newValue in - self.updatePulse(for: newValue) + self.updatePulse(for: newValue, scenePhase: self.scenePhase) + } + .onChange(of: self.scenePhase) { _, newValue in + self.updatePulse(for: self.bridge, scenePhase: newValue) } } - private func updatePulse(for bridge: BridgeState) { - guard bridge == .connecting else { + private func updatePulse(for bridge: BridgeState, scenePhase: ScenePhase) { + guard bridge == .connecting, scenePhase == .active else { withAnimation(.easeOut(duration: 0.2)) { self.pulse = false } return } diff --git a/apps/macos/Sources/Clawdis/Onboarding.swift b/apps/macos/Sources/Clawdis/Onboarding.swift index 5150f90f0..3087796e1 100644 --- a/apps/macos/Sources/Clawdis/Onboarding.swift +++ b/apps/macos/Sources/Clawdis/Onboarding.swift @@ -1357,6 +1357,8 @@ struct OnboardingView: View { } private struct GlowingClawdisIcon: View { + @Environment(\.scenePhase) private var scenePhase + let size: CGFloat let glowIntensity: Double let enableFloating: Bool @@ -1398,11 +1400,21 @@ private struct GlowingClawdisIcon: View { .frame( width: glowCanvasSize + (glowBlurRadius * 2), height: glowCanvasSize + (glowBlurRadius * 2)) - .onAppear { - guard self.enableFloating else { return } - withAnimation(Animation.easeInOut(duration: 3.6).repeatForever(autoreverses: true)) { - self.breathe.toggle() - } + .onAppear { self.updateBreatheAnimation() } + .onDisappear { self.breathe = false } + .onChange(of: self.scenePhase) { _, _ in + self.updateBreatheAnimation() + } + } + + private func updateBreatheAnimation() { + guard self.enableFloating, self.scenePhase == .active else { + self.breathe = false + return + } + guard !self.breathe else { return } + withAnimation(Animation.easeInOut(duration: 3.6).repeatForever(autoreverses: true)) { + self.breathe = true } } }