Просмотр исходного кода

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 3 месяцев назад
Родитель
Сommit
91d83ff35c
1 измененных файлов с 51 добавлено и 25 удалено
  1. 51 25
      meetings_app/ViewController.swift

+ 51 - 25
meetings_app/ViewController.swift

@@ -398,8 +398,8 @@ final class ViewController: NSViewController {
             onToggleDarkMode: { [weak self] enabled in
             onToggleDarkMode: { [weak self] enabled in
                 self?.setDarkMode(enabled)
                 self?.setDarkMode(enabled)
             },
             },
-            onAction: { [weak self] action in
-                self?.handleSettingsAction(action)
+            onAction: { [weak self] action, sourceView, clickPoint in
+                self?.handleSettingsAction(action, sourceView: sourceView, clickLocationInSourceView: clickPoint)
             }
             }
         )
         )
         return popover
         return popover
@@ -763,7 +763,7 @@ private extension ViewController {
         return nil
         return nil
     }
     }
 
 
-    private func shareAppFromSettingsMenu() {
+    private func shareAppFromSettingsMenu(sourceView: NSView? = nil, clickLocationInSourceView: NSPoint? = nil) {
         let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
         let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
             ?? Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String
             ?? Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String
             ?? "Meetings App"
             ?? "Meetings App"
@@ -772,8 +772,11 @@ private extension ViewController {
         let shareItems: [Any] = appURL.map { [message, $0] } ?? [message]
         let shareItems: [Any] = appURL.map { [message, $0] } ?? [message]
 
 
         let picker = NSSharingServicePicker(items: shareItems)
         let picker = NSSharingServicePicker(items: shareItems)
-        let anchorView = sidebarRowViews[.settings] ?? view
-        picker.show(relativeTo: anchorView.bounds, of: anchorView, preferredEdge: .maxX)
+        let anchorView = sourceView ?? sidebarRowViews[.settings] ?? view
+        let anchorPoint = clickLocationInSourceView
+            ?? NSPoint(x: anchorView.bounds.midX, y: anchorView.bounds.midY)
+        let anchorRect = NSRect(x: anchorPoint.x, y: anchorPoint.y, width: 1, height: 1)
+        picker.show(relativeTo: anchorRect, of: anchorView, preferredEdge: .minY)
 
 
         let clipboardText = ([message, appURL?.absoluteString].compactMap { $0 }).joined(separator: "\n")
         let clipboardText = ([message, appURL?.absoluteString].compactMap { $0 }).joined(separator: "\n")
         NSPasteboard.general.clearContents()
         NSPasteboard.general.clearContents()
@@ -855,7 +858,7 @@ private extension ViewController {
         showSidebarPage(selectedSidebarPage)
         showSidebarPage(selectedSidebarPage)
     }
     }
 
 
-    private func handleSettingsAction(_ action: SettingsAction) {
+    private func handleSettingsAction(_ action: SettingsAction, sourceView: NSView? = nil, clickLocationInSourceView: NSPoint? = nil) {
         switch action {
         switch action {
         case .restore:
         case .restore:
             Task { [weak self] in
             Task { [weak self] in
@@ -878,7 +881,7 @@ private extension ViewController {
                 openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
                 openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
             }
             }
         case .shareApp:
         case .shareApp:
-            shareAppFromSettingsMenu()
+            shareAppFromSettingsMenu(sourceView: sourceView, clickLocationInSourceView: clickLocationInSourceView)
         case .upgrade:
         case .upgrade:
             showPaywall(upgradeFlow: true, preferredPlan: .lifetime)
             showPaywall(upgradeFlow: true, preferredPlan: .lifetime)
         }
         }
@@ -1228,13 +1231,9 @@ private extension ViewController {
         premiumUpgradeRatingPromptWorkItem?.cancel()
         premiumUpgradeRatingPromptWorkItem?.cancel()
         refreshPaywallStoreUI()
         refreshPaywallStoreUI()
         refreshScheduleCardsForPremiumStateChange()
         refreshScheduleCardsForPremiumStateChange()
-
-        pageCache[.joinMeetings] = nil
-        pageCache[.video] = nil
-        if selectedSidebarPage == .joinMeetings {
-            showSidebarPage(.joinMeetings)
-        } else if selectedSidebarPage == .video {
-            showSidebarPage(.video)
+        refreshPagesAfterPremiumStateUpdate()
+        Task { [weak self] in
+            await self?.loadSchedule()
         }
         }
 
 
         if !hadPremiumAccess && hasPremiumAccess {
         if !hadPremiumAccess && hasPremiumAccess {
@@ -1254,6 +1253,14 @@ private extension ViewController {
         }
         }
     }
     }
 
 
+    private func refreshPagesAfterPremiumStateUpdate() {
+        pageCache[.joinMeetings] = nil
+        pageCache[.photo] = nil
+        pageCache[.video] = nil
+        pageCache[.settings] = nil
+        showSidebarPage(selectedSidebarPage)
+    }
+
     private var userHasRated: Bool {
     private var userHasRated: Bool {
         UserDefaults.standard.bool(forKey: userHasRatedDefaultsKey)
         UserDefaults.standard.bool(forKey: userHasRatedDefaultsKey)
     }
     }
@@ -1426,6 +1433,10 @@ private extension ViewController {
             self.refreshPaywallStoreUI()
             self.refreshPaywallStoreUI()
             switch result {
             switch result {
             case .success:
             case .success:
+                self.refreshPagesAfterPremiumStateUpdate()
+                Task { [weak self] in
+                    await self?.loadSchedule()
+                }
                 self.showSimpleAlert(title: "Purchase Complete", message: "Premium has been unlocked successfully.")
                 self.showSimpleAlert(title: "Purchase Complete", message: "Premium has been unlocked successfully.")
                 self.paywallWindow?.performClose(nil)
                 self.paywallWindow?.performClose(nil)
                 self.scheduleRatingPromptAfterPremiumUpgrade()
                 self.scheduleRatingPromptAfterPremiumUpgrade()
@@ -1583,7 +1594,14 @@ private extension ViewController {
         let shareButton = makeSettingsActionButton(icon: "⤴︎", title: "Share App", action: .shareApp)
         let shareButton = makeSettingsActionButton(icon: "⤴︎", title: "Share App", action: .shareApp)
         stack.addArrangedSubview(shareButton)
         stack.addArrangedSubview(shareButton)
         shareButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
         shareButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
-        stack.setCustomSpacing(24, after: shareButton)
+        if storeKitCoordinator.hasPremiumAccess && !storeKitCoordinator.hasLifetimeAccess {
+            let upgradeButton = makeSettingsActionButton(icon: "⬆︎", title: "Upgrade", action: .upgrade)
+            stack.addArrangedSubview(upgradeButton)
+            upgradeButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
+            stack.setCustomSpacing(24, after: upgradeButton)
+        } else {
+            stack.setCustomSpacing(24, after: shareButton)
+        }
 
 
         let legalTitle = textLabel("Help & Legal", font: typography.joinWithURLTitle, color: palette.textPrimary)
         let legalTitle = textLabel("Help & Legal", font: typography.joinWithURLTitle, color: palette.textPrimary)
         stack.addArrangedSubview(legalTitle)
         stack.addArrangedSubview(legalTitle)
@@ -1596,12 +1614,6 @@ private extension ViewController {
         let termsButton = makeSettingsActionButton(icon: "📄", title: "Terms of Services", action: .termsOfServices)
         let termsButton = makeSettingsActionButton(icon: "📄", title: "Terms of Services", action: .termsOfServices)
         stack.addArrangedSubview(termsButton)
         stack.addArrangedSubview(termsButton)
         termsButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
         termsButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
-        if storeKitCoordinator.hasPremiumAccess && !storeKitCoordinator.hasLifetimeAccess {
-            let upgradeButton = makeSettingsActionButton(icon: "⬆︎", title: "Upgrade", action: .upgrade)
-            stack.addArrangedSubview(upgradeButton)
-            upgradeButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
-        }
-
         NSLayoutConstraint.activate([
         NSLayoutConstraint.activate([
             scroll.leadingAnchor.constraint(equalTo: panel.leadingAnchor),
             scroll.leadingAnchor.constraint(equalTo: panel.leadingAnchor),
             scroll.trailingAnchor.constraint(equalTo: panel.trailingAnchor),
             scroll.trailingAnchor.constraint(equalTo: panel.trailingAnchor),
@@ -1725,7 +1737,14 @@ private extension ViewController {
 
 
     @objc private func settingsPageActionButtonClicked(_ sender: NSButton) {
     @objc private func settingsPageActionButtonClicked(_ sender: NSButton) {
         guard let action = SettingsAction(rawValue: sender.tag) else { return }
         guard let action = SettingsAction(rawValue: sender.tag) else { return }
-        handleSettingsAction(action)
+        let clickPoint: NSPoint?
+        if let event = NSApp.currentEvent {
+            let pointInWindow = event.locationInWindow
+            clickPoint = sender.convert(pointInWindow, from: nil)
+        } else {
+            clickPoint = nil
+        }
+        handleSettingsAction(action, sourceView: sender, clickLocationInSourceView: clickPoint)
     }
     }
 
 
     @objc private func settingsGoogleActionButtonClicked(_ sender: NSButton) {
     @objc private func settingsGoogleActionButtonClicked(_ sender: NSButton) {
@@ -4503,7 +4522,7 @@ private final class SettingsMenuViewController: NSViewController {
     private let palette: Palette
     private let palette: Palette
     private let typography: Typography
     private let typography: Typography
     private let onToggleDarkMode: (Bool) -> Void
     private let onToggleDarkMode: (Bool) -> Void
-    private let onAction: (SettingsAction) -> Void
+    private let onAction: (SettingsAction, NSView?, NSPoint?) -> Void
 
 
     private var darkToggle: NSSwitch?
     private var darkToggle: NSSwitch?
 
 
@@ -4514,7 +4533,7 @@ private final class SettingsMenuViewController: NSViewController {
         showRateUsInSettings: Bool,
         showRateUsInSettings: Bool,
         showUpgradeInSettings: Bool,
         showUpgradeInSettings: Bool,
         onToggleDarkMode: @escaping (Bool) -> Void,
         onToggleDarkMode: @escaping (Bool) -> Void,
-        onAction: @escaping (SettingsAction) -> Void
+        onAction: @escaping (SettingsAction, NSView?, NSPoint?) -> Void
     ) {
     ) {
         self.palette = palette
         self.palette = palette
         self.typography = typography
         self.typography = typography
@@ -4690,7 +4709,14 @@ private final class SettingsMenuViewController: NSViewController {
 
 
     @objc private func settingsActionButtonPressed(_ sender: NSButton) {
     @objc private func settingsActionButtonPressed(_ sender: NSButton) {
         guard let action = SettingsAction(rawValue: sender.tag) else { return }
         guard let action = SettingsAction(rawValue: sender.tag) else { return }
-        onAction(action)
+        let clickPoint: NSPoint?
+        if let event = NSApp.currentEvent {
+            let pointInWindow = event.locationInWindow
+            clickPoint = sender.convert(pointInWindow, from: nil)
+        } else {
+            clickPoint = nil
+        }
+        onAction(action, sender, clickPoint)
     }
     }
 
 
 }
 }