浏览代码

Integrate the home top strip into the titlebar and remove duplicate traffic lights.

This unifies the left chrome and right top controls into a single titlebar-aligned header while preserving existing actions and visual theme.

Made-with: Cursor
huzaifahayat12 6 天之前
父节点
当前提交
fafaf19cf8
共有 1 个文件被更改,包括 101 次插入54 次删除
  1. 101 54
      zoom_app/ViewController.swift

+ 101 - 54
zoom_app/ViewController.swift

@@ -69,8 +69,14 @@ class ViewController: NSViewController {
69
 
69
 
70
     override func viewDidAppear() {
70
     override func viewDidAppear() {
71
         super.viewDidAppear()
71
         super.viewDidAppear()
72
-        view.window?.setContentSize(NSSize(width: 1020, height: 690))
73
-        view.window?.title = "zoom Workplace"
72
+        if let window = view.window {
73
+            window.setContentSize(NSSize(width: 1020, height: 690))
74
+            // Use full-size content view so custom top chrome sits in the titlebar region.
75
+            window.titleVisibility = .hidden
76
+            window.titlebarAppearsTransparent = true
77
+            window.isMovableByWindowBackground = true
78
+            window.styleMask.insert(.fullSizeContentView)
79
+        }
74
         if isUserLoggedIn() {
80
         if isUserLoggedIn() {
75
             showHomeView(profile: nil)
81
             showHomeView(profile: nil)
76
         } else {
82
         } else {
@@ -648,33 +654,69 @@ class ViewController: NSViewController {
648
         shell.layer?.cornerRadius = appShellCornerRadius
654
         shell.layer?.cornerRadius = appShellCornerRadius
649
         shell.layer?.borderWidth = 1
655
         shell.layer?.borderWidth = 1
650
         shell.layer?.borderColor = NSColor.white.withAlphaComponent(0.06).cgColor
656
         shell.layer?.borderColor = NSColor.white.withAlphaComponent(0.06).cgColor
657
+        let chromeColumn = NSView()
658
+        chromeColumn.wantsLayer = true
659
+        chromeColumn.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.03).cgColor
660
+        let chromeDivider = NSView()
661
+        chromeDivider.wantsLayer = true
662
+        chromeDivider.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.32).cgColor
663
+        let chromeHeader = NSView()
664
+        chromeHeader.wantsLayer = true
665
+        chromeHeader.layer?.backgroundColor = NSColor.clear.cgColor
651
         let sidebar = makeSidebar(items: ["Home", "Meetings", "Chat", "Scheduler", "Hub", "More"], selected: "Home", style: .home)
666
         let sidebar = makeSidebar(items: ["Home", "Meetings", "Chat", "Scheduler", "Hub", "More"], selected: "Home", style: .home)
652
         let content = NSView()
667
         let content = NSView()
653
         content.wantsLayer = true
668
         content.wantsLayer = true
654
         content.layer?.backgroundColor = NSColor.clear.cgColor
669
         content.layer?.backgroundColor = NSColor.clear.cgColor
655
 
670
 
656
         root.addSubview(shell)
671
         root.addSubview(shell)
657
-        shell.addSubview(sidebar)
672
+        shell.addSubview(chromeColumn)
658
         shell.addSubview(content)
673
         shell.addSubview(content)
674
+        chromeColumn.addSubview(chromeDivider)
675
+        chromeColumn.addSubview(chromeHeader)
676
+        chromeColumn.addSubview(sidebar)
659
         shell.translatesAutoresizingMaskIntoConstraints = false
677
         shell.translatesAutoresizingMaskIntoConstraints = false
678
+        chromeColumn.translatesAutoresizingMaskIntoConstraints = false
679
+        chromeDivider.translatesAutoresizingMaskIntoConstraints = false
680
+        chromeHeader.translatesAutoresizingMaskIntoConstraints = false
660
         sidebar.translatesAutoresizingMaskIntoConstraints = false
681
         sidebar.translatesAutoresizingMaskIntoConstraints = false
661
         content.translatesAutoresizingMaskIntoConstraints = false
682
         content.translatesAutoresizingMaskIntoConstraints = false
662
 
683
 
663
         NSLayoutConstraint.activate([
684
         NSLayoutConstraint.activate([
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),
671
-            sidebar.widthAnchor.constraint(equalToConstant: sidebarWidth),
672
-            content.leadingAnchor.constraint(equalTo: sidebar.trailingAnchor),
685
+            shell.leadingAnchor.constraint(equalTo: root.leadingAnchor, constant: 8),
686
+            shell.trailingAnchor.constraint(equalTo: root.trailingAnchor, constant: -8),
687
+            shell.topAnchor.constraint(equalTo: root.topAnchor, constant: 0),
688
+            shell.bottomAnchor.constraint(equalTo: root.bottomAnchor, constant: -8),
689
+            chromeColumn.leadingAnchor.constraint(equalTo: shell.leadingAnchor),
690
+            chromeColumn.topAnchor.constraint(equalTo: shell.topAnchor),
691
+            chromeColumn.bottomAnchor.constraint(equalTo: shell.bottomAnchor),
692
+            chromeColumn.widthAnchor.constraint(equalToConstant: 146),
693
+            chromeDivider.topAnchor.constraint(equalTo: chromeColumn.topAnchor),
694
+            chromeDivider.bottomAnchor.constraint(equalTo: chromeColumn.bottomAnchor),
695
+            chromeDivider.trailingAnchor.constraint(equalTo: chromeColumn.trailingAnchor),
696
+            chromeDivider.widthAnchor.constraint(equalToConstant: 1),
697
+            chromeHeader.topAnchor.constraint(equalTo: chromeColumn.topAnchor),
698
+            chromeHeader.leadingAnchor.constraint(equalTo: chromeColumn.leadingAnchor),
699
+            chromeHeader.trailingAnchor.constraint(equalTo: chromeColumn.trailingAnchor),
700
+            chromeHeader.heightAnchor.constraint(equalToConstant: 56),
701
+            sidebar.leadingAnchor.constraint(equalTo: chromeColumn.leadingAnchor),
702
+            sidebar.trailingAnchor.constraint(equalTo: chromeColumn.trailingAnchor),
703
+            sidebar.topAnchor.constraint(equalTo: chromeHeader.bottomAnchor, constant: 2),
704
+            sidebar.bottomAnchor.constraint(equalTo: chromeColumn.bottomAnchor),
705
+            content.leadingAnchor.constraint(equalTo: chromeColumn.trailingAnchor),
673
             content.trailingAnchor.constraint(equalTo: shell.trailingAnchor),
706
             content.trailingAnchor.constraint(equalTo: shell.trailingAnchor),
674
             content.topAnchor.constraint(equalTo: shell.topAnchor),
707
             content.topAnchor.constraint(equalTo: shell.topAnchor),
675
             content.bottomAnchor.constraint(equalTo: shell.bottomAnchor)
708
             content.bottomAnchor.constraint(equalTo: shell.bottomAnchor)
676
         ])
709
         ])
677
 
710
 
711
+        let brandStack = NSStackView()
712
+        brandStack.orientation = .vertical
713
+        brandStack.spacing = 0
714
+        brandStack.alignment = .leading
715
+        let brandTop = makeLabel("zoom", size: 14, color: primaryText, weight: .semibold, centered: false)
716
+        let brandBottom = makeLabel("Workplace", size: 27, color: primaryText, weight: .bold, centered: false)
717
+        brandBottom.font = .systemFont(ofSize: 14, weight: .bold)
718
+        [brandTop, brandBottom].forEach { brandStack.addArrangedSubview($0) }
719
+
678
         let topBar = NSView()
720
         let topBar = NSView()
679
         topBar.wantsLayer = true
721
         topBar.wantsLayer = true
680
         topBar.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.03).cgColor
722
         topBar.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.03).cgColor
@@ -689,15 +731,6 @@ class ViewController: NSViewController {
689
         searchPill.layer?.cornerRadius = 10
731
         searchPill.layer?.cornerRadius = 10
690
         let search = makeLabel("Search (\u{2318}E)", size: 13, color: mutedText, weight: .regular, centered: true)
732
         let search = makeLabel("Search (\u{2318}E)", size: 13, color: mutedText, weight: .regular, centered: true)
691
         
733
         
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()
734
         let leftTopBarCluster = NSStackView()
702
         leftTopBarCluster.orientation = .horizontal
735
         leftTopBarCluster.orientation = .horizontal
703
         leftTopBarCluster.spacing = 10
736
         leftTopBarCluster.spacing = 10
@@ -779,38 +812,65 @@ class ViewController: NSViewController {
779
         openRecordings.layer?.borderWidth = 1
812
         openRecordings.layer?.borderWidth = 1
780
         openRecordings.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
813
         openRecordings.layer?.borderColor = NSColor.white.withAlphaComponent(0.07).cgColor
781
 
814
 
815
+        let contentPanel = NSView()
816
+        contentPanel.wantsLayer = true
817
+        contentPanel.layer?.backgroundColor = contentShellBackground.cgColor
818
+        contentPanel.layer?.cornerRadius = 12
819
+        contentPanel.layer?.borderWidth = 1
820
+        contentPanel.layer?.borderColor = NSColor.white.withAlphaComponent(0.04).cgColor
782
         let contentColumn = NSView()
821
         let contentColumn = NSView()
783
         contentColumn.translatesAutoresizingMaskIntoConstraints = false
822
         contentColumn.translatesAutoresizingMaskIntoConstraints = false
784
-        content.addSubview(contentColumn)
823
+        content.addSubview(topBar)
824
+        content.addSubview(topBarDivider)
825
+        content.addSubview(contentPanel)
826
+        contentPanel.addSubview(contentColumn)
785
 
827
 
786
-        [topBar, topBarDivider, brandStack, leftTopBarCluster, rightTopBarCluster, searchPill, search, welcome, timeTitle, dateTitle, actions, panel, panelHeaderStrip, panelHeader, meetingsStatus, noMeeting, meetingsScrollView, openRecordings].forEach {
828
+        [brandStack, leftTopBarCluster, rightTopBarCluster, searchPill, search].forEach {
829
+            $0.translatesAutoresizingMaskIntoConstraints = false
830
+        }
831
+        [brandStack].forEach {
832
+            chromeHeader.addSubview($0)
833
+        }
834
+        [leftTopBarCluster, rightTopBarCluster, searchPill, search].forEach {
835
+            $0.translatesAutoresizingMaskIntoConstraints = false
836
+            topBar.addSubview($0)
837
+        }
838
+        [welcome, timeTitle, dateTitle, actions, panel, panelHeaderStrip, panelHeader, meetingsStatus, noMeeting, meetingsScrollView, openRecordings].forEach {
787
             $0.translatesAutoresizingMaskIntoConstraints = false
839
             $0.translatesAutoresizingMaskIntoConstraints = false
788
             contentColumn.addSubview($0)
840
             contentColumn.addSubview($0)
789
         }
841
         }
842
+        topBar.translatesAutoresizingMaskIntoConstraints = false
843
+        topBarDivider.translatesAutoresizingMaskIntoConstraints = false
844
+        contentPanel.translatesAutoresizingMaskIntoConstraints = false
790
         meetingsDocument.translatesAutoresizingMaskIntoConstraints = false
845
         meetingsDocument.translatesAutoresizingMaskIntoConstraints = false
791
         meetingsStack.translatesAutoresizingMaskIntoConstraints = false
846
         meetingsStack.translatesAutoresizingMaskIntoConstraints = false
792
         meetingsScrollView.documentView = meetingsDocument
847
         meetingsScrollView.documentView = meetingsDocument
793
         meetingsDocument.addSubview(meetingsStack)
848
         meetingsDocument.addSubview(meetingsStack)
794
 
849
 
795
         NSLayoutConstraint.activate([
850
         NSLayoutConstraint.activate([
796
-            contentColumn.topAnchor.constraint(equalTo: content.topAnchor),
797
-            contentColumn.bottomAnchor.constraint(equalTo: content.bottomAnchor),
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),
851
+            brandStack.leadingAnchor.constraint(equalTo: chromeHeader.leadingAnchor, constant: 60),
852
+            brandStack.centerYAnchor.constraint(equalTo: chromeHeader.centerYAnchor),
853
+
854
+            topBar.topAnchor.constraint(equalTo: content.topAnchor),
855
+            topBar.leadingAnchor.constraint(equalTo: content.leadingAnchor),
856
+            topBar.trailingAnchor.constraint(equalTo: content.trailingAnchor),
857
+            topBar.heightAnchor.constraint(equalToConstant: 56),
805
             topBarDivider.topAnchor.constraint(equalTo: topBar.bottomAnchor),
858
             topBarDivider.topAnchor.constraint(equalTo: topBar.bottomAnchor),
806
-            topBarDivider.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor),
807
-            topBarDivider.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor),
859
+            topBarDivider.leadingAnchor.constraint(equalTo: content.leadingAnchor),
860
+            topBarDivider.trailingAnchor.constraint(equalTo: content.trailingAnchor),
808
             topBarDivider.heightAnchor.constraint(equalToConstant: 1),
861
             topBarDivider.heightAnchor.constraint(equalToConstant: 1),
809
 
862
 
810
-            brandStack.leadingAnchor.constraint(equalTo: topBar.leadingAnchor, constant: 12),
811
-            brandStack.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
863
+            contentPanel.topAnchor.constraint(equalTo: topBarDivider.bottomAnchor, constant: 6),
864
+            contentPanel.leadingAnchor.constraint(equalTo: content.leadingAnchor, constant: 8),
865
+            contentPanel.trailingAnchor.constraint(equalTo: content.trailingAnchor, constant: -8),
866
+            contentPanel.bottomAnchor.constraint(equalTo: content.bottomAnchor, constant: -8),
867
+
868
+            contentColumn.topAnchor.constraint(equalTo: contentPanel.topAnchor),
869
+            contentColumn.bottomAnchor.constraint(equalTo: contentPanel.bottomAnchor),
870
+            contentColumn.leadingAnchor.constraint(equalTo: contentPanel.leadingAnchor),
871
+            contentColumn.trailingAnchor.constraint(equalTo: contentPanel.trailingAnchor),
812
 
872
 
813
-            leftTopBarCluster.leadingAnchor.constraint(equalTo: brandStack.trailingAnchor, constant: 18),
873
+            leftTopBarCluster.leadingAnchor.constraint(equalTo: topBar.leadingAnchor, constant: 16),
814
             leftTopBarCluster.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
874
             leftTopBarCluster.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
815
             rightTopBarCluster.trailingAnchor.constraint(equalTo: topBar.trailingAnchor, constant: -12),
875
             rightTopBarCluster.trailingAnchor.constraint(equalTo: topBar.trailingAnchor, constant: -12),
816
             rightTopBarCluster.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
876
             rightTopBarCluster.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
@@ -827,7 +887,7 @@ class ViewController: NSViewController {
827
             profileChip.widthAnchor.constraint(equalToConstant: 34),
887
             profileChip.widthAnchor.constraint(equalToConstant: 34),
828
             profileChip.heightAnchor.constraint(equalToConstant: 34),
888
             profileChip.heightAnchor.constraint(equalToConstant: 34),
829
 
889
 
830
-            welcome.topAnchor.constraint(equalTo: topBar.bottomAnchor, constant: 22),
890
+            welcome.topAnchor.constraint(equalTo: contentColumn.topAnchor, constant: 22),
831
             welcome.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
891
             welcome.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
832
 
892
 
833
             timeTitle.topAnchor.constraint(equalTo: welcome.bottomAnchor, constant: 12),
893
             timeTitle.topAnchor.constraint(equalTo: welcome.bottomAnchor, constant: 12),
@@ -845,7 +905,7 @@ class ViewController: NSViewController {
845
             panel.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor, constant: 26),
905
             panel.leadingAnchor.constraint(equalTo: contentColumn.leadingAnchor, constant: 26),
846
             panel.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor, constant: -26),
906
             panel.trailingAnchor.constraint(equalTo: contentColumn.trailingAnchor, constant: -26),
847
             panel.heightAnchor.constraint(equalToConstant: 316),
907
             panel.heightAnchor.constraint(equalToConstant: 316),
848
-            panel.bottomAnchor.constraint(lessThanOrEqualTo: contentColumn.bottomAnchor, constant: -20),
908
+            panel.bottomAnchor.constraint(lessThanOrEqualTo: contentColumn.bottomAnchor, constant: -24),
849
             
909
             
850
             panelHeaderStrip.topAnchor.constraint(equalTo: panel.topAnchor, constant: 10),
910
             panelHeaderStrip.topAnchor.constraint(equalTo: panel.topAnchor, constant: 10),
851
             panelHeaderStrip.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 10),
911
             panelHeaderStrip.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 10),
@@ -911,19 +971,6 @@ class ViewController: NSViewController {
911
         let sidebar = NSView()
971
         let sidebar = NSView()
912
         sidebar.wantsLayer = true
972
         sidebar.wantsLayer = true
913
         sidebar.layer?.backgroundColor = (style == .home ? NSColor.white.withAlphaComponent(0.03) : sidebarBackground).cgColor
973
         sidebar.layer?.backgroundColor = (style == .home ? NSColor.white.withAlphaComponent(0.03) : 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
-        }
927
 
974
 
928
         let stack = NSStackView()
975
         let stack = NSStackView()
929
         stack.orientation = .vertical
976
         stack.orientation = .vertical
@@ -981,7 +1028,7 @@ class ViewController: NSViewController {
981
         }
1028
         }
982
 
1029
 
983
         NSLayoutConstraint.activate([
1030
         NSLayoutConstraint.activate([
984
-            stack.topAnchor.constraint(equalTo: sidebar.topAnchor, constant: style == .home ? 16 : 18),
1031
+            stack.topAnchor.constraint(equalTo: sidebar.topAnchor, constant: style == .home ? 8 : 18),
985
             stack.leadingAnchor.constraint(equalTo: sidebar.leadingAnchor, constant: 4),
1032
             stack.leadingAnchor.constraint(equalTo: sidebar.leadingAnchor, constant: 4),
986
             stack.trailingAnchor.constraint(equalTo: sidebar.trailingAnchor, constant: -4)
1033
             stack.trailingAnchor.constraint(equalTo: sidebar.trailingAnchor, constant: -4)
987
         ])
1034
         ])
@@ -991,7 +1038,7 @@ class ViewController: NSViewController {
991
 
1038
 
992
         return sidebar
1039
         return sidebar
993
     }
1040
     }
994
-    
1041
+
995
     private func makeTopBarIconButton(symbol: String, action: Selector?) -> NSButton {
1042
     private func makeTopBarIconButton(symbol: String, action: Selector?) -> NSButton {
996
         let button = NSButton(title: "", target: action == nil ? nil : self, action: action)
1043
         let button = NSButton(title: "", target: action == nil ? nil : self, action: action)
997
         button.isBordered = false
1044
         button.isBordered = false