83 lines
3.2 KiB
Swift
83 lines
3.2 KiB
Swift
// SPDX-FileCopyrightText: 2026 Kaede Akino
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
import RevenueCatUI
|
|
import SwiftUI
|
|
import TermindDomain
|
|
import TermindInfrastructure
|
|
import TermindPresentation
|
|
|
|
struct MobileProView: View {
|
|
@Bindable var pro: ProAccessController
|
|
@Environment(\.dismiss) private var dismiss
|
|
@Environment(\.locale) private var locale
|
|
@State private var ignoresPurchaseDismissal = false
|
|
|
|
var body: some View {
|
|
VStack(spacing: 0) {
|
|
if pro.status == .loading {
|
|
ProgressView(AppStrings.Pro.contactingTheAppStoreProgress.swiftUIKey)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.overlay(alignment: .topLeading) { closeButton }
|
|
} else if pro.usesRevenueCat {
|
|
PaywallView(displayCloseButton: true)
|
|
.customPaywallVariables(paywallVariables)
|
|
.onPurchaseInitiated { [pro] _, resume in
|
|
Task { @MainActor in resume(shouldProceed: !pro.hasProAccess) }
|
|
}
|
|
.onPurchaseCompleted { _ in
|
|
ignoresPurchaseDismissal = true
|
|
Task { await pro.completePaywallOperation() }
|
|
}
|
|
.onRestoreCompleted { _ in Task { await pro.completePaywallOperation() } }
|
|
.onRequestedDismissal {
|
|
// RevenueCat requests dismissal after purchase; keep the account variant visible.
|
|
if ignoresPurchaseDismissal {
|
|
ignoresPurchaseDismissal = false
|
|
} else {
|
|
dismiss()
|
|
}
|
|
}
|
|
} else {
|
|
ContentUnavailableView {
|
|
Label(AppStrings.Pro.termindPro, systemImage: "cart")
|
|
} description: {
|
|
Text(AppStrings.Pro.productUnavailable)
|
|
} actions: {
|
|
Button(AppStrings.Common.close) { dismiss() }
|
|
}
|
|
}
|
|
}
|
|
.mobileSheetPresentation()
|
|
.onChange(of: pro.isPaywallPresented) { if !pro.isPaywallPresented { dismiss() } }
|
|
}
|
|
private var paywallVariables: [String: CustomVariableValue] {
|
|
let account = ProPaywallState(status: pro.status)
|
|
return [
|
|
"pro": .bool(account.hasProAccess),
|
|
"manage": .bool(account.canManageSubscription),
|
|
"state": .string(account.state),
|
|
"family": .bool(account.isFamilyShared),
|
|
"dated": .bool(account.expiresAt != nil),
|
|
"date": .string(
|
|
account.expiresAt?.formatted(
|
|
.dateTime.year().month().day().hour().minute().locale(locale)) ?? ""),
|
|
]
|
|
}
|
|
|
|
private var closeButton: some View {
|
|
Button {
|
|
dismiss()
|
|
} label: {
|
|
Label(AppStrings.Common.close, systemImage: "xmark")
|
|
.labelStyle(.iconOnly)
|
|
.font(.system(size: 20, weight: .medium))
|
|
.frame(width: 44, height: 44)
|
|
.contentShape(.rect)
|
|
}
|
|
.buttonStyle(.plain)
|
|
.padding(16)
|
|
}
|
|
|
|
}
|