|
|
@@ -3235,6 +3235,59 @@ private extension ViewController {
|
|
3235
|
3235
|
stack.bottomAnchor.constraint(equalTo: card.bottomAnchor, constant: -14)
|
|
3236
|
3236
|
])
|
|
3237
|
3237
|
|
|
|
3238
|
+ if !storeKitCoordinator.hasPremiumAccess {
|
|
|
3239
|
+ // Keep the content present (so layout stays stable), but visually lock it and route clicks to the paywall.
|
|
|
3240
|
+ notesButton.isEnabled = false
|
|
|
3241
|
+
|
|
|
3242
|
+ let lockOverlay = NSVisualEffectView()
|
|
|
3243
|
+ lockOverlay.translatesAutoresizingMaskIntoConstraints = false
|
|
|
3244
|
+ lockOverlay.material = darkModeEnabled ? .hudWindow : .popover
|
|
|
3245
|
+ lockOverlay.blendingMode = .withinWindow
|
|
|
3246
|
+ lockOverlay.state = .active
|
|
|
3247
|
+ lockOverlay.wantsLayer = true
|
|
|
3248
|
+ lockOverlay.layer?.cornerRadius = 14
|
|
|
3249
|
+ lockOverlay.layer?.masksToBounds = true
|
|
|
3250
|
+ lockOverlay.layer?.backgroundColor = NSColor.black.withAlphaComponent(darkModeEnabled ? 0.30 : 0.12).cgColor
|
|
|
3251
|
+ card.addSubview(lockOverlay)
|
|
|
3252
|
+
|
|
|
3253
|
+ let message = textLabel(
|
|
|
3254
|
+ "Premium required. Click to unlock AI Companion notes.",
|
|
|
3255
|
+ font: NSFont.systemFont(ofSize: 13, weight: .semibold),
|
|
|
3256
|
+ color: darkModeEnabled ? .white : .black
|
|
|
3257
|
+ )
|
|
|
3258
|
+ message.alignment = .center
|
|
|
3259
|
+ message.maximumNumberOfLines = 2
|
|
|
3260
|
+ message.lineBreakMode = .byWordWrapping
|
|
|
3261
|
+ lockOverlay.addSubview(message)
|
|
|
3262
|
+
|
|
|
3263
|
+ let hit = HoverTrackingView()
|
|
|
3264
|
+ hit.translatesAutoresizingMaskIntoConstraints = false
|
|
|
3265
|
+ hit.wantsLayer = true
|
|
|
3266
|
+ hit.layer?.backgroundColor = NSColor.clear.cgColor
|
|
|
3267
|
+ hit.onClick = { [weak self] in
|
|
|
3268
|
+ self?.showPaywall()
|
|
|
3269
|
+ }
|
|
|
3270
|
+ hit.toolTip = "Premium required. Click to open paywall."
|
|
|
3271
|
+ lockOverlay.addSubview(hit)
|
|
|
3272
|
+
|
|
|
3273
|
+ NSLayoutConstraint.activate([
|
|
|
3274
|
+ lockOverlay.leadingAnchor.constraint(equalTo: card.leadingAnchor),
|
|
|
3275
|
+ lockOverlay.trailingAnchor.constraint(equalTo: card.trailingAnchor),
|
|
|
3276
|
+ lockOverlay.topAnchor.constraint(equalTo: card.topAnchor),
|
|
|
3277
|
+ lockOverlay.bottomAnchor.constraint(equalTo: card.bottomAnchor),
|
|
|
3278
|
+
|
|
|
3279
|
+ message.centerXAnchor.constraint(equalTo: lockOverlay.centerXAnchor),
|
|
|
3280
|
+ message.centerYAnchor.constraint(equalTo: lockOverlay.centerYAnchor),
|
|
|
3281
|
+ message.leadingAnchor.constraint(greaterThanOrEqualTo: lockOverlay.leadingAnchor, constant: 18),
|
|
|
3282
|
+ message.trailingAnchor.constraint(lessThanOrEqualTo: lockOverlay.trailingAnchor, constant: -18),
|
|
|
3283
|
+
|
|
|
3284
|
+ hit.leadingAnchor.constraint(equalTo: lockOverlay.leadingAnchor),
|
|
|
3285
|
+ hit.trailingAnchor.constraint(equalTo: lockOverlay.trailingAnchor),
|
|
|
3286
|
+ hit.topAnchor.constraint(equalTo: lockOverlay.topAnchor),
|
|
|
3287
|
+ hit.bottomAnchor.constraint(equalTo: lockOverlay.bottomAnchor)
|
|
|
3288
|
+ ])
|
|
|
3289
|
+ }
|
|
|
3290
|
+
|
|
3238
|
3291
|
return card
|
|
3239
|
3292
|
}
|
|
3240
|
3293
|
|
|
|
@@ -3706,6 +3759,10 @@ private extension ViewController {
|
|
3706
|
3759
|
}
|
|
3707
|
3760
|
|
|
3708
|
3761
|
@objc private func aiCompanionNotesTapped(_ sender: NSButton) {
|
|
|
3762
|
+ guard storeKitCoordinator.hasPremiumAccess else {
|
|
|
3763
|
+ showPaywall()
|
|
|
3764
|
+ return
|
|
|
3765
|
+ }
|
|
3709
|
3766
|
let senderId = ObjectIdentifier(sender)
|
|
3710
|
3767
|
guard let meetingId = aiCompanionNotesMeetingIdByView[senderId] else { return }
|
|
3711
|
3768
|
guard let recording = aiCompanionLocalRecordings.first(where: { $0.id == meetingId }) else {
|