// // PurchaseButtonView.swift // Feels // // Subscription status and purchase view for settings. // import SwiftUI import StoreKit struct PurchaseButtonView: View { @AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system @AppStorage(UserDefaultsStore.Keys.textColor.rawValue, store: GroupUserDefaults.groupDefaults) private var textColor: Color = DefaultTextColor.textColor @ObservedObject var iapManager: IAPManager @State private var showSubscriptionStore = false @State private var showManageSubscriptions = false var body: some View { VStack(spacing: 16) { if iapManager.isLoading { loadingView } else if iapManager.isSubscribed { subscribedView } else { notSubscribedView } } .padding() .background(theme.currentTheme.secondaryBGColor) .cornerRadius(10) .sheet(isPresented: $showSubscriptionStore) { FeelsSubscriptionStoreView() } .manageSubscriptionsSheet(isPresented: $showManageSubscriptions) } // MARK: - Loading View private var loadingView: some View { VStack(spacing: 12) { ProgressView() Text(String(localized: "purchase_view_loading")) .font(.body) .foregroundColor(textColor) } .frame(maxWidth: .infinity) .padding() } // MARK: - Subscribed View private var subscribedView: some View { VStack(alignment: .leading, spacing: 12) { Text(String(localized: "purchase_view_current_subscription")) .font(.title3) .bold() .foregroundColor(textColor) if let product = iapManager.currentProduct { HStack { VStack(alignment: .leading, spacing: 4) { Text(product.displayName) .font(.headline) .foregroundColor(textColor) Text(product.displayPrice) .font(.subheadline) .foregroundColor(.secondary) } Spacer() subscriptionStatusBadge } } Divider() // Manage subscription button Button { showManageSubscriptions = true } label: { Text(String(localized: "purchase_view_manage_subscription")) .font(.body) .foregroundColor(.blue) .frame(maxWidth: .infinity) } // Show other subscription options if iapManager.sortedProducts.count > 1 { Button { showSubscriptionStore = true } label: { Text(String(localized: "purchase_view_change_plan")) .font(.body) .foregroundColor(.secondary) .frame(maxWidth: .infinity) } } } } private var subscriptionStatusBadge: some View { Group { if case .subscribed(_, let willAutoRenew) = iapManager.state { if willAutoRenew { Text(String(localized: "subscription_status_active")) .font(.caption) .foregroundColor(.white) .padding(.horizontal, 8) .padding(.vertical, 4) .background(Color.green) .cornerRadius(4) } else { Text(String(localized: "subscription_status_expires")) .font(.caption) .foregroundColor(.white) .padding(.horizontal, 8) .padding(.vertical, 4) .background(Color.orange) .cornerRadius(4) } } } } // MARK: - Not Subscribed View private var notSubscribedView: some View { VStack(spacing: 16) { Text(String(localized: "purchase_view_title")) .font(.title3) .bold() .foregroundColor(textColor) .frame(maxWidth: .infinity, alignment: .leading) // Trial status if iapManager.shouldShowTrialWarning { trialStatusView } else if iapManager.shouldShowPaywall { Text(String(localized: "purchase_view_trial_expired")) .font(.body) .foregroundColor(.secondary) } Text(String(localized: "purchase_view_current_why_subscribe")) .font(.body) .foregroundColor(.secondary) .multilineTextAlignment(.center) // Subscribe button Button { showSubscriptionStore = true } label: { Text(String(localized: "purchase_view_subscribe_button")) .font(.headline) .foregroundColor(.white) .frame(maxWidth: .infinity) .padding() .background(Color.pink) .cornerRadius(10) } // Restore purchases Button { Task { await iapManager.restore() } } label: { Text(String(localized: "purchase_view_restore")) .font(.body) .foregroundColor(.blue) } } } private var trialStatusView: some View { HStack { Image(systemName: "clock") .foregroundColor(.orange) if let expirationDate = iapManager.trialExpirationDate { Text(String(localized: "purchase_view_trial_expires_in")) .foregroundColor(textColor) + Text(" ") + Text(expirationDate, style: .relative) .foregroundColor(.orange) .bold() } } .font(.body) } } #Preview { PurchaseButtonView(iapManager: IAPManager()) }