|
|
@@ -398,8 +398,8 @@ final class ViewController: NSViewController {
|
|
398
|
398
|
onToggleDarkMode: { [weak self] enabled in
|
|
399
|
399
|
self?.setDarkMode(enabled)
|
|
400
|
400
|
},
|
|
401
|
|
- onAction: { [weak self] action in
|
|
402
|
|
- self?.handleSettingsAction(action)
|
|
|
401
|
+ onAction: { [weak self] action, sourceView, clickPoint in
|
|
|
402
|
+ self?.handleSettingsAction(action, sourceView: sourceView, clickLocationInSourceView: clickPoint)
|
|
403
|
403
|
}
|
|
404
|
404
|
)
|
|
405
|
405
|
return popover
|
|
|
@@ -763,7 +763,7 @@ private extension ViewController {
|
|
763
|
763
|
return nil
|
|
764
|
764
|
}
|
|
765
|
765
|
|
|
766
|
|
- private func shareAppFromSettingsMenu() {
|
|
|
766
|
+ private func shareAppFromSettingsMenu(sourceView: NSView? = nil, clickLocationInSourceView: NSPoint? = nil) {
|
|
767
|
767
|
let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
|
|
768
|
768
|
?? Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String
|
|
769
|
769
|
?? "Meetings App"
|
|
|
@@ -772,8 +772,11 @@ private extension ViewController {
|
|
772
|
772
|
let shareItems: [Any] = appURL.map { [message, $0] } ?? [message]
|
|
773
|
773
|
|
|
774
|
774
|
let picker = NSSharingServicePicker(items: shareItems)
|
|
775
|
|
- let anchorView = sidebarRowViews[.settings] ?? view
|
|
776
|
|
- picker.show(relativeTo: anchorView.bounds, of: anchorView, preferredEdge: .maxX)
|
|
|
775
|
+ let anchorView = sourceView ?? sidebarRowViews[.settings] ?? view
|
|
|
776
|
+ let anchorPoint = clickLocationInSourceView
|
|
|
777
|
+ ?? NSPoint(x: anchorView.bounds.midX, y: anchorView.bounds.midY)
|
|
|
778
|
+ let anchorRect = NSRect(x: anchorPoint.x, y: anchorPoint.y, width: 1, height: 1)
|
|
|
779
|
+ picker.show(relativeTo: anchorRect, of: anchorView, preferredEdge: .minY)
|
|
777
|
780
|
|
|
778
|
781
|
let clipboardText = ([message, appURL?.absoluteString].compactMap { $0 }).joined(separator: "\n")
|
|
779
|
782
|
NSPasteboard.general.clearContents()
|
|
|
@@ -855,7 +858,7 @@ private extension ViewController {
|
|
855
|
858
|
showSidebarPage(selectedSidebarPage)
|
|
856
|
859
|
}
|
|
857
|
860
|
|
|
858
|
|
- private func handleSettingsAction(_ action: SettingsAction) {
|
|
|
861
|
+ private func handleSettingsAction(_ action: SettingsAction, sourceView: NSView? = nil, clickLocationInSourceView: NSPoint? = nil) {
|
|
859
|
862
|
switch action {
|
|
860
|
863
|
case .restore:
|
|
861
|
864
|
Task { [weak self] in
|
|
|
@@ -878,7 +881,7 @@ private extension ViewController {
|
|
878
|
881
|
openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
|
|
879
|
882
|
}
|
|
880
|
883
|
case .shareApp:
|
|
881
|
|
- shareAppFromSettingsMenu()
|
|
|
884
|
+ shareAppFromSettingsMenu(sourceView: sourceView, clickLocationInSourceView: clickLocationInSourceView)
|
|
882
|
885
|
case .upgrade:
|
|
883
|
886
|
showPaywall(upgradeFlow: true, preferredPlan: .lifetime)
|
|
884
|
887
|
}
|
|
|
@@ -1228,13 +1231,9 @@ private extension ViewController {
|
|
1228
|
1231
|
premiumUpgradeRatingPromptWorkItem?.cancel()
|
|
1229
|
1232
|
refreshPaywallStoreUI()
|
|
1230
|
1233
|
refreshScheduleCardsForPremiumStateChange()
|
|
1231
|
|
-
|
|
1232
|
|
- pageCache[.joinMeetings] = nil
|
|
1233
|
|
- pageCache[.video] = nil
|
|
1234
|
|
- if selectedSidebarPage == .joinMeetings {
|
|
1235
|
|
- showSidebarPage(.joinMeetings)
|
|
1236
|
|
- } else if selectedSidebarPage == .video {
|
|
1237
|
|
- showSidebarPage(.video)
|
|
|
1234
|
+ refreshPagesAfterPremiumStateUpdate()
|
|
|
1235
|
+ Task { [weak self] in
|
|
|
1236
|
+ await self?.loadSchedule()
|
|
1238
|
1237
|
}
|
|
1239
|
1238
|
|
|
1240
|
1239
|
if !hadPremiumAccess && hasPremiumAccess {
|
|
|
@@ -1254,6 +1253,14 @@ private extension ViewController {
|
|
1254
|
1253
|
}
|
|
1255
|
1254
|
}
|
|
1256
|
1255
|
|
|
|
1256
|
+ private func refreshPagesAfterPremiumStateUpdate() {
|
|
|
1257
|
+ pageCache[.joinMeetings] = nil
|
|
|
1258
|
+ pageCache[.photo] = nil
|
|
|
1259
|
+ pageCache[.video] = nil
|
|
|
1260
|
+ pageCache[.settings] = nil
|
|
|
1261
|
+ showSidebarPage(selectedSidebarPage)
|
|
|
1262
|
+ }
|
|
|
1263
|
+
|
|
1257
|
1264
|
private var userHasRated: Bool {
|
|
1258
|
1265
|
UserDefaults.standard.bool(forKey: userHasRatedDefaultsKey)
|
|
1259
|
1266
|
}
|
|
|
@@ -1426,6 +1433,10 @@ private extension ViewController {
|
|
1426
|
1433
|
self.refreshPaywallStoreUI()
|
|
1427
|
1434
|
switch result {
|
|
1428
|
1435
|
case .success:
|
|
|
1436
|
+ self.refreshPagesAfterPremiumStateUpdate()
|
|
|
1437
|
+ Task { [weak self] in
|
|
|
1438
|
+ await self?.loadSchedule()
|
|
|
1439
|
+ }
|
|
1429
|
1440
|
self.showSimpleAlert(title: "Purchase Complete", message: "Premium has been unlocked successfully.")
|
|
1430
|
1441
|
self.paywallWindow?.performClose(nil)
|
|
1431
|
1442
|
self.scheduleRatingPromptAfterPremiumUpgrade()
|
|
|
@@ -1583,7 +1594,14 @@ private extension ViewController {
|
|
1583
|
1594
|
let shareButton = makeSettingsActionButton(icon: "⤴︎", title: "Share App", action: .shareApp)
|
|
1584
|
1595
|
stack.addArrangedSubview(shareButton)
|
|
1585
|
1596
|
shareButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
1586
|
|
- stack.setCustomSpacing(24, after: shareButton)
|
|
|
1597
|
+ if storeKitCoordinator.hasPremiumAccess && !storeKitCoordinator.hasLifetimeAccess {
|
|
|
1598
|
+ let upgradeButton = makeSettingsActionButton(icon: "⬆︎", title: "Upgrade", action: .upgrade)
|
|
|
1599
|
+ stack.addArrangedSubview(upgradeButton)
|
|
|
1600
|
+ upgradeButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
|
1601
|
+ stack.setCustomSpacing(24, after: upgradeButton)
|
|
|
1602
|
+ } else {
|
|
|
1603
|
+ stack.setCustomSpacing(24, after: shareButton)
|
|
|
1604
|
+ }
|
|
1587
|
1605
|
|
|
1588
|
1606
|
let legalTitle = textLabel("Help & Legal", font: typography.joinWithURLTitle, color: palette.textPrimary)
|
|
1589
|
1607
|
stack.addArrangedSubview(legalTitle)
|
|
|
@@ -1596,12 +1614,6 @@ private extension ViewController {
|
|
1596
|
1614
|
let termsButton = makeSettingsActionButton(icon: "📄", title: "Terms of Services", action: .termsOfServices)
|
|
1597
|
1615
|
stack.addArrangedSubview(termsButton)
|
|
1598
|
1616
|
termsButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
1599
|
|
- if storeKitCoordinator.hasPremiumAccess && !storeKitCoordinator.hasLifetimeAccess {
|
|
1600
|
|
- let upgradeButton = makeSettingsActionButton(icon: "⬆︎", title: "Upgrade", action: .upgrade)
|
|
1601
|
|
- stack.addArrangedSubview(upgradeButton)
|
|
1602
|
|
- upgradeButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
1603
|
|
- }
|
|
1604
|
|
-
|
|
1605
|
1617
|
NSLayoutConstraint.activate([
|
|
1606
|
1618
|
scroll.leadingAnchor.constraint(equalTo: panel.leadingAnchor),
|
|
1607
|
1619
|
scroll.trailingAnchor.constraint(equalTo: panel.trailingAnchor),
|
|
|
@@ -1725,7 +1737,14 @@ private extension ViewController {
|
|
1725
|
1737
|
|
|
1726
|
1738
|
@objc private func settingsPageActionButtonClicked(_ sender: NSButton) {
|
|
1727
|
1739
|
guard let action = SettingsAction(rawValue: sender.tag) else { return }
|
|
1728
|
|
- handleSettingsAction(action)
|
|
|
1740
|
+ let clickPoint: NSPoint?
|
|
|
1741
|
+ if let event = NSApp.currentEvent {
|
|
|
1742
|
+ let pointInWindow = event.locationInWindow
|
|
|
1743
|
+ clickPoint = sender.convert(pointInWindow, from: nil)
|
|
|
1744
|
+ } else {
|
|
|
1745
|
+ clickPoint = nil
|
|
|
1746
|
+ }
|
|
|
1747
|
+ handleSettingsAction(action, sourceView: sender, clickLocationInSourceView: clickPoint)
|
|
1729
|
1748
|
}
|
|
1730
|
1749
|
|
|
1731
|
1750
|
@objc private func settingsGoogleActionButtonClicked(_ sender: NSButton) {
|
|
|
@@ -4503,7 +4522,7 @@ private final class SettingsMenuViewController: NSViewController {
|
|
4503
|
4522
|
private let palette: Palette
|
|
4504
|
4523
|
private let typography: Typography
|
|
4505
|
4524
|
private let onToggleDarkMode: (Bool) -> Void
|
|
4506
|
|
- private let onAction: (SettingsAction) -> Void
|
|
|
4525
|
+ private let onAction: (SettingsAction, NSView?, NSPoint?) -> Void
|
|
4507
|
4526
|
|
|
4508
|
4527
|
private var darkToggle: NSSwitch?
|
|
4509
|
4528
|
|
|
|
@@ -4514,7 +4533,7 @@ private final class SettingsMenuViewController: NSViewController {
|
|
4514
|
4533
|
showRateUsInSettings: Bool,
|
|
4515
|
4534
|
showUpgradeInSettings: Bool,
|
|
4516
|
4535
|
onToggleDarkMode: @escaping (Bool) -> Void,
|
|
4517
|
|
- onAction: @escaping (SettingsAction) -> Void
|
|
|
4536
|
+ onAction: @escaping (SettingsAction, NSView?, NSPoint?) -> Void
|
|
4518
|
4537
|
) {
|
|
4519
|
4538
|
self.palette = palette
|
|
4520
|
4539
|
self.typography = typography
|
|
|
@@ -4690,7 +4709,14 @@ private final class SettingsMenuViewController: NSViewController {
|
|
4690
|
4709
|
|
|
4691
|
4710
|
@objc private func settingsActionButtonPressed(_ sender: NSButton) {
|
|
4692
|
4711
|
guard let action = SettingsAction(rawValue: sender.tag) else { return }
|
|
4693
|
|
- onAction(action)
|
|
|
4712
|
+ let clickPoint: NSPoint?
|
|
|
4713
|
+ if let event = NSApp.currentEvent {
|
|
|
4714
|
+ let pointInWindow = event.locationInWindow
|
|
|
4715
|
+ clickPoint = sender.convert(pointInWindow, from: nil)
|
|
|
4716
|
+ } else {
|
|
|
4717
|
+ clickPoint = nil
|
|
|
4718
|
+ }
|
|
|
4719
|
+ onAction(action, sender, clickPoint)
|
|
4694
|
4720
|
}
|
|
4695
|
4721
|
|
|
4696
|
4722
|
}
|