Procházet zdrojové kódy

Add Indeed wordmark to splash screen and sidebar header.

Introduce a reusable logo view so launch and navigation surfaces show consistent Indeed branding.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 před 3 týdny
rodič
revize
68a5042bf7

+ 12 - 3
App for Indeed/Views/DashboardView.swift

@@ -2369,14 +2369,23 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
2369 2369
             $0.removeFromSuperview()
2370 2370
         }
2371 2371
 
2372
+        let logo = IndeedLogoView(displayHeight: 26)
2373
+        logo.translatesAutoresizingMaskIntoConstraints = false
2374
+
2372 2375
         let brand = NSTextField(labelWithString: AppMarketingLinks.appDisplayName)
2373
-        brand.font = .systemFont(ofSize: 18, weight: .bold)
2376
+        brand.font = .systemFont(ofSize: 15, weight: .semibold)
2374 2377
         brand.textColor = Theme.brandBlue
2375 2378
         brand.alignment = .left
2376 2379
         brand.maximumNumberOfLines = 2
2377 2380
         brand.preferredMaxLayoutWidth = 194
2378
-        sidebar.addArrangedSubview(brand)
2379
-        sidebar.setCustomSpacing(22, after: brand)
2381
+
2382
+        let brandHeader = NSStackView(views: [logo, brand])
2383
+        brandHeader.orientation = .vertical
2384
+        brandHeader.alignment = .leading
2385
+        brandHeader.spacing = 6
2386
+        brandHeader.translatesAutoresizingMaskIntoConstraints = false
2387
+        sidebar.addArrangedSubview(brandHeader)
2388
+        sidebar.setCustomSpacing(22, after: brandHeader)
2380 2389
 
2381 2390
         items.enumerated().forEach { index, item in
2382 2391
             let isSelected = index == selectedSidebarIndex

+ 83 - 0
App for Indeed/Views/IndeedLogoView.swift

@@ -0,0 +1,83 @@
1
+//
2
+//  IndeedLogoView.swift
3
+//  App for Indeed
4
+//
5
+
6
+import Cocoa
7
+
8
+/// Indeed wordmark (`indeed` in brand blue) for splash and branding surfaces.
9
+enum IndeedBrandLogo {
10
+    static let brandBlue = NSColor(srgbRed: 37 / 255, green: 87 / 255, blue: 167 / 255, alpha: 1)
11
+
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
31
+    }
32
+}
33
+
34
+final class IndeedLogoView: NSView {
35
+    private let imageView = NSImageView()
36
+    private var displayHeight: CGFloat = 44
37
+
38
+    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)
44
+    }
45
+
46
+    init(displayHeight: CGFloat = 44) {
47
+        self.displayHeight = displayHeight
48
+        super.init(frame: .zero)
49
+        setUp()
50
+    }
51
+
52
+    @available(*, unavailable)
53
+    required init?(coder: NSCoder) {
54
+        fatalError("init(coder:) has not been implemented")
55
+    }
56
+
57
+    func setDisplayHeight(_ height: CGFloat) {
58
+        displayHeight = height
59
+        refreshImage()
60
+        invalidateIntrinsicContentSize()
61
+    }
62
+
63
+    private func setUp() {
64
+        translatesAutoresizingMaskIntoConstraints = false
65
+        imageView.translatesAutoresizingMaskIntoConstraints = false
66
+        imageView.imageScaling = .scaleProportionallyUpOrDown
67
+        addSubview(imageView)
68
+        NSLayoutConstraint.activate([
69
+            imageView.leadingAnchor.constraint(equalTo: leadingAnchor),
70
+            imageView.trailingAnchor.constraint(equalTo: trailingAnchor),
71
+            imageView.topAnchor.constraint(equalTo: topAnchor),
72
+            imageView.bottomAnchor.constraint(equalTo: bottomAnchor)
73
+        ])
74
+        refreshImage()
75
+        setAccessibilityElement(true)
76
+        setAccessibilityRole(.image)
77
+        setAccessibilityLabel("Indeed")
78
+    }
79
+
80
+    private func refreshImage() {
81
+        imageView.image = IndeedBrandLogo.wordmarkImage(fittingHeight: displayHeight)
82
+    }
83
+}

+ 9 - 11
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 iconView = NSImageView()
27
+    private let logoView = IndeedLogoView(displayHeight: 44)
28 28
     private let aiBadgeHost = NSView()
29 29
     private let aiBadgeLabel = NSTextField(labelWithString: "AI-POWERED")
30 30
     private let titleLabel = NSTextField(labelWithString: AppMarketingLinks.displayName)
@@ -105,9 +105,7 @@ final class LoadingView: NSView {
105 105
         iconWell.layer?.shadowRadius = 16
106 106
         iconWell.layer?.shadowOffset = CGSize(width: 0, height: -4)
107 107
 
108
-        iconView.translatesAutoresizingMaskIntoConstraints = false
109
-        iconView.imageScaling = .scaleProportionallyUpOrDown
110
-        iconView.image = NSApp.applicationIconImage
108
+        logoView.translatesAutoresizingMaskIntoConstraints = false
111 109
 
112 110
         aiBadgeHost.translatesAutoresizingMaskIntoConstraints = false
113 111
         aiBadgeHost.wantsLayer = true
@@ -149,7 +147,7 @@ final class LoadingView: NSView {
149 147
 
150 148
         thinkingIndicator.translatesAutoresizingMaskIntoConstraints = false
151 149
 
152
-        iconWell.addSubview(iconView)
150
+        iconWell.addSubview(logoView)
153 151
         aiBadgeHost.addSubview(aiBadgeLabel)
154 152
 
155 153
         let heroStack = NSStackView(views: [
@@ -187,13 +185,13 @@ final class LoadingView: NSView {
187 185
             heroBackground.topAnchor.constraint(equalTo: topAnchor),
188 186
             heroBackground.bottomAnchor.constraint(equalTo: bottomAnchor),
189 187
 
190
-            iconWell.widthAnchor.constraint(equalToConstant: 128),
191
-            iconWell.heightAnchor.constraint(equalToConstant: 128),
188
+            iconWell.widthAnchor.constraint(greaterThanOrEqualToConstant: 200),
189
+            iconWell.heightAnchor.constraint(equalToConstant: 96),
192 190
 
193
-            iconView.centerXAnchor.constraint(equalTo: iconWell.centerXAnchor),
194
-            iconView.centerYAnchor.constraint(equalTo: iconWell.centerYAnchor),
195
-            iconView.widthAnchor.constraint(equalToConstant: 88),
196
-            iconView.heightAnchor.constraint(equalToConstant: 88),
191
+            logoView.centerXAnchor.constraint(equalTo: iconWell.centerXAnchor),
192
+            logoView.centerYAnchor.constraint(equalTo: iconWell.centerYAnchor),
193
+            logoView.leadingAnchor.constraint(greaterThanOrEqualTo: iconWell.leadingAnchor, constant: 24),
194
+            logoView.trailingAnchor.constraint(lessThanOrEqualTo: iconWell.trailingAnchor, constant: -24),
197 195
 
198 196
             aiBadgeHost.heightAnchor.constraint(equalToConstant: 26),
199 197
             aiBadgeLabel.leadingAnchor.constraint(equalTo: aiBadgeHost.leadingAnchor, constant: 14),