Bläddra i källkod

Refresh all pages on premium state changes and improve Share popup anchor.

Ensure purchase and downgrade flows immediately rebuild page caches, and anchor the Share menu to the exact clicked location in Settings actions.

Made-with: Cursor
huzaifahayat12 1 vecka sedan
förälder
incheckning
91d83ff35c
1 ändrade filer med 51 tillägg och 25 borttagningar
  1. 51 25
      meetings_app/ViewController.swift

+ 51 - 25
meetings_app/ViewController.swift

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