|
@@ -512,6 +512,9 @@ class ViewController: NSViewController {
|
|
|
|
|
|
|
|
private let storeKitCoordinator = StoreKitCoordinator()
|
|
private let storeKitCoordinator = StoreKitCoordinator()
|
|
|
private var storeKitStartupTask: Task<Void, Never>?
|
|
private var storeKitStartupTask: Task<Void, Never>?
|
|
|
|
|
+ private var launchPaywallWorkItem: DispatchWorkItem?
|
|
|
|
|
+ private let launchPaywallDelay: TimeInterval = 2
|
|
|
|
|
+ private var hasPresentedLaunchPaywall = false
|
|
|
|
|
|
|
|
override func viewDidLoad() {
|
|
override func viewDidLoad() {
|
|
|
super.viewDidLoad()
|
|
super.viewDidLoad()
|
|
@@ -541,6 +544,7 @@ class ViewController: NSViewController {
|
|
|
alignNativeTrafficLights()
|
|
alignNativeTrafficLights()
|
|
|
showHomeView(profile: nil)
|
|
showHomeView(profile: nil)
|
|
|
syncBrandPositionForCurrentWindowState(animated: false)
|
|
syncBrandPositionForCurrentWindowState(animated: false)
|
|
|
|
|
+ scheduleLaunchPaywallIfNeeded()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
override func viewDidLayout() {
|
|
override func viewDidLayout() {
|
|
@@ -3386,16 +3390,47 @@ class ViewController: NSViewController {
|
|
|
self.premiumRatingPromptWorkItem = nil
|
|
self.premiumRatingPromptWorkItem = nil
|
|
|
self.showPaywall()
|
|
self.showPaywall()
|
|
|
}
|
|
}
|
|
|
|
|
+ if newIsPremium {
|
|
|
|
|
+ self.launchPaywallWorkItem?.cancel()
|
|
|
|
|
+ self.launchPaywallWorkItem = nil
|
|
|
|
|
+ self.hasPresentedLaunchPaywall = true
|
|
|
|
|
+ } else {
|
|
|
|
|
+ self.scheduleLaunchPaywallIfNeeded()
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
storeKitStartupTask = Task { [weak self] in
|
|
storeKitStartupTask = Task { [weak self] in
|
|
|
await self?.storeKitCoordinator.start()
|
|
await self?.storeKitCoordinator.start()
|
|
|
await MainActor.run {
|
|
await MainActor.run {
|
|
|
self?.updatePremiumButtons()
|
|
self?.updatePremiumButtons()
|
|
|
|
|
+ self?.scheduleLaunchPaywallIfNeeded()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private func scheduleLaunchPaywallIfNeeded() {
|
|
|
|
|
+ guard hasPresentedLaunchPaywall == false else { return }
|
|
|
|
|
+ guard storeKitCoordinator.hasPremiumAccess == false else {
|
|
|
|
|
+ hasPresentedLaunchPaywall = true
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ guard launchPaywallWorkItem == nil else { return }
|
|
|
|
|
+
|
|
|
|
|
+ let workItem = DispatchWorkItem { [weak self] in
|
|
|
|
|
+ guard let self else { return }
|
|
|
|
|
+ self.launchPaywallWorkItem = nil
|
|
|
|
|
+ guard self.hasPresentedLaunchPaywall == false else { return }
|
|
|
|
|
+ guard self.storeKitCoordinator.hasPremiumAccess == false else {
|
|
|
|
|
+ self.hasPresentedLaunchPaywall = true
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ self.hasPresentedLaunchPaywall = true
|
|
|
|
|
+ self.showPaywall()
|
|
|
|
|
+ }
|
|
|
|
|
+ launchPaywallWorkItem = workItem
|
|
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + launchPaywallDelay, execute: workItem)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@MainActor
|
|
@MainActor
|
|
|
private func updatePremiumButtons() {
|
|
private func updatePremiumButtons() {
|
|
|
let isPremium = storeKitCoordinator.hasPremiumAccess
|
|
let isPremium = storeKitCoordinator.hasPremiumAccess
|
|
@@ -3497,6 +3532,9 @@ class ViewController: NSViewController {
|
|
|
// MARK: - Paywall (ported from meetings_app)
|
|
// MARK: - Paywall (ported from meetings_app)
|
|
|
|
|
|
|
|
private func showPaywall() {
|
|
private func showPaywall() {
|
|
|
|
|
+ if storeKitCoordinator.hasPremiumAccess && storeKitCoordinator.hasLifetimePremiumAccess == false {
|
|
|
|
|
+ selectedPremiumPlan = .lifetime
|
|
|
|
|
+ }
|
|
|
if let existing = paywallOverlayView {
|
|
if let existing = paywallOverlayView {
|
|
|
refreshPaywallStoreUI()
|
|
refreshPaywallStoreUI()
|
|
|
if let superview = existing.superview {
|
|
if let superview = existing.superview {
|
|
@@ -4495,6 +4533,8 @@ class ViewController: NSViewController {
|
|
|
paywallPurchaseTask?.cancel()
|
|
paywallPurchaseTask?.cancel()
|
|
|
updatePaywallContinueState(isLoading: true)
|
|
updatePaywallContinueState(isLoading: true)
|
|
|
let selectedPlan = selectedPremiumPlan
|
|
let selectedPlan = selectedPremiumPlan
|
|
|
|
|
+ let hadPremiumBeforePurchase = storeKitCoordinator.hasPremiumAccess
|
|
|
|
|
+ let hadLifetimeBeforePurchase = storeKitCoordinator.hasLifetimePremiumAccess
|
|
|
paywallPurchaseTask = Task { [weak self] in
|
|
paywallPurchaseTask = Task { [weak self] in
|
|
|
guard let self else { return }
|
|
guard let self else { return }
|
|
|
if self.storeKitCoordinator.productsByID[selectedPlan.rawValue] == nil {
|
|
if self.storeKitCoordinator.productsByID[selectedPlan.rawValue] == nil {
|
|
@@ -4513,7 +4553,14 @@ class ViewController: NSViewController {
|
|
|
UserDefaults.standard.set(false, forKey: self.ratingPromptShownKey)
|
|
UserDefaults.standard.set(false, forKey: self.ratingPromptShownKey)
|
|
|
self.schedulePremiumRatingPromptIfNeeded()
|
|
self.schedulePremiumRatingPromptIfNeeded()
|
|
|
}
|
|
}
|
|
|
- self.showSimpleAlert(title: "Purchase Complete", message: "Premium has been unlocked successfully.")
|
|
|
|
|
|
|
+ if selectedPlan == .lifetime, hadLifetimeBeforePurchase == false, hadPremiumBeforePurchase {
|
|
|
|
|
+ self.showSimpleAlert(
|
|
|
|
|
+ title: "Lifetime Activated",
|
|
|
|
|
+ message: "Lifetime premium is now active. If you previously subscribed (weekly/monthly/yearly), please cancel that subscription in your Apple ID subscriptions to avoid future renewals."
|
|
|
|
|
+ )
|
|
|
|
|
+ } else {
|
|
|
|
|
+ self.showSimpleAlert(title: "Purchase Complete", message: "Premium has been unlocked successfully.")
|
|
|
|
|
+ }
|
|
|
self.hidePaywall()
|
|
self.hidePaywall()
|
|
|
if self.storeKitCoordinator.hasPremiumAccess {
|
|
if self.storeKitCoordinator.hasPremiumAccess {
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) { [weak self] in
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) { [weak self] in
|