SelfieCam/SelfieCam/Features/Paywall/Views/ProPaywallView.swift

141 lines
5.6 KiB
Swift

import SwiftUI
import RevenueCat
import Bedrock
struct ProPaywallView: View {
@State private var manager = PremiumManager()
@Environment(\.dismiss) private var dismiss
@ScaledMetric(relativeTo: .body) private var bodyFontSize: CGFloat = Design.FontSize.body
var body: some View {
NavigationStack {
ScrollView {
VStack(spacing: Design.Spacing.xLarge) {
// Crown icon
Image(systemName: "crown.fill")
.font(.system(size: Design.FontSize.hero))
.foregroundStyle(.yellow)
Text(String(localized: "Go Pro"))
.font(.system(size: Design.FontSize.title, weight: .bold))
// Benefits list
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
BenefitRow(image: "paintpalette.fill", text: String(localized: "Premium Colors + Custom Color Picker"))
BenefitRow(image: "sparkles", text: String(localized: "Skin Smoothing Beauty Filter"))
BenefitRow(image: "arrow.left.and.right.righttriangle.left.righttriangle.right.fill", text: String(localized: "True Mirror Mode"))
BenefitRow(image: "bolt.fill", text: String(localized: "Flash Sync with Ring Light"))
BenefitRow(image: "camera.filters", text: String(localized: "HDR Mode for Better Photos"))
BenefitRow(image: "person.crop.rectangle.fill", text: String(localized: "Center Stage Auto-Framing"))
BenefitRow(image: "timer", text: String(localized: "Extended Self-Timers (5s, 10s)"))
BenefitRow(image: "star.fill", text: String(localized: "High Quality Photo Export"))
}
.frame(maxWidth: .infinity, alignment: .leading)
// Product packages
if manager.availablePackages.isEmpty {
ProgressView()
.padding()
} else {
ForEach(manager.availablePackages, id: \.identifier) { package in
ProductPackageButton(
package: package,
isPremiumUnlocked: manager.isPremiumUnlocked,
onPurchase: {
Task {
_ = try? await manager.purchase(package)
if manager.isPremiumUnlocked {
dismiss()
}
}
}
)
}
}
// Restore purchases
Button(String(localized: "Restore Purchases")) {
Task { try? await manager.restorePurchases() }
}
.font(.footnote)
.foregroundStyle(.secondary)
}
.padding(Design.Spacing.large)
}
.background(AppSurface.overlay)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button(String(localized: "Cancel")) { dismiss() }
.foregroundStyle(.white)
}
}
}
.font(.system(size: bodyFontSize))
.task { try? await manager.loadProducts() }
}
}
// MARK: - Product Package Button
private struct ProductPackageButton: View {
let package: Package
let isPremiumUnlocked: Bool
let onPurchase: () -> Void
var body: some View {
Button(action: onPurchase) {
VStack(spacing: Design.Spacing.small) {
Text(package.storeProduct.localizedTitle)
.font(.headline)
.foregroundStyle(.white)
Text(package.localizedPriceString)
.font(.title2.bold())
.foregroundStyle(.white)
if package.packageType == .annual {
Text(String(localized: "Best Value • Save 33%"))
.font(.caption)
.foregroundStyle(.white.opacity(Design.Opacity.accent))
}
}
.frame(maxWidth: .infinity)
.padding(Design.Spacing.large)
.background(AppAccent.primary.opacity(Design.Opacity.medium))
.clipShape(.rect(cornerRadius: Design.CornerRadius.large))
.overlay(
RoundedRectangle(cornerRadius: Design.CornerRadius.large)
.strokeBorder(AppAccent.primary, lineWidth: Design.LineWidth.thin)
)
}
.accessibilityLabel(String(localized: "Subscribe to \(package.storeProduct.localizedTitle) for \(package.localizedPriceString)"))
}
}
// MARK: - Benefit Row
struct BenefitRow: View {
let image: String
let text: String
var body: some View {
HStack(spacing: Design.Spacing.medium) {
Image(systemName: image)
.font(.title2)
.foregroundStyle(AppAccent.primary)
.frame(width: Design.IconSize.xLarge)
Text(text)
.foregroundStyle(.white)
Spacer()
}
}
}
#Preview {
ProPaywallView()
.preferredColorScheme(.dark)
}