diff --git a/wake/Assets/Svg/BlindBoxBg.svg b/wake/Assets/Svg/BlindBoxBg.svg new file mode 100644 index 0000000..0575c3e --- /dev/null +++ b/wake/Assets/Svg/BlindBoxBg.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/wake/Assets/Svg/LoadingNpng.svg b/wake/Assets/Svg/LoadingNpng.svg new file mode 100644 index 0000000..7f0f20e --- /dev/null +++ b/wake/Assets/Svg/LoadingNpng.svg @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/wake/Utils/APIConfig.swift b/wake/Utils/APIConfig.swift index 5b8265b..5257f1b 100644 --- a/wake/Utils/APIConfig.swift +++ b/wake/Utils/APIConfig.swift @@ -3,7 +3,7 @@ import Foundation /// API 配置信息 public enum APIConfig { /// API 基础 URL - public static let baseURL = "https://api-dev.memorywake.com:31274/api/v1" + public static let baseURL = "https://api.memorywake.com/api/v1" /// 认证 token - 从 Keychain 中获取 public static var authToken: String { diff --git a/wake/View/Blind/Apng.swift b/wake/View/Blind/Apng.swift new file mode 100644 index 0000000..3b6a755 --- /dev/null +++ b/wake/View/Blind/Apng.swift @@ -0,0 +1,38 @@ +import SwiftUI +import UIKit + +// 包装UIImageView以支持APNG动画 +struct APNGView: UIViewRepresentable { + let imageName: String + @Binding var isAnimating: Bool + + func makeUIView(context: Context) -> UIImageView { + let imageView = UIImageView() + + // 从资源加载APNG + if let image = UIImage(named: imageName) { + imageView.image = image + // 启用动画 + imageView.animationImages = image.images + // 设置动画时长(根据实际帧数调整) + imageView.animationDuration = image.duration + // 根据isAnimating状态决定是否开始动画 + if isAnimating { + imageView.startAnimating() + } + } + + return imageView + } + + func updateUIView(_ uiView: UIImageView, context: Context) { + // 根据isAnimating状态控制动画 + if isAnimating { + if !uiView.isAnimating { + uiView.startAnimating() + } + } else { + uiView.stopAnimating() + } + } +} \ No newline at end of file diff --git a/wake/View/Blind/BlindBox.swift b/wake/View/Blind/BlindBox.swift index 7aab3a9..0c3e399 100644 --- a/wake/View/Blind/BlindBox.swift +++ b/wake/View/Blind/BlindBox.swift @@ -4,8 +4,9 @@ import AVKit // MARK: - Constants private enum MediaURLs { - static let videoURL = "https://minio-dev.memorywake.com:31274/memo/users/7363409620351717377/files/7366438998098710529/65273FCE-963F-4AA9-B0EB-C5C4ACE76655.mov?x-amz-signature=aa9e1f9c4a3682d1b74fdc090bc49be6870dbaa14e00c5add6483a529667f0f2&x-amz-signedheaders=host&x-amz-date=20250827T120711Z&x-amz-expires=360000&x-amz-algorithm=AWS4-HMAC-SHA256&x-amz-credential=minio%2F20250827%2Fus-east-1%2Fs3%2Faws4_request" + static let videoURL = "https://cdn.memorywake.com/users/7363409620351717377/files/7366657553935241216/39C069E1-7C3E-4261-8486-12058F855B38.mov" static let imageURL = "https://cdn.fairclip.cn/files/7343228671693557760/20250604-164000.jpg" + static let VideoBlindURL = "https://cdn.memorywake.com/users/7363409620351717377/files/7366658779259211776/AD970D28-9D1E-4817-A245-F11967441B8F.mp4" } extension Notification.Name { @@ -73,6 +74,7 @@ struct BlindBoxView: View { @State private var scale: CGFloat = 0.1 @State private var videoPlayer: AVPlayer? @State private var showControls = false + @State private var isAnimating = true @State private var aspectRatio: CGFloat = 1.0 @State private var isPortrait: Bool = false @State private var displayImage: UIImage? @@ -132,6 +134,23 @@ struct BlindBoxView: View { } } + // MARK: - Computed Properties + private var scaledWidth: CGFloat { + if isPortrait { + return UIScreen.main.bounds.height * scale * 1/aspectRatio + } else { + return UIScreen.main.bounds.width * scale + } + } + + private var scaledHeight: CGFloat { + if isPortrait { + return UIScreen.main.bounds.height * scale + } else { + return UIScreen.main.bounds.width * scale * 1/aspectRatio + } + } + var body: some View { ZStack { Color.themeTextWhiteSecondary.ignoresSafeArea() @@ -139,20 +158,14 @@ struct BlindBoxView: View { if showScalingOverlay { ZStack { VisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterialLight)) + .opacity(0.3) .edgesIgnoringSafeArea(.all) Group { if mediaType == .video, let player = videoPlayer { // Video Player AVPlayerController(player: $videoPlayer) - .frame( - width: isPortrait ? - UIScreen.main.bounds.height * scale * 1/aspectRatio : - UIScreen.main.bounds.width * scale, - height: isPortrait ? - UIScreen.main.bounds.height * scale : - UIScreen.main.bounds.width * scale * 1/aspectRatio - ) + .frame(width: scaledWidth, height: scaledHeight) .opacity(scale == 1 ? 1 : 0.7) .onAppear { player.play() } @@ -161,14 +174,7 @@ struct BlindBoxView: View { Image(uiImage: image) .resizable() .scaledToFit() - .frame( - width: isPortrait ? - UIScreen.main.bounds.height * scale * 1/aspectRatio : - UIScreen.main.bounds.width * scale, - height: isPortrait ? - UIScreen.main.bounds.height * scale : - UIScreen.main.bounds.width * scale * 1/aspectRatio - ) + .frame(width: scaledWidth, height: scaledHeight) .opacity(scale == 1 ? 1 : 0.7) } } @@ -248,7 +254,7 @@ struct BlindBoxView: View { ZStack { // 1. 背景SVG if !showScalingOverlay { - SVGImage(svgName: "BlindBg") + SVGImage(svgName: "BlindBoxBg") .frame( width: UIScreen.main.bounds.width * 1.8, height: UIScreen.main.bounds.height * 0.85 @@ -260,12 +266,21 @@ struct BlindBoxView: View { } if !showScalingOverlay { - LottieView(name: "data", loopMode: .loop) - .frame(width: 200, height: 200) - .position(x: UIScreen.main.bounds.width / 2, - y: UIScreen.main.bounds.height * 0.325) - .opacity(showScalingOverlay ? 0 : 1) - .animation(.easeOut(duration: 0.5), value: showScalingOverlay) + VStack(spacing: 20) { + let player = AVPlayer(url: URL(string: MediaURLs.VideoBlindURL)!) + VideoPlayer(player: player) + .background(TransparentVideoPlayer()) + .frame(width: 300, height: 300) + .onAppear { + player.play() + player.isMuted = true + } + .onDisappear { + player.pause() + } + } + .compositingGroup() + .padding() } } .frame( @@ -298,3 +313,14 @@ struct BlindBoxView: View { #Preview { BlindBoxView(mediaType: .video) } + +struct TransparentVideoPlayer: UIViewRepresentable { + func makeUIView(context: Context) -> UIView { + let view = UIView() + view.backgroundColor = .clear + view.isOpaque = false + return view + } + + func updateUIView(_ uiView: UIView, context: Context) {} +} diff --git a/wake/View/Owner/UserInfo/UserInfo.swift b/wake/View/Owner/UserInfo/UserInfo.swift index 6b82708..af54e66 100644 --- a/wake/View/Owner/UserInfo/UserInfo.swift +++ b/wake/View/Owner/UserInfo/UserInfo.swift @@ -141,6 +141,7 @@ struct UserInfo: View { // Continue Button Button(action: { + Router.shared.navigate(to: .blindBox(mediaType: .image)) if showUsername { let parameters: [String: Any] = [ "username": userName, diff --git a/wake/WakeApp.swift b/wake/WakeApp.swift index 85fefae..13ff9ad 100644 --- a/wake/WakeApp.swift +++ b/wake/WakeApp.swift @@ -52,10 +52,10 @@ struct WakeApp: App { .environmentObject(authState) } else { // 未登录:显示登录界面 - LoginView() - .environmentObject(authState) - // UserInfo() + // LoginView() // .environmentObject(authState) + UserInfo() + .environmentObject(authState) } } }