Преглед на файлове

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 преди 3 месеца
родител
ревизия
6b3d3b587f
променени са 1 файла, в които са добавени 63 реда и са изтрити 5 реда
  1. 63 5
      meetings_app/ViewController.swift

+ 63 - 5
meetings_app/ViewController.swift

@@ -543,11 +543,7 @@ private extension ViewController {
 
     @objc private func premiumButtonClicked(_ sender: NSClickGestureRecognizer) {
         if storeKitCoordinator.hasPremiumAccess {
-            if hasReachedRatingUsageThreshold && !userHasRated {
-                requestAppRatingIfEligible(markAsRated: false)
-                return
-            }
-            showPaywall(upgradeFlow: true, preferredPlan: .lifetime)
+            openManageSubscriptions()
         } else {
             showPaywall()
         }
@@ -1112,8 +1108,11 @@ private extension ViewController {
         refreshScheduleCardsForPremiumStateChange()
 
         pageCache[.joinMeetings] = nil
+        pageCache[.video] = nil
         if selectedSidebarPage == .joinMeetings {
             showSidebarPage(.joinMeetings)
+        } else if selectedSidebarPage == .video {
+            showSidebarPage(.video)
         }
 
         if !hadPremiumAccess && hasPremiumAccess {
@@ -1976,6 +1975,52 @@ private extension ViewController {
             daySummary.widthAnchor.constraint(equalTo: contentStack.widthAnchor)
         ])
 
+        if !storeKitCoordinator.hasPremiumAccess {
+            let lockOverlay = NSVisualEffectView()
+            lockOverlay.translatesAutoresizingMaskIntoConstraints = false
+            lockOverlay.material = darkModeEnabled ? .hudWindow : .popover
+            lockOverlay.blendingMode = .withinWindow
+            lockOverlay.state = .active
+            lockOverlay.wantsLayer = true
+            lockOverlay.layer?.cornerRadius = 14
+            lockOverlay.layer?.masksToBounds = true
+            lockOverlay.layer?.backgroundColor = NSColor.black.withAlphaComponent(darkModeEnabled ? 0.30 : 0.12).cgColor
+            panel.addSubview(lockOverlay)
+
+            let message = textLabel("Premium required. Get Premium now to unlock Calendar.", font: NSFont.systemFont(ofSize: 14, weight: .semibold), color: darkModeEnabled ? .white : .black)
+            message.alignment = .center
+            message.maximumNumberOfLines = 2
+            message.lineBreakMode = .byWordWrapping
+            lockOverlay.addSubview(message)
+
+            let hit = HoverTrackingView()
+            hit.translatesAutoresizingMaskIntoConstraints = false
+            hit.wantsLayer = true
+            hit.layer?.backgroundColor = NSColor.clear.cgColor
+            hit.onClick = { [weak self] in
+                self?.showPaywall()
+            }
+            hit.toolTip = "Premium required. Click to open paywall."
+            lockOverlay.addSubview(hit)
+
+            NSLayoutConstraint.activate([
+                lockOverlay.leadingAnchor.constraint(equalTo: contentStack.leadingAnchor),
+                lockOverlay.trailingAnchor.constraint(equalTo: contentStack.trailingAnchor),
+                lockOverlay.topAnchor.constraint(equalTo: contentStack.topAnchor),
+                lockOverlay.bottomAnchor.constraint(equalTo: contentStack.bottomAnchor),
+
+                message.centerXAnchor.constraint(equalTo: lockOverlay.centerXAnchor),
+                message.centerYAnchor.constraint(equalTo: lockOverlay.centerYAnchor),
+                message.leadingAnchor.constraint(greaterThanOrEqualTo: lockOverlay.leadingAnchor, constant: 22),
+                message.trailingAnchor.constraint(lessThanOrEqualTo: lockOverlay.trailingAnchor, constant: -22),
+
+                hit.leadingAnchor.constraint(equalTo: lockOverlay.leadingAnchor),
+                hit.trailingAnchor.constraint(equalTo: lockOverlay.trailingAnchor),
+                hit.topAnchor.constraint(equalTo: lockOverlay.topAnchor),
+                hit.bottomAnchor.constraint(equalTo: lockOverlay.bottomAnchor)
+            ])
+        }
+
         let calendar = Calendar.current
         calendarPageMonthAnchor = calendarStartOfMonth(for: Date())
         calendarPageSelectedDate = calendar.startOfDay(for: Date())
@@ -4274,6 +4319,17 @@ private final class SettingsMenuViewController: NSViewController {
 }
 
 private extension ViewController {
+    private func requireGoogleLoginForCalendarScheduling() -> Bool {
+        guard googleOAuth.loadTokens() != nil else {
+            showSimpleAlert(
+                title: "Connect Google",
+                message: "Sign in with Google first to schedule a meeting from Calendar."
+            )
+            return false
+        }
+        return true
+    }
+
     func roundedContainer(cornerRadius: CGFloat, color: NSColor) -> NSView {
         let view = NSView()
         view.wantsLayer = true
@@ -4550,6 +4606,7 @@ private extension ViewController {
     }
 
     @objc func calendarDayCellPressed(_ sender: NSButton) {
+        guard requireGoogleLoginForCalendarScheduling() else { return }
         guard let raw = sender.identifier?.rawValue,
               let date = calendarDayKeyFormatter.date(from: raw) else { return }
         calendarPageSelectedDate = Calendar.current.startOfDay(for: date)
@@ -5792,6 +5849,7 @@ private extension ViewController {
                     self.applyGoogleProfile(profile.map { self.makeGoogleProfileDisplay(from: $0) })
                     self.pageCache[.joinMeetings] = nil
                     self.pageCache[.photo] = nil
+                    self.pageCache[.video] = nil
                     self.showSidebarPage(self.selectedSidebarPage)
                 }
             } catch {