Explorar o código

Fix dashboard scroll: only job list uses NSScrollView

Remove the full-window scroll view so the chrome, welcome block, and
search bar stay fixed. Wrap job cards in a dedicated vertical
NSScrollView with document layout tied to the clip view.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 hai 3 semanas
pai
achega
6b4c5b3f4e
Modificáronse 1 ficheiros con 21 adicións e 35 borrados
  1. 21 35
      App for Indeed/Views/DashboardView.swift

+ 21 - 35
App for Indeed/Views/DashboardView.swift

@@ -35,7 +35,6 @@ final class DashboardView: NSView, NSTextFieldDelegate {
35 35
     }
36 36
 
37 37
     private let contentStack = NSStackView()
38
-    private let documentContainer = NSView()
39 38
     private let chromeContainer = NSView()
40 39
     private let sidebar = NSStackView()
41 40
     private let mainHost = NSView()
@@ -50,7 +49,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
50 49
     private let findJobsCTAHost = NSView()
51 50
     private let findJobsCTAChrome = NSView()
52 51
     private var findJobsCTAGradientLayer: CAGradientLayer?
53
-    private let scrollView = NSScrollView()
52
+    private let jobListingsScrollView = NSScrollView()
54 53
     private let jobListingsContainer = NSView()
55 54
     private let jobListingsStack = NSStackView()
56 55
 
@@ -69,7 +68,6 @@ final class DashboardView: NSView, NSTextFieldDelegate {
69 68
 
70 69
     override func layout() {
71 70
         super.layout()
72
-        updateDocumentLayout()
73 71
         updateSearchBarShadowPath()
74 72
         findJobsCTAGradientLayer?.frame = findJobsCTAChrome.bounds
75 73
         updateFindJobsCTAShadowPath()
@@ -85,18 +83,12 @@ final class DashboardView: NSView, NSTextFieldDelegate {
85 83
         }
86 84
         configureSidebar()
87 85
         configureJobListings(data.jobListings)
88
-        updateDocumentLayout()
89 86
     }
90 87
 
91 88
     private func setupLayout() {
92 89
         wantsLayer = true
93 90
         layer?.backgroundColor = Theme.pageBackground.cgColor
94 91
 
95
-        scrollView.translatesAutoresizingMaskIntoConstraints = false
96
-        scrollView.hasVerticalScroller = true
97
-        scrollView.drawsBackground = false
98
-        addSubview(scrollView)
99
-
100 92
         contentStack.orientation = .horizontal
101 93
         contentStack.spacing = 20
102 94
         contentStack.distribution = .fill
@@ -104,16 +96,12 @@ final class DashboardView: NSView, NSTextFieldDelegate {
104 96
         contentStack.alignment = .height
105 97
         contentStack.edgeInsets = NSEdgeInsets(top: 24, left: 24, bottom: 24, right: 24)
106 98
 
107
-        documentContainer.translatesAutoresizingMaskIntoConstraints = true
108
-        documentContainer.autoresizingMask = [.width]
109
-        documentContainer.frame = NSRect(x: 0, y: 0, width: 1040, height: 900)
110 99
         chromeContainer.translatesAutoresizingMaskIntoConstraints = false
111 100
         chromeContainer.wantsLayer = true
112 101
         chromeContainer.layer?.backgroundColor = Theme.chromeBackground.cgColor
113 102
         chromeContainer.layer?.cornerRadius = 0
114
-        documentContainer.addSubview(chromeContainer)
103
+        addSubview(chromeContainer)
115 104
         chromeContainer.addSubview(contentStack)
116
-        scrollView.documentView = documentContainer
117 105
 
118 106
         sidebar.orientation = .vertical
119 107
         sidebar.spacing = 10
@@ -188,32 +176,31 @@ final class DashboardView: NSView, NSTextFieldDelegate {
188 176
             jobListingsStack.bottomAnchor.constraint(equalTo: jobListingsContainer.bottomAnchor)
189 177
         ])
190 178
 
191
-        let overlayBottomSpacer = NSView()
192
-        overlayBottomSpacer.translatesAutoresizingMaskIntoConstraints = false
193
-        overlayBottomSpacer.setContentHuggingPriority(.defaultLow, for: .vertical)
194
-        overlayBottomSpacer.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
179
+        jobListingsScrollView.translatesAutoresizingMaskIntoConstraints = false
180
+        jobListingsScrollView.hasVerticalScroller = true
181
+        jobListingsScrollView.hasHorizontalScroller = false
182
+        jobListingsScrollView.autohidesScrollers = true
183
+        jobListingsScrollView.drawsBackground = false
184
+        jobListingsScrollView.borderType = .noBorder
185
+        jobListingsScrollView.documentView = jobListingsContainer
186
+        jobListingsScrollView.setContentHuggingPriority(.defaultLow, for: .vertical)
187
+        jobListingsScrollView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
195 188
 
196 189
         mainOverlay.addArrangedSubview(topInset)
197 190
         mainOverlay.addArrangedSubview(titleBlock)
198 191
         mainOverlay.addArrangedSubview(midSpacer)
199 192
         mainOverlay.addArrangedSubview(searchBarShadowHost)
200 193
         mainOverlay.addArrangedSubview(listingsTopSpacer)
201
-        mainOverlay.addArrangedSubview(jobListingsContainer)
202
-        mainOverlay.addArrangedSubview(overlayBottomSpacer)
194
+        mainOverlay.addArrangedSubview(jobListingsScrollView)
203 195
 
204 196
         contentStack.addArrangedSubview(sidebar)
205 197
         contentStack.addArrangedSubview(mainHost)
206 198
 
207 199
         NSLayoutConstraint.activate([
208
-            scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
209
-            scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
210
-            scrollView.topAnchor.constraint(equalTo: topAnchor),
211
-            scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
212
-
213
-            chromeContainer.leadingAnchor.constraint(equalTo: documentContainer.leadingAnchor),
214
-            chromeContainer.trailingAnchor.constraint(equalTo: documentContainer.trailingAnchor),
215
-            chromeContainer.topAnchor.constraint(equalTo: documentContainer.topAnchor),
216
-            chromeContainer.bottomAnchor.constraint(equalTo: documentContainer.bottomAnchor),
200
+            chromeContainer.leadingAnchor.constraint(equalTo: leadingAnchor),
201
+            chromeContainer.trailingAnchor.constraint(equalTo: trailingAnchor),
202
+            chromeContainer.topAnchor.constraint(equalTo: topAnchor),
203
+            chromeContainer.bottomAnchor.constraint(equalTo: bottomAnchor),
217 204
 
218 205
             contentStack.leadingAnchor.constraint(equalTo: chromeContainer.leadingAnchor),
219 206
             contentStack.trailingAnchor.constraint(equalTo: chromeContainer.trailingAnchor),
@@ -229,7 +216,11 @@ final class DashboardView: NSView, NSTextFieldDelegate {
229 216
             mainOverlay.bottomAnchor.constraint(equalTo: mainHost.bottomAnchor, constant: -24),
230 217
 
231 218
             searchBarShadowHost.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
232
-            jobListingsContainer.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
219
+            jobListingsScrollView.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
220
+
221
+            jobListingsContainer.topAnchor.constraint(equalTo: jobListingsScrollView.contentView.topAnchor),
222
+            jobListingsContainer.leadingAnchor.constraint(equalTo: jobListingsScrollView.contentView.leadingAnchor),
223
+            jobListingsContainer.widthAnchor.constraint(equalTo: jobListingsScrollView.contentView.widthAnchor),
233 224
 
234 225
             greetingLabel.leadingAnchor.constraint(equalTo: mainOverlay.leadingAnchor, constant: 24),
235 226
             greetingLabel.trailingAnchor.constraint(equalTo: mainOverlay.trailingAnchor, constant: -24),
@@ -699,11 +690,6 @@ final class DashboardView: NSView, NSTextFieldDelegate {
699 690
         configureSidebar()
700 691
     }
701 692
 
702
-    private func updateDocumentLayout() {
703
-        documentContainer.layoutSubtreeIfNeeded()
704
-        let fittingHeight = max(chromeContainer.fittingSize.height, bounds.height)
705
-        documentContainer.frame = NSRect(x: 0, y: 0, width: bounds.width, height: fittingHeight)
706
-    }
707 693
 }
708 694
 
709 695
 /// Captures clicks for the full sidebar pill so icon, label, and padding behave as one tab.