|
|
@@ -8,6 +8,7 @@ import Cocoa
|
|
8
|
8
|
final class DashboardView: NSView {
|
|
9
|
9
|
private let contentStack = NSStackView()
|
|
10
|
10
|
private let documentContainer = NSView()
|
|
|
11
|
+ private let chromeContainer = NSView()
|
|
11
|
12
|
private let sidebar = NSStackView()
|
|
12
|
13
|
private let mainColumn = NSStackView()
|
|
13
|
14
|
private let greetingLabel = NSTextField(labelWithString: "")
|
|
|
@@ -17,6 +18,8 @@ final class DashboardView: NSView {
|
|
17
|
18
|
private let recommendationsStack = NSStackView()
|
|
18
|
19
|
private let insightsStack = NSStackView()
|
|
19
|
20
|
private let scrollView = NSScrollView()
|
|
|
21
|
+ private var recommendationsWidthConstraint: NSLayoutConstraint?
|
|
|
22
|
+ private var insightsWidthConstraint: NSLayoutConstraint?
|
|
20
|
23
|
|
|
21
|
24
|
override init(frame frameRect: NSRect) {
|
|
22
|
25
|
super.init(frame: frameRect)
|
|
|
@@ -54,12 +57,18 @@ final class DashboardView: NSView {
|
|
54
|
57
|
contentStack.orientation = .horizontal
|
|
55
|
58
|
contentStack.spacing = 20
|
|
56
|
59
|
contentStack.translatesAutoresizingMaskIntoConstraints = false
|
|
57
|
|
- contentStack.edgeInsets = NSEdgeInsets(top: 20, left: 20, bottom: 24, right: 20)
|
|
|
60
|
+ contentStack.alignment = .top
|
|
|
61
|
+ contentStack.edgeInsets = NSEdgeInsets(top: 24, left: 24, bottom: 24, right: 24)
|
|
58
|
62
|
|
|
59
|
63
|
documentContainer.translatesAutoresizingMaskIntoConstraints = true
|
|
60
|
64
|
documentContainer.autoresizingMask = [.width]
|
|
61
|
65
|
documentContainer.frame = NSRect(x: 0, y: 0, width: 1040, height: 900)
|
|
62
|
|
- documentContainer.addSubview(contentStack)
|
|
|
66
|
+ chromeContainer.translatesAutoresizingMaskIntoConstraints = false
|
|
|
67
|
+ chromeContainer.wantsLayer = true
|
|
|
68
|
+ chromeContainer.layer?.backgroundColor = NSColor(calibratedRed: 0.03, green: 0.08, blue: 0.2, alpha: 1).cgColor
|
|
|
69
|
+ chromeContainer.layer?.cornerRadius = 18
|
|
|
70
|
+ documentContainer.addSubview(chromeContainer)
|
|
|
71
|
+ chromeContainer.addSubview(contentStack)
|
|
63
|
72
|
scrollView.documentView = documentContainer
|
|
64
|
73
|
|
|
65
|
74
|
sidebar.orientation = .vertical
|
|
|
@@ -96,6 +105,7 @@ final class DashboardView: NSView {
|
|
96
|
105
|
lowerSection.orientation = .horizontal
|
|
97
|
106
|
lowerSection.spacing = 12
|
|
98
|
107
|
lowerSection.alignment = .top
|
|
|
108
|
+ lowerSection.distribution = .fill
|
|
99
|
109
|
lowerSection.translatesAutoresizingMaskIntoConstraints = false
|
|
100
|
110
|
|
|
101
|
111
|
let recommendationsBox = sectionBox(title: "Recommended for You", content: recommendationsStack)
|
|
|
@@ -121,14 +131,19 @@ final class DashboardView: NSView {
|
|
121
|
131
|
scrollView.topAnchor.constraint(equalTo: topAnchor),
|
|
122
|
132
|
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
123
|
133
|
|
|
124
|
|
- contentStack.leadingAnchor.constraint(equalTo: documentContainer.leadingAnchor),
|
|
125
|
|
- contentStack.trailingAnchor.constraint(equalTo: documentContainer.trailingAnchor),
|
|
126
|
|
- contentStack.topAnchor.constraint(equalTo: documentContainer.topAnchor),
|
|
127
|
|
- contentStack.bottomAnchor.constraint(equalTo: documentContainer.bottomAnchor),
|
|
128
|
|
- contentStack.widthAnchor.constraint(equalTo: documentContainer.widthAnchor),
|
|
|
134
|
+ chromeContainer.topAnchor.constraint(equalTo: documentContainer.topAnchor, constant: 18),
|
|
|
135
|
+ chromeContainer.bottomAnchor.constraint(equalTo: documentContainer.bottomAnchor, constant: -18),
|
|
|
136
|
+ chromeContainer.centerXAnchor.constraint(equalTo: documentContainer.centerXAnchor),
|
|
|
137
|
+ chromeContainer.widthAnchor.constraint(lessThanOrEqualToConstant: 1240),
|
|
|
138
|
+ chromeContainer.widthAnchor.constraint(equalTo: documentContainer.widthAnchor, constant: -36),
|
|
|
139
|
+
|
|
|
140
|
+ contentStack.leadingAnchor.constraint(equalTo: chromeContainer.leadingAnchor),
|
|
|
141
|
+ contentStack.trailingAnchor.constraint(equalTo: chromeContainer.trailingAnchor),
|
|
|
142
|
+ contentStack.topAnchor.constraint(equalTo: chromeContainer.topAnchor),
|
|
|
143
|
+ contentStack.bottomAnchor.constraint(equalTo: chromeContainer.bottomAnchor),
|
|
129
|
144
|
|
|
130
|
145
|
sidebar.widthAnchor.constraint(equalToConstant: 225),
|
|
131
|
|
- mainColumn.widthAnchor.constraint(greaterThanOrEqualToConstant: 760),
|
|
|
146
|
+ mainColumn.widthAnchor.constraint(greaterThanOrEqualToConstant: 720),
|
|
132
|
147
|
heroCard.widthAnchor.constraint(equalTo: mainColumn.widthAnchor),
|
|
133
|
148
|
heroCard.heightAnchor.constraint(equalToConstant: 140),
|
|
134
|
149
|
|
|
|
@@ -137,9 +152,13 @@ final class DashboardView: NSView {
|
|
137
|
152
|
hero.topAnchor.constraint(equalTo: heroCard.topAnchor, constant: 18),
|
|
138
|
153
|
hero.bottomAnchor.constraint(equalTo: heroCard.bottomAnchor, constant: -18),
|
|
139
|
154
|
|
|
140
|
|
- recommendationsBox.widthAnchor.constraint(equalToConstant: 510),
|
|
141
|
|
- insightsBox.widthAnchor.constraint(equalToConstant: 238)
|
|
|
155
|
+ lowerSection.widthAnchor.constraint(equalTo: mainColumn.widthAnchor)
|
|
142
|
156
|
])
|
|
|
157
|
+
|
|
|
158
|
+ recommendationsWidthConstraint = recommendationsBox.widthAnchor.constraint(equalTo: mainColumn.widthAnchor, multiplier: 0.68)
|
|
|
159
|
+ insightsWidthConstraint = insightsBox.widthAnchor.constraint(equalTo: mainColumn.widthAnchor, multiplier: 0.32, constant: -8)
|
|
|
160
|
+ recommendationsWidthConstraint?.isActive = true
|
|
|
161
|
+ insightsWidthConstraint?.isActive = true
|
|
143
|
162
|
}
|
|
144
|
163
|
|
|
145
|
164
|
private func buildHeroContent() -> NSView {
|
|
|
@@ -408,7 +427,7 @@ final class DashboardView: NSView {
|
|
408
|
427
|
|
|
409
|
428
|
private func updateDocumentLayout() {
|
|
410
|
429
|
documentContainer.layoutSubtreeIfNeeded()
|
|
411
|
|
- let fittingHeight = max(contentStack.fittingSize.height, bounds.height)
|
|
|
430
|
+ let fittingHeight = max(chromeContainer.fittingSize.height + 36, bounds.height)
|
|
412
|
431
|
documentContainer.frame = NSRect(x: 0, y: 0, width: bounds.width, height: fittingHeight)
|
|
413
|
432
|
}
|
|
414
|
433
|
}
|