From 0ab33cab474a07eae3a03138bf03de885fd3308f Mon Sep 17 00:00:00 2001 From: Junhui Chen Date: Thu, 11 Sep 2025 17:06:12 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E8=BF=9B=E4=B8=80=E6=AD=A5?= =?UTF-8?q?=E6=8B=86=E8=A7=A3BlindBoxView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/AVPlayerController.swift | 20 + .../Components/BlindBoxActionButton.swift | 53 +++ .../Components/BlindBoxDescriptionView.swift | 19 + .../Components/BlindBoxHeaderBar.swift | 37 ++ .../Components/BlindBoxMediaOverlay.swift | 98 +++++ .../Components/BlindBoxTitleView.swift | 15 + .../BlindBox/Components/BlindCountBadge.swift | 19 + .../Components/VisualEffectView.swift | 30 ++ .../Features/BlindBox/View/BlindBoxView.swift | 354 ++---------------- 9 files changed, 324 insertions(+), 321 deletions(-) create mode 100644 wake/Features/BlindBox/Components/AVPlayerController.swift create mode 100644 wake/Features/BlindBox/Components/BlindBoxActionButton.swift create mode 100644 wake/Features/BlindBox/Components/BlindBoxDescriptionView.swift create mode 100644 wake/Features/BlindBox/Components/BlindBoxHeaderBar.swift create mode 100644 wake/Features/BlindBox/Components/BlindBoxMediaOverlay.swift create mode 100644 wake/Features/BlindBox/Components/BlindBoxTitleView.swift create mode 100644 wake/Features/BlindBox/Components/BlindCountBadge.swift create mode 100644 wake/Features/BlindBox/Components/VisualEffectView.swift diff --git a/wake/Features/BlindBox/Components/AVPlayerController.swift b/wake/Features/BlindBox/Components/AVPlayerController.swift new file mode 100644 index 0000000..3178689 --- /dev/null +++ b/wake/Features/BlindBox/Components/AVPlayerController.swift @@ -0,0 +1,20 @@ +import SwiftUI +import AVKit + +// AVPlayer 容器,隐藏系统控制、透明背景 +struct AVPlayerController: UIViewControllerRepresentable { + @Binding var player: AVPlayer? + + func makeUIViewController(context: Context) -> AVPlayerViewController { + let controller = AVPlayerViewController() + controller.player = player + controller.showsPlaybackControls = false + controller.videoGravity = .resizeAspect + controller.view.backgroundColor = .clear + return controller + } + + func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) { + uiViewController.player = player + } +} diff --git a/wake/Features/BlindBox/Components/BlindBoxActionButton.swift b/wake/Features/BlindBox/Components/BlindBoxActionButton.swift new file mode 100644 index 0000000..655306f --- /dev/null +++ b/wake/Features/BlindBox/Components/BlindBoxActionButton.swift @@ -0,0 +1,53 @@ +import SwiftUI + +struct BlindBoxActionButton: View { + let phase: BlindBoxAnimationPhase + let countdownText: String + let onOpen: () -> Void + let onGoToBuy: () -> Void + + var body: some View { + Button(action: { + switch phase { + case .ready: + onOpen() + case .none: + onGoToBuy() + default: + break + } + }) { + Group { + switch phase { + case .loading: + Text("Next: \(countdownText)") + .font(Typography.font(for: .body)) + .fontWeight(.bold) + .frame(maxWidth: .infinity) + .padding() + .background(Color.white) + .foregroundColor(.black) + .cornerRadius(32) + case .ready: + Text("Ready") + .font(Typography.font(for: .body)) + .fontWeight(.bold) + .frame(maxWidth: .infinity) + .padding() + .background(Color.themePrimary) + .foregroundColor(Color.themeTextMessageMain) + .cornerRadius(32) + default: + Text("Go to Buy") + .font(Typography.font(for: .body)) + .fontWeight(.bold) + .frame(maxWidth: .infinity) + .padding() + .background(Color.themePrimary) + .foregroundColor(Color.themeTextMessageMain) + .cornerRadius(32) + } + } + } + } +} diff --git a/wake/Features/BlindBox/Components/BlindBoxDescriptionView.swift b/wake/Features/BlindBox/Components/BlindBoxDescriptionView.swift new file mode 100644 index 0000000..31e7772 --- /dev/null +++ b/wake/Features/BlindBox/Components/BlindBoxDescriptionView.swift @@ -0,0 +1,19 @@ +import SwiftUI + +struct BlindBoxDescriptionView: View { + let name: String + let description: String + + var body: some View { + VStack(alignment: .leading, spacing: 8) { + Text(name) + .font(Typography.font(for: .body, family: .quicksandBold)) + .foregroundColor(Color.themeTextMessageMain) + Text(description) + .font(.system(size: 14)) + .foregroundColor(Color.themeTextMessageMain) + } + .frame(width: UIScreen.main.bounds.width * 0.70, alignment: .leading) + .padding() + } +} diff --git a/wake/Features/BlindBox/Components/BlindBoxHeaderBar.swift b/wake/Features/BlindBox/Components/BlindBoxHeaderBar.swift new file mode 100644 index 0000000..43074a6 --- /dev/null +++ b/wake/Features/BlindBox/Components/BlindBoxHeaderBar.swift @@ -0,0 +1,37 @@ +import SwiftUI + +struct BlindBoxHeaderBar: View { + let onMenuTap: () -> Void + let remainPoints: Int + @Binding var showLogin: Bool + + var body: some View { + HStack { + Button(action: onMenuTap) { + Image(systemName: "line.3.horizontal") + .font(.system(size: 20, weight: .regular)) + .foregroundColor(.primary) + .padding(13) + .contentShape(Rectangle()) + } + .buttonStyle(PlainButtonStyle()) + Spacer() + NavigationLink(destination: SubscribeView()) { + Text("\(remainPoints)") + .font(Typography.font(for: .subtitle)) + .fontWeight(.bold) + .padding(.horizontal, 12) + .padding(.vertical, 6) + .background(Color.black) + .foregroundColor(.white) + .cornerRadius(16) + } + .padding(.trailing) + .fullScreenCover(isPresented: $showLogin) { + LoginView() + } + } + .padding(.horizontal) + .padding(.top, 20) + } +} diff --git a/wake/Features/BlindBox/Components/BlindBoxMediaOverlay.swift b/wake/Features/BlindBox/Components/BlindBoxMediaOverlay.swift new file mode 100644 index 0000000..22e5cfd --- /dev/null +++ b/wake/Features/BlindBox/Components/BlindBoxMediaOverlay.swift @@ -0,0 +1,98 @@ +import SwiftUI +import UIKit +import AVKit + +// 展示媒体的扩散缩放覆盖层(视频/图片) +struct BlindBoxMediaOverlay: View { + let mediaType: BlindBoxMediaType + @Binding var player: AVPlayer? + let displayImage: UIImage? + let isPortrait: Bool + let aspectRatio: CGFloat + @Binding var scale: CGFloat + let onBack: () -> Void + + @State private var showControls: Bool = false + + 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 { + VisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterialLight)) + .opacity(0.3) + .edgesIgnoringSafeArea(.all) + + Group { + if mediaType == .all, player != nil { + AVPlayerController(player: $player) + .frame(width: scaledWidth, height: scaledHeight) + .opacity(scale == 1 ? 1 : 0.7) + .onAppear { player?.play() } + } else if mediaType == .image, let image = displayImage { + Image(uiImage: image) + .resizable() + .scaledToFit() + .frame(width: scaledWidth, height: scaledHeight) + .opacity(scale == 1 ? 1 : 0.7) + } + } + .contentShape(Rectangle()) + .onTapGesture { + withAnimation(.easeInOut(duration: 0.1)) { + showControls.toggle() + } + } + + if showControls { + VStack { + HStack { + Button(action: onBack) { + Image(systemName: "chevron.left") + .font(.system(size: 24)) + .foregroundColor(.black) + } + Spacer() + } + Spacer() + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .padding(.top, 50) + .padding(.leading, 20) + .zIndex(1000) + .transition(.opacity) + .onAppear { + // 2秒后显示按钮(首显时) + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + withAnimation(.easeInOut(duration: 0.3)) { + showControls = true + } + } + } + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .animation(.easeInOut(duration: 1.0), value: scale) + .ignoresSafeArea() + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { + withAnimation(.spring(response: 2.5, dampingFraction: 0.6, blendDuration: 1.0)) { + self.scale = 1.0 + } + } + } + } +} diff --git a/wake/Features/BlindBox/Components/BlindBoxTitleView.swift b/wake/Features/BlindBox/Components/BlindBoxTitleView.swift new file mode 100644 index 0000000..e2ab1b4 --- /dev/null +++ b/wake/Features/BlindBox/Components/BlindBoxTitleView.swift @@ -0,0 +1,15 @@ +import SwiftUI + +struct BlindBoxTitleView: View { + var body: some View { + VStack(alignment: .leading, spacing: 4) { + Text("Hi! Click And") + Text("Open Your Box~") + } + .font(Typography.font(for: .smallLargeTitle)) + .fontWeight(.bold) + .foregroundColor(Color.themeTextMessageMain) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal) + } +} diff --git a/wake/Features/BlindBox/Components/BlindCountBadge.swift b/wake/Features/BlindBox/Components/BlindCountBadge.swift new file mode 100644 index 0000000..4a54315 --- /dev/null +++ b/wake/Features/BlindBox/Components/BlindCountBadge.swift @@ -0,0 +1,19 @@ +import SwiftUI + +// 盲盒数量徽标 +struct BlindCountBadge: View { + let text: String + + var body: some View { + Text(text) + .font(Typography.font(for: .body, family: .quicksandBold)) + .foregroundColor(.white) + .padding(.horizontal, 12) + .padding(.vertical, 8) + .background( + Capsule() + .fill(Color.black) + .shadow(color: Color.black.opacity(0.15), radius: 4, x: 0, y: 2) + ) + } +} diff --git a/wake/Features/BlindBox/Components/VisualEffectView.swift b/wake/Features/BlindBox/Components/VisualEffectView.swift new file mode 100644 index 0000000..91bd733 --- /dev/null +++ b/wake/Features/BlindBox/Components/VisualEffectView.swift @@ -0,0 +1,30 @@ +import SwiftUI +import UIKit + +// 通用毛玻璃效果视图(弱化强度) +struct VisualEffectView: UIViewRepresentable { + var effect: UIVisualEffect? + + func makeUIView(context: Context) -> UIVisualEffectView { + let view = UIVisualEffectView(effect: nil) + + let blurEffect = UIBlurEffect(style: .systemUltraThinMaterialLight) + let blurView = UIVisualEffectView(effect: blurEffect) + blurView.alpha = 0.3 + + let backgroundView = UIView() + backgroundView.backgroundColor = UIColor.white.withAlphaComponent(0.1) + backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + + view.contentView.addSubview(backgroundView) + view.contentView.addSubview(blurView) + blurView.frame = view.bounds + blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + + return view + } + + func updateUIView(_ uiView: UIVisualEffectView, context: Context) { + // 无需动态更新 + } +} diff --git a/wake/Features/BlindBox/View/BlindBoxView.swift b/wake/Features/BlindBox/View/BlindBoxView.swift index 5da5b38..5d15a9b 100644 --- a/wake/Features/BlindBox/View/BlindBoxView.swift +++ b/wake/Features/BlindBox/View/BlindBoxView.swift @@ -8,7 +8,7 @@ extension Notification.Name { static let blindBoxStatusChanged = Notification.Name("blindBoxStatusChanged") } -private enum BlindBoxAnimationPhase { +internal enum BlindBoxAnimationPhase { case loading case ready case opening @@ -20,54 +20,6 @@ extension Notification.Name { } // MARK: - 主视图 -struct VisualEffectView: UIViewRepresentable { - var effect: UIVisualEffect? - - func makeUIView(context: Context) -> UIVisualEffectView { - let view = UIVisualEffectView(effect: nil) - - // Use a simpler approach without animator - let blurEffect = UIBlurEffect(style: .systemUltraThinMaterialLight) - - // Create a custom blur effect with reduced intensity - let blurView = UIVisualEffectView(effect: blurEffect) - blurView.alpha = 0.3 // Reduce intensity - - // Add a white background with low opacity for better frosted effect - let backgroundView = UIView() - backgroundView.backgroundColor = UIColor.white.withAlphaComponent(0.1) - backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - - view.contentView.addSubview(backgroundView) - view.contentView.addSubview(blurView) - blurView.frame = view.bounds - blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - - return view - } - - func updateUIView(_ uiView: UIVisualEffectView, context: Context) { - // No need to update the effect - } -} - -struct AVPlayerController: UIViewControllerRepresentable { - @Binding var player: AVPlayer? - - func makeUIViewController(context: Context) -> AVPlayerViewController { - let controller = AVPlayerViewController() - controller.player = player - controller.showsPlaybackControls = false - controller.videoGravity = .resizeAspect - controller.view.backgroundColor = .clear - return controller - } - - func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) { - uiViewController.player = player - } -} - struct BlindBoxView: View { let mediaType: BlindBoxMediaType let currentBoxId: String? @@ -80,7 +32,7 @@ struct BlindBoxView: View { @State private var showScalingOverlay = false @State private var animationPhase: BlindBoxAnimationPhase = .none @State private var scale: CGFloat = 0.1 - @State private var showControls = false + // showControls 状态已迁移至 BlindBoxMediaOverlay 组件内 @State private var isAnimating = true @State private var showMedia = false @@ -93,18 +45,6 @@ struct BlindBoxView: View { _viewModel = StateObject(wrappedValue: BlindBoxViewModel(mediaType: mediaType, currentBoxId: blindBoxId)) } - // 倒计时已迁移至 ViewModel - - // 已由 ViewModel 承担加载与轮询逻辑 - - // 已迁移至 ViewModel - - // 已迁移至 ViewModel - - // 已迁移至 ViewModel - - // 本地媒体加载逻辑已迁移至 ViewModel.prepareMedia() - private func startScalingAnimation() { self.scale = 0.1 self.showScalingOverlay = true @@ -114,22 +54,7 @@ struct BlindBoxView: View { } } - // MARK: - Computed Properties - private var scaledWidth: CGFloat { - if viewModel.isPortrait { - return UIScreen.main.bounds.height * scale * 1/viewModel.aspectRatio - } else { - return UIScreen.main.bounds.width * scale - } - } - - private var scaledHeight: CGFloat { - if viewModel.isPortrait { - return UIScreen.main.bounds.height * scale - } else { - return UIScreen.main.bounds.width * scale * 1/viewModel.aspectRatio - } - } + // 计算尺寸逻辑已迁移至 BlindBoxMediaOverlay 组件 var body: some View { ZStack { @@ -139,40 +64,6 @@ struct BlindBoxView: View { print("🎯 BlindBoxView appeared with mediaType: \(mediaType)") print("🎯 Current thread: \(Thread.current)") - - - // 初始化显示数据 - // if mediaType == .all, let firstItem = blindList.first { - // displayData = BlindBoxData(from: firstItem) - // } else { - // displayData = blindGenerate - // } - - // 添加盲盒状态变化监听 - // NotificationCenter.default.addObserver( - // forName: .blindBoxStatusChanged, - // object: nil, - // queue: .main - // ) { notification in - // if let status = notification.userInfo?["status"] as? String { - // switch status { - // case "Preparing": - // withAnimation { - // self.animationPhase = .loading - // } - // case "Unopened": - // withAnimation { - // self.animationPhase = .ready - // } - // default: - // // 其他状态不处理 - // withAnimation { - // self.animationPhase = .ready - // } - // break - // } - // } - // } // 调用接口 Task { await viewModel.load() @@ -233,151 +124,35 @@ struct BlindBoxView: View { } if showScalingOverlay { - ZStack { - VisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterialLight)) - .opacity(0.3) - .edgesIgnoringSafeArea(.all) - - Group { - if mediaType == .all, viewModel.player != nil { - // Video Player - AVPlayerController(player: .init(get: { viewModel.player }, set: { viewModel.player = $0 })) - .frame(width: scaledWidth, height: scaledHeight) - .opacity(scale == 1 ? 1 : 0.7) - .onAppear { viewModel.player?.play() } - + BlindBoxMediaOverlay( + mediaType: mediaType, + player: .init(get: { viewModel.player }, set: { viewModel.player = $0 }), + displayImage: viewModel.displayImage, + isPortrait: viewModel.isPortrait, + aspectRatio: viewModel.aspectRatio, + scale: $scale, + onBack: { + if mediaType == .all, !viewModel.videoURL.isEmpty, let url = URL(string: viewModel.videoURL) { + Router.shared.navigate(to: .blindOutcome(media: .video(url, nil), time: viewModel.blindGenerate?.name ?? "Your box", description: viewModel.blindGenerate?.description ?? "", isMember: viewModel.isMember)) } else if mediaType == .image, let image = viewModel.displayImage { - // Image View - Image(uiImage: image) - .resizable() - .scaledToFit() - .frame(width: scaledWidth, height: scaledHeight) - .opacity(scale == 1 ? 1 : 0.7) + Router.shared.navigate(to: .blindOutcome(media: .image(image), time: viewModel.blindGenerate?.name ?? "Your box", description: viewModel.blindGenerate?.description ?? "", isMember: viewModel.isMember)) } } - .onTapGesture { - withAnimation(.easeInOut(duration: 0.1)) { - showControls.toggle() - } - } - - // 返回按钮 - if showControls { - VStack { - HStack { - Button(action: { - // 导航到BlindOutcomeView - if mediaType == .all, !viewModel.videoURL.isEmpty, let url = URL(string: viewModel.videoURL) { - Router.shared.navigate(to: .blindOutcome(media: .video(url, nil), time: viewModel.blindGenerate?.name ?? "Your box", description:viewModel.blindGenerate?.description ?? "", isMember: viewModel.isMember)) - } else if mediaType == .image, let image = viewModel.displayImage { - Router.shared.navigate(to: .blindOutcome(media: .image(image), time: viewModel.blindGenerate?.name ?? "Your box", description:viewModel.blindGenerate?.description ?? "", isMember: viewModel.isMember)) - } - }) { - Image(systemName: "chevron.left") - .font(.system(size: 24)) - .foregroundColor(.black) - } - Spacer() - } - Spacer() - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - .padding(.top, 50) - .padding(.leading, 20) - .zIndex(1000) - .transition(.opacity) - .onAppear { - // 2秒后显示按钮 - DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - withAnimation(.easeInOut(duration: 0.3)) { - showControls = true - } - } - } - } - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - .animation(.easeInOut(duration: 1.0), value: scale) - .ignoresSafeArea() - .onAppear { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { - withAnimation(.spring(response: 2.5, dampingFraction: 0.6, blendDuration: 1.0)) { - self.scale = 1.0 - } - } - } + ) } else { // Original content VStack { VStack(spacing: 20) { if mediaType == .all { - // 顶部导航栏 - HStack { - // 设置按钮 - Button(action: showUserProfile) { - Image(systemName: "line.3.horizontal") - .font(.system(size: 20, weight: .regular)) - .foregroundColor(.primary) - .padding(13) // Increases tap area while keeping visual size - .contentShape(Rectangle()) // Makes the padded area tappable - } - .buttonStyle(PlainButtonStyle()) // Prevents the button from affecting the layout - - Spacer() - // // 测试质感页面入口 - // NavigationLink(destination: TestView()) { - // Text("TestView") - // .font(.subheadline) - // .padding(.horizontal, 12) - // .padding(.vertical, 6) - // .background(Color.brown) - // .foregroundColor(.white) - // .cornerRadius(8) - // } - - // // 订阅测试按钮 - // NavigationLink(destination: SubscribeView()) { - // Text("Subscribe") - // .font(.subheadline) - // .padding(.horizontal, 12) - // .padding(.vertical, 6) - // .background(Color.orange) - // .foregroundColor(.white) - // .cornerRadius(8) - // } - // .padding(.trailing) - // .fullScreenCover(isPresented: $showLogin) { - // LoginView() - // } - NavigationLink(destination: SubscribeView()) { - Text("\(viewModel.memberProfile?.remainPoints ?? 0)") - .font(Typography.font(for: .subtitle)) - .fontWeight(.bold) - .padding(.horizontal, 12) - .padding(.vertical, 6) - .background(Color.black) - .foregroundColor(.white) - .cornerRadius(16) - } - .padding(.trailing) - .fullScreenCover(isPresented: $showLogin) { - LoginView() - } - } - .padding(.horizontal) - .padding(.top, 20) + BlindBoxHeaderBar( + onMenuTap: showUserProfile, + remainPoints: viewModel.memberProfile?.remainPoints ?? 0, + showLogin: $showLogin + ) } // 标题 - VStack(alignment: .leading, spacing: 4) { - Text("Hi! Click And") - Text("Open Your Box~") - } - .font(Typography.font(for: .smallLargeTitle)) - .fontWeight(.bold) - .foregroundColor(Color.themeTextMessageMain) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal) + BlindBoxTitleView() .opacity(showScalingOverlay ? 0 : 1) .offset(y: showScalingOverlay ? -UIScreen.main.bounds.height * 0.2 : 0) .animation(.easeInOut(duration: 0.5), value: showScalingOverlay) @@ -501,17 +276,10 @@ struct BlindBoxView: View { } // 只在未显示媒体且未播放动画时显示文字 if !showScalingOverlay && !showMedia { - VStack(alignment: .leading, spacing: 8) { - // 从变量blindGenerate中获取description - Text(viewModel.blindGenerate?.name ?? "Some box") - .font(Typography.font(for: .body, family: .quicksandBold)) - .foregroundColor(Color.themeTextMessageMain) - Text(viewModel.blindGenerate?.description ?? "") - .font(.system(size: 14)) - .foregroundColor(Color.themeTextMessageMain) - } - .frame(width: UIScreen.main.bounds.width * 0.70, alignment: .leading) - .padding() + BlindBoxDescriptionView( + name: viewModel.blindGenerate?.name ?? "Some box", + description: viewModel.blindGenerate?.description ?? "" + ) .offset(x: -10, y: UIScreen.main.bounds.height * 0.2) } } @@ -527,9 +295,10 @@ struct BlindBoxView: View { // 打开 TODO 引导时,也要有按钮 if mediaType == .all, viewModel.didBootstrap { - Button(action: { - if animationPhase == .ready { - // 准备就绪点击,开启盲盒 + BlindBoxActionButton( + phase: animationPhase, + countdownText: viewModel.countdownText, + onOpen: { let boxIdToOpen = self.currentBoxId ?? self.viewModel.blindGenerate?.id if let boxId = boxIdToOpen { Task { @@ -544,39 +313,11 @@ struct BlindBoxView: View { withAnimation { animationPhase = .opening } - } else if animationPhase == .none { + }, + onGoToBuy: { Router.shared.navigate(to: .mediaUpload) } - }) { - if animationPhase == .loading { - Text("Next: \(viewModel.countdownText)") - .font(Typography.font(for: .body)) - .fontWeight(.bold) - .frame(maxWidth: .infinity) - .padding() - .background(Color.white) - .foregroundColor(.black) - .cornerRadius(32) - } else if animationPhase == .ready { - Text("Ready") - .font(Typography.font(for: .body)) - .fontWeight(.bold) - .frame(maxWidth: .infinity) - .padding() - .background(Color.themePrimary) - .foregroundColor(Color.themeTextMessageMain) - .cornerRadius(32) - } else { - Text("Go to Buy") - .font(Typography.font(for: .body)) - .fontWeight(.bold) - .frame(maxWidth: .infinity) - .padding() - .background(Color.themePrimary) - .foregroundColor(Color.themeTextMessageMain) - .cornerRadius(32) - } - } + ) .padding(.horizontal) } } @@ -644,25 +385,6 @@ struct BlindBoxView: View { } } - // MARK: - 盲盒数量徽标(SwiftUI 重绘) - private struct BlindCountBadge: View { - let text: String - - var body: some View { - Text(text) - .font(Typography.font(for: .body, family: .quicksandBold)) - .foregroundColor(.white) - .padding(.horizontal, 12) - .padding(.vertical, 8) - .background( - Capsule() - .fill(Color.black) - .shadow(color: Color.black.opacity(0.15), radius: 4, x: 0, y: 2) - ) - } - } - - /// 隐藏设置页面 private func hideSettings() { withAnimation(.spring(response: 0.6, dampingFraction: 0.8)) { @@ -701,14 +423,4 @@ struct BlindBoxView: View { } #endif } -} -// 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) {} -// } +} \ No newline at end of file