|
|
@@ -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 {
|