Quellcode durchsuchen

Fix calendar access guards and subscription button behavior.

Prevent calendar scheduling when Google is not connected, lock Calendar behind a premium overlay that opens paywall on click, refresh Calendar after auth/entitlement updates, and route Manage Subscription directly to subscriptions.

Made-with: Cursor
huzaifahayat12 vor 1 Woche
Ursprung
Commit
6b3d3b587f
1 geänderte Dateien mit 63 neuen und 5 gelöschten Zeilen
  1. 63 5
      meetings_app/ViewController.swift

+ 63 - 5
meetings_app/ViewController.swift

@@ -543,11 +543,7 @@ private extension ViewController {
543 543
 
544 544
     @objc private func premiumButtonClicked(_ sender: NSClickGestureRecognizer) {
545 545
         if storeKitCoordinator.hasPremiumAccess {
546
-            if hasReachedRatingUsageThreshold && !userHasRated {
547
-                requestAppRatingIfEligible(markAsRated: false)
548
-                return
549
-            }
550
-            showPaywall(upgradeFlow: true, preferredPlan: .lifetime)
546
+            openManageSubscriptions()
551 547
         } else {
552 548
             showPaywall()
553 549
         }
@@ -1112,8 +1108,11 @@ private extension ViewController {
1112 1108
         refreshScheduleCardsForPremiumStateChange()
1113 1109
 
1114 1110
         pageCache[.joinMeetings] = nil
1111
+        pageCache[.video] = nil
1115 1112
         if selectedSidebarPage == .joinMeetings {
1116 1113
             showSidebarPage(.joinMeetings)
1114
+        } else if selectedSidebarPage == .video {
1115
+            showSidebarPage(.video)
1117 1116
         }
1118 1117
 
1119 1118
         if !hadPremiumAccess && hasPremiumAccess {
@@ -1976,6 +1975,52 @@ private extension ViewController {
1976 1975
             daySummary.widthAnchor.constraint(equalTo: contentStack.widthAnchor)
1977 1976
         ])
1978 1977
 
1978
+        if !storeKitCoordinator.hasPremiumAccess {
1979
+            let lockOverlay = NSVisualEffectView()
1980
+            lockOverlay.translatesAutoresizingMaskIntoConstraints = false
1981
+            lockOverlay.material = darkModeEnabled ? .hudWindow : .popover
1982
+            lockOverlay.blendingMode = .withinWindow
1983
+            lockOverlay.state = .active
1984
+            lockOverlay.wantsLayer = true
1985
+            lockOverlay.layer?.cornerRadius = 14
1986
+            lockOverlay.layer?.masksToBounds = true
1987
+            lockOverlay.layer?.backgroundColor = NSColor.black.withAlphaComponent(darkModeEnabled ? 0.30 : 0.12).cgColor
1988
+            panel.addSubview(lockOverlay)
1989
+
1990
+            let message = textLabel("Premium required. Get Premium now to unlock Calendar.", font: NSFont.systemFont(ofSize: 14, weight: .semibold), color: darkModeEnabled ? .white : .black)
1991
+            message.alignment = .center
1992
+            message.maximumNumberOfLines = 2
1993
+            message.lineBreakMode = .byWordWrapping
1994
+            lockOverlay.addSubview(message)
1995
+
1996
+            let hit = HoverTrackingView()
1997
+            hit.translatesAutoresizingMaskIntoConstraints = false
1998
+            hit.wantsLayer = true
1999
+            hit.layer?.backgroundColor = NSColor.clear.cgColor
2000
+            hit.onClick = { [weak self] in
2001
+                self?.showPaywall()
2002
+            }
2003
+            hit.toolTip = "Premium required. Click to open paywall."
2004
+            lockOverlay.addSubview(hit)
2005
+
2006
+            NSLayoutConstraint.activate([
2007
+                lockOverlay.leadingAnchor.constraint(equalTo: contentStack.leadingAnchor),
2008
+                lockOverlay.trailingAnchor.constraint(equalTo: contentStack.trailingAnchor),
2009
+                lockOverlay.topAnchor.constraint(equalTo: contentStack.topAnchor),
2010
+                lockOverlay.bottomAnchor.constraint(equalTo: contentStack.bottomAnchor),
2011
+
2012
+                message.centerXAnchor.constraint(equalTo: lockOverlay.centerXAnchor),
2013
+                message.centerYAnchor.constraint(equalTo: lockOverlay.centerYAnchor),
2014
+                message.leadingAnchor.constraint(greaterThanOrEqualTo: lockOverlay.leadingAnchor, constant: 22),
2015
+                message.trailingAnchor.constraint(lessThanOrEqualTo: lockOverlay.trailingAnchor, constant: -22),
2016
+
2017
+                hit.leadingAnchor.constraint(equalTo: lockOverlay.leadingAnchor),
2018
+                hit.trailingAnchor.constraint(equalTo: lockOverlay.trailingAnchor),
2019
+                hit.topAnchor.constraint(equalTo: lockOverlay.topAnchor),
2020
+                hit.bottomAnchor.constraint(equalTo: lockOverlay.bottomAnchor)
2021
+            ])
2022
+        }
2023
+
1979 2024
         let calendar = Calendar.current
1980 2025
         calendarPageMonthAnchor = calendarStartOfMonth(for: Date())
1981 2026
         calendarPageSelectedDate = calendar.startOfDay(for: Date())
@@ -4274,6 +4319,17 @@ private final class SettingsMenuViewController: NSViewController {
4274 4319
 }
4275 4320
 
4276 4321
 private extension ViewController {
4322
+    private func requireGoogleLoginForCalendarScheduling() -> Bool {
4323
+        guard googleOAuth.loadTokens() != nil else {
4324
+            showSimpleAlert(
4325
+                title: "Connect Google",
4326
+                message: "Sign in with Google first to schedule a meeting from Calendar."
4327
+            )
4328
+            return false
4329
+        }
4330
+        return true
4331
+    }
4332
+
4277 4333
     func roundedContainer(cornerRadius: CGFloat, color: NSColor) -> NSView {
4278 4334
         let view = NSView()
4279 4335
         view.wantsLayer = true
@@ -4550,6 +4606,7 @@ private extension ViewController {
4550 4606
     }
4551 4607
 
4552 4608
     @objc func calendarDayCellPressed(_ sender: NSButton) {
4609
+        guard requireGoogleLoginForCalendarScheduling() else { return }
4553 4610
         guard let raw = sender.identifier?.rawValue,
4554 4611
               let date = calendarDayKeyFormatter.date(from: raw) else { return }
4555 4612
         calendarPageSelectedDate = Calendar.current.startOfDay(for: date)
@@ -5792,6 +5849,7 @@ private extension ViewController {
5792 5849
                     self.applyGoogleProfile(profile.map { self.makeGoogleProfileDisplay(from: $0) })
5793 5850
                     self.pageCache[.joinMeetings] = nil
5794 5851
                     self.pageCache[.photo] = nil
5852
+                    self.pageCache[.video] = nil
5795 5853
                     self.showSidebarPage(self.selectedSidebarPage)
5796 5854
                 }
5797 5855
             } catch {