Kaynağa Gözat

Fix schedule filter dropdown interaction.

Replace the custom click-to-menu filter with a native AppKit popup button so filter selection reliably updates and reloads meetings.

Made-with: Cursor
huzaifahayat12 1 hafta önce
ebeveyn
işleme
d6931c1d42
1 değiştirilmiş dosya ile 36 ekleme ve 63 silme
  1. 36 63
      meetings_app/ViewController.swift

+ 36 - 63
meetings_app/ViewController.swift

@@ -74,7 +74,7 @@ final class ViewController: NSViewController {
74 74
     private var scheduleFilter: ScheduleFilter = .all
75 75
     private weak var scheduleDateHeadingLabel: NSTextField?
76 76
     private weak var scheduleCardsStack: NSStackView?
77
-    private weak var scheduleFilterLabel: NSTextField?
77
+    private weak var scheduleFilterDropdown: NSPopUpButton?
78 78
 
79 79
     /// In-app browser navigation: `.allowAll` or `.whitelist(hostSuffixes:)` (e.g. `["google.com"]` matches `meet.google.com`).
80 80
     private let inAppBrowserDefaultPolicy: InAppBrowserURLPolicy = .allowAll
@@ -1807,45 +1807,39 @@ private extension ViewController {
1807 1807
         connectButton.action = #selector(scheduleConnectButtonPressed(_:))
1808 1808
         row.addArrangedSubview(connectButton)
1809 1809
 
1810
-        let filter = roundedContainer(cornerRadius: 8, color: palette.inputBackground)
1811
-        filter.translatesAutoresizingMaskIntoConstraints = false
1812
-        filter.widthAnchor.constraint(equalToConstant: 156).isActive = true
1813
-        filter.heightAnchor.constraint(equalToConstant: 34).isActive = true
1814
-        styleSurface(filter, borderColor: palette.inputBorder, borderWidth: 1, shadow: false)
1815
-        let filterText = textLabel(scheduleFilterTitle(scheduleFilter), font: typography.filterText, color: palette.textSecondary)
1816
-        scheduleFilterLabel = filterText
1817
-        let arrow = textLabel("▾", font: typography.filterArrow, color: palette.textMuted)
1818
-        filterText.translatesAutoresizingMaskIntoConstraints = false
1819
-        arrow.translatesAutoresizingMaskIntoConstraints = false
1820
-        filter.addSubview(filterText)
1821
-        filter.addSubview(arrow)
1810
+        row.addArrangedSubview(makeScheduleFilterDropdown())
1811
+        row.widthAnchor.constraint(greaterThanOrEqualToConstant: 780).isActive = true
1812
+        return row
1813
+    }
1822 1814
 
1823
-        NSLayoutConstraint.activate([
1824
-            filterText.leadingAnchor.constraint(equalTo: filter.leadingAnchor, constant: 12),
1825
-            filterText.centerYAnchor.constraint(equalTo: filter.centerYAnchor),
1826
-            arrow.trailingAnchor.constraint(equalTo: filter.trailingAnchor, constant: -10),
1827
-            arrow.centerYAnchor.constraint(equalTo: filter.centerYAnchor)
1828
-        ])
1815
+    private func makeScheduleFilterDropdown() -> NSPopUpButton {
1816
+        let button = NSPopUpButton(frame: .zero, pullsDown: false)
1817
+        button.translatesAutoresizingMaskIntoConstraints = false
1818
+        button.autoenablesItems = false
1819
+        button.wantsLayer = true
1820
+        button.layer?.cornerRadius = 8
1821
+        button.layer?.backgroundColor = palette.inputBackground.cgColor
1822
+        button.layer?.borderColor = palette.inputBorder.cgColor
1823
+        button.layer?.borderWidth = 1
1824
+        button.font = typography.filterText
1825
+        button.contentTintColor = palette.textSecondary
1826
+        button.target = self
1827
+        button.action = #selector(scheduleFilterDropdownChanged(_:))
1828
+        button.heightAnchor.constraint(equalToConstant: 34).isActive = true
1829
+        button.widthAnchor.constraint(equalToConstant: 156).isActive = true
1829 1830
 
1830
-        let filterHit = HoverTrackingView()
1831
-        filterHit.translatesAutoresizingMaskIntoConstraints = false
1832
-        filterHit.addSubview(filter)
1833
-        NSLayoutConstraint.activate([
1834
-            filterHit.widthAnchor.constraint(equalToConstant: 156),
1835
-            filterHit.heightAnchor.constraint(equalToConstant: 34),
1836
-            filter.leadingAnchor.constraint(equalTo: filterHit.leadingAnchor),
1837
-            filter.trailingAnchor.constraint(equalTo: filterHit.trailingAnchor),
1838
-            filter.topAnchor.constraint(equalTo: filterHit.topAnchor),
1839
-            filter.bottomAnchor.constraint(equalTo: filterHit.bottomAnchor)
1840
-        ])
1841
-        filterHit.onClick = { [weak self, weak filterHit] in
1842
-            guard let self, let anchor = filterHit else { return }
1843
-            self.showScheduleFilterMenu(anchor: anchor)
1831
+        button.removeAllItems()
1832
+        button.addItems(withTitles: ["All", "Today", "This week"])
1833
+        button.selectItem(at: scheduleFilter.rawValue)
1834
+
1835
+        if let menu = button.menu {
1836
+            for (index, item) in menu.items.enumerated() {
1837
+                item.tag = index
1838
+            }
1844 1839
         }
1845 1840
 
1846
-        row.addArrangedSubview(filterHit)
1847
-        row.widthAnchor.constraint(greaterThanOrEqualToConstant: 780).isActive = true
1848
-        return row
1841
+        scheduleFilterDropdown = button
1842
+        return button
1849 1843
     }
1850 1844
 
1851 1845
     private func makeSchedulePillButton(title: String) -> NSButton {
@@ -2552,36 +2546,15 @@ private extension ViewController {
2552 2546
         googleOAuth.loadTokens() == nil ? "Connect Google to see meetings" : "Loading…"
2553 2547
     }
2554 2548
 
2555
-    private func scheduleFilterTitle(_ filter: ScheduleFilter) -> String {
2556
-        switch filter {
2557
-        case .all: return "All"
2558
-        case .today: return "Today"
2559
-        case .week: return "This week"
2560
-        }
2561
-    }
2562
-
2563
-    private func showScheduleFilterMenu(anchor: NSView) {
2564
-        let menu = NSMenu()
2565
-        let items: [(ScheduleFilter, String)] = [
2566
-            (.all, "All"),
2567
-            (.today, "Today"),
2568
-            (.week, "This week")
2569
-        ]
2570
-        for (filter, title) in items {
2571
-            let item = NSMenuItem(title: title, action: #selector(scheduleFilterSelected(_:)), keyEquivalent: "")
2572
-            item.target = self
2573
-            item.tag = filter.rawValue
2574
-            item.state = (filter == scheduleFilter) ? .on : .off
2575
-            menu.addItem(item)
2576
-        }
2577
-        let loc = NSPoint(x: 8, y: anchor.bounds.height + 2)
2578
-        menu.popUp(positioning: nil, at: loc, in: anchor)
2549
+    @objc func scheduleFilterDropdownChanged(_ sender: NSPopUpButton) {
2550
+        guard let selectedItem = sender.selectedItem,
2551
+              let filter = ScheduleFilter(rawValue: selectedItem.tag) else { return }
2552
+        applyScheduleFilter(filter)
2579 2553
     }
2580 2554
 
2581
-    @objc func scheduleFilterSelected(_ sender: NSMenuItem) {
2582
-        guard let filter = ScheduleFilter(rawValue: sender.tag) else { return }
2555
+    private func applyScheduleFilter(_ filter: ScheduleFilter) {
2583 2556
         scheduleFilter = filter
2584
-        scheduleFilterLabel?.stringValue = scheduleFilterTitle(filter)
2557
+        scheduleFilterDropdown?.selectItem(at: filter.rawValue)
2585 2558
         Task { [weak self] in
2586 2559
             await self?.loadSchedule()
2587 2560
         }