@@ -42,7 +42,7 @@ struct WidgetView: View {
4242 value: isHovering
4343 )
4444 . animation (
45- . easeInOut( duration: 0.2 ) ,
45+ . easeInOut( duration: 0.4 ) ,
4646 value: store. isProcessing
4747 )
4848 }
@@ -54,11 +54,9 @@ struct WidgetAnimatedCapsule: View {
5454 let store : StoreOf < CircularWidget >
5555 var isHovering : Bool
5656
57- @State private var animatedProgress : CGFloat = 0 // 0~1
57+ @State private var breathingOpacity : CGFloat = 1.0
5858 @State private var animationTask : Task < Void , Never > ?
5959
60- private let movingSegmentLength : CGFloat = 0.28
61-
6260 var body : some View {
6361 GeometryReader { geo in
6462 WithPerceptionTracking {
@@ -68,6 +66,7 @@ struct WidgetAnimatedCapsule: View {
6866 let backgroundWidth = capsuleWidth
6967 let foregroundWidth = max ( capsuleWidth - 4 , 2 )
7068 let padding = ( backgroundWidth - foregroundWidth) / 2
69+ let foregroundHeight = capsuleHeight - padding * 2
7170
7271 ZStack {
7372 Capsule ( )
@@ -91,87 +90,65 @@ struct WidgetAnimatedCapsule: View {
9190 }
9291 }
9392 . frame ( width: backgroundWidth, height: capsuleHeight)
94- . animation ( . easeInOut( duration: 0.14 ) , value: isHovering)
9593
9694 Capsule ( )
97- . fill ( Color . accentColor . opacity ( 0.8 ) )
95+ . fill ( Color . white )
9896 . frame (
9997 width: foregroundWidth,
100- height: capsuleHeight * movingSegmentLength
101- )
102- . opacity ( store. isProcessing ? 1 : 0 )
103- . position (
104- x: capsuleWidth / 2 ,
105- y: {
106- let height = capsuleHeight - padding * 2
107- let base = padding
108- return base + height * ( normalizedStart ( ) + movingSegmentLength / 2 )
109- } ( )
98+ height: foregroundHeight
11099 )
111- . animation ( nil , value: store. isProcessing)
112- . animation ( . easeInOut( duration: 0.14 ) , value: isHovering)
100+ . opacity ( {
101+ let base = store. isProcessing ? breathingOpacity : 0
102+ if isHovering {
103+ return min ( base + 0.5 , 1.0 )
104+ }
105+ return base
106+ } ( ) )
107+ . blur ( radius: 2 )
113108 }
114109 . onAppear {
115- updateAnimationTask ( isProcessing: store. isProcessing)
110+ updateBreathingAnimation ( isProcessing: store. isProcessing)
116111 }
117112 . onChange ( of: store. isProcessing) { newValue in
118- updateAnimationTask ( isProcessing: newValue)
119- }
120- . onChange ( of: store. isContentEmpty) { _ in
121- if !store. isProcessing {
122- animatedProgress = store. isContentEmpty ? 0 : 1
123- }
113+ updateBreathingAnimation ( isProcessing: newValue)
124114 }
125- . onChange ( of: isHovering) { _ in }
126115 }
127116 }
128117 }
129118
130- // 进度条起点
131- private func normalizedStart( ) -> CGFloat {
132- let p = max ( 0 , min ( 1 , animatedProgress) )
133- return p * ( 1 - movingSegmentLength)
134- }
135-
136- // 动画任务
137- private func updateAnimationTask( isProcessing: Bool ) {
119+ private func updateBreathingAnimation( isProcessing: Bool ) {
138120 animationTask? . cancel ( )
139121 animationTask = nil
140122
141123 if isProcessing {
142- animationTask = Task { [ weak store] in
143- await MainActor . run {
144- animatedProgress = 0
145- }
124+ animationTask = Task {
146125 while !Task. isCancelled {
147126 await MainActor . run {
148- withAnimation ( . linear ( duration: 1.2 ) ) {
149- animatedProgress = 1
127+ withAnimation ( . easeInOut ( duration: 1.2 ) ) {
128+ breathingOpacity = 0.3
150129 }
151130 }
152131 try ? await Task . sleep ( nanoseconds: UInt64 ( 1.2 * 1_000_000_000 ) )
153132 if Task . isCancelled { break }
154- if !( store? . isProcessing ?? true ) { break }
133+ if !( store. isProcessing) { break }
155134 await MainActor . run {
156- withAnimation ( . linear ( duration: 1.2 ) ) {
157- animatedProgress = 0
135+ withAnimation ( . easeInOut ( duration: 1.2 ) ) {
136+ breathingOpacity = 1. 0
158137 }
159138 }
160139 try ? await Task . sleep ( nanoseconds: UInt64 ( 1.2 * 1_000_000_000 ) )
161140 if Task . isCancelled { break }
162- if !( store? . isProcessing ?? true ) { break }
141+ if !( store. isProcessing) { break }
163142 }
164143 }
165144 } else {
166145 withAnimation ( . easeInOut( duration: 0.2 ) ) {
167- animatedProgress = store . isContentEmpty ? 0 : 1
146+ breathingOpacity = 0
168147 }
169148 }
170149 }
171150}
172151
173- // 下面的WidgetContextMenu和其它内容保持不变喵~
174-
175152struct WidgetContextMenu : View {
176153 @AppStorage ( \. useGlobalChat) var useGlobalChat
177154 @AppStorage ( \. realtimeSuggestionToggle) var realtimeSuggestionToggle
0 commit comments