Parcourir la Source

Use asset catalog logos in dashboard, loading, and logo views.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 il y a 3 semaines
Parent
commit
3b4bd83a1c

+ 22 - 59
App for Indeed/Views/DashboardView.swift

@@ -97,9 +97,8 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
97 97
     private let findJobsCTAHost = NSView()
98 98
     private let welcomeHeroHost = NSView()
99 99
     private let welcomeHeroBackgroundView = WelcomeHeroBackgroundView()
100
-    private lazy var welcomeSparkleCluster: WelcomeSparkleClusterView = {
101
-        WelcomeSparkleClusterView(iconWell: Theme.welcomeHeroIconWell, tint: Theme.welcomeHeroHeadingBlue)
102
-    }()
100
+    private let welcomeLogoWell = NSView()
101
+    private let welcomeLogoView = IndeedLogoView(displayHeight: 40, variant: .compact)
103 102
     private let featureCardsRow = NSStackView()
104 103
     private let clearChatButton = NSButton(title: "Clear chat", target: nil, action: nil)
105 104
     private let chatScrollView = NSScrollView()
@@ -290,7 +289,18 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
290 289
         welcomeHeroBackgroundView.translatesAutoresizingMaskIntoConstraints = false
291 290
         welcomeHeroBackgroundView.waveTint = Theme.welcomeHeroWaveTint
292 291
 
293
-        let welcomeHeroContent = NSStackView(views: [welcomeSparkleCluster, greetingLabel, subtitleLabel])
292
+        welcomeLogoWell.translatesAutoresizingMaskIntoConstraints = false
293
+        welcomeLogoWell.wantsLayer = true
294
+        welcomeLogoWell.layer?.backgroundColor = Theme.welcomeHeroIconWell.cgColor
295
+        welcomeLogoWell.layer?.cornerRadius = 28
296
+        if #available(macOS 11.0, *) {
297
+            welcomeLogoWell.layer?.cornerCurve = .continuous
298
+        }
299
+
300
+        welcomeLogoView.translatesAutoresizingMaskIntoConstraints = false
301
+        welcomeLogoWell.addSubview(welcomeLogoView)
302
+
303
+        let welcomeHeroContent = NSStackView(views: [welcomeLogoWell, greetingLabel, subtitleLabel])
294 304
         welcomeHeroContent.orientation = .vertical
295 305
         welcomeHeroContent.spacing = 8
296 306
         welcomeHeroContent.alignment = .centerX
@@ -309,7 +319,12 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
309 319
             welcomeHeroContent.leadingAnchor.constraint(greaterThanOrEqualTo: welcomeHeroHost.leadingAnchor, constant: 16),
310 320
             welcomeHeroContent.trailingAnchor.constraint(lessThanOrEqualTo: welcomeHeroHost.trailingAnchor, constant: -16),
311 321
             welcomeHeroContent.topAnchor.constraint(equalTo: welcomeHeroHost.topAnchor, constant: 4),
312
-            welcomeHeroContent.bottomAnchor.constraint(equalTo: welcomeHeroHost.bottomAnchor, constant: -2)
322
+            welcomeHeroContent.bottomAnchor.constraint(equalTo: welcomeHeroHost.bottomAnchor, constant: -2),
323
+
324
+            welcomeLogoWell.widthAnchor.constraint(equalToConstant: 56),
325
+            welcomeLogoWell.heightAnchor.constraint(equalToConstant: 56),
326
+            welcomeLogoView.centerXAnchor.constraint(equalTo: welcomeLogoWell.centerXAnchor),
327
+            welcomeLogoView.centerYAnchor.constraint(equalTo: welcomeLogoWell.centerYAnchor)
313 328
         ])
314 329
 
315 330
         configureFeatureShortcutCards()
@@ -2361,11 +2376,11 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
2361 2376
             $0.removeFromSuperview()
2362 2377
         }
2363 2378
 
2364
-        let logo = IndeedLogoView(displayHeight: 26)
2379
+        let logo = IndeedLogoView(displayHeight: 34, variant: .compact)
2365 2380
         logo.translatesAutoresizingMaskIntoConstraints = false
2366 2381
 
2367 2382
         let brand = NSTextField(labelWithString: AppMarketingLinks.appDisplayName)
2368
-        brand.font = .systemFont(ofSize: 15, weight: .semibold)
2383
+        brand.font = .systemFont(ofSize: 14, weight: .semibold)
2369 2384
         brand.textColor = Theme.brandBlue
2370 2385
         brand.alignment = .left
2371 2386
         brand.maximumNumberOfLines = 2
@@ -3149,58 +3164,6 @@ private final class WelcomeHeroBackgroundView: NSView {
3149 3164
     }
3150 3165
 }
3151 3166
 
3152
-/// Circular pastel well with three sparkle symbols (reference: layered stars of different sizes).
3153
-private final class WelcomeSparkleClusterView: NSView {
3154
-    private let diameter: CGFloat = 56
3155
-
3156
-    override var intrinsicContentSize: NSSize {
3157
-        NSSize(width: diameter, height: diameter)
3158
-    }
3159
-
3160
-    init(iconWell: NSColor, tint: NSColor) {
3161
-        super.init(frame: .zero)
3162
-        translatesAutoresizingMaskIntoConstraints = false
3163
-        wantsLayer = true
3164
-        layer?.cornerRadius = diameter / 2
3165
-        if #available(macOS 11.0, *) {
3166
-            layer?.cornerCurve = .continuous
3167
-        }
3168
-        layer?.backgroundColor = iconWell.cgColor
3169
-
3170
-        let configs: [(CGFloat, NSFont.Weight, CGFloat, CGFloat)] = [
3171
-            (17, .medium, 0, 0),
3172
-            (11, .regular, -11, -9),
3173
-            (9, .regular, 12, 10)
3174
-        ]
3175
-
3176
-        let symbolName = Self.sparkleSymbolName()
3177
-        for (size, weight, ox, oy) in configs {
3178
-            let iv = NSImageView()
3179
-            iv.translatesAutoresizingMaskIntoConstraints = false
3180
-            iv.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: size, weight: weight)
3181
-            iv.image = NSImage(systemSymbolName: symbolName, accessibilityDescription: nil)
3182
-            iv.contentTintColor = tint
3183
-            addSubview(iv)
3184
-            NSLayoutConstraint.activate([
3185
-                iv.centerXAnchor.constraint(equalTo: centerXAnchor, constant: ox),
3186
-                iv.centerYAnchor.constraint(equalTo: centerYAnchor, constant: oy)
3187
-            ])
3188
-        }
3189
-    }
3190
-
3191
-    private static func sparkleSymbolName() -> String {
3192
-        if NSImage(systemSymbolName: "sparkle", accessibilityDescription: nil) != nil {
3193
-            return "sparkle"
3194
-        }
3195
-        return "sparkles"
3196
-    }
3197
-
3198
-    @available(*, unavailable)
3199
-    required init?(coder: NSCoder) {
3200
-        fatalError("init(coder:) has not been implemented")
3201
-    }
3202
-}
3203
-
3204 3167
 /// Home welcome row: three tappable shortcuts that seed the main search field (reference: white cards, pastel icon well, arrow at bottom trailing).
3205 3168
 private final class FeatureShortcutCardView: NSView {
3206 3169
     private static let cardCornerRadius: CGFloat = 14

+ 32 - 36
App for Indeed/Views/IndeedLogoView.swift

@@ -5,46 +5,36 @@
5 5
 
6 6
 import Cocoa
7 7
 
8
-/// Indeed wordmark (`indeed` in brand blue) for splash and branding surfaces.
8
+/// App logo from the asset catalog for splash and branding surfaces.
9 9
 enum IndeedBrandLogo {
10
-    static let brandBlue = NSColor(srgbRed: 37 / 255, green: 87 / 255, blue: 167 / 255, alpha: 1)
10
+    enum Variant {
11
+        case standard
12
+        case compact
13
+    }
11 14
 
12
-    static func wordmarkImage(fittingHeight height: CGFloat) -> NSImage {
13
-        let fontSize = height * 0.92
14
-        let font = NSFont.systemFont(ofSize: fontSize, weight: .heavy)
15
-        let text = "indeed" as NSString
16
-        let attributes: [NSAttributedString.Key: Any] = [
17
-            .font: font,
18
-            .foregroundColor: brandBlue,
19
-            .kern: -0.6
20
-        ]
21
-        let size = text.size(withAttributes: attributes)
22
-        let canvas = NSSize(width: ceil(size.width) + 4, height: ceil(size.height) + 4)
23
-        let image = NSImage(size: canvas)
24
-        image.lockFocus()
25
-        defer { image.unlockFocus() }
26
-        NSColor.clear.set()
27
-        NSRect(origin: .zero, size: canvas).fill()
28
-        let origin = NSPoint(x: 2, y: (canvas.height - size.height) / 2)
29
-        text.draw(at: origin, withAttributes: attributes)
30
-        return image
15
+    static func logoImage(variant: Variant = .standard) -> NSImage? {
16
+        switch variant {
17
+        case .standard:
18
+            NSImage(named: NSImage.Name("IndeedLogo"))
19
+        case .compact:
20
+            NSImage(named: NSImage.Name("IndeedLogoSmall"))
21
+        }
31 22
     }
32 23
 }
33 24
 
34 25
 final class IndeedLogoView: NSView {
35 26
     private let imageView = NSImageView()
36
-    private var displayHeight: CGFloat = 44
27
+    private let variant: IndeedBrandLogo.Variant
28
+    private var displayHeight: CGFloat
29
+    private var sizeConstraints: [NSLayoutConstraint] = []
37 30
 
38 31
     override var intrinsicContentSize: NSSize {
39
-        guard let image = imageView.image, image.size.height > 0 else {
40
-            return NSSize(width: 140, height: displayHeight)
41
-        }
42
-        let aspect = image.size.width / image.size.height
43
-        return NSSize(width: displayHeight * aspect, height: displayHeight)
32
+        NSSize(width: displayHeight, height: displayHeight)
44 33
     }
45 34
 
46
-    init(displayHeight: CGFloat = 44) {
35
+    init(displayHeight: CGFloat = 44, variant: IndeedBrandLogo.Variant = .standard) {
47 36
         self.displayHeight = displayHeight
37
+        self.variant = variant
48 38
         super.init(frame: .zero)
49 39
         setUp()
50 40
     }
@@ -56,28 +46,34 @@ final class IndeedLogoView: NSView {
56 46
 
57 47
     func setDisplayHeight(_ height: CGFloat) {
58 48
         displayHeight = height
59
-        refreshImage()
49
+        sizeConstraints.forEach { $0.constant = height }
60 50
         invalidateIntrinsicContentSize()
61 51
     }
62 52
 
63 53
     private func setUp() {
64 54
         translatesAutoresizingMaskIntoConstraints = false
55
+        setContentHuggingPriority(.required, for: .horizontal)
56
+        setContentHuggingPriority(.required, for: .vertical)
57
+        setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
58
+        setContentCompressionResistancePriority(.defaultLow, for: .vertical)
59
+
65 60
         imageView.translatesAutoresizingMaskIntoConstraints = false
66 61
         imageView.imageScaling = .scaleProportionallyUpOrDown
62
+        imageView.image = IndeedBrandLogo.logoImage(variant: variant)
67 63
         addSubview(imageView)
68
-        NSLayoutConstraint.activate([
64
+
65
+        let width = widthAnchor.constraint(equalToConstant: displayHeight)
66
+        let height = heightAnchor.constraint(equalToConstant: displayHeight)
67
+        sizeConstraints = [width, height]
68
+
69
+        NSLayoutConstraint.activate(sizeConstraints + [
69 70
             imageView.leadingAnchor.constraint(equalTo: leadingAnchor),
70 71
             imageView.trailingAnchor.constraint(equalTo: trailingAnchor),
71 72
             imageView.topAnchor.constraint(equalTo: topAnchor),
72 73
             imageView.bottomAnchor.constraint(equalTo: bottomAnchor)
73 74
         ])
74
-        refreshImage()
75 75
         setAccessibilityElement(true)
76 76
         setAccessibilityRole(.image)
77
-        setAccessibilityLabel("Indeed")
78
-    }
79
-
80
-    private func refreshImage() {
81
-        imageView.image = IndeedBrandLogo.wordmarkImage(fittingHeight: displayHeight)
77
+        setAccessibilityLabel(AppMarketingLinks.displayName)
82 78
     }
83 79
 }

+ 3 - 3
App for Indeed/Views/LoadingView.swift

@@ -24,7 +24,7 @@ final class LoadingView: NSView {
24 24
     private let backgroundGradientHost = NSView()
25 25
     private let heroBackground = LoadingSplashBackgroundView()
26 26
     private let iconWell = NSView()
27
-    private let logoView = IndeedLogoView(displayHeight: 44)
27
+    private let logoView = IndeedLogoView(displayHeight: 40, variant: .compact)
28 28
     private let aiBadgeHost = NSView()
29 29
     private let aiBadgeLabel = NSTextField(labelWithString: "AI-POWERED")
30 30
     private let titleLabel = NSTextField(labelWithString: AppMarketingLinks.displayName)
@@ -185,8 +185,8 @@ final class LoadingView: NSView {
185 185
             heroBackground.topAnchor.constraint(equalTo: topAnchor),
186 186
             heroBackground.bottomAnchor.constraint(equalTo: bottomAnchor),
187 187
 
188
-            iconWell.widthAnchor.constraint(greaterThanOrEqualToConstant: 200),
189
-            iconWell.heightAnchor.constraint(equalToConstant: 96),
188
+            iconWell.widthAnchor.constraint(greaterThanOrEqualToConstant: 160),
189
+            iconWell.heightAnchor.constraint(equalToConstant: 80),
190 190
 
191 191
             logoView.centerXAnchor.constraint(equalTo: iconWell.centerXAnchor),
192 192
             logoView.centerYAnchor.constraint(equalTo: iconWell.centerYAnchor),