|
@@ -20,6 +20,14 @@ class ViewController: NSViewController {
|
|
20
|
private let sidebarActiveBackground = NSColor(calibratedRed: 22 / 255, green: 23 / 255, blue: 26 / 255, alpha: 1)
|
20
|
private let sidebarActiveBackground = NSColor(calibratedRed: 22 / 255, green: 23 / 255, blue: 26 / 255, alpha: 1)
|
|
21
|
private let cardBackground = NSColor(calibratedRed: 20 / 255, green: 21 / 255, blue: 24 / 255, alpha: 1)
|
21
|
private let cardBackground = NSColor(calibratedRed: 20 / 255, green: 21 / 255, blue: 24 / 255, alpha: 1)
|
|
22
|
private let secondaryCardBackground = NSColor(calibratedRed: 26 / 255, green: 28 / 255, blue: 33 / 255, alpha: 1)
|
22
|
private let secondaryCardBackground = NSColor(calibratedRed: 26 / 255, green: 28 / 255, blue: 33 / 255, alpha: 1)
|
|
|
|
23
|
+ private let appShellBackground = NSColor(calibratedRed: 13 / 255, green: 14 / 255, blue: 17 / 255, alpha: 1)
|
|
|
|
24
|
+ private let contentShellBackground = NSColor(calibratedRed: 14 / 255, green: 15 / 255, blue: 19 / 255, alpha: 1)
|
|
|
|
25
|
+ private let topStripBackground = NSColor(calibratedRed: 28 / 255, green: 30 / 255, blue: 36 / 255, alpha: 1)
|
|
|
|
26
|
+ private let searchPillBackground = NSColor.white.withAlphaComponent(0.06)
|
|
|
|
27
|
+ private let meetingCardBackground = NSColor(calibratedRed: 38 / 255, green: 43 / 255, blue: 58 / 255, alpha: 1)
|
|
|
|
28
|
+ private let titleBarControlBackground = NSColor.white.withAlphaComponent(0.04)
|
|
|
|
29
|
+ private let titleBarLightControlBackground = NSColor.white.withAlphaComponent(0.02)
|
|
|
|
30
|
+ private let appShellCornerRadius: CGFloat = 20
|
|
23
|
private let accentBlue = NSColor(calibratedRed: 56 / 255, green: 132 / 255, blue: 255 / 255, alpha: 1)
|
31
|
private let accentBlue = NSColor(calibratedRed: 56 / 255, green: 132 / 255, blue: 255 / 255, alpha: 1)
|
|
24
|
private let accentOrange = NSColor(calibratedRed: 241 / 255, green: 116 / 255, blue: 49 / 255, alpha: 1)
|
32
|
private let accentOrange = NSColor(calibratedRed: 241 / 255, green: 116 / 255, blue: 49 / 255, alpha: 1)
|
|
25
|
private let primaryText = NSColor(calibratedWhite: 0.98, alpha: 1)
|
33
|
private let primaryText = NSColor(calibratedWhite: 0.98, alpha: 1)
|
|
@@ -48,6 +56,11 @@ class ViewController: NSViewController {
|
|
48
|
private var lastScrollEdgeRefreshAt = Date.distantPast
|
56
|
private var lastScrollEdgeRefreshAt = Date.distantPast
|
|
49
|
private let meetingsRefreshInterval: TimeInterval = 8
|
57
|
private let meetingsRefreshInterval: TimeInterval = 8
|
|
50
|
private let scrollRefreshCooldown: TimeInterval = 3
|
58
|
private let scrollRefreshCooldown: TimeInterval = 3
|
|
|
|
59
|
+
|
|
|
|
60
|
+ private enum SidebarStyle {
|
|
|
|
61
|
+ case login
|
|
|
|
62
|
+ case home
|
|
|
|
63
|
+ }
|
|
51
|
|
64
|
|
|
52
|
override func viewDidLoad() {
|
65
|
override func viewDidLoad() {
|
|
53
|
super.viewDidLoad()
|
66
|
super.viewDidLoad()
|
|
@@ -209,6 +222,10 @@ class ViewController: NSViewController {
|
|
209
|
persistLoggedInState(false)
|
222
|
persistLoggedInState(false)
|
|
210
|
showLoginView()
|
223
|
showLoginView()
|
|
211
|
}
|
224
|
}
|
|
|
|
225
|
+
|
|
|
|
226
|
+ @objc private func topBarPlaceholderTapped() {
|
|
|
|
227
|
+ // Reserved for future titlebar control actions.
|
|
|
|
228
|
+ }
|
|
212
|
|
229
|
|
|
213
|
private func startMeetingsAutoRefresh() {
|
230
|
private func startMeetingsAutoRefresh() {
|
|
214
|
meetingsRefreshTimer?.invalidate()
|
231
|
meetingsRefreshTimer?.invalidate()
|
|
@@ -520,7 +537,7 @@ class ViewController: NSViewController {
|
|
520
|
|
537
|
|
|
521
|
private func makeLoginView() -> NSView {
|
538
|
private func makeLoginView() -> NSView {
|
|
522
|
let root = NSView()
|
539
|
let root = NSView()
|
|
523
|
- let sidebar = makeSidebar(items: ["Home", "Chat", "Phone", "Docs", "Whiteboards", "Clips", "More"], selected: "Home")
|
|
|
|
|
|
540
|
+ let sidebar = makeSidebar(items: ["Home", "Chat", "Phone", "Docs", "Whiteboards", "Clips", "More"], selected: "Home", style: .login)
|
|
524
|
let content = NSView()
|
541
|
let content = NSView()
|
|
525
|
|
542
|
|
|
526
|
root.addSubview(sidebar)
|
543
|
root.addSubview(sidebar)
|
|
@@ -625,53 +642,91 @@ class ViewController: NSViewController {
|
|
625
|
|
642
|
|
|
626
|
private func makeHomeView(profile: GoogleUserProfile?) -> NSView {
|
643
|
private func makeHomeView(profile: GoogleUserProfile?) -> NSView {
|
|
627
|
let root = NSView()
|
644
|
let root = NSView()
|
|
628
|
- let sidebar = makeSidebar(items: ["Home", "Meetings", "Chat", "Scheduler", "Hub", "More"], selected: "Home")
|
|
|
|
|
|
645
|
+ let shell = NSView()
|
|
|
|
646
|
+ shell.wantsLayer = true
|
|
|
|
647
|
+ shell.layer?.backgroundColor = appShellBackground.cgColor
|
|
|
|
648
|
+ shell.layer?.cornerRadius = appShellCornerRadius
|
|
|
|
649
|
+ shell.layer?.borderWidth = 1
|
|
|
|
650
|
+ shell.layer?.borderColor = NSColor.white.withAlphaComponent(0.06).cgColor
|
|
|
|
651
|
+ let sidebar = makeSidebar(items: ["Home", "Meetings", "Chat", "Scheduler", "Hub", "More"], selected: "Home", style: .home)
|
|
629
|
let content = NSView()
|
652
|
let content = NSView()
|
|
|
|
653
|
+ content.wantsLayer = true
|
|
|
|
654
|
+ content.layer?.backgroundColor = NSColor.clear.cgColor
|
|
630
|
|
655
|
|
|
631
|
- root.addSubview(sidebar)
|
|
|
|
632
|
- root.addSubview(content)
|
|
|
|
|
|
656
|
+ root.addSubview(shell)
|
|
|
|
657
|
+ shell.addSubview(sidebar)
|
|
|
|
658
|
+ shell.addSubview(content)
|
|
|
|
659
|
+ shell.translatesAutoresizingMaskIntoConstraints = false
|
|
633
|
sidebar.translatesAutoresizingMaskIntoConstraints = false
|
660
|
sidebar.translatesAutoresizingMaskIntoConstraints = false
|
|
634
|
content.translatesAutoresizingMaskIntoConstraints = false
|
661
|
content.translatesAutoresizingMaskIntoConstraints = false
|
|
635
|
|
662
|
|
|
636
|
NSLayoutConstraint.activate([
|
663
|
NSLayoutConstraint.activate([
|
|
637
|
- sidebar.leadingAnchor.constraint(equalTo: root.leadingAnchor),
|
|
|
|
638
|
- sidebar.topAnchor.constraint(equalTo: root.topAnchor),
|
|
|
|
639
|
- sidebar.bottomAnchor.constraint(equalTo: root.bottomAnchor),
|
|
|
|
|
|
664
|
+ shell.leadingAnchor.constraint(equalTo: root.leadingAnchor, constant: 10),
|
|
|
|
665
|
+ shell.trailingAnchor.constraint(equalTo: root.trailingAnchor, constant: -10),
|
|
|
|
666
|
+ shell.topAnchor.constraint(equalTo: root.topAnchor, constant: 10),
|
|
|
|
667
|
+ shell.bottomAnchor.constraint(equalTo: root.bottomAnchor, constant: -10),
|
|
|
|
668
|
+ sidebar.leadingAnchor.constraint(equalTo: shell.leadingAnchor),
|
|
|
|
669
|
+ sidebar.topAnchor.constraint(equalTo: shell.topAnchor),
|
|
|
|
670
|
+ sidebar.bottomAnchor.constraint(equalTo: shell.bottomAnchor),
|
|
640
|
sidebar.widthAnchor.constraint(equalToConstant: sidebarWidth),
|
671
|
sidebar.widthAnchor.constraint(equalToConstant: sidebarWidth),
|
|
641
|
content.leadingAnchor.constraint(equalTo: sidebar.trailingAnchor),
|
672
|
content.leadingAnchor.constraint(equalTo: sidebar.trailingAnchor),
|
|
642
|
- content.trailingAnchor.constraint(equalTo: root.trailingAnchor),
|
|
|
|
643
|
- content.topAnchor.constraint(equalTo: root.topAnchor),
|
|
|
|
644
|
- content.bottomAnchor.constraint(equalTo: root.bottomAnchor)
|
|
|
|
|
|
673
|
+ content.trailingAnchor.constraint(equalTo: shell.trailingAnchor),
|
|
|
|
674
|
+ content.topAnchor.constraint(equalTo: shell.topAnchor),
|
|
|
|
675
|
+ content.bottomAnchor.constraint(equalTo: shell.bottomAnchor)
|
|
645
|
])
|
676
|
])
|
|
646
|
|
677
|
|
|
647
|
let topBar = NSView()
|
678
|
let topBar = NSView()
|
|
648
|
topBar.wantsLayer = true
|
679
|
topBar.wantsLayer = true
|
|
649
|
- topBar.layer?.backgroundColor = cardBackground.cgColor
|
|
|
|
650
|
- topBar.layer?.cornerRadius = 12
|
|
|
|
651
|
- topBar.layer?.borderWidth = 1
|
|
|
|
652
|
- topBar.layer?.borderColor = NSColor.white.withAlphaComponent(0.06).cgColor
|
|
|
|
|
|
680
|
+ topBar.layer?.backgroundColor = topStripBackground.withAlphaComponent(0.88).cgColor
|
|
|
|
681
|
+
|
|
|
|
682
|
+ let topBarDivider = NSView()
|
|
|
|
683
|
+ topBarDivider.wantsLayer = true
|
|
|
|
684
|
+ topBarDivider.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.06).cgColor
|
|
653
|
|
685
|
|
|
654
|
let searchPill = NSView()
|
686
|
let searchPill = NSView()
|
|
655
|
searchPill.wantsLayer = true
|
687
|
searchPill.wantsLayer = true
|
|
656
|
- searchPill.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.05).cgColor
|
|
|
|
657
|
- searchPill.layer?.cornerRadius = 9
|
|
|
|
658
|
- let search = makeLabel("Search meetings, people (\u{2318}E)", size: 13, color: mutedText, weight: .regular, centered: false)
|
|
|
|
659
|
-
|
|
|
|
660
|
- let profileChip = NSView()
|
|
|
|
|
|
688
|
+ searchPill.layer?.backgroundColor = searchPillBackground.cgColor
|
|
|
|
689
|
+ searchPill.layer?.cornerRadius = 10
|
|
|
|
690
|
+ let search = makeLabel("Search (\u{2318}E)", size: 13, color: mutedText, weight: .regular, centered: true)
|
|
|
|
691
|
+
|
|
|
|
692
|
+ let brandStack = NSStackView()
|
|
|
|
693
|
+ brandStack.orientation = .vertical
|
|
|
|
694
|
+ brandStack.spacing = 0
|
|
|
|
695
|
+ brandStack.alignment = .leading
|
|
|
|
696
|
+ let brandTop = makeLabel("zoom", size: 14, color: primaryText, weight: .semibold, centered: false)
|
|
|
|
697
|
+ let brandBottom = makeLabel("Workplace", size: 27, color: primaryText, weight: .bold, centered: false)
|
|
|
|
698
|
+ brandBottom.font = .systemFont(ofSize: 14, weight: .bold)
|
|
|
|
699
|
+ [brandTop, brandBottom].forEach { brandStack.addArrangedSubview($0) }
|
|
|
|
700
|
+
|
|
|
|
701
|
+ let leftTopBarCluster = NSStackView()
|
|
|
|
702
|
+ leftTopBarCluster.orientation = .horizontal
|
|
|
|
703
|
+ leftTopBarCluster.spacing = 10
|
|
|
|
704
|
+ leftTopBarCluster.alignment = .centerY
|
|
|
|
705
|
+ let backButton = makeTopBarGlyphButton(symbol: "chevron.left", action: #selector(topBarPlaceholderTapped))
|
|
|
|
706
|
+ let forwardButton = makeTopBarGlyphButton(symbol: "chevron.right", action: #selector(topBarPlaceholderTapped))
|
|
|
|
707
|
+ let historyButton = makeTopBarGlyphButton(symbol: "clock.arrow.circlepath", action: #selector(topBarPlaceholderTapped))
|
|
|
|
708
|
+ [backButton, forwardButton, historyButton].forEach { leftTopBarCluster.addArrangedSubview($0) }
|
|
|
|
709
|
+
|
|
|
|
710
|
+ let rightTopBarCluster = NSStackView()
|
|
|
|
711
|
+ rightTopBarCluster.orientation = .horizontal
|
|
|
|
712
|
+ rightTopBarCluster.spacing = 8
|
|
|
|
713
|
+ rightTopBarCluster.alignment = .centerY
|
|
|
|
714
|
+ let plusButton = makeTopBarGlyphButton(symbol: "plus", action: #selector(topBarPlaceholderTapped))
|
|
|
|
715
|
+ let notificationButton = makeTopBarGlyphButton(symbol: "bell", action: #selector(topBarPlaceholderTapped))
|
|
|
|
716
|
+ let appsButton = makeTopBarIconButton(symbol: "square.grid.2x2", action: #selector(topBarPlaceholderTapped))
|
|
|
|
717
|
+
|
|
|
|
718
|
+ let profileChip = NSButton(title: String((profile?.name ?? "H").prefix(1)).uppercased(), target: self, action: #selector(logoutTapped))
|
|
|
|
719
|
+ profileChip.isBordered = false
|
|
661
|
profileChip.wantsLayer = true
|
720
|
profileChip.wantsLayer = true
|
|
662
|
- profileChip.layer?.backgroundColor = accentBlue.withAlphaComponent(0.22).cgColor
|
|
|
|
663
|
- profileChip.layer?.cornerRadius = 9
|
|
|
|
664
|
- let name = makeLabel(profile?.name ?? "User", size: 13, color: primaryText, weight: .semibold, centered: false)
|
|
|
|
665
|
- let logoutButton = NSButton(title: "Logout", target: self, action: #selector(logoutTapped))
|
|
|
|
666
|
- logoutButton.isBordered = false
|
|
|
|
667
|
- logoutButton.font = .systemFont(ofSize: 13, weight: .semibold)
|
|
|
|
668
|
- logoutButton.contentTintColor = primaryText
|
|
|
|
669
|
- logoutButton.wantsLayer = true
|
|
|
|
670
|
- logoutButton.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.07).cgColor
|
|
|
|
671
|
- logoutButton.layer?.cornerRadius = 8
|
|
|
|
|
|
721
|
+ profileChip.layer?.backgroundColor = accentBlue.withAlphaComponent(0.75).cgColor
|
|
|
|
722
|
+ profileChip.layer?.cornerRadius = 10
|
|
|
|
723
|
+ profileChip.contentTintColor = primaryText
|
|
|
|
724
|
+ profileChip.font = .systemFont(ofSize: 14, weight: .bold)
|
|
|
|
725
|
+ profileChip.toolTip = "Profile (click to logout)"
|
|
|
|
726
|
+ [plusButton, notificationButton, appsButton, profileChip].forEach { rightTopBarCluster.addArrangedSubview($0) }
|
|
672
|
|
727
|
|
|
673
|
let welcome = makeLabel("Home", size: 15, color: secondaryText, weight: .medium, centered: false)
|
728
|
let welcome = makeLabel("Home", size: 15, color: secondaryText, weight: .medium, centered: false)
|
|
674
|
- let timeTitle = makeLabel("--:--", size: 50, color: primaryText, weight: .bold, centered: true)
|
|
|
|
|
|
729
|
+ let timeTitle = makeLabel("--:--", size: 56, color: primaryText, weight: .bold, centered: true)
|
|
675
|
let dateTitle = makeLabel("-", size: 16, color: secondaryText, weight: .regular, centered: true)
|
730
|
let dateTitle = makeLabel("-", size: 16, color: secondaryText, weight: .regular, centered: true)
|
|
676
|
|
731
|
|
|
677
|
let actions = NSStackView(views: [
|
732
|
let actions = NSStackView(views: [
|
|
@@ -688,14 +743,19 @@ class ViewController: NSViewController {
|
|
688
|
|
743
|
|
|
689
|
let panel = NSView()
|
744
|
let panel = NSView()
|
|
690
|
panel.wantsLayer = true
|
745
|
panel.wantsLayer = true
|
|
691
|
- panel.layer?.backgroundColor = secondaryCardBackground.cgColor
|
|
|
|
|
|
746
|
+ panel.layer?.backgroundColor = secondaryCardBackground.withAlphaComponent(0.94).cgColor
|
|
692
|
panel.layer?.cornerRadius = 16
|
747
|
panel.layer?.cornerRadius = 16
|
|
693
|
panel.layer?.borderWidth = 1
|
748
|
panel.layer?.borderWidth = 1
|
|
694
|
panel.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
|
749
|
panel.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
|
|
|
|
750
|
+
|
|
|
|
751
|
+ let panelHeaderStrip = NSView()
|
|
|
|
752
|
+ panelHeaderStrip.wantsLayer = true
|
|
|
|
753
|
+ panelHeaderStrip.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.03).cgColor
|
|
|
|
754
|
+ panelHeaderStrip.layer?.cornerRadius = 12
|
|
695
|
|
755
|
|
|
696
|
let todaysDateFormatter = DateFormatter()
|
756
|
let todaysDateFormatter = DateFormatter()
|
|
697
|
todaysDateFormatter.dateFormat = "EEEE, MMM d"
|
757
|
todaysDateFormatter.dateFormat = "EEEE, MMM d"
|
|
698
|
- let panelHeader = makeLabel(todaysDateFormatter.string(from: Date()), size: 22, color: primaryText, weight: .semibold, centered: false)
|
|
|
|
|
|
758
|
+ let panelHeader = makeLabel(todaysDateFormatter.string(from: Date()), size: 21, color: primaryText, weight: .semibold, centered: false)
|
|
699
|
let meetingsStatus = makeLabel("Upcoming meetings", size: 12, color: secondaryText, weight: .medium, centered: false)
|
759
|
let meetingsStatus = makeLabel("Upcoming meetings", size: 12, color: secondaryText, weight: .medium, centered: false)
|
|
700
|
let noMeeting = makeLabel("No meetings scheduled for today.", size: 18, color: secondaryText, weight: .regular, centered: true)
|
760
|
let noMeeting = makeLabel("No meetings scheduled for today.", size: 18, color: secondaryText, weight: .regular, centered: true)
|
|
701
|
let meetingsScrollView = NSScrollView()
|
761
|
let meetingsScrollView = NSScrollView()
|
|
@@ -714,7 +774,7 @@ class ViewController: NSViewController {
|
|
714
|
openRecordings.font = .systemFont(ofSize: 14, weight: .semibold)
|
774
|
openRecordings.font = .systemFont(ofSize: 14, weight: .semibold)
|
|
715
|
openRecordings.contentTintColor = primaryText
|
775
|
openRecordings.contentTintColor = primaryText
|
|
716
|
openRecordings.wantsLayer = true
|
776
|
openRecordings.wantsLayer = true
|
|
717
|
- openRecordings.layer?.backgroundColor = NSColor(calibratedRed: 31 / 255, green: 33 / 255, blue: 39 / 255, alpha: 1).cgColor
|
|
|
|
|
|
777
|
+ openRecordings.layer?.backgroundColor = NSColor(calibratedRed: 36 / 255, green: 39 / 255, blue: 46 / 255, alpha: 1).cgColor
|
|
718
|
openRecordings.layer?.cornerRadius = 11
|
778
|
openRecordings.layer?.cornerRadius = 11
|
|
719
|
openRecordings.layer?.borderWidth = 1
|
779
|
openRecordings.layer?.borderWidth = 1
|
|
720
|
openRecordings.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
|
780
|
openRecordings.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
|
|
@@ -723,7 +783,7 @@ class ViewController: NSViewController {
|
|
723
|
contentColumn.translatesAutoresizingMaskIntoConstraints = false
|
783
|
contentColumn.translatesAutoresizingMaskIntoConstraints = false
|
|
724
|
content.addSubview(contentColumn)
|
784
|
content.addSubview(contentColumn)
|
|
725
|
|
785
|
|
|
726
|
- [topBar, searchPill, search, profileChip, name, logoutButton, welcome, timeTitle, dateTitle, actions, panel, panelHeader, meetingsStatus, noMeeting, meetingsScrollView, openRecordings].forEach {
|
|
|
|
|
|
786
|
+ [topBar, topBarDivider, brandStack, leftTopBarCluster, rightTopBarCluster, searchPill, search, welcome, timeTitle, dateTitle, actions, panel, panelHeaderStrip, panelHeader, meetingsStatus, noMeeting, meetingsScrollView, openRecordings].forEach {
|
|
727
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
787
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
728
|
contentColumn.addSubview($0)
|
788
|
contentColumn.addSubview($0)
|
|
729
|
}
|
789
|
}
|
|
@@ -735,64 +795,72 @@ class ViewController: NSViewController {
|
|
735
|
NSLayoutConstraint.activate([
|
795
|
NSLayoutConstraint.activate([
|
|
736
|
contentColumn.topAnchor.constraint(equalTo: content.topAnchor),
|
796
|
contentColumn.topAnchor.constraint(equalTo: content.topAnchor),
|
|
737
|
contentColumn.bottomAnchor.constraint(equalTo: content.bottomAnchor),
|
797
|
contentColumn.bottomAnchor.constraint(equalTo: content.bottomAnchor),
|
|
738
|
- contentColumn.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 20),
|
|
|
|
739
|
- contentColumn.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -20),
|
|
|
|
740
|
-
|
|
|
|
741
|
- topBar.topAnchor.constraint(equalTo: contentColumn.topAnchor, constant: 12),
|
|
|
|
742
|
- topBar.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor, constant: 12),
|
|
|
|
743
|
- topBar.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor, constant: -12),
|
|
|
|
744
|
- topBar.heightAnchor.constraint(equalToConstant: 50),
|
|
|
|
745
|
-
|
|
|
|
746
|
- searchPill.leadingAnchor.constraint(equalTo: topBar.leadingAnchor, constant: 12),
|
|
|
|
|
|
798
|
+ contentColumn.leadingAnchor.constraint(equalTo: content.leadingAnchor),
|
|
|
|
799
|
+ contentColumn.trailingAnchor.constraint(equalTo: content.trailingAnchor),
|
|
|
|
800
|
+
|
|
|
|
801
|
+ topBar.topAnchor.constraint(equalTo: contentColumn.topAnchor),
|
|
|
|
802
|
+ topBar.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor),
|
|
|
|
803
|
+ topBar.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor),
|
|
|
|
804
|
+ topBar.heightAnchor.constraint(equalToConstant: 48),
|
|
|
|
805
|
+ topBarDivider.topAnchor.constraint(equalTo: topBar.bottomAnchor),
|
|
|
|
806
|
+ topBarDivider.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor),
|
|
|
|
807
|
+ topBarDivider.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor),
|
|
|
|
808
|
+ topBarDivider.heightAnchor.constraint(equalToConstant: 1),
|
|
|
|
809
|
+
|
|
|
|
810
|
+ brandStack.leadingAnchor.constraint(equalTo: topBar.leadingAnchor, constant: 12),
|
|
|
|
811
|
+ brandStack.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
|
|
|
|
812
|
+
|
|
|
|
813
|
+ leftTopBarCluster.leadingAnchor.constraint(equalTo: brandStack.trailingAnchor, constant: 18),
|
|
|
|
814
|
+ leftTopBarCluster.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
|
|
|
|
815
|
+ rightTopBarCluster.trailingAnchor.constraint(equalTo: topBar.trailingAnchor, constant: -12),
|
|
|
|
816
|
+ rightTopBarCluster.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
|
|
|
|
817
|
+
|
|
|
|
818
|
+ searchPill.centerXAnchor.constraint(equalTo: topBar.centerXAnchor),
|
|
747
|
searchPill.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
|
819
|
searchPill.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
|
|
748
|
searchPill.heightAnchor.constraint(equalToConstant: 32),
|
820
|
searchPill.heightAnchor.constraint(equalToConstant: 32),
|
|
749
|
searchPill.widthAnchor.constraint(equalToConstant: 320),
|
821
|
searchPill.widthAnchor.constraint(equalToConstant: 320),
|
|
|
|
822
|
+ searchPill.leadingAnchor.constraint(greaterThanOrEqualTo: leftTopBarCluster.trailingAnchor, constant: 12),
|
|
|
|
823
|
+ searchPill.trailingAnchor.constraint(lessThanOrEqualTo: rightTopBarCluster.leadingAnchor, constant: -12),
|
|
750
|
search.leadingAnchor.constraint(equalTo: searchPill.leadingAnchor, constant: 12),
|
824
|
search.leadingAnchor.constraint(equalTo: searchPill.leadingAnchor, constant: 12),
|
|
751
|
search.trailingAnchor.constraint(equalTo: searchPill.trailingAnchor, constant: -12),
|
825
|
search.trailingAnchor.constraint(equalTo: searchPill.trailingAnchor, constant: -12),
|
|
752
|
search.centerYAnchor.constraint(equalTo: searchPill.centerYAnchor),
|
826
|
search.centerYAnchor.constraint(equalTo: searchPill.centerYAnchor),
|
|
|
|
827
|
+ profileChip.widthAnchor.constraint(equalToConstant: 34),
|
|
|
|
828
|
+ profileChip.heightAnchor.constraint(equalToConstant: 34),
|
|
753
|
|
829
|
|
|
754
|
- profileChip.trailingAnchor.constraint(equalTo: topBar.trailingAnchor, constant: -10),
|
|
|
|
755
|
- profileChip.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
|
|
|
|
756
|
- profileChip.heightAnchor.constraint(equalToConstant: 32),
|
|
|
|
757
|
- profileChip.widthAnchor.constraint(greaterThanOrEqualToConstant: 92),
|
|
|
|
758
|
- name.leadingAnchor.constraint(equalTo: profileChip.leadingAnchor, constant: 12),
|
|
|
|
759
|
- name.trailingAnchor.constraint(equalTo: profileChip.trailingAnchor, constant: -12),
|
|
|
|
760
|
- name.centerYAnchor.constraint(equalTo: profileChip.centerYAnchor),
|
|
|
|
761
|
-
|
|
|
|
762
|
- logoutButton.trailingAnchor.constraint(equalTo: profileChip.leadingAnchor, constant: -10),
|
|
|
|
763
|
- logoutButton.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
|
|
|
|
764
|
- logoutButton.widthAnchor.constraint(equalToConstant: 76),
|
|
|
|
765
|
- logoutButton.heightAnchor.constraint(equalToConstant: 32),
|
|
|
|
766
|
-
|
|
|
|
767
|
- welcome.topAnchor.constraint(equalTo: topBar.bottomAnchor, constant: 18),
|
|
|
|
|
|
830
|
+ welcome.topAnchor.constraint(equalTo: topBar.bottomAnchor, constant: 22),
|
|
768
|
welcome.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
831
|
welcome.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
|
769
|
|
832
|
|
|
770
|
- timeTitle.topAnchor.constraint(equalTo: welcome.bottomAnchor, constant: 14),
|
|
|
|
|
|
833
|
+ timeTitle.topAnchor.constraint(equalTo: welcome.bottomAnchor, constant: 12),
|
|
771
|
timeTitle.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
834
|
timeTitle.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
|
772
|
dateTitle.topAnchor.constraint(equalTo: timeTitle.bottomAnchor, constant: 6),
|
835
|
dateTitle.topAnchor.constraint(equalTo: timeTitle.bottomAnchor, constant: 6),
|
|
773
|
dateTitle.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
836
|
dateTitle.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
|
774
|
|
837
|
|
|
775
|
- actions.topAnchor.constraint(equalTo: dateTitle.bottomAnchor, constant: 30),
|
|
|
|
|
|
838
|
+ actions.topAnchor.constraint(equalTo: dateTitle.bottomAnchor, constant: 28),
|
|
776
|
actions.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
839
|
actions.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
|
|
777
|
actions.leadingAnchor.constraint(greaterThanOrEqualTo: contentColumn.leadingAnchor, constant: 18),
|
840
|
actions.leadingAnchor.constraint(greaterThanOrEqualTo: contentColumn.leadingAnchor, constant: 18),
|
|
778
|
actions.trailingAnchor.constraint(lessThanOrEqualTo: contentColumn.trailingAnchor, constant: -18),
|
841
|
actions.trailingAnchor.constraint(lessThanOrEqualTo: contentColumn.trailingAnchor, constant: -18),
|
|
779
|
- actions.heightAnchor.constraint(equalToConstant: 96),
|
|
|
|
|
|
842
|
+ actions.heightAnchor.constraint(equalToConstant: 100),
|
|
780
|
|
843
|
|
|
781
|
- panel.topAnchor.constraint(equalTo: actions.bottomAnchor, constant: 24),
|
|
|
|
782
|
- panel.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor, constant: 28),
|
|
|
|
783
|
- panel.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor, constant: -28),
|
|
|
|
784
|
- panel.heightAnchor.constraint(equalToConstant: 300),
|
|
|
|
|
|
844
|
+ panel.topAnchor.constraint(equalTo: actions.bottomAnchor, constant: 22),
|
|
|
|
845
|
+ panel.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor, constant: 26),
|
|
|
|
846
|
+ panel.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor, constant: -26),
|
|
|
|
847
|
+ panel.heightAnchor.constraint(equalToConstant: 316),
|
|
785
|
panel.bottomAnchor.constraint(lessThanOrEqualTo: contentColumn.bottomAnchor, constant: -20),
|
848
|
panel.bottomAnchor.constraint(lessThanOrEqualTo: contentColumn.bottomAnchor, constant: -20),
|
|
786
|
-
|
|
|
|
787
|
- panelHeader.topAnchor.constraint(equalTo: panel.topAnchor, constant: 16),
|
|
|
|
788
|
- panelHeader.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 18),
|
|
|
|
789
|
- meetingsStatus.centerYAnchor.constraint(equalTo: panelHeader.centerYAnchor),
|
|
|
|
790
|
- meetingsStatus.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -18),
|
|
|
|
|
|
849
|
+
|
|
|
|
850
|
+ panelHeaderStrip.topAnchor.constraint(equalTo: panel.topAnchor, constant: 10),
|
|
|
|
851
|
+ panelHeaderStrip.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 10),
|
|
|
|
852
|
+ panelHeaderStrip.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -10),
|
|
|
|
853
|
+ panelHeaderStrip.heightAnchor.constraint(equalToConstant: 44),
|
|
|
|
854
|
+
|
|
|
|
855
|
+ panelHeader.centerYAnchor.constraint(equalTo: panelHeaderStrip.centerYAnchor),
|
|
|
|
856
|
+ panelHeader.leadingAnchor.constraint(equalTo: panelHeaderStrip.leadingAnchor, constant: 14),
|
|
|
|
857
|
+ meetingsStatus.centerYAnchor.constraint(equalTo: panelHeaderStrip.centerYAnchor),
|
|
|
|
858
|
+ meetingsStatus.trailingAnchor.constraint(equalTo: panelHeaderStrip.trailingAnchor, constant: -14),
|
|
791
|
noMeeting.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 18),
|
859
|
noMeeting.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 18),
|
|
792
|
noMeeting.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -18),
|
860
|
noMeeting.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -18),
|
|
793
|
noMeeting.centerYAnchor.constraint(equalTo: panel.centerYAnchor),
|
861
|
noMeeting.centerYAnchor.constraint(equalTo: panel.centerYAnchor),
|
|
794
|
|
862
|
|
|
795
|
- meetingsScrollView.topAnchor.constraint(equalTo: panel.topAnchor, constant: 58),
|
|
|
|
|
|
863
|
+ meetingsScrollView.topAnchor.constraint(equalTo: panelHeaderStrip.bottomAnchor, constant: 10),
|
|
796
|
meetingsScrollView.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
|
864
|
meetingsScrollView.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
|
|
797
|
meetingsScrollView.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
|
865
|
meetingsScrollView.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
|
|
798
|
meetingsScrollView.bottomAnchor.constraint(equalTo: openRecordings.topAnchor, constant: -14),
|
866
|
meetingsScrollView.bottomAnchor.constraint(equalTo: openRecordings.topAnchor, constant: -14),
|
|
@@ -806,7 +874,7 @@ class ViewController: NSViewController {
|
|
806
|
openRecordings.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
|
874
|
openRecordings.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 14),
|
|
807
|
openRecordings.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
|
875
|
openRecordings.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -14),
|
|
808
|
openRecordings.bottomAnchor.constraint(equalTo: panel.bottomAnchor, constant: -12),
|
876
|
openRecordings.bottomAnchor.constraint(equalTo: panel.bottomAnchor, constant: -12),
|
|
809
|
- openRecordings.heightAnchor.constraint(equalToConstant: 38)
|
|
|
|
|
|
877
|
+ openRecordings.heightAnchor.constraint(equalToConstant: 40)
|
|
810
|
])
|
878
|
])
|
|
811
|
|
879
|
|
|
812
|
timeLabel = timeTitle
|
880
|
timeLabel = timeTitle
|
|
@@ -839,14 +907,27 @@ class ViewController: NSViewController {
|
|
839
|
|
907
|
|
|
840
|
// MARK: - Shared UI
|
908
|
// MARK: - Shared UI
|
|
841
|
|
909
|
|
|
842
|
- private func makeSidebar(items: [String], selected: String) -> NSView {
|
|
|
|
|
|
910
|
+ private func makeSidebar(items: [String], selected: String, style: SidebarStyle = .login) -> NSView {
|
|
843
|
let sidebar = NSView()
|
911
|
let sidebar = NSView()
|
|
844
|
sidebar.wantsLayer = true
|
912
|
sidebar.wantsLayer = true
|
|
845
|
- sidebar.layer?.backgroundColor = sidebarBackground.cgColor
|
|
|
|
|
|
913
|
+ sidebar.layer?.backgroundColor = (style == .home ? appShellBackground.withAlphaComponent(0.98) : sidebarBackground).cgColor
|
|
|
|
914
|
+ if style == .home {
|
|
|
|
915
|
+ let divider = NSView()
|
|
|
|
916
|
+ divider.wantsLayer = true
|
|
|
|
917
|
+ divider.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.06).cgColor
|
|
|
|
918
|
+ divider.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
919
|
+ sidebar.addSubview(divider)
|
|
|
|
920
|
+ NSLayoutConstraint.activate([
|
|
|
|
921
|
+ divider.topAnchor.constraint(equalTo: sidebar.topAnchor),
|
|
|
|
922
|
+ divider.bottomAnchor.constraint(equalTo: sidebar.bottomAnchor),
|
|
|
|
923
|
+ divider.trailingAnchor.constraint(equalTo: sidebar.trailingAnchor),
|
|
|
|
924
|
+ divider.widthAnchor.constraint(equalToConstant: 1)
|
|
|
|
925
|
+ ])
|
|
|
|
926
|
+ }
|
|
846
|
|
927
|
|
|
847
|
let stack = NSStackView()
|
928
|
let stack = NSStackView()
|
|
848
|
stack.orientation = .vertical
|
929
|
stack.orientation = .vertical
|
|
849
|
- stack.spacing = 16
|
|
|
|
|
|
930
|
+ stack.spacing = style == .home ? 12 : 16
|
|
850
|
stack.alignment = .centerX
|
931
|
stack.alignment = .centerX
|
|
851
|
stack.translatesAutoresizingMaskIntoConstraints = false
|
932
|
stack.translatesAutoresizingMaskIntoConstraints = false
|
|
852
|
sidebar.addSubview(stack)
|
933
|
sidebar.addSubview(stack)
|
|
@@ -856,46 +937,106 @@ class ViewController: NSViewController {
|
|
856
|
row.translatesAutoresizingMaskIntoConstraints = false
|
937
|
row.translatesAutoresizingMaskIntoConstraints = false
|
|
857
|
row.wantsLayer = true
|
938
|
row.wantsLayer = true
|
|
858
|
let selectedRow = item == selected
|
939
|
let selectedRow = item == selected
|
|
859
|
- row.layer?.backgroundColor = selectedRow ? sidebarActiveBackground.cgColor : NSColor.clear.cgColor
|
|
|
|
860
|
- row.layer?.cornerRadius = 10
|
|
|
|
861
|
- row.widthAnchor.constraint(equalToConstant: 70).isActive = true
|
|
|
|
|
|
940
|
+ row.layer?.backgroundColor = selectedRow ? sidebarActiveBackground.withAlphaComponent(0.95).cgColor : NSColor.clear.cgColor
|
|
|
|
941
|
+ row.layer?.cornerRadius = style == .home ? 12 : 10
|
|
|
|
942
|
+ row.widthAnchor.constraint(equalToConstant: style == .home ? 68 : 70).isActive = true
|
|
862
|
|
943
|
|
|
863
|
- let icon = makeLabel(selectedRow ? "⌂" : "◻︎", size: 15, color: primaryText, weight: .regular, centered: true)
|
|
|
|
864
|
- let label = makeLabel(item, size: 11, color: selectedRow ? primaryText : secondaryText, weight: .regular, centered: true)
|
|
|
|
|
|
944
|
+ let icon = makeLabel(selectedRow ? "⌂" : "◻︎", size: style == .home ? 14 : 15, color: primaryText, weight: .regular, centered: true)
|
|
|
|
945
|
+ let label = makeLabel(item, size: style == .home ? 10 : 11, color: selectedRow ? primaryText : secondaryText, weight: .regular, centered: true)
|
|
865
|
[icon, label].forEach {
|
946
|
[icon, label].forEach {
|
|
866
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
947
|
$0.translatesAutoresizingMaskIntoConstraints = false
|
|
867
|
row.addSubview($0)
|
948
|
row.addSubview($0)
|
|
868
|
}
|
949
|
}
|
|
869
|
NSLayoutConstraint.activate([
|
950
|
NSLayoutConstraint.activate([
|
|
870
|
- icon.topAnchor.constraint(equalTo: row.topAnchor, constant: 10),
|
|
|
|
|
|
951
|
+ icon.topAnchor.constraint(equalTo: row.topAnchor, constant: style == .home ? 8 : 10),
|
|
871
|
icon.centerXAnchor.constraint(equalTo: row.centerXAnchor),
|
952
|
icon.centerXAnchor.constraint(equalTo: row.centerXAnchor),
|
|
872
|
- label.topAnchor.constraint(equalTo: icon.bottomAnchor, constant: 5),
|
|
|
|
|
|
953
|
+ label.topAnchor.constraint(equalTo: icon.bottomAnchor, constant: style == .home ? 4 : 5),
|
|
873
|
label.centerXAnchor.constraint(equalTo: row.centerXAnchor),
|
954
|
label.centerXAnchor.constraint(equalTo: row.centerXAnchor),
|
|
874
|
- label.bottomAnchor.constraint(equalTo: row.bottomAnchor, constant: -8)
|
|
|
|
|
|
955
|
+ label.bottomAnchor.constraint(equalTo: row.bottomAnchor, constant: style == .home ? -7 : -8)
|
|
875
|
])
|
956
|
])
|
|
876
|
stack.addArrangedSubview(row)
|
957
|
stack.addArrangedSubview(row)
|
|
877
|
}
|
958
|
}
|
|
|
|
959
|
+
|
|
|
|
960
|
+ if style == .home {
|
|
|
|
961
|
+ let spacer = NSView()
|
|
|
|
962
|
+ spacer.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
963
|
+ spacer.heightAnchor.constraint(greaterThanOrEqualToConstant: 12).isActive = true
|
|
|
|
964
|
+ stack.addArrangedSubview(spacer)
|
|
|
|
965
|
+
|
|
|
|
966
|
+ let settingsBadge = NSView()
|
|
|
|
967
|
+ settingsBadge.wantsLayer = true
|
|
|
|
968
|
+ settingsBadge.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.03).cgColor
|
|
|
|
969
|
+ settingsBadge.layer?.cornerRadius = 12
|
|
|
|
970
|
+ settingsBadge.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
971
|
+ settingsBadge.widthAnchor.constraint(equalToConstant: 40).isActive = true
|
|
|
|
972
|
+ settingsBadge.heightAnchor.constraint(equalToConstant: 40).isActive = true
|
|
|
|
973
|
+ let gear = makeLabel("⚙︎", size: 14, color: secondaryText, weight: .regular, centered: true)
|
|
|
|
974
|
+ gear.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
975
|
+ settingsBadge.addSubview(gear)
|
|
|
|
976
|
+ NSLayoutConstraint.activate([
|
|
|
|
977
|
+ gear.centerXAnchor.constraint(equalTo: settingsBadge.centerXAnchor),
|
|
|
|
978
|
+ gear.centerYAnchor.constraint(equalTo: settingsBadge.centerYAnchor)
|
|
|
|
979
|
+ ])
|
|
|
|
980
|
+ stack.addArrangedSubview(settingsBadge)
|
|
|
|
981
|
+ }
|
|
878
|
|
982
|
|
|
879
|
NSLayoutConstraint.activate([
|
983
|
NSLayoutConstraint.activate([
|
|
880
|
- stack.topAnchor.constraint(equalTo: sidebar.topAnchor, constant: 18),
|
|
|
|
|
|
984
|
+ stack.topAnchor.constraint(equalTo: sidebar.topAnchor, constant: style == .home ? 16 : 18),
|
|
881
|
stack.leadingAnchor.constraint(equalTo: sidebar.leadingAnchor, constant: 4),
|
985
|
stack.leadingAnchor.constraint(equalTo: sidebar.leadingAnchor, constant: 4),
|
|
882
|
stack.trailingAnchor.constraint(equalTo: sidebar.trailingAnchor, constant: -4)
|
986
|
stack.trailingAnchor.constraint(equalTo: sidebar.trailingAnchor, constant: -4)
|
|
883
|
])
|
987
|
])
|
|
|
|
988
|
+ if style == .home {
|
|
|
|
989
|
+ stack.bottomAnchor.constraint(lessThanOrEqualTo: sidebar.bottomAnchor, constant: -18).isActive = true
|
|
|
|
990
|
+ }
|
|
884
|
|
991
|
|
|
885
|
return sidebar
|
992
|
return sidebar
|
|
886
|
}
|
993
|
}
|
|
|
|
994
|
+
|
|
|
|
995
|
+ private func makeTopBarIconButton(symbol: String, action: Selector?) -> NSButton {
|
|
|
|
996
|
+ let button = NSButton(title: "", target: action == nil ? nil : self, action: action)
|
|
|
|
997
|
+ button.isBordered = false
|
|
|
|
998
|
+ button.wantsLayer = true
|
|
|
|
999
|
+ button.layer?.backgroundColor = titleBarControlBackground.cgColor
|
|
|
|
1000
|
+ button.layer?.cornerRadius = 10
|
|
|
|
1001
|
+ button.layer?.borderWidth = 1
|
|
|
|
1002
|
+ button.layer?.borderColor = NSColor.white.withAlphaComponent(0.05).cgColor
|
|
|
|
1003
|
+ button.contentTintColor = secondaryText
|
|
|
|
1004
|
+ button.image = NSImage(systemSymbolName: symbol, accessibilityDescription: symbol)
|
|
|
|
1005
|
+ button.imageScaling = .scaleProportionallyUpOrDown
|
|
|
|
1006
|
+ button.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
1007
|
+ button.widthAnchor.constraint(equalToConstant: 30).isActive = true
|
|
|
|
1008
|
+ button.heightAnchor.constraint(equalToConstant: 30).isActive = true
|
|
|
|
1009
|
+ return button
|
|
|
|
1010
|
+ }
|
|
|
|
1011
|
+
|
|
|
|
1012
|
+ private func makeTopBarGlyphButton(symbol: String, action: Selector?) -> NSButton {
|
|
|
|
1013
|
+ let button = NSButton(title: "", target: action == nil ? nil : self, action: action)
|
|
|
|
1014
|
+ button.isBordered = false
|
|
|
|
1015
|
+ button.wantsLayer = true
|
|
|
|
1016
|
+ button.layer?.backgroundColor = titleBarLightControlBackground.cgColor
|
|
|
|
1017
|
+ button.layer?.cornerRadius = 9
|
|
|
|
1018
|
+ button.layer?.borderWidth = 1
|
|
|
|
1019
|
+ button.layer?.borderColor = NSColor.white.withAlphaComponent(0.03).cgColor
|
|
|
|
1020
|
+ button.contentTintColor = secondaryText
|
|
|
|
1021
|
+ button.image = NSImage(systemSymbolName: symbol, accessibilityDescription: symbol)
|
|
|
|
1022
|
+ button.imageScaling = .scaleProportionallyUpOrDown
|
|
|
|
1023
|
+ button.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
1024
|
+ button.widthAnchor.constraint(equalToConstant: 26).isActive = true
|
|
|
|
1025
|
+ button.heightAnchor.constraint(equalToConstant: 26).isActive = true
|
|
|
|
1026
|
+ return button
|
|
|
|
1027
|
+ }
|
|
887
|
|
1028
|
|
|
888
|
private func makeActionTile(title: String, symbol: String, color: NSColor, action: Selector? = nil) -> NSView {
|
1029
|
private func makeActionTile(title: String, symbol: String, color: NSColor, action: Selector? = nil) -> NSView {
|
|
889
|
let root = NSView()
|
1030
|
let root = NSView()
|
|
890
|
root.translatesAutoresizingMaskIntoConstraints = false
|
1031
|
root.translatesAutoresizingMaskIntoConstraints = false
|
|
891
|
- root.widthAnchor.constraint(equalToConstant: 100).isActive = true
|
|
|
|
892
|
- root.heightAnchor.constraint(equalToConstant: 96).isActive = true
|
|
|
|
|
|
1032
|
+ root.widthAnchor.constraint(equalToConstant: 104).isActive = true
|
|
|
|
1033
|
+ root.heightAnchor.constraint(equalToConstant: 100).isActive = true
|
|
893
|
|
1034
|
|
|
894
|
let iconButton = NSButton(title: "", target: action == nil ? nil : self, action: action)
|
1035
|
let iconButton = NSButton(title: "", target: action == nil ? nil : self, action: action)
|
|
895
|
iconButton.isBordered = false
|
1036
|
iconButton.isBordered = false
|
|
896
|
iconButton.wantsLayer = true
|
1037
|
iconButton.wantsLayer = true
|
|
897
|
iconButton.layer?.backgroundColor = color.cgColor
|
1038
|
iconButton.layer?.backgroundColor = color.cgColor
|
|
898
|
- iconButton.layer?.cornerRadius = 18
|
|
|
|
|
|
1039
|
+ iconButton.layer?.cornerRadius = 20
|
|
899
|
iconButton.layer?.shadowOpacity = 0.2
|
1040
|
iconButton.layer?.shadowOpacity = 0.2
|
|
900
|
iconButton.layer?.shadowRadius = 7
|
1041
|
iconButton.layer?.shadowRadius = 7
|
|
901
|
iconButton.layer?.shadowOffset = NSSize(width: 0, height: -1)
|
1042
|
iconButton.layer?.shadowOffset = NSSize(width: 0, height: -1)
|
|
@@ -911,9 +1052,9 @@ class ViewController: NSViewController {
|
|
911
|
NSLayoutConstraint.activate([
|
1052
|
NSLayoutConstraint.activate([
|
|
912
|
iconButton.topAnchor.constraint(equalTo: root.topAnchor),
|
1053
|
iconButton.topAnchor.constraint(equalTo: root.topAnchor),
|
|
913
|
iconButton.centerXAnchor.constraint(equalTo: root.centerXAnchor),
|
1054
|
iconButton.centerXAnchor.constraint(equalTo: root.centerXAnchor),
|
|
914
|
- iconButton.widthAnchor.constraint(equalToConstant: 62),
|
|
|
|
915
|
- iconButton.heightAnchor.constraint(equalToConstant: 62),
|
|
|
|
916
|
- label.topAnchor.constraint(equalTo: iconButton.bottomAnchor, constant: 9),
|
|
|
|
|
|
1055
|
+ iconButton.widthAnchor.constraint(equalToConstant: 64),
|
|
|
|
1056
|
+ iconButton.heightAnchor.constraint(equalToConstant: 64),
|
|
|
|
1057
|
+ label.topAnchor.constraint(equalTo: iconButton.bottomAnchor, constant: 10),
|
|
917
|
label.centerXAnchor.constraint(equalTo: root.centerXAnchor),
|
1058
|
label.centerXAnchor.constraint(equalTo: root.centerXAnchor),
|
|
918
|
label.bottomAnchor.constraint(equalTo: root.bottomAnchor)
|
1059
|
label.bottomAnchor.constraint(equalTo: root.bottomAnchor)
|
|
919
|
])
|
1060
|
])
|
|
@@ -923,10 +1064,12 @@ class ViewController: NSViewController {
|
|
923
|
private func makeMeetingRowCard(_ meeting: ScheduledMeeting) -> NSView {
|
1064
|
private func makeMeetingRowCard(_ meeting: ScheduledMeeting) -> NSView {
|
|
924
|
let card = NSView()
|
1065
|
let card = NSView()
|
|
925
|
card.wantsLayer = true
|
1066
|
card.wantsLayer = true
|
|
926
|
- card.layer?.backgroundColor = NSColor(calibratedRed: 35 / 255, green: 40 / 255, blue: 56 / 255, alpha: 1).cgColor
|
|
|
|
927
|
- card.layer?.cornerRadius = 14
|
|
|
|
|
|
1067
|
+ card.layer?.backgroundColor = meetingCardBackground.cgColor
|
|
|
|
1068
|
+ card.layer?.cornerRadius = 13
|
|
|
|
1069
|
+ card.layer?.borderWidth = 1
|
|
|
|
1070
|
+ card.layer?.borderColor = NSColor.white.withAlphaComponent(0.06).cgColor
|
|
928
|
card.translatesAutoresizingMaskIntoConstraints = false
|
1071
|
card.translatesAutoresizingMaskIntoConstraints = false
|
|
929
|
- card.heightAnchor.constraint(equalToConstant: 110).isActive = true
|
|
|
|
|
|
1072
|
+ card.heightAnchor.constraint(equalToConstant: 116).isActive = true
|
|
930
|
|
1073
|
|
|
931
|
let dateFormatter = DateFormatter()
|
1074
|
let dateFormatter = DateFormatter()
|
|
932
|
dateFormatter.dateFormat = "EEE, MMM d"
|
1075
|
dateFormatter.dateFormat = "EEE, MMM d"
|
|
@@ -936,7 +1079,7 @@ class ViewController: NSViewController {
|
|
936
|
let endText = meeting.end.map { timeFormatter.string(from: $0) } ?? ""
|
1079
|
let endText = meeting.end.map { timeFormatter.string(from: $0) } ?? ""
|
|
937
|
let range = endText.isEmpty ? startText : "\(startText) - \(endText)"
|
1080
|
let range = endText.isEmpty ? startText : "\(startText) - \(endText)"
|
|
938
|
|
1081
|
|
|
939
|
- let title = makeLabel(meeting.title, size: 17, color: primaryText, weight: .semibold, centered: false)
|
|
|
|
|
|
1082
|
+ let title = makeLabel(meeting.title, size: 26, color: primaryText, weight: .regular, centered: false)
|
|
940
|
let detail = makeLabel("\(dateFormatter.string(from: meeting.start))\n\(range)", size: 14, color: secondaryText, weight: .regular, centered: false)
|
1083
|
let detail = makeLabel("\(dateFormatter.string(from: meeting.start))\n\(range)", size: 14, color: secondaryText, weight: .regular, centered: false)
|
|
941
|
detail.maximumNumberOfLines = 2
|
1084
|
detail.maximumNumberOfLines = 2
|
|
942
|
let host = makeLabel("Host: \(meeting.host) • \(meeting.source)", size: 13, color: secondaryText, weight: .regular, centered: false)
|
1085
|
let host = makeLabel("Host: \(meeting.host) • \(meeting.source)", size: 13, color: secondaryText, weight: .regular, centered: false)
|
|
@@ -947,15 +1090,15 @@ class ViewController: NSViewController {
|
|
947
|
}
|
1090
|
}
|
|
948
|
|
1091
|
|
|
949
|
NSLayoutConstraint.activate([
|
1092
|
NSLayoutConstraint.activate([
|
|
950
|
- title.topAnchor.constraint(equalTo: card.topAnchor, constant: 12),
|
|
|
|
951
|
- title.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 14),
|
|
|
|
|
|
1093
|
+ title.topAnchor.constraint(equalTo: card.topAnchor, constant: 11),
|
|
|
|
1094
|
+ title.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 16),
|
|
952
|
title.trailingAnchor.constraint(equalTo: card.trailingAnchor, constant: -14),
|
1095
|
title.trailingAnchor.constraint(equalTo: card.trailingAnchor, constant: -14),
|
|
953
|
|
1096
|
|
|
954
|
- detail.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 6),
|
|
|
|
|
|
1097
|
+ detail.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 3),
|
|
955
|
detail.leadingAnchor.constraint(equalTo: title.leadingAnchor),
|
1098
|
detail.leadingAnchor.constraint(equalTo: title.leadingAnchor),
|
|
956
|
detail.trailingAnchor.constraint(equalTo: title.trailingAnchor),
|
1099
|
detail.trailingAnchor.constraint(equalTo: title.trailingAnchor),
|
|
957
|
|
1100
|
|
|
958
|
- host.topAnchor.constraint(equalTo: detail.bottomAnchor, constant: 6),
|
|
|
|
|
|
1101
|
+ host.topAnchor.constraint(equalTo: detail.bottomAnchor, constant: 7),
|
|
959
|
host.leadingAnchor.constraint(equalTo: title.leadingAnchor),
|
1102
|
host.leadingAnchor.constraint(equalTo: title.leadingAnchor),
|
|
960
|
host.trailingAnchor.constraint(equalTo: title.trailingAnchor)
|
1103
|
host.trailingAnchor.constraint(equalTo: title.trailingAnchor)
|
|
961
|
])
|
1104
|
])
|