From c293b248d0fa125723150cefb89336ca3661d29e Mon Sep 17 00:00:00 2001 From: Junhui Chen Date: Wed, 20 Aug 2025 10:39:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=A2=E9=98=85=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserInterfaceState.xcuserstate | Bin 57109 -> 75042 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 24 ++ wake/Theme.swift | 26 +- wake/Typography.swift | 6 +- wake/View/Credits/CreditsDetailView.swift | 288 ++++++++++++++++++ wake/View/Credits/CreditsInfoCard.swift | 271 ++-------------- .../Subscribe/Components/PlanCompare.swift | 1 + .../Subscribe/Components/PlanSelector.swift | 135 ++++++++ .../Components/SubscriptionStatusBar.swift | 20 +- wake/View/Subscribe/SubscribeView.swift | 155 ++++------ 10 files changed, 579 insertions(+), 347 deletions(-) create mode 100644 wake.xcodeproj/xcuserdata/fairclip.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 wake/View/Credits/CreditsDetailView.swift create mode 100644 wake/View/Subscribe/Components/PlanCompare.swift diff --git a/wake.xcodeproj/project.xcworkspace/xcuserdata/fairclip.xcuserdatad/UserInterfaceState.xcuserstate b/wake.xcodeproj/project.xcworkspace/xcuserdata/fairclip.xcuserdatad/UserInterfaceState.xcuserstate index 6e6e72499448001a99e3761746a5dee7d7cabe07..b5dc67cc0d5c3c097c15c9feff19653e9c867950 100644 GIT binary patch literal 75042 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 diff --git a/wake.xcodeproj/xcuserdata/fairclip.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/wake.xcodeproj/xcuserdata/fairclip.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..0ff5029 --- /dev/null +++ b/wake.xcodeproj/xcuserdata/fairclip.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/wake/Theme.swift b/wake/Theme.swift index 7a3f307..dfcc994 100644 --- a/wake/Theme.swift +++ b/wake/Theme.swift @@ -23,7 +23,7 @@ struct Theme { static let accent = Color(hex: "FF6B6B") // 强调红色 // MARK: - 中性色 - static let background = Color(hex: "F8F9FA") // 背景色 + static let background = Color(hex: "FAFAFA") // 背景色 static let surface = Color.white // 表面色 static let surfaceSecondary = Color(hex: "F5F5F5") // 次级表面色 @@ -40,14 +40,18 @@ struct Theme { static let info = Color(hex: "3B82F6") // 信息色 // MARK: - 边框色 - static let border = Color(hex: "E5E7EB") // 边框色 + static let border = Color(hex: "D9D9D9") // 边框色 static let borderLight = Color(hex: "F3F4F6") // 浅边框色 - static let borderDark = Color(hex: "D1D5DB") // 深边框色 + static let borderBlack = Color.black // 黑色边框色 + static let borderDark = borderBlack // 深边框色 // MARK: - 订阅相关色 static let freeBackground = primaryLight // Free版背景 static let pioneerBackground = primary // Pioneer版背景 static let subscribeButton = primary // 订阅按钮色 + + // MARK: - 卡片相关色 + static let cardBackground = Color.white // 卡片背景 } // MARK: - 渐变色 @@ -59,9 +63,13 @@ struct Theme { ) static let backgroundGradient = LinearGradient( - colors: [Colors.background, Colors.surface], - startPoint: .top, - endPoint: .bottom + gradient: Gradient(colors: [ + Color(hex: "FBC063"), + Color(hex: "FEE9BE"), + Color(hex: "FAB851") + ]), + startPoint: .topLeading, + endPoint: .bottomTrailing ) static let accentGradient = LinearGradient( @@ -69,6 +77,12 @@ struct Theme { startPoint: .leading, endPoint: .trailing ) + + // static let creditsInfoTooltip = LinearGradient( + // colors: [Colors(hex: "FFD38F"), Colors(hex: "FFF8DE"), Colors(hex: "FECE83")], + // startPoint: .topLeading, + // endPoint: .bottomTrailing + // ) } // MARK: - 阴影 diff --git a/wake/Typography.swift b/wake/Typography.swift index 27f7b98..91ba2d3 100644 --- a/wake/Typography.swift +++ b/wake/Typography.swift @@ -60,21 +60,21 @@ struct Typography { /// - style: 文本样式 /// - family: 字体库,默认为 nil 使用默认字体库 /// - Returns: 配置好的 Font 对象 - static func font(for style: TypographyStyle, family: FontFamily? = nil) -> Font { + static func font(for style: TypographyStyle, family: FontFamily? = nil, size: CGFloat? = nil) -> Font { let fontFamily = family ?? defaultFontFamily guard let config = styleConfig[style] else { return .body } // 尝试加载自定义字体 - if let customFont = UIFont(name: fontFamily.name, size: config.size) { + if let customFont = UIFont(name: fontFamily.name, size: size ?? config.size) { let metrics = UIFontMetrics(forTextStyle: config.textStyle) let scaledFont = metrics.scaledFont(for: customFont) return Font(scaledFont) } // 如果自定义字体加载失败,回退到系统字体 - let systemFont = UIFont.systemFont(ofSize: config.size, weight: config.weight) + let systemFont = UIFont.systemFont(ofSize: size ?? config.size, weight: config.weight) let metrics = UIFontMetrics(forTextStyle: config.textStyle) let scaledFont = metrics.scaledFont(for: systemFont) return Font(scaledFont) diff --git a/wake/View/Credits/CreditsDetailView.swift b/wake/View/Credits/CreditsDetailView.swift new file mode 100644 index 0000000..8d6c496 --- /dev/null +++ b/wake/View/Credits/CreditsDetailView.swift @@ -0,0 +1,288 @@ +// +// CreditsDetailView.swift +// wake +// +// Created by fairclip on 2025/8/19. +// + +import SwiftUI + +// MARK: - 积分交易类型 +enum CreditTransactionType: String, CaseIterable { + case photoUnderstanding = "Photo Understanding" + case videoUnderstanding = "Video Understanding" + case mysteryBoxPurchase = "Mystery Box Purchase" + case dailyBonus = "Daily Bonus" + case subscriptionBonus = "Subscription Bonus" + + var creditChange: Int { + switch self { + case .photoUnderstanding: + return -1 + case .videoUnderstanding: + return -32 + case .mysteryBoxPurchase: + return -100 + case .dailyBonus: + return 200 + case .subscriptionBonus: + return 500 + } + } + + var icon: String { + switch self { + case .photoUnderstanding: + return "photo" + case .videoUnderstanding: + return "video" + case .mysteryBoxPurchase: + return "gift" + case .dailyBonus: + return "calendar" + case .subscriptionBonus: + return "star.fill" + } + } +} + +// MARK: - 积分交易记录 +struct CreditTransaction { + let id = UUID() + let type: CreditTransactionType + let date: Date + let creditChange: Int + + init(type: CreditTransactionType, date: Date, creditChange: Int? = nil) { + self.type = type + self.date = date + self.creditChange = creditChange ?? type.creditChange + } +} + +// MARK: - 积分详情页面 +struct CreditsDetailView: View { + @Environment(\.presentationMode) var presentationMode + @State private var showRules = false + + // 示例数据 + private let totalCredits = 3290 + private let expiringToday = 200 + private let transactions: [CreditTransaction] = [ + CreditTransaction(type: .photoUnderstanding, date: Calendar.current.date(byAdding: .hour, value: -2, to: Date()) ?? Date()), + CreditTransaction(type: .videoUnderstanding, date: Calendar.current.date(byAdding: .hour, value: -4, to: Date()) ?? Date()), + CreditTransaction(type: .mysteryBoxPurchase, date: Calendar.current.date(byAdding: .day, value: -1, to: Date()) ?? Date()), + CreditTransaction(type: .dailyBonus, date: Calendar.current.date(byAdding: .day, value: -1, to: Date()) ?? Date()), + CreditTransaction(type: .subscriptionBonus, date: Calendar.current.date(byAdding: .day, value: -2, to: Date()) ?? Date()) + ] + + var body: some View { + NavigationView { + ScrollView { + VStack(spacing: 0) { + // 导航栏 + navigationHeader + + // 主积分卡片 + mainCreditsCard + + // 积分历史 + creditsHistorySection + + Spacer(minLength: 100) + } + } + .background(Color(.systemGroupedBackground)) + .navigationBarHidden(true) + } + } + + // MARK: - 导航栏 + private var navigationHeader: some View { + NaviHeader(title: "Credits") { + presentationMode.wrappedValue.dismiss() + } + } + + // MARK: - 主积分卡片 + private var mainCreditsCard: some View { + VStack(spacing: 0) { + // 主要积分显示区域 + HStack { + // 左侧三角形图标 + Circle() + .fill(Color.black) + .frame(width: 80, height: 80) + .overlay( + Image(systemName: "triangle.fill") + .foregroundColor(.white) + .font(.system(size: 24, weight: .bold)) + ) + + Spacer() + + // 右侧积分信息 + VStack(alignment: .trailing, spacing: 8) { + HStack(spacing: 8) { + Circle() + .fill(Color.black) + .frame(width: 24, height: 24) + .overlay( + Image(systemName: "triangle.fill") + .foregroundColor(.white) + .font(.system(size: 8)) + ) + + Text("\(totalCredits)") + .font(Typography.font(for: .headline, family: .quicksandBold, size: 36)) + .foregroundColor(.black) + } + + Text("Expiring Today : \(expiringToday)") + .font(Typography.font(for: .body, family: .quicksand)) + .foregroundColor(.black.opacity(0.8)) + } + } + .padding(Theme.Spacing.xl) + + // 虚线分隔 + DashedLine() + .stroke(Color.black.opacity(0.3), style: StrokeStyle(lineWidth: 1, dash: [5, 5])) + .frame(height: 1) + .padding(.horizontal, Theme.Spacing.xl) + + // 积分规则展开区域 + creditsRulesSection + } + .background( + LinearGradient( + colors: [ + Color(hex: "FFB645"), + Color(hex: "FFA726") + ], + startPoint: .topLeading, + endPoint: .bottomTrailing + ) + ) + .cornerRadius(Theme.CornerRadius.large) + .padding(.horizontal, Theme.Spacing.xl) + .padding(.top, Theme.Spacing.xl) + } + + // MARK: - 积分规则区域 + private var creditsRulesSection: some View { + VStack(spacing: 0) { + // 规则标题按钮 + Button(action: { + withAnimation(.easeInOut(duration: 0.3)) { + showRules.toggle() + } + }) { + HStack { + Text("Credits Rules") + .font(Typography.font(for: .body, family: .quicksandBold)) + .foregroundColor(.black) + + Spacer() + + Image(systemName: showRules ? "chevron.up" : "chevron.down") + .foregroundColor(.black) + .font(.system(size: 14, weight: .medium)) + } + .padding(.horizontal, Theme.Spacing.xl) + .padding(.vertical, Theme.Spacing.lg) + } + + // 规则内容 + if showRules { + VStack(alignment: .leading, spacing: Theme.Spacing.sm) { + Text("Credits can be used for material indexing (1 credit per photo or per second of video) and for buying blind boxes (100 credits each).") + .font(Typography.font(for: .subtitle, family: .quicksand)) + .foregroundColor(.black.opacity(0.8)) + .multilineTextAlignment(.leading) + } + .padding(.horizontal, Theme.Spacing.xl) + .padding(.bottom, Theme.Spacing.lg) + } + } + } + + // MARK: - 积分历史区域 + private var creditsHistorySection: some View { + VStack(alignment: .leading, spacing: Theme.Spacing.lg) { + Text("Points History") + .font(Typography.font(for: .title, family: .quicksandBold)) + .foregroundColor(Theme.Colors.textPrimary) + .padding(.horizontal, Theme.Spacing.xl) + + LazyVStack(spacing: 0) { + ForEach(Array(transactions.enumerated()), id: \.element.id) { index, transaction in + CreditTransactionRow( + transaction: transaction, + isLast: index == transactions.count - 1 + ) + } + } + .background(Color(.systemBackground)) + .cornerRadius(Theme.CornerRadius.medium) + .padding(.horizontal, Theme.Spacing.xl) + } + .padding(.top, Theme.Spacing.xl) + } +} + +// MARK: - 积分交易行组件 +struct CreditTransactionRow: View { + let transaction: CreditTransaction + let isLast: Bool + + var body: some View { + VStack(spacing: 0) { + HStack(spacing: Theme.Spacing.lg) { + VStack(alignment: .leading, spacing: 4) { + Text(transaction.type.rawValue) + .font(Typography.font(for: .body, family: .quicksandBold)) + .foregroundColor(Theme.Colors.textPrimary) + + Text(formatDate(transaction.date)) + .font(Typography.font(for: .caption, family: .quicksand)) + .foregroundColor(Theme.Colors.textSecondary) + } + + Spacer() + + Text("\(transaction.creditChange > 0 ? "+" : "")\(transaction.creditChange)") + .font(Typography.font(for: .body, family: .quicksandBold)) + .foregroundColor(transaction.creditChange > 0 ? Theme.Colors.success : Theme.Colors.textPrimary) + } + .padding(.horizontal, Theme.Spacing.lg) + .padding(.vertical, Theme.Spacing.lg) + + if !isLast { + Divider() + .background(Theme.Colors.borderLight) + } + } + } + + private func formatDate(_ date: Date) -> String { + let formatter = DateFormatter() + formatter.dateFormat = "MM-dd-yyyy" + return formatter.string(from: date) + } +} + +// MARK: - 虚线组件 +struct DashedLine: Shape { + func path(in rect: CGRect) -> Path { + var path = Path() + path.move(to: CGPoint(x: 0, y: 0)) + path.addLine(to: CGPoint(x: rect.width, y: 0)) + return path + } +} + +// MARK: - 预览 +#Preview { + CreditsDetailView() +} diff --git a/wake/View/Credits/CreditsInfoCard.swift b/wake/View/Credits/CreditsInfoCard.swift index 1ec5010..b374a4c 100644 --- a/wake/View/Credits/CreditsInfoCard.swift +++ b/wake/View/Credits/CreditsInfoCard.swift @@ -1,4 +1,4 @@ -// + // // CreditsInfoCard.swift // wake // @@ -7,294 +7,93 @@ import SwiftUI -// MARK: - 积分类型枚举 -enum CreditType: String, CaseIterable { - case daily = "Daily" - case purchased = "Purchased" - case bonus = "Bonus" - case permanent = "Permanent" - - var displayName: String { - switch self { - case .daily: - return "Daily Credits" - case .purchased: - return "Purchased Credits" - case .bonus: - return "Bonus Credits" - case .permanent: - return "Permanent Credits" - } - } - - var icon: String { - switch self { - case .daily: - return "calendar" - case .purchased: - return "creditcard" - case .bonus: - return "gift" - case .permanent: - return "infinity" - } - } - - var color: Color { - switch self { - case .daily: - return Theme.Colors.info - case .purchased: - return Theme.Colors.success - case .bonus: - return Theme.Colors.warning - case .permanent: - return Theme.Colors.primary - } - } -} - -// MARK: - 积分信息数据模型 -struct CreditInfo { - let type: CreditType - let amount: Int - let description: String -} - // MARK: - 积分信息卡片组件 struct CreditsInfoCard: View { let totalCredits: Int - let creditBreakdown: [CreditInfo] let onInfoTap: (() -> Void)? let onDetailTap: (() -> Void)? - @State private var showBreakdown = false + @State private var showInfoPopover = false init( totalCredits: Int, - creditBreakdown: [CreditInfo] = [], onInfoTap: (() -> Void)? = nil, onDetailTap: (() -> Void)? = nil ) { self.totalCredits = totalCredits - self.creditBreakdown = creditBreakdown self.onInfoTap = onInfoTap self.onDetailTap = onDetailTap } var body: some View { - VStack(spacing: 0) { - // 主要积分显示区域 + Button(action: { + onDetailTap?() + }) { mainCreditsSection - - // 积分明细展开区域 - if showBreakdown && !creditBreakdown.isEmpty { - creditsBreakdownSection - } } - .background(Color(.systemBackground)) - .cornerRadius(Theme.CornerRadius.medium) + .buttonStyle(PlainButtonStyle()) + .background(Theme.Colors.primaryLight) + .cornerRadius(Theme.CornerRadius.extraLarge) .shadow(color: Theme.Shadows.small, radius: Theme.Shadows.cardShadow.radius, x: Theme.Shadows.cardShadow.x, y: Theme.Shadows.cardShadow.y) } // MARK: - 主要积分显示区域 private var mainCreditsSection: some View { - HStack(spacing: Theme.Spacing.lg) { + HStack(spacing: Theme.Spacing.md) { // 积分图标和数量 HStack(spacing: Theme.Spacing.sm) { - Circle() - .fill(Theme.Gradients.primaryGradient) - .frame(width: 40, height: 40) - .overlay( - Image(systemName: "star.fill") - .foregroundColor(.white) - .font(.system(size: 18, weight: .semibold)) - ) + Text("Credits:") + .font(Typography.font(for: .subtitle, family: .quicksandBold)) + .foregroundColor(Theme.Colors.textPrimary) - VStack(alignment: .leading, spacing: 2) { - Text("Credits") - .font(Typography.font(for: .caption, family: .quicksand)) - .foregroundColor(Theme.Colors.textSecondary) - - Text("\(totalCredits)") - .font(Typography.font(for: .title, family: .quicksandBold)) - .foregroundColor(Theme.Colors.textPrimary) - } + Text("\(totalCredits)") + .font(Typography.font(for: .subtitle, family: .quicksandBold)) + .foregroundColor(Theme.Colors.textPrimary) } - Spacer() // 操作按钮区域 HStack(spacing: Theme.Spacing.sm) { // 信息按钮 Button(action: { + showInfoPopover = true onInfoTap?() }) { - Image(systemName: "info.circle") + Image(systemName: "questionmark.circle") .foregroundColor(Theme.Colors.textSecondary) .font(.system(size: 16)) } - - // 展开/收起按钮 - if !creditBreakdown.isEmpty { - Button(action: { - withAnimation(.easeInOut(duration: 0.3)) { - showBreakdown.toggle() - } - }) { - Image(systemName: showBreakdown ? "chevron.up" : "chevron.down") - .foregroundColor(Theme.Colors.textSecondary) - .font(.system(size: 14, weight: .medium)) - } + .popover(isPresented: $showInfoPopover, attachmentAnchor: .point(.bottom), arrowEdge: .top) { + Text("Credits can be used for material indexing (1 credit per photo or per second of video) and for buying blind boxes (100 crediteach)") + .font(Typography.font(for: .caption, family: .quicksandRegular)) + .multilineTextAlignment(.center) + .presentationBackground(Theme.Gradients.backgroundGradient) + .frame(minWidth: 240, maxWidth: UIScreen.main.bounds.width * 0.6) + .presentationCompactAdaptation(.popover) + .padding(.horizontal, Theme.Spacing.md) + .padding(.vertical, Theme.Spacing.sm) } - - // 详情按钮 - Button(action: { - onDetailTap?() - }) { - Image(systemName: "chevron.right") - .foregroundColor(Theme.Colors.textSecondary) - .font(.system(size: 14, weight: .medium)) - } - } - } - .padding(Theme.Spacing.lg) - } - - // MARK: - 积分明细展开区域 - private var creditsBreakdownSection: some View { - VStack(spacing: 0) { - Divider() - .background(Theme.Colors.border) - - VStack(spacing: Theme.Spacing.sm) { - ForEach(Array(creditBreakdown.enumerated()), id: \.offset) { index, credit in - CreditBreakdownRow(credit: credit, isLast: index == creditBreakdown.count - 1) - } - } - .padding(Theme.Spacing.lg) - } - } -} -// MARK: - 积分明细行组件 -struct CreditBreakdownRow: View { - let credit: CreditInfo - let isLast: Bool - - var body: some View { - HStack(spacing: Theme.Spacing.md) { - // 积分类型图标 - Circle() - .fill(credit.type.color.opacity(0.1)) - .frame(width: 32, height: 32) - .overlay( - Image(systemName: credit.type.icon) - .foregroundColor(credit.type.color) - .font(.system(size: 14, weight: .medium)) - ) - - // 积分信息 - VStack(alignment: .leading, spacing: 2) { - Text(credit.type.displayName) - .font(Typography.font(for: .subtitle, family: .quicksand)) - .foregroundColor(Theme.Colors.textPrimary) - - Text(credit.description) - .font(Typography.font(for: .caption, family: .quicksand)) - .foregroundColor(Theme.Colors.textSecondary) - .lineLimit(2) - } - - Spacer() - - // 积分数量 - Text("+\(credit.amount)") - .font(Typography.font(for: .body, family: .quicksandBold)) - .foregroundColor(credit.type.color) - } - .padding(.vertical, Theme.Spacing.xs) - - if !isLast { - Divider() - .background(Theme.Colors.borderLight) - .padding(.leading, 44) - } - } -} - -// MARK: - 积分使用统计组件 -struct CreditsUsageCard: View { - let todayUsed: Int - let weeklyUsed: Int - let monthlyUsed: Int - - var body: some View { - VStack(spacing: Theme.Spacing.md) { - HStack { - Text("Credits Usage") - .font(Typography.font(for: .subtitle, family: .quicksandBold)) - .foregroundColor(Theme.Colors.textPrimary) - Spacer() - Text("This Period") - .font(Typography.font(for: .caption, family: .quicksand)) - .foregroundColor(Theme.Colors.textSecondary) - } - - HStack(spacing: Theme.Spacing.lg) { - UsageStatItem(title: "Today", value: todayUsed, color: Theme.Colors.info) - - Divider() - .frame(height: 40) - - UsageStatItem(title: "Week", value: weeklyUsed, color: Theme.Colors.warning) - - Divider() - .frame(height: 40) - - UsageStatItem(title: "Month", value: monthlyUsed, color: Theme.Colors.success) + // 详情按钮 + Image(systemName: "chevron.right") + .foregroundColor(Theme.Colors.textPrimary) + .font(.system(size: 14, weight: .medium)) } } .padding(Theme.Spacing.lg) - .background(Color(.systemBackground)) - .cornerRadius(Theme.CornerRadius.medium) - .shadow(color: Theme.Shadows.small, radius: Theme.Shadows.cardShadow.radius, x: Theme.Shadows.cardShadow.x, y: Theme.Shadows.cardShadow.y) } + + } -// MARK: - 使用统计项组件 -struct UsageStatItem: View { - let title: String - let value: Int - let color: Color - - var body: some View { - VStack(spacing: Theme.Spacing.xs) { - Text("\(value)") - .font(Typography.font(for: .title, family: .quicksandBold)) - .foregroundColor(color) - - Text(title) - .font(Typography.font(for: .caption, family: .quicksand)) - .foregroundColor(Theme.Colors.textSecondary) - } - .frame(maxWidth: .infinity) - } -} // MARK: - 预览 #Preview("Credits Info Card") { VStack(spacing: 20) { CreditsInfoCard( totalCredits: 3290, - creditBreakdown: [ - CreditInfo(type: .daily, amount: 200, description: "Daily free credits"), - CreditInfo(type: .purchased, amount: 1000, description: "Purchased package"), - CreditInfo(type: .bonus, amount: 500, description: "Welcome bonus"), - CreditInfo(type: .permanent, amount: 1590, description: "Subscription credits") - ], onInfoTap: { print("Info tapped") }, @@ -302,12 +101,6 @@ struct UsageStatItem: View { print("Detail tapped") } ) - - CreditsUsageCard( - todayUsed: 45, - weeklyUsed: 280, - monthlyUsed: 1150 - ) } .padding() .background(Color(.systemGroupedBackground)) diff --git a/wake/View/Subscribe/Components/PlanCompare.swift b/wake/View/Subscribe/Components/PlanCompare.swift new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/wake/View/Subscribe/Components/PlanCompare.swift @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wake/View/Subscribe/Components/PlanSelector.swift b/wake/View/Subscribe/Components/PlanSelector.swift index e69de29..d37fe54 100644 --- a/wake/View/Subscribe/Components/PlanSelector.swift +++ b/wake/View/Subscribe/Components/PlanSelector.swift @@ -0,0 +1,135 @@ +// +// PlanSelector.swift +// wake +// +// Created by fairclip on 2025/8/19. +// + +import SwiftUI + +// MARK: - 计划选择器组件 +struct PlanSelector: View { + @Binding var selectedPlan: SubscriptionPlan? + let onPlanSelected: (SubscriptionPlan) -> Void + + private let plans: [SubscriptionPlan] = [.free, .pioneer] + + init( + selectedPlan: Binding, + onPlanSelected: @escaping (SubscriptionPlan) -> Void = { _ in } + ) { + self._selectedPlan = selectedPlan + self.onPlanSelected = onPlanSelected + } + + var body: some View { + HStack(spacing: Theme.Spacing.md) { + ForEach(plans, id: \.self) { plan in + PlanCard( + plan: plan, + isSelected: selectedPlan == plan, + onTap: { + selectedPlan = plan + onPlanSelected(plan) + } + ) + } + } + } +} + +// MARK: - 单个计划卡片 +struct PlanCard: View { + let plan: SubscriptionPlan + let isSelected: Bool + let onTap: () -> Void + + var body: some View { + Button(action: onTap) { + ZStack { + // 主卡片内容 + VStack(spacing: Theme.Spacing.sm) { + // Popular 标签 + if plan.isPopular { + VStack { + HStack { + Spacer() + Text("Popular") + .font(Typography.font(for: .caption, family: .quicksandRegular)) + .foregroundColor(Color.white) + .padding(.horizontal, Theme.Spacing.sm) + .padding(.vertical, Theme.Spacing.xs) + .background(Color.black) + .cornerRadius(Theme.CornerRadius.round, corners: [.bottomLeft]) + } + Spacer() + + VStack { + // 计划名称 + Text(plan.displayName) + .font(Typography.font(for: .title, family: .quicksandBold, size: 18)) + .foregroundColor(plan == .pioneer ? Theme.Colors.textPrimary: Theme.Colors.textTertiary ) + + // 价格 + if plan == .pioneer { + Text(plan.price) + .font(Typography.font(for: .body, family: .quicksandBold, size: 20)) + .foregroundColor(Theme.Colors.textPrimary) + } + } + Spacer() + Spacer() + } + } + else { + // 计划名称 + Text(plan.displayName) + .font(Typography.font(for: .title, family: .quicksandBold, size: 18)) + .foregroundColor(plan == .pioneer ? Theme.Colors.textPrimary: Theme.Colors.textTertiary ) + + // 价格 + if plan == .pioneer { + Text(plan.price) + .font(Typography.font(for: .body, family: .quicksandBold, size: 20)) + .foregroundColor(Theme.Colors.textPrimary) + } + } + } + .frame(maxWidth: .infinity) + .frame(height: 120) + .background( + plan == .pioneer ? + Theme.Colors.primary : + Theme.Colors.surface + ) + .overlay( + RoundedRectangle(cornerRadius: Theme.CornerRadius.medium) + .stroke( + isSelected ? Theme.Colors.borderDark : Theme.Colors.border, + lineWidth: 2 + ) + ) + .cornerRadius(Theme.CornerRadius.medium) + } + } + .buttonStyle(PlainButtonStyle()) + } +} + + +// MARK: - 预览 +#Preview("Plan Selector") { + @State var selectedPlan: SubscriptionPlan? = .pioneer + + VStack(spacing: 20) { + PlanSelector( + selectedPlan: $selectedPlan, + onPlanSelected: { plan in + print("Selected plan: \(plan.displayName)") + } + ) + + } + .padding() + .background(Color(.systemGroupedBackground)) +} diff --git a/wake/View/Subscribe/Components/SubscriptionStatusBar.swift b/wake/View/Subscribe/Components/SubscriptionStatusBar.swift index 1a92267..48231b7 100644 --- a/wake/View/Subscribe/Components/SubscriptionStatusBar.swift +++ b/wake/View/Subscribe/Components/SubscriptionStatusBar.swift @@ -61,21 +61,21 @@ struct SubscriptionStatusBar: View { var body: some View { HStack(spacing: 16) { - VStack(alignment: .leading, spacing: 8) { + VStack(alignment: .leading, spacing: 20) { // 订阅类型标题 Text(status.title) - .font(.system(size: 28, weight: .bold, design: .rounded)) + .font(Typography.font(for: .headline, family: .quicksandBold, size: 32)) .foregroundColor(status.textColor) // 过期时间或订阅按钮 if case .pioneer(let expiryDate) = status { VStack(alignment: .leading, spacing: 4) { Text("Expires on :") - .font(.system(size: 14, weight: .medium)) - .foregroundColor(status.textColor.opacity(0.8)) + .font(Typography.font(for: .body, family: .quicksandRegular)) + .foregroundColor(status.textColor.opacity(0.7)) Text(formatDate(expiryDate)) - .font(.system(size: 16, weight: .semibold)) + .font(Typography.font(for: .body, family: .quicksandRegular)) .foregroundColor(status.textColor) } } else { @@ -83,12 +83,12 @@ struct SubscriptionStatusBar: View { onSubscribeTap?() }) { Text("Subscribe") - .font(.system(size: 14, weight: .semibold)) + .font(Typography.font(for: .title, family: .quicksandRegular, size: 16)) .foregroundColor(Theme.Colors.textPrimary) - .padding(.horizontal, 20) - .padding(.vertical, 8) - .background(Theme.Colors.subscribeButton) - .cornerRadius(Theme.CornerRadius.large) + .padding(.horizontal, 12) + .padding(.vertical, 6) + .background(Theme.Gradients.backgroundGradient) + .cornerRadius(Theme.CornerRadius.extraLarge) } } } diff --git a/wake/View/Subscribe/SubscribeView.swift b/wake/View/Subscribe/SubscribeView.swift index ab3eb10..3b5be88 100644 --- a/wake/View/Subscribe/SubscribeView.swift +++ b/wake/View/Subscribe/SubscribeView.swift @@ -38,7 +38,7 @@ struct SubscriptionFeature { } struct SubscribeView: View { - @State private var selectedPlan: SubscriptionPlan = .free + @State private var selectedPlan: SubscriptionPlan? = .pioneer @State private var isLoading = false @Environment(\.presentationMode) var presentationMode @@ -62,11 +62,18 @@ struct SubscribeView: View { // 积分信息 creditsSection - // 订阅计划选择 - subscriptionPlansSection - - // 特别优惠提示 - specialOfferBanner + VStack { + // 订阅计划选择 + subscriptionPlansSection + + // 特别优惠提示 + specialOfferBanner + } + .background(Theme.Colors.cardBackground) + .cornerRadius(Theme.CornerRadius.medium) + .padding(.horizontal, Theme.Spacing.xl) + .padding(.vertical, Theme.Spacing.xl) + // 功能对比表 featureComparisonTable @@ -80,7 +87,7 @@ struct SubscribeView: View { Spacer(minLength: 100) } } - .background(Color(.systemGroupedBackground)) + .background(Theme.Colors.background) .navigationBarHidden(true) } } @@ -94,103 +101,73 @@ struct SubscribeView: View { // MARK: - 当前订阅状态卡片 private var currentSubscriptionCard: some View { - VStack(spacing: 0) { - HStack { - VStack(alignment: .leading, spacing: 8) { - Text("Free") - .font(Typography.font(for: .headline, family: .quicksand)) - .fontWeight(.bold) - - Button(action: { - // 订阅操作 - }) { - Text("Subscribe") - .font(Typography.font(for: .subtitle, family: .quicksand)) - .fontWeight(.medium) - .foregroundColor(.black) - .padding(.horizontal, 16) - .padding(.vertical, 8) - .background(Color.orange) - .cornerRadius(20) - } - } - - Spacer() - - // 播放按钮图标 - Circle() - .fill(Color.black) - .frame(width: 60, height: 60) - .overlay( - Image(systemName: "play.fill") - .foregroundColor(.white) - .font(.title2) - ) + SubscriptionStatusBar( + status: .pioneer(expiryDate: Date()) , + onSubscribeTap: { + // 订阅操作 + handleSubscribe() } - .padding(20) - .background(Color.orange.opacity(0.2)) - .cornerRadius(16) - .padding(.horizontal, 20) - } + ) + .padding(.horizontal, Theme.Spacing.xl) } // MARK: - 积分信息 private var creditsSection: some View { - HStack { - Text("Credits: 3290") - .font(Typography.font(for: .body, family: .quicksand)) - .fontWeight(.medium) + VStack(spacing: 16) { + CreditsInfoCard( + totalCredits: 3290, + onInfoTap: { + // 显示积分信息说明 + }, + onDetailTap: { + // 跳转到积分详情页面 + } + ) - Button(action: { - // 积分信息操作 - }) { - Image(systemName: "info.circle") - .foregroundColor(.gray) - } - - Spacer() - - Image(systemName: "chevron.right") - .foregroundColor(.gray) - .font(.caption) } - .padding(.horizontal, 20) - .padding(.vertical, 16) - .background(Color(.systemBackground)) - .cornerRadius(12) - .padding(.horizontal, 20) - .padding(.top, 20) + .padding(.horizontal, Theme.Spacing.xl) + .padding(.top, Theme.Spacing.xl) } // MARK: - 订阅计划选择 private var subscriptionPlansSection: some View { - HStack(spacing: 16) { - // Free 计划 - SubscriptionPlanCard( - plan: .free, - isSelected: selectedPlan == .free, - onTap: { selectedPlan = .free } - ) - - // Pioneer 计划 - SubscriptionPlanCard( - plan: .pioneer, - isSelected: selectedPlan == .pioneer, - onTap: { selectedPlan = .pioneer } - ) - } - .padding(.horizontal, 20) - .padding(.top, 20) + PlanSelector( + selectedPlan: $selectedPlan, + onPlanSelected: { plan in + print("Selected plan: \(plan.displayName)") + } + ) + .padding(.horizontal, Theme.Spacing.xl) + .padding(.top, Theme.Spacing.xl) } // MARK: - 特别优惠横幅 private var specialOfferBanner: some View { - Text("First 100 users get a special deal: just $1 for your first month!") - .font(Typography.font(for: .caption, family: .quicksand)) - .multilineTextAlignment(.center) - .padding(.horizontal, 20) - .padding(.top, 12) - .foregroundColor(.secondary) + HStack(spacing: 0) { + Text("First") + .font(Typography.font(for: .footnote, family: .quicksandRegular)) + .foregroundColor(Theme.Colors.textPrimary) + + Text(" 100") + .font(Typography.font(for: .footnote, family: .quicksandBold)) + .foregroundColor(Theme.Colors.textPrimary) + + Text(" users get a special deal: justs") + .font(Typography.font(for: .footnote, family: .quicksandRegular)) + .foregroundColor(Theme.Colors.textPrimary) + + Text(" $1") + .font(Typography.font(for: .footnote, family: .quicksandBold)) + .foregroundColor(Theme.Colors.textPrimary) + + Text(" for your first month!") + .font(Typography.font(for: .footnote, family: .quicksandRegular)) + .foregroundColor(Theme.Colors.textPrimary) + } + .multilineTextAlignment(.center) + .padding(.horizontal, Theme.Spacing.lg) + .padding(.top, Theme.Spacing.sm) + .padding(.bottom, Theme.Spacing.lg) } // MARK: - 功能对比表