Jelajahi Sumber

Fix AI Companion premium card gating.

Blur/lock AI Companion meeting cards for non-premium users and route clicks to the paywall.

Co-authored-by: Cursor <cursoragent@cursor.com>
huzaifahayat12 2 bulan lalu
induk
melakukan
40a43b78e8
1 mengubah file dengan 57 tambahan dan 0 penghapusan
  1. 57 0
      meetings_app/ViewController.swift

+ 57 - 0
meetings_app/ViewController.swift

@@ -3235,6 +3235,59 @@ private extension ViewController {
             stack.bottomAnchor.constraint(equalTo: card.bottomAnchor, constant: -14)
         ])
 
+        if !storeKitCoordinator.hasPremiumAccess {
+            // Keep the content present (so layout stays stable), but visually lock it and route clicks to the paywall.
+            notesButton.isEnabled = false
+
+            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
+            card.addSubview(lockOverlay)
+
+            let message = textLabel(
+                "Premium required. Click to unlock AI Companion notes.",
+                font: NSFont.systemFont(ofSize: 13, 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: card.leadingAnchor),
+                lockOverlay.trailingAnchor.constraint(equalTo: card.trailingAnchor),
+                lockOverlay.topAnchor.constraint(equalTo: card.topAnchor),
+                lockOverlay.bottomAnchor.constraint(equalTo: card.bottomAnchor),
+
+                message.centerXAnchor.constraint(equalTo: lockOverlay.centerXAnchor),
+                message.centerYAnchor.constraint(equalTo: lockOverlay.centerYAnchor),
+                message.leadingAnchor.constraint(greaterThanOrEqualTo: lockOverlay.leadingAnchor, constant: 18),
+                message.trailingAnchor.constraint(lessThanOrEqualTo: lockOverlay.trailingAnchor, constant: -18),
+
+                hit.leadingAnchor.constraint(equalTo: lockOverlay.leadingAnchor),
+                hit.trailingAnchor.constraint(equalTo: lockOverlay.trailingAnchor),
+                hit.topAnchor.constraint(equalTo: lockOverlay.topAnchor),
+                hit.bottomAnchor.constraint(equalTo: lockOverlay.bottomAnchor)
+            ])
+        }
+
         return card
     }
 
@@ -3706,6 +3759,10 @@ private extension ViewController {
     }
 
     @objc private func aiCompanionNotesTapped(_ sender: NSButton) {
+        guard storeKitCoordinator.hasPremiumAccess else {
+            showPaywall()
+            return
+        }
         let senderId = ObjectIdentifier(sender)
         guard let meetingId = aiCompanionNotesMeetingIdByView[senderId] else { return }
         guard let recording = aiCompanionLocalRecordings.first(where: { $0.id == meetingId }) else {