Quellcode durchsuchen

Add sidebar navigation state

Make Home sidebar items clickable with stronger selected styling, and hide Home dashboard widgets on Meetings/Scheduler.

Made-with: Cursor
huzaifahayat12 vor 5 Tagen
Ursprung
Commit
a31a516cfe
1 geänderte Dateien mit 107 neuen und 10 gelöschten Zeilen
  1. 107 10
      zoom_app/ViewController.swift

+ 107 - 10
zoom_app/ViewController.swift

@@ -54,10 +54,20 @@ class ViewController: NSViewController {
54
     private weak var meetingsNextDayButton: NSButton?
54
     private weak var meetingsNextDayButton: NSButton?
55
     private weak var meetingsTodayButton: NSButton?
55
     private weak var meetingsTodayButton: NSButton?
56
     private weak var refreshMeetingsButton: NSButton?
56
     private weak var refreshMeetingsButton: NSButton?
57
+    private weak var homeWelcomeLabel: NSTextField?
58
+    private weak var homeTimeLabelView: NSTextField?
59
+    private weak var homeDateLabelView: NSTextField?
60
+    private weak var homeActionsRow: NSView?
61
+    private weak var homeMeetingsPanel: NSView?
62
+    private weak var homePlaceholderLabel: NSTextField?
57
     private weak var homeSearchField: NSTextField?
63
     private weak var homeSearchField: NSTextField?
58
     private weak var homeSearchPill: NSView?
64
     private weak var homeSearchPill: NSView?
59
     private var allScheduledMeetings: [ScheduledMeeting] = []
65
     private var allScheduledMeetings: [ScheduledMeeting] = []
60
     private var selectedMeetingsDayStart: Date = Calendar.current.startOfDay(for: Date())
66
     private var selectedMeetingsDayStart: Date = Calendar.current.startOfDay(for: Date())
67
+    private var selectedHomeSidebarItem: String = "Home"
68
+    private var homeSidebarRowViews: [String: NSView] = [:]
69
+    private var homeSidebarIconViews: [String: NSImageView] = [:]
70
+    private var homeSidebarLabels: [String: NSTextField] = [:]
61
     private var searchTextObserver: NSObjectProtocol?
71
     private var searchTextObserver: NSObjectProtocol?
62
     private var searchShortcutMonitor: Any?
72
     private var searchShortcutMonitor: Any?
63
     private var searchOutsideClickMonitor: Any?
73
     private var searchOutsideClickMonitor: Any?
@@ -160,6 +170,8 @@ class ViewController: NSViewController {
160
         startClock()
170
         startClock()
161
         startMeetingsAutoRefresh()
171
         startMeetingsAutoRefresh()
162
         triggerMeetingsRefresh(force: true)
172
         triggerMeetingsRefresh(force: true)
173
+        updateHomeSidebarHighlight()
174
+        updateSelectedHomeSectionUI()
163
     }
175
     }
164
 
176
 
165
     private func isUserLoggedIn() -> Bool {
177
     private func isUserLoggedIn() -> Bool {
@@ -930,7 +942,10 @@ class ViewController: NSViewController {
930
         let chromeHeader = NSView()
942
         let chromeHeader = NSView()
931
         chromeHeader.wantsLayer = true
943
         chromeHeader.wantsLayer = true
932
         chromeHeader.layer?.backgroundColor = chromeUnifiedBackground.cgColor
944
         chromeHeader.layer?.backgroundColor = chromeUnifiedBackground.cgColor
933
-        let sidebar = makeSidebar(items: ["Home", "Meetings", "Scheduler"], selected: "Home", style: .home)
945
+        homeSidebarRowViews = [:]
946
+        homeSidebarIconViews = [:]
947
+        homeSidebarLabels = [:]
948
+        let sidebar = makeSidebar(items: ["Home", "Meetings", "Scheduler"], selected: selectedHomeSidebarItem, style: .home)
934
         let content = NSView()
949
         let content = NSView()
935
         content.wantsLayer = true
950
         content.wantsLayer = true
936
         content.layer?.backgroundColor = NSColor.clear.cgColor
951
         content.layer?.backgroundColor = NSColor.clear.cgColor
@@ -1140,6 +1155,9 @@ class ViewController: NSViewController {
1140
         refreshMeetingsButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
1155
         refreshMeetingsButton.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
1141
         self.refreshMeetingsButton = refreshMeetingsButton
1156
         self.refreshMeetingsButton = refreshMeetingsButton
1142
 
1157
 
1158
+        let placeholder = makeLabel("Coming soon", size: 22, color: secondaryText, weight: .semibold, centered: true)
1159
+        placeholder.isHidden = true
1160
+
1143
         let contentColumn = NSView()
1161
         let contentColumn = NSView()
1144
         contentColumn.translatesAutoresizingMaskIntoConstraints = false
1162
         contentColumn.translatesAutoresizingMaskIntoConstraints = false
1145
         content.addSubview(topBar)
1163
         content.addSubview(topBar)
@@ -1158,7 +1176,7 @@ class ViewController: NSViewController {
1158
         [searchIcon, searchField, searchHintLabel].forEach {
1176
         [searchIcon, searchField, searchHintLabel].forEach {
1159
             searchPill.addSubview($0)
1177
             searchPill.addSubview($0)
1160
         }
1178
         }
1161
-        [welcome, timeTitle, dateTitle, actions, panel, panelHeader, meetingsStatus, meetingsDayNav, noMeeting, meetingsScrollView, refreshMeetingsButton].forEach {
1179
+        [welcome, timeTitle, dateTitle, actions, panel, panelHeader, meetingsStatus, meetingsDayNav, noMeeting, meetingsScrollView, refreshMeetingsButton, placeholder].forEach {
1162
             $0.translatesAutoresizingMaskIntoConstraints = false
1180
             $0.translatesAutoresizingMaskIntoConstraints = false
1163
             contentColumn.addSubview($0)
1181
             contentColumn.addSubview($0)
1164
         }
1182
         }
@@ -1261,11 +1279,20 @@ class ViewController: NSViewController {
1261
             refreshMeetingsButton.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
1279
             refreshMeetingsButton.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
1262
             refreshMeetingsButton.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
1280
             refreshMeetingsButton.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
1263
             refreshMeetingsButton.bottomAnchor.constraint(equalTo: panel.bottomAnchor, constant: -12),
1281
             refreshMeetingsButton.bottomAnchor.constraint(equalTo: panel.bottomAnchor, constant: -12),
1264
-            refreshMeetingsButton.heightAnchor.constraint(equalToConstant: 40)
1282
+            refreshMeetingsButton.heightAnchor.constraint(equalToConstant: 40),
1283
+
1284
+            placeholder.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
1285
+            placeholder.centerYAnchor.constraint(equalTo: contentColumn.centerYAnchor)
1265
         ])
1286
         ])
1266
 
1287
 
1267
         timeLabel = timeTitle
1288
         timeLabel = timeTitle
1268
         dateLabel = dateTitle
1289
         dateLabel = dateTitle
1290
+        homeWelcomeLabel = welcome
1291
+        homeTimeLabelView = timeTitle
1292
+        homeDateLabelView = dateTitle
1293
+        homeActionsRow = actions
1294
+        homeMeetingsPanel = panel
1295
+        homePlaceholderLabel = placeholder
1269
         meetingsDayHeaderLabel = panelHeader
1296
         meetingsDayHeaderLabel = panelHeader
1270
         meetingsListStack = meetingsStack
1297
         meetingsListStack = meetingsStack
1271
         meetingsStatusLabel = meetingsStatus
1298
         meetingsStatusLabel = meetingsStatus
@@ -1356,16 +1383,24 @@ class ViewController: NSViewController {
1356
 
1383
 
1357
                 let iconView = NSImageView()
1384
                 let iconView = NSImageView()
1358
                 iconView.translatesAutoresizingMaskIntoConstraints = false
1385
                 iconView.translatesAutoresizingMaskIntoConstraints = false
1359
-                iconView.contentTintColor = primaryText
1386
+                iconView.contentTintColor = selectedRow ? primaryText : secondaryText
1360
                 iconView.imageScaling = .scaleProportionallyUpOrDown
1387
                 iconView.imageScaling = .scaleProportionallyUpOrDown
1361
                 iconView.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 20, weight: .regular)
1388
                 iconView.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 20, weight: .regular)
1362
-                iconView.image = NSImage(systemSymbolName: sidebarSymbolName(for: item), accessibilityDescription: item)
1389
+                iconView.image = NSImage(systemSymbolName: sidebarSymbolName(for: item, filled: selectedRow), accessibilityDescription: item)
1363
                 iconContainer.addSubview(iconView)
1390
                 iconContainer.addSubview(iconView)
1364
 
1391
 
1365
                 let label = makeLabel(item, size: 10, color: selectedRow ? primaryText : secondaryText, weight: .regular, centered: true)
1392
                 let label = makeLabel(item, size: 10, color: selectedRow ? primaryText : secondaryText, weight: .regular, centered: true)
1366
                 label.translatesAutoresizingMaskIntoConstraints = false
1393
                 label.translatesAutoresizingMaskIntoConstraints = false
1367
                 row.addSubview(label)
1394
                 row.addSubview(label)
1368
 
1395
 
1396
+                let hit = NSButton(title: "", target: self, action: #selector(homeSidebarItemTapped(_:)))
1397
+                hit.identifier = NSUserInterfaceItemIdentifier(item)
1398
+                hit.isBordered = false
1399
+                hit.bezelStyle = .shadowlessSquare
1400
+                hit.focusRingType = .none
1401
+                hit.translatesAutoresizingMaskIntoConstraints = false
1402
+                row.addSubview(hit, positioned: .above, relativeTo: nil)
1403
+
1369
                 NSLayoutConstraint.activate([
1404
                 NSLayoutConstraint.activate([
1370
                     iconContainer.topAnchor.constraint(equalTo: row.topAnchor, constant: 9),
1405
                     iconContainer.topAnchor.constraint(equalTo: row.topAnchor, constant: 9),
1371
                     iconContainer.centerXAnchor.constraint(equalTo: row.centerXAnchor),
1406
                     iconContainer.centerXAnchor.constraint(equalTo: row.centerXAnchor),
@@ -1379,9 +1414,18 @@ class ViewController: NSViewController {
1379
 
1414
 
1380
                     label.topAnchor.constraint(equalTo: iconContainer.bottomAnchor, constant: 6),
1415
                     label.topAnchor.constraint(equalTo: iconContainer.bottomAnchor, constant: 6),
1381
                     label.centerXAnchor.constraint(equalTo: row.centerXAnchor),
1416
                     label.centerXAnchor.constraint(equalTo: row.centerXAnchor),
1382
-                    label.bottomAnchor.constraint(equalTo: row.bottomAnchor, constant: -8)
1417
+                    label.bottomAnchor.constraint(equalTo: row.bottomAnchor, constant: -8),
1418
+
1419
+                    hit.leadingAnchor.constraint(equalTo: row.leadingAnchor),
1420
+                    hit.trailingAnchor.constraint(equalTo: row.trailingAnchor),
1421
+                    hit.topAnchor.constraint(equalTo: row.topAnchor),
1422
+                    hit.bottomAnchor.constraint(equalTo: row.bottomAnchor)
1383
                 ])
1423
                 ])
1384
 
1424
 
1425
+                homeSidebarRowViews[item] = row
1426
+                homeSidebarIconViews[item] = iconView
1427
+                homeSidebarLabels[item] = label
1428
+
1385
                 if item == "Hub" {
1429
                 if item == "Hub" {
1386
                     let badge = makeSidebarBadge(text: "1")
1430
                     let badge = makeSidebarBadge(text: "1")
1387
                     badge.translatesAutoresizingMaskIntoConstraints = false
1431
                     badge.translatesAutoresizingMaskIntoConstraints = false
@@ -1491,15 +1535,68 @@ class ViewController: NSViewController {
1491
         return sidebar
1535
         return sidebar
1492
     }
1536
     }
1493
 
1537
 
1494
-    private func sidebarSymbolName(for item: String) -> String {
1538
+    @objc private func homeSidebarItemTapped(_ sender: NSButton) {
1539
+        guard let item = sender.identifier?.rawValue else { return }
1540
+        selectedHomeSidebarItem = item
1541
+        updateHomeSidebarHighlight()
1542
+        updateSelectedHomeSectionUI()
1543
+    }
1544
+
1545
+    @MainActor
1546
+    private func updateHomeSidebarHighlight() {
1547
+        for (item, row) in homeSidebarRowViews {
1548
+            let selected = item == selectedHomeSidebarItem
1549
+            row.layer?.backgroundColor = selected ? sidebarActiveBackground.withAlphaComponent(0.95).cgColor : NSColor.clear.cgColor
1550
+            homeSidebarLabels[item]?.textColor = selected ? primaryText : secondaryText
1551
+            homeSidebarIconViews[item]?.contentTintColor = selected ? primaryText : secondaryText
1552
+            let symbolName = sidebarSymbolName(for: item, filled: selected)
1553
+            if let image = NSImage(systemSymbolName: symbolName, accessibilityDescription: item) {
1554
+                homeSidebarIconViews[item]?.image = image
1555
+            }
1556
+        }
1557
+    }
1558
+
1559
+    @MainActor
1560
+    private func updateSelectedHomeSectionUI() {
1561
+        let isHome = selectedHomeSidebarItem == "Home"
1562
+        let title = selectedHomeSidebarItem
1563
+
1564
+        homeWelcomeLabel?.stringValue = title
1565
+
1566
+        let dashboardViews: [NSView?] = [
1567
+            homeTimeLabelView,
1568
+            homeDateLabelView,
1569
+            homeActionsRow,
1570
+            homeMeetingsPanel,
1571
+            meetingsDayHeaderLabel,
1572
+            meetingsStatusLabel,
1573
+            meetingsPrevDayButton,
1574
+            meetingsTodayButton,
1575
+            meetingsNextDayButton,
1576
+            emptyMeetingLabel,
1577
+            meetingsScrollView,
1578
+            refreshMeetingsButton
1579
+        ]
1580
+        dashboardViews.forEach { $0?.isHidden = isHome == false }
1581
+
1582
+        if isHome {
1583
+            homePlaceholderLabel?.isHidden = true
1584
+        } else {
1585
+            // Keep non-Home pages empty for now.
1586
+            homePlaceholderLabel?.isHidden = true
1587
+        }
1588
+    }
1589
+
1590
+    private func sidebarSymbolName(for item: String, filled: Bool = false) -> String {
1495
         switch item {
1591
         switch item {
1496
         case "Home":
1592
         case "Home":
1497
-            return "house"
1593
+            return filled ? "house.fill" : "house"
1498
         case "Meetings":
1594
         case "Meetings":
1499
-            return "video"
1595
+            return filled ? "video.fill" : "video"
1500
         case "Chat":
1596
         case "Chat":
1501
-            return "message"
1597
+            return filled ? "message.fill" : "message"
1502
         case "Scheduler":
1598
         case "Scheduler":
1599
+            // `calendar.badge.clock.fill` is not available on macOS; keep a stable symbol.
1503
             return "calendar.badge.clock"
1600
             return "calendar.badge.clock"
1504
         case "Hub":
1601
         case "Hub":
1505
             return "square.grid.3x3"
1602
             return "square.grid.3x3"