Browse Source

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 3 months ago
parent
commit
d6931c1d42
1 changed files with 36 additions and 63 deletions
  1. 36 63
      meetings_app/ViewController.swift

+ 36 - 63
meetings_app/ViewController.swift

@@ -74,7 +74,7 @@ final class ViewController: NSViewController {
     private var scheduleFilter: ScheduleFilter = .all
     private weak var scheduleDateHeadingLabel: NSTextField?
     private weak var scheduleCardsStack: NSStackView?
-    private weak var scheduleFilterLabel: NSTextField?
+    private weak var scheduleFilterDropdown: NSPopUpButton?
 
     /// In-app browser navigation: `.allowAll` or `.whitelist(hostSuffixes:)` (e.g. `["google.com"]` matches `meet.google.com`).
     private let inAppBrowserDefaultPolicy: InAppBrowserURLPolicy = .allowAll
@@ -1807,45 +1807,39 @@ private extension ViewController {
         connectButton.action = #selector(scheduleConnectButtonPressed(_:))
         row.addArrangedSubview(connectButton)
 
-        let filter = roundedContainer(cornerRadius: 8, color: palette.inputBackground)
-        filter.translatesAutoresizingMaskIntoConstraints = false
-        filter.widthAnchor.constraint(equalToConstant: 156).isActive = true
-        filter.heightAnchor.constraint(equalToConstant: 34).isActive = true
-        styleSurface(filter, borderColor: palette.inputBorder, borderWidth: 1, shadow: false)
-        let filterText = textLabel(scheduleFilterTitle(scheduleFilter), font: typography.filterText, color: palette.textSecondary)
-        scheduleFilterLabel = filterText
-        let arrow = textLabel("▾", font: typography.filterArrow, color: palette.textMuted)
-        filterText.translatesAutoresizingMaskIntoConstraints = false
-        arrow.translatesAutoresizingMaskIntoConstraints = false
-        filter.addSubview(filterText)
-        filter.addSubview(arrow)
+        row.addArrangedSubview(makeScheduleFilterDropdown())
+        row.widthAnchor.constraint(greaterThanOrEqualToConstant: 780).isActive = true
+        return row
+    }
 
-        NSLayoutConstraint.activate([
-            filterText.leadingAnchor.constraint(equalTo: filter.leadingAnchor, constant: 12),
-            filterText.centerYAnchor.constraint(equalTo: filter.centerYAnchor),
-            arrow.trailingAnchor.constraint(equalTo: filter.trailingAnchor, constant: -10),
-            arrow.centerYAnchor.constraint(equalTo: filter.centerYAnchor)
-        ])
+    private func makeScheduleFilterDropdown() -> NSPopUpButton {
+        let button = NSPopUpButton(frame: .zero, pullsDown: false)
+        button.translatesAutoresizingMaskIntoConstraints = false
+        button.autoenablesItems = false
+        button.wantsLayer = true
+        button.layer?.cornerRadius = 8
+        button.layer?.backgroundColor = palette.inputBackground.cgColor
+        button.layer?.borderColor = palette.inputBorder.cgColor
+        button.layer?.borderWidth = 1
+        button.font = typography.filterText
+        button.contentTintColor = palette.textSecondary
+        button.target = self
+        button.action = #selector(scheduleFilterDropdownChanged(_:))
+        button.heightAnchor.constraint(equalToConstant: 34).isActive = true
+        button.widthAnchor.constraint(equalToConstant: 156).isActive = true
 
-        let filterHit = HoverTrackingView()
-        filterHit.translatesAutoresizingMaskIntoConstraints = false
-        filterHit.addSubview(filter)
-        NSLayoutConstraint.activate([
-            filterHit.widthAnchor.constraint(equalToConstant: 156),
-            filterHit.heightAnchor.constraint(equalToConstant: 34),
-            filter.leadingAnchor.constraint(equalTo: filterHit.leadingAnchor),
-            filter.trailingAnchor.constraint(equalTo: filterHit.trailingAnchor),
-            filter.topAnchor.constraint(equalTo: filterHit.topAnchor),
-            filter.bottomAnchor.constraint(equalTo: filterHit.bottomAnchor)
-        ])
-        filterHit.onClick = { [weak self, weak filterHit] in
-            guard let self, let anchor = filterHit else { return }
-            self.showScheduleFilterMenu(anchor: anchor)
+        button.removeAllItems()
+        button.addItems(withTitles: ["All", "Today", "This week"])
+        button.selectItem(at: scheduleFilter.rawValue)
+
+        if let menu = button.menu {
+            for (index, item) in menu.items.enumerated() {
+                item.tag = index
+            }
         }
 
-        row.addArrangedSubview(filterHit)
-        row.widthAnchor.constraint(greaterThanOrEqualToConstant: 780).isActive = true
-        return row
+        scheduleFilterDropdown = button
+        return button
     }
 
     private func makeSchedulePillButton(title: String) -> NSButton {
@@ -2552,36 +2546,15 @@ private extension ViewController {
         googleOAuth.loadTokens() == nil ? "Connect Google to see meetings" : "Loading…"
     }
 
-    private func scheduleFilterTitle(_ filter: ScheduleFilter) -> String {
-        switch filter {
-        case .all: return "All"
-        case .today: return "Today"
-        case .week: return "This week"
-        }
-    }
-
-    private func showScheduleFilterMenu(anchor: NSView) {
-        let menu = NSMenu()
-        let items: [(ScheduleFilter, String)] = [
-            (.all, "All"),
-            (.today, "Today"),
-            (.week, "This week")
-        ]
-        for (filter, title) in items {
-            let item = NSMenuItem(title: title, action: #selector(scheduleFilterSelected(_:)), keyEquivalent: "")
-            item.target = self
-            item.tag = filter.rawValue
-            item.state = (filter == scheduleFilter) ? .on : .off
-            menu.addItem(item)
-        }
-        let loc = NSPoint(x: 8, y: anchor.bounds.height + 2)
-        menu.popUp(positioning: nil, at: loc, in: anchor)
+    @objc func scheduleFilterDropdownChanged(_ sender: NSPopUpButton) {
+        guard let selectedItem = sender.selectedItem,
+              let filter = ScheduleFilter(rawValue: selectedItem.tag) else { return }
+        applyScheduleFilter(filter)
     }
 
-    @objc func scheduleFilterSelected(_ sender: NSMenuItem) {
-        guard let filter = ScheduleFilter(rawValue: sender.tag) else { return }
+    private func applyScheduleFilter(_ filter: ScheduleFilter) {
         scheduleFilter = filter
-        scheduleFilterLabel?.stringValue = scheduleFilterTitle(filter)
+        scheduleFilterDropdown?.selectItem(at: filter.rawValue)
         Task { [weak self] in
             await self?.loadSchedule()
         }