SelfieCam/SelfieCam/Features/Onboarding/Views/OnboardingSoftPaywallView.swift

160 lines
5.8 KiB
Swift

//
// OnboardingSoftPaywallView.swift
// SelfieCam
//
// Soft paywall shown to free users during onboarding.
// Presents premium benefits with options to upgrade or continue with free version.
// Supports landscape and iPad layouts with max width constraints.
//
import SwiftUI
import Bedrock
struct OnboardingSoftPaywallView: View {
@Bindable var viewModel: OnboardingViewModel
@Bindable var settingsViewModel: SettingsViewModel
@Binding var showPaywall: Bool
let onComplete: () -> Void
/// Premium manager for restore purchases
@State private var premiumManager = PremiumManager()
/// Whether a restore is in progress
@State private var isRestoring = false
var body: some View {
OnboardingContentContainer {
VStack(spacing: Design.Spacing.large) {
Spacer()
// Header
VStack(spacing: Design.Spacing.medium) {
SymbolIcon("crown.fill", size: .hero, color: AppStatus.warning)
OnboardingSectionTitle(
title: String(localized: "Unlock Pro Features"),
subtitle: String(localized: "Get the most out of SelfieCam")
)
}
Spacer()
// Benefits list
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
OnboardingBenefitRow(
image: "paintpalette.fill",
text: String(localized: "Premium Colors + Custom Color Picker")
)
OnboardingBenefitRow(
image: "sparkles",
text: String(localized: "Skin Smoothing Beauty Filter")
)
OnboardingBenefitRow(
image: "arrow.left.and.right.righttriangle.left.righttriangle.right.fill",
text: String(localized: "True Mirror Mode")
)
OnboardingBenefitRow(
image: "camera.filters",
text: String(localized: "HDR Mode for Better Photos")
)
OnboardingBenefitRow(
image: "timer",
text: String(localized: "Extended Self-Timers (5s, 10s)")
)
OnboardingBenefitRow(
image: "star.fill",
text: String(localized: "High Quality Photo Export")
)
}
.padding(.horizontal, Design.Spacing.large)
Spacer()
// Action buttons
VStack(spacing: Design.Spacing.medium) {
// Upgrade button
OnboardingPrimaryButton(
title: String(localized: "Upgrade to Pro"),
action: { showPaywall = true },
icon: "crown.fill",
style: .premium
)
// Maybe Later button
OnboardingSecondaryButton(
title: String(localized: "Maybe Later"),
action: {
viewModel.completeOnboarding(settingsViewModel: settingsViewModel)
onComplete()
}
)
// Restore Purchases button
Button {
Task {
isRestoring = true
try? await premiumManager.restorePurchases()
isRestoring = false
// Check if premium was restored
if premiumManager.isPremiumUnlocked {
viewModel.completeOnboarding(settingsViewModel: settingsViewModel)
onComplete()
}
}
} label: {
if isRestoring {
ProgressView()
.tint(.secondary)
} else {
Text(String(localized: "Restore Purchases"))
}
}
.font(.footnote)
.foregroundStyle(.secondary)
.disabled(isRestoring)
}
.padding(.horizontal, Design.Spacing.xLarge)
.padding(.bottom, Design.Spacing.xLarge)
}
.padding(.horizontal, Design.Spacing.medium)
}
.onChange(of: viewModel.isPremiumUser) { _, isPremium in
// If user subscribed during paywall, complete onboarding
if isPremium {
viewModel.completeOnboarding(settingsViewModel: settingsViewModel)
onComplete()
}
}
}
}
// MARK: - Preview
#Preview {
OnboardingSoftPaywallView(
viewModel: OnboardingViewModel(),
settingsViewModel: SettingsViewModel(),
showPaywall: .constant(false),
onComplete: {}
)
.background(AppSurface.primary)
.preferredColorScheme(.dark)
}
#Preview("Landscape", traits: .landscapeLeft) {
OnboardingSoftPaywallView(
viewModel: OnboardingViewModel(),
settingsViewModel: SettingsViewModel(),
showPaywall: .constant(false),
onComplete: {}
)
.background(AppSurface.primary)
.preferredColorScheme(.dark)
}