import SwiftUI import os.log struct BlindOutcomeView: View { let media: MediaType let title: String? let description: String? let isMember: Bool let onContinue: () -> Void let showJoinModal: Bool // Removed presentationMode; use Router.shared.pop() for back navigation @State private var showIPListModal = false init(media: MediaType, title: String? = nil, description: String? = nil, isMember: Bool = false, onContinue: @escaping () -> Void, showJoinModal: Bool = false) { self.media = media self.title = title self.description = description self.isMember = isMember self.onContinue = onContinue self.showJoinModal = showJoinModal } var body: some View { ZStack { Color.themeTextWhiteSecondary.ignoresSafeArea() VStack(spacing: 0) { // 通用导航栏 // NaviHeader( // title: "Blind Box", // onBackTap: { Router.shared.pop() }, // showBackButton: true, // titleStyle: .title, // backgroundColor: Color.themeTextWhiteSecondary // ) // .zIndex(1) Spacer() .frame(height: Theme.Spacing.lg) // Media content GeometryReader { geometry in VStack(spacing: 16) { ZStack { RoundedRectangle(cornerRadius: 12) .fill(Color.white) .shadow(color: Color.black.opacity(0.1), radius: 8, x: 0, y: 2) VStack(spacing: 0) { switch media { case .image(let uiImage): Image(uiImage: uiImage) .resizable() .scaledToFit() .frame(maxWidth: .infinity, maxHeight: .infinity) .cornerRadius(10) .padding(4) // 图片不启用全屏切换 case .video(let url, _): WakeVideoPlayer( url: url, autoPlay: true, isLooping: true, showsControls: true, allowFullscreen: true, muteInitially: false, videoGravity: .resizeAspect ) .frame(width: UIScreen.main.bounds.width - 40) .background(Color.clear) .cornerRadius(10) .clipped() } if let description = description, !description.isEmpty { VStack(alignment: .leading, spacing: 2) { // Text("Description") // .font(Typography.font(for: .body, family: .quicksandBold)) // .foregroundColor(.themeTextMessageMain) Text(description) .font(.system(size: 12)) .foregroundColor(Color.themeTextMessageMain) .fixedSize(horizontal: false, vertical: true) } .padding(Theme.Spacing.lg) } } .padding(.top, 8) } } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .padding(.bottom, 20) } .padding(.horizontal) Spacer() // Button at bottom VStack { Spacer() Button(action: { if showJoinModal { withAnimation { showIPListModal = true } } else { onContinue() } }) { Text("Continue") .font(.headline) .foregroundColor(.themeTextMessageMain) .frame(maxWidth: .infinity) .padding() .background(Color.themePrimary) .cornerRadius(26) } // 弹窗显示时,按钮淡出且不可交互 .opacity(showIPListModal ? 0 : 1) .animation(.easeInOut(duration: 0.2), value: showIPListModal) .allowsHitTesting(!showIPListModal) .padding(.horizontal) } .padding(.bottom, 20) } } .navigationBarHidden(true) .navigationBarBackButtonHidden(true) .overlay( JoinModal(isPresented: $showIPListModal, onClose: { onContinue() }) ) } } #if DEBUG // MARK: - Previews struct BlindOutcomeView_Previews: PreviewProvider { private static func coloredImage(_ color: UIColor, size: CGSize = CGSize(width: 300, height: 300)) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 2 let renderer = UIGraphicsImageRenderer(size: size, format: format) return renderer.image { ctx in color.setFill() ctx.fill(CGRect(origin: .zero, size: size)) } } private static func remoteImage(_ urlString: String, placeholder: UIColor = .systemPink, size: CGSize = CGSize(width: 300, height: 300)) -> UIImage { if let url = URL(string: urlString), let data = try? Data(contentsOf: url), let image = UIImage(data: data) { return image } return coloredImage(placeholder, size: size) } static var previews: some View { Group { // 预览 1:含描述与时间,非会员 BlindOutcomeView( media: .image(remoteImage("https://cdn.memorywake.com/files/7350515957925810176/original_1752499572813_screenshot-20250514-170854.png")), title: "00:23", description: "这是一段示例描述,用于在预览中验证样式与布局。", isMember: false, onContinue: {} ) .previewDisplayName("Image • With Description • Guest") // 预览 2:无描述无时间,会员 BlindOutcomeView( media: .image(remoteImage("https://cdn.memorywake.com/files/7350515957925810176/original_1752499572813_screenshot-20250514-170854.png")), title: nil, description: nil, isMember: true, onContinue: {} ) .previewDisplayName("Image • Minimal • Member") // 预览 3:视频示例 BlindOutcomeView( media: .video(URL(string: "https://cdn.memorywake.com/users/7350439663116619888/files/7361241959983353857/7361241920703696897.mp4")!, nil), title: "00:23", description: "视频预览示例", isMember: false, onContinue: {} ) .previewDisplayName("Video • With Description • Guest") } } } #endif