Janky animation

This commit is contained in:
Hariharan Mudaliar 2025-10-03 11:52:18 +05:30
commit 6eba9eff0b
5 changed files with 66 additions and 60 deletions

View file

@ -76,7 +76,6 @@ struct ContentView: View {
@State private var lastHapticTime: Date = Date()
@State private var gestureProgress: CGFloat = .zero
@State private var isPulsing: Bool = false
@State private var haptics: Bool = false
@ -562,7 +561,7 @@ struct ContentView: View {
}
}
)
.frame(width: (coordinator.expandingView.show && (coordinator.expandingView.type == .music || coordinator.expandingView.type == .timer || coordinator.expandingView.type == .recording) && Defaults[.enableSneakPeek] && Defaults[.sneakPeekStyles] == .inline) ? 380 : vm.closedNotchSize.width + (isHovering ? 8 : 0))
.frame(width: (coordinator.expandingView.show && (coordinator.expandingView.type == .music || coordinator.expandingView.type == .timer) && Defaults[.enableSneakPeek] && Defaults[.sneakPeekStyles] == .inline) ? 380 : vm.closedNotchSize.width + (isHovering ? 8 : 0))
HStack {
@ -590,47 +589,52 @@ struct ContentView: View {
func RecordingLiveActivity() -> some View {
HStack {
// Left side - Recording icon with record.circle (same pattern as album art)
// Left side - Recording icon (EXACT same structure as music album art)
HStack {
ZStack {
// Background circle matching notch style
RoundedRectangle(cornerRadius: MusicPlayerImageSizes.cornerRadiusInset.closed)
.fill(Color.red.opacity(0.1))
// Circle.fill icon with pulsing animation
Image(systemName: "circle.fill")
.font(.system(size: 12, weight: .medium))
.foregroundColor(.red)
.scaleEffect(isPulsing ? 1.2 : 1.0)
.opacity(isPulsing ? 0.7 : 1.0)
}
.onAppear {
withAnimation(.easeInOut(duration: 0.8).repeatForever(autoreverses: true)) {
isPulsing = true
}
}
.onDisappear {
isPulsing = false
}
.frame(width: max(0, vm.effectiveClosedNotchHeight - 12), height: max(0, vm.effectiveClosedNotchHeight - 12))
Color.clear
.aspectRatio(1, contentMode: .fit)
.background(
ZStack {
RoundedRectangle(cornerRadius: MusicPlayerImageSizes.cornerRadiusInset.closed)
.fill(Color.red.opacity(0.1))
Circle()
.fill(Color.red)
.frame(width: 12, height: 12)
.modifier(PulsingModifier())
}
)
.frame(width: max(0, vm.effectiveClosedNotchHeight - 12), height: max(0, vm.effectiveClosedNotchHeight - 12))
}
.frame(width: max(0, vm.effectiveClosedNotchHeight - (isHovering ? 0 : 12) + gestureProgress / 2),
height: max(0, vm.effectiveClosedNotchHeight - (isHovering ? 0 : 12)))
// Center - Recording indicator (no expansion needed since no text)
// Center - Fixed width (SAME as music)
Rectangle()
.fill(.black)
.frame(width: vm.closedNotchSize.width + (isHovering ? 8 : 0))
// Right side - Empty (as requested)
// Right side - Empty space to balance (SAME structure as music visualizer)
HStack {
// Empty space
// Empty - no content
}
.frame(width: max(0, vm.effectiveClosedNotchHeight - (isHovering ? 0 : 12) + gestureProgress / 2),
height: max(0, vm.effectiveClosedNotchHeight - (isHovering ? 0 : 12)), alignment: .center)
}
.frame(height: vm.effectiveClosedNotchHeight + (isHovering ? 8 : 0), alignment: .center)
.animation(.easeInOut(duration: 0.3), value: isPulsing)
}
// Helper function to format recording duration
private func formatDuration(_ duration: TimeInterval) -> String {
let hours = Int(duration) / 3600
let minutes = Int(duration) / 60 % 60
let seconds = Int(duration) % 60
if hours > 0 {
return String(format: "%d:%02d:%02d", hours, minutes, seconds)
} else {
return String(format: "%d:%02d", minutes, seconds)
}
}
@ViewBuilder
@ -903,3 +907,19 @@ struct FullScreenDropDelegate: DropDelegate {
return true
}
}
// Pulsing animation modifier for recording indicator
struct PulsingModifier: ViewModifier {
@State private var isPulsing = false
func body(content: Content) -> some View {
content
.scaleEffect(isPulsing ? 1.2 : 1.0)
.opacity(isPulsing ? 0.7 : 1.0)
.onAppear {
withAnimation(.easeInOut(duration: 0.8).repeatForever(autoreverses: true)) {
isPulsing = true
}
}
}
}