feat: add a bundled sparkle application icon

This commit is contained in:
2026-10-12 13:46:04 +02:00
parent ec30ceb8ee
commit 37f6cab256
4 changed files with 62 additions and 1 deletions
+3 -1
View File
@@ -5,9 +5,11 @@ INSTALL_DIR ?= /Applications
build: build:
swift build -c release swift build -c release
mkdir -p $(APP)/Contents/MacOS mkdir -p $(APP)/Contents/MacOS $(APP)/Contents/Resources
cp .build/release/Conjure $(APP)/Contents/MacOS/Conjure cp .build/release/Conjure $(APP)/Contents/MacOS/Conjure
cp Resources/Info.plist $(APP)/Contents/Info.plist cp Resources/Info.plist $(APP)/Contents/Info.plist
swift Scripts/icon.swift .build/Conjure.iconset
iconutil -c icns .build/Conjure.iconset -o $(APP)/Contents/Resources/Conjure.icns
codesign --force --sign - $(APP) codesign --force --sign - $(APP)
run: build run: build
+2
View File
@@ -77,6 +77,8 @@ Applications with identical display names show a muted containing-folder hint be
The launcher keeps its Raycast-inspired 750 × 474-point, titlebar-free rounded panel, large borderless search field, compact icon rows, right-aligned application labels, and bottom-right launch pill. Its Sunset palette uses a dark brown background, soft amber and rust glows, warm cream text, and orange accents on the caret, selection, and action outline. The launcher keeps its Raycast-inspired 750 × 474-point, titlebar-free rounded panel, large borderless search field, compact icon rows, right-aligned application labels, and bottom-right launch pill. Its Sunset palette uses a dark brown background, soft amber and rust glows, warm cream text, and orange accents on the caret, selection, and action outline.
The application icon uses the same orange `sparkles` SF Symbol on a self-contained, rounded dark-brown tile. `Scripts/icon.swift` renders every standard and Retina icon size, and `make build` packages the resulting `.icns` in the signed bundle for Finder and other system icon surfaces. Conjure remains an accessory app; adding an application icon does not add a Dock or app-switcher entry.
The brown tint is 35% opaque over an active, behind-window `NSVisualEffectView` using the native HUD material. This exposes macOS's blurred backdrop while retaining the warm palette and glows; the system material supplies an opaque fallback when Reduce Transparency is enabled. Both the panel and launch pill use native rounded alpha masks alongside layer clipping, keeping material inside its rounded outline and making the window shadow follow the same shape. The brown tint is 35% opaque over an active, behind-window `NSVisualEffectView` using the native HUD material. This exposes macOS's blurred backdrop while retaining the warm palette and glows; the system material supplies an opaque fallback when Reduce Transparency is enabled. Both the panel and launch pill use native rounded alpha masks alongside layer clipping, keeping material inside its rounded outline and making the window shadow follow the same shape.
AppKit still provides text editing, table navigation, scrolling, application icons, controls, menus, fonts, and visual-effect materials. The background uses cached native radial gradients that fade to transparent: static soft blobs, without animations, timers, image assets, blur filters, or third-party UI dependencies. Decorative drawing does not intercept clicks. Increased-contrast settings strengthen the selection outline, and text colors are tuned for readability across the glows and selection. AppKit still provides text editing, table navigation, scrolling, application icons, controls, menus, fonts, and visual-effect materials. The background uses cached native radial gradients that fade to transparent: static soft blobs, without animations, timers, image assets, blur filters, or third-party UI dependencies. Decorative drawing does not intercept clicks. Increased-contrast settings strengthen the selection outline, and text colors are tuned for readability across the glows and selection.
+2
View File
@@ -14,6 +14,8 @@
<string>Conjure</string> <string>Conjure</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Conjure</string> <string>Conjure</string>
<key>CFBundleIconFile</key>
<string>Conjure.icns</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
+55
View File
@@ -0,0 +1,55 @@
import AppKit
// Render the launcher's SF Symbol directly at every macOS icon resolution.
precondition(CommandLine.arguments.count == 2, "Usage: swift Scripts/icon.swift <output.iconset>")
let directory = URL(fileURLWithPath: CommandLine.arguments[1], isDirectory: true)
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
let accent = NSColor(srgbRed: 0.95, green: 0.58, blue: 0.23, alpha: 1)
guard let symbol = NSImage(systemSymbolName: "sparkles", accessibilityDescription: nil)?
.withSymbolConfiguration(NSImage.SymbolConfiguration(paletteColors: [accent])) else {
fatalError("The sparkles SF Symbol is unavailable.")
}
let gradient = NSGradient(starting: NSColor(srgbRed: 0.27, green: 0.19, blue: 0.13, alpha: 1),
ending: NSColor(srgbRed: 0.12, green: 0.09, blue: 0.08, alpha: 1))!
for size in [16, 32, 128, 256, 512] {
for scale in [1, 2] {
let pixels = size * scale
let bitmap = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: pixels, pixelsHigh: pixels,
bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true,
isPlanar: false, colorSpaceName: .deviceRGB,
bytesPerRow: 0, bitsPerPixel: 0)!
NSGraphicsContext.saveGraphicsState()
NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: bitmap)
let context = NSGraphicsContext.current!.cgContext
context.scaleBy(x: CGFloat(pixels) / 1024, y: CGFloat(pixels) / 1024)
let tile = NSBezierPath(roundedRect: NSRect(x: 100, y: 100, width: 824, height: 824),
xRadius: 184, yRadius: 184)
NSGraphicsContext.saveGraphicsState()
let shadow = NSShadow()
shadow.shadowColor = NSColor.black.withAlphaComponent(0.28)
shadow.shadowBlurRadius = 24
shadow.shadowOffset = NSSize(width: 0, height: -12)
shadow.set()
NSColor(srgbRed: 0.12, green: 0.09, blue: 0.08, alpha: 1).setFill()
tile.fill()
NSGraphicsContext.restoreGraphicsState()
gradient.draw(in: tile, angle: -90)
NSColor.white.withAlphaComponent(0.10).setStroke()
tile.lineWidth = 2
tile.stroke()
let glyphHeight: CGFloat = 540
let glyphWidth = glyphHeight * symbol.size.width / symbol.size.height
symbol.draw(in: NSRect(x: (1024 - glyphWidth) / 2, y: (1024 - glyphHeight) / 2,
width: glyphWidth, height: glyphHeight),
from: .zero, operation: .sourceOver, fraction: 1)
NSGraphicsContext.restoreGraphicsState()
let suffix = scale == 2 ? "@2x" : ""
let output = directory.appendingPathComponent("icon_\(size)x\(size)\(suffix).png")
guard let png = bitmap.representation(using: .png, properties: [:]) else {
fatalError("Could not encode \(output.lastPathComponent).")
}
try png.write(to: output)
}
}