Selaa lähdekoodia

Tune launch experience for non-premium users by delaying the initial paywall and nudging the main window slightly left on startup.

This makes the first app open feel more balanced while still surfacing upgrade access shortly after launch.

Made-with: Cursor
huzaifahayat12 1 viikko sitten
vanhempi
commit
a9601e3919
1 muutettua tiedostoa jossa 20 lisäystä ja 1 poistoa
  1. 20 1
      meetings_app/ViewController.swift

+ 20 - 1
meetings_app/ViewController.swift

@@ -248,6 +248,7 @@ final class ViewController: NSViewController {
248
     private weak var centeredTitleLabel: NSTextField?
248
     private weak var centeredTitleLabel: NSTextField?
249
     private var paywallWindow: NSWindow?
249
     private var paywallWindow: NSWindow?
250
     private let paywallContentWidth: CGFloat = 520
250
     private let paywallContentWidth: CGFloat = 520
251
+    private let launchWindowLeftOffset: CGFloat = 80
251
     private var selectedPremiumPlan: PremiumPlan = .monthly
252
     private var selectedPremiumPlan: PremiumPlan = .monthly
252
     private var paywallPlanViews: [PremiumPlan: NSView] = [:]
253
     private var paywallPlanViews: [PremiumPlan: NSView] = [:]
253
     private var premiumPlanByView = [ObjectIdentifier: PremiumPlan]()
254
     private var premiumPlanByView = [ObjectIdentifier: PremiumPlan]()
@@ -275,8 +276,10 @@ final class ViewController: NSViewController {
275
     private var paywallSubtitleLabels: [PremiumPlan: NSTextField] = [:]
276
     private var paywallSubtitleLabels: [PremiumPlan: NSTextField] = [:]
276
     private var paywallContinueEnabled = true
277
     private var paywallContinueEnabled = true
277
     private var paywallUpgradeFlowEnabled = false
278
     private var paywallUpgradeFlowEnabled = false
279
+    private let launchPaywallDelay: TimeInterval = 3
278
     private var hasCompletedInitialStoreKitSync = false
280
     private var hasCompletedInitialStoreKitSync = false
279
     private var hasPresentedLaunchPaywall = false
281
     private var hasPresentedLaunchPaywall = false
282
+    private var launchPaywallWorkItem: DispatchWorkItem?
280
     private var hasViewAppearedOnce = false
283
     private var hasViewAppearedOnce = false
281
     private var lastKnownPremiumAccess = false
284
     private var lastKnownPremiumAccess = false
282
     private var displayedScheduleMeetings: [ScheduledMeeting] = []
285
     private var displayedScheduleMeetings: [ScheduledMeeting] = []
@@ -376,6 +379,13 @@ final class ViewController: NSViewController {
376
             newFrame.size = frameSize
379
             newFrame.size = frameSize
377
             window.setFrame(newFrame, display: true)
380
             window.setFrame(newFrame, display: true)
378
             window.center()
381
             window.center()
382
+            if let screen = window.screen ?? NSScreen.main {
383
+                var adjustedFrame = window.frame
384
+                adjustedFrame.origin.x -= self.launchWindowLeftOffset
385
+                let minX = screen.visibleFrame.minX
386
+                adjustedFrame.origin.x = max(minX, adjustedFrame.origin.x)
387
+                window.setFrame(adjustedFrame, display: true)
388
+            }
379
 
389
 
380
             window.minSize = window.frameRect(forContentRect: NSRect(origin: .zero, size: self.launchMinContentSize)).size
390
             window.minSize = window.frameRect(forContentRect: NSRect(origin: .zero, size: self.launchMinContentSize)).size
381
             self.installCenteredTitleIfNeeded(on: window)
391
             self.installCenteredTitleIfNeeded(on: window)
@@ -389,6 +399,7 @@ final class ViewController: NSViewController {
389
     deinit {
399
     deinit {
390
         storeKitStartupTask?.cancel()
400
         storeKitStartupTask?.cancel()
391
         paywallPurchaseTask?.cancel()
401
         paywallPurchaseTask?.cancel()
402
+        launchPaywallWorkItem?.cancel()
392
     }
403
     }
393
 }
404
 }
394
 
405
 
@@ -1058,7 +1069,15 @@ private extension ViewController {
1058
         guard hasCompletedInitialStoreKitSync, hasViewAppearedOnce, !hasPresentedLaunchPaywall else { return }
1069
         guard hasCompletedInitialStoreKitSync, hasViewAppearedOnce, !hasPresentedLaunchPaywall else { return }
1059
         hasPresentedLaunchPaywall = true
1070
         hasPresentedLaunchPaywall = true
1060
         if !storeKitCoordinator.hasPremiumAccess {
1071
         if !storeKitCoordinator.hasPremiumAccess {
1061
-            showPaywall()
1072
+            launchPaywallWorkItem?.cancel()
1073
+            let workItem = DispatchWorkItem { [weak self] in
1074
+                guard let self else { return }
1075
+                self.launchPaywallWorkItem = nil
1076
+                guard !self.storeKitCoordinator.hasPremiumAccess else { return }
1077
+                self.showPaywall()
1078
+            }
1079
+            launchPaywallWorkItem = workItem
1080
+            DispatchQueue.main.asyncAfter(deadline: .now() + launchPaywallDelay, execute: workItem)
1062
         }
1081
         }
1063
     }
1082
     }
1064
 
1083