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