瀏覽代碼

Improve schedule refresh button UI and reload behavior.

Replace the custom refresh hit area with a standard AppKit button and make refresh follow the same reload path as Connect so cards are rebuilt and re-fetched reliably.

Made-with: Cursor
huzaifahayat12 1 周之前
父節點
當前提交
ecc2d063f0
共有 1 個文件被更改,包括 51 次插入14 次删除
  1. 51 14
      meetings_app/ViewController.swift

+ 51 - 14
meetings_app/ViewController.swift

@@ -1800,12 +1800,7 @@ private extension ViewController {
1800 1800
         row.addArrangedSubview(spacer)
1801 1801
         spacer.setContentHuggingPriority(.defaultLow, for: .horizontal)
1802 1802
 
1803
-        row.addArrangedSubview(iconRoundButton("?", size: 34, onClick: { [weak self] in
1804
-            self?.showScheduleHelp()
1805
-        }))
1806
-        row.addArrangedSubview(iconRoundButton("⟳", size: 34, onClick: { [weak self] in
1807
-            self?.scheduleReloadClicked()
1808
-        }))
1803
+        row.addArrangedSubview(makeScheduleRefreshButton())
1809 1804
 
1810 1805
         let connectButton = makeSchedulePillButton(title: googleOAuth.loadTokens() == nil ? "Connect" : "Connected")
1811 1806
         connectButton.target = self
@@ -1871,6 +1866,28 @@ private extension ViewController {
1871 1866
         return button
1872 1867
     }
1873 1868
 
1869
+    private func makeScheduleRefreshButton() -> NSButton {
1870
+        let button = NSButton(title: "", target: self, action: #selector(scheduleReloadButtonPressed(_:)))
1871
+        button.translatesAutoresizingMaskIntoConstraints = false
1872
+        button.isBordered = false
1873
+        button.bezelStyle = .regularSquare
1874
+        button.wantsLayer = true
1875
+        button.layer?.cornerRadius = 21
1876
+        button.layer?.backgroundColor = palette.inputBackground.cgColor
1877
+        button.layer?.borderColor = palette.inputBorder.cgColor
1878
+        button.layer?.borderWidth = 1
1879
+        button.setButtonType(.momentaryChange)
1880
+        button.contentTintColor = palette.textSecondary
1881
+        button.image = NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: "Refresh meetings")
1882
+        button.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 18, weight: .semibold)
1883
+        button.imagePosition = .imageOnly
1884
+        button.imageScaling = .scaleProportionallyDown
1885
+        button.focusRingType = .none
1886
+        button.heightAnchor.constraint(equalToConstant: 42).isActive = true
1887
+        button.widthAnchor.constraint(equalToConstant: 42).isActive = true
1888
+        return button
1889
+    }
1890
+
1874 1891
     func scheduleCardsRow(meetings: [ScheduledMeeting]) -> NSView {
1875 1892
         let scroll = NSScrollView()
1876 1893
         scroll.translatesAutoresizingMaskIntoConstraints = false
@@ -2485,7 +2502,7 @@ private extension ViewController {
2485 2502
         return button
2486 2503
     }
2487 2504
 
2488
-    func iconRoundButton(_ symbol: String, size: CGFloat, onClick: (() -> Void)? = nil) -> NSView {
2505
+    func iconRoundButton(systemSymbol: String, size: CGFloat, iconPointSize: CGFloat = 16, onClick: (() -> Void)? = nil) -> NSView {
2489 2506
         let button = HoverTrackingView()
2490 2507
         button.wantsLayer = true
2491 2508
         button.layer?.cornerRadius = size / 2
@@ -2495,11 +2512,16 @@ private extension ViewController {
2495 2512
         button.heightAnchor.constraint(equalToConstant: size).isActive = true
2496 2513
         styleSurface(button, borderColor: palette.inputBorder, borderWidth: 1, shadow: false)
2497 2514
 
2498
-        let label = textLabel(symbol, font: typography.iconButton, color: palette.textSecondary)
2499
-        button.addSubview(label)
2515
+        let symbolConfig = NSImage.SymbolConfiguration(pointSize: iconPointSize, weight: .semibold)
2516
+        let iconView = NSImageView()
2517
+        iconView.translatesAutoresizingMaskIntoConstraints = false
2518
+        iconView.image = NSImage(systemSymbolName: systemSymbol, accessibilityDescription: "Refresh")
2519
+        iconView.symbolConfiguration = symbolConfig
2520
+        iconView.contentTintColor = palette.textSecondary
2521
+        button.addSubview(iconView)
2500 2522
         NSLayoutConstraint.activate([
2501
-            label.centerXAnchor.constraint(equalTo: button.centerXAnchor),
2502
-            label.centerYAnchor.constraint(equalTo: button.centerYAnchor)
2523
+            iconView.centerXAnchor.constraint(equalTo: button.centerXAnchor),
2524
+            iconView.centerYAnchor.constraint(equalTo: button.centerYAnchor)
2503 2525
         ])
2504 2526
 
2505 2527
         let baseColor = palette.inputBackground
@@ -2518,6 +2540,10 @@ private extension ViewController {
2518 2540
 // MARK: - Schedule actions (OAuth entry)
2519 2541
 
2520 2542
 private extension ViewController {
2543
+    @objc func scheduleReloadButtonPressed(_ sender: NSButton) {
2544
+        scheduleReloadClicked()
2545
+    }
2546
+
2521 2547
     @objc func scheduleConnectButtonPressed(_ sender: NSButton) {
2522 2548
         scheduleConnectClicked()
2523 2549
     }
@@ -2674,11 +2700,22 @@ private extension ViewController {
2674 2700
     }
2675 2701
 
2676 2702
     func scheduleReloadClicked() {
2677
-        // Data loading is wired in the Calendar step.
2678
-        // For now, this triggers a sign-in if needed so the next step can fetch events.
2679 2703
         Task { [weak self] in
2680 2704
             guard let self else { return }
2681
-            _ = try? await googleOAuth.validAccessToken(presentingWindow: view.window)
2705
+            do {
2706
+                try await ensureGoogleClientIdConfigured(presentingWindow: view.window)
2707
+                _ = try await googleOAuth.validAccessToken(presentingWindow: view.window)
2708
+                await MainActor.run {
2709
+                    scheduleDateHeadingLabel?.stringValue = "Refreshing…"
2710
+                    pageCache[.joinMeetings] = nil
2711
+                    showSidebarPage(.joinMeetings)
2712
+                }
2713
+                await loadSchedule()
2714
+            } catch {
2715
+                await MainActor.run {
2716
+                    showSimpleError("Couldn’t refresh schedule.", error: error)
2717
+                }
2718
+            }
2682 2719
         }
2683 2720
     }
2684 2721