From 85bd75b03a6af4cdc5592ce9e9c7201d5d0b2481 Mon Sep 17 00:00:00 2001 From: jinyaqiu Date: Mon, 1 Sep 2025 14:46:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=94=AE=E7=9B=98=E5=94=A4=E8=B5=B7?= =?UTF-8?q?=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wake/View/Owner/UserInfo/AvatarPicker.swift | 54 +++++++++++++-------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/wake/View/Owner/UserInfo/AvatarPicker.swift b/wake/View/Owner/UserInfo/AvatarPicker.swift index 98e3982..0b1d657 100644 --- a/wake/View/Owner/UserInfo/AvatarPicker.swift +++ b/wake/View/Owner/UserInfo/AvatarPicker.swift @@ -23,20 +23,26 @@ public struct AvatarPicker: View { self._uploadedFileId = uploadedFileId } - private var avatarSize: CGFloat { - isKeyboardVisible ? 125 : 225 + // 添加缩放比例 + private var scaleFactor: CGFloat { + isKeyboardVisible ? 0.55 : 1.0 } private var borderWidth: CGFloat { isKeyboardVisible ? 3 : 4 } + // 添加动画配置 + private var animation: Animation { + .spring(response: 0.4, dampingFraction: 0.7, blendDuration: 0.3) + } + public var body: some View { - VStack() { + VStack(spacing: 20) { VStack(spacing: 20) { // Avatar Image Button Button(action: { - withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) { + withAnimation(animation) { showMediaPicker = true } }) { @@ -45,18 +51,21 @@ public struct AvatarPicker: View { Image(uiImage: selectedImage) .resizable() .scaledToFill() - .frame(width: avatarSize, height: avatarSize) - .clipShape(RoundedRectangle(cornerRadius: 20)) + .frame(width: 225, height: 225) + .scaleEffect(scaleFactor) + .clipShape(RoundedRectangle(cornerRadius: 20 * scaleFactor)) .overlay( RoundedRectangle(cornerRadius: 20) .stroke(Color.themePrimary, lineWidth: borderWidth) + .scaleEffect(scaleFactor) ) } else { // Default SVG avatar with animated dashed border SVGImage(svgName: "IP") - .frame(width: avatarSize, height: avatarSize) + .frame(width: 225, height: 225) + .scaleEffect(scaleFactor) .contentShape(Rectangle()) - .clipShape(RoundedRectangle(cornerRadius: 20)) + .clipShape(RoundedRectangle(cornerRadius: 20 * scaleFactor)) .overlay( RoundedRectangle(cornerRadius: 20) .stroke(style: StrokeStyle( @@ -66,6 +75,7 @@ public struct AvatarPicker: View { dashPhase: isAnimating ? 40 : 0 )) .foregroundColor(Color.themePrimary) + .scaleEffect(scaleFactor) ) .onAppear { withAnimation(Animation.linear(duration: 1.5).repeatForever(autoreverses: false)) { @@ -78,22 +88,23 @@ public struct AvatarPicker: View { if isUploading { ProgressView() .progressViewStyle(CircularProgressViewStyle(tint: .themePrimary)) - .scaleEffect(1.5) - .frame(maxWidth: .infinity, maxHeight: .infinity) + .scaleEffect(1.5 * scaleFactor) + .frame(width: 225, height: 225) + .scaleEffect(scaleFactor) .background(Color.black.opacity(0.3)) - .clipShape(RoundedRectangle(cornerRadius: 20)) + .clipShape(RoundedRectangle(cornerRadius: 20 * scaleFactor)) .transition(.opacity) } } - .frame(width: avatarSize, height: avatarSize) - .animation(.spring(response: 0.4, dampingFraction: 0.7), value: isKeyboardVisible) + .frame(width: 225 * scaleFactor, height: 225 * scaleFactor) + .animation(animation, value: isKeyboardVisible) } .buttonStyle(ScaleButtonStyle()) // Upload Button (only shown when username is not shown) if !showUsername { Button(action: { - withAnimation { + withAnimation(animation) { showMediaPicker = true } }) { @@ -107,11 +118,14 @@ public struct AvatarPicker: View { RoundedRectangle(cornerRadius: 16) .fill(Color.themePrimaryLight) ) + .scaleEffect(scaleFactor) } .frame(maxWidth: .infinity) .transition(.opacity.combined(with: .move(edge: .bottom))) + .animation(animation, value: isKeyboardVisible) } } + .animation(animation, value: isKeyboardVisible) .sheet(isPresented: $showMediaPicker) { MediaPicker( selectedMedia: Binding( @@ -123,7 +137,7 @@ public struct AvatarPicker: View { uploadManager.addMedia(newMedia) // Start upload process - withAnimation { + withAnimation(animation) { isUploading = true } uploadManager.startUpload() @@ -168,7 +182,7 @@ public struct AvatarPicker: View { print("🖼️ Updating selected image") DispatchQueue.main.async { - withAnimation(.spring()) { + withAnimation(animation) { self.selectedImage = image self.uploadedFileId = fileId self.isUploading = false @@ -190,7 +204,7 @@ public struct AvatarPicker: View { if hasFailures { print("❌ Some uploads failed") DispatchQueue.main.async { - withAnimation { + withAnimation(animation) { self.isUploading = false } } @@ -198,7 +212,7 @@ public struct AvatarPicker: View { } if !showUsername { Button(action: { - withAnimation { + withAnimation(animation) { showImageCapture = true } }) { @@ -212,14 +226,16 @@ public struct AvatarPicker: View { RoundedRectangle(cornerRadius: 16) .fill(Color.themePrimaryLight) ) + .scaleEffect(scaleFactor) } .frame(maxWidth: .infinity) + .animation(animation, value: isKeyboardVisible) .sheet(isPresented: $showImageCapture) { CustomCameraView(isPresented: $showImageCapture) { image in selectedImage = image uploadManager.clearAllMedia() uploadManager.addMedia([.image(image)]) - withAnimation { + withAnimation(animation) { isUploading = true } uploadManager.startUpload()