New logo: diagonal transfer arrows + lock (SVG-first icon pipeline)
Glyph composed from mynaui arrow-diagonal-one (both diagonals) with the mini-lock of lock-square centered between them — the macOS squircle plays the role of lock-square's outer square. Indigo gradient + white strokes + amber lock face for the app icon; a pure black+alpha variant for the macOS template tray icon, plus 21 pre-rendered tray progress frames (faded arrows + fill bar, 0-100% in 5% steps) for the upcoming tray feature. Pipeline: scripts/gen-icons.ts renders every size directly from the SVGs with @resvg/resvg-js (dev-only dep, prebuilt binaries, no postinstall); replaces make-icon.py + gen-iconset.sh and the sips/iconutil path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
// Regenerate every raster icon asset from the SVG sources (dev-time only).
|
||||
// bun scripts/gen-icons.ts
|
||||
// Produces: assets/icon.png (1024), assets/icon.iconset/* (macOS app icon),
|
||||
// assets/tray/tray-44-template.png, assets/tray/progress/p{0..100}.png.
|
||||
import { mkdir } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { Resvg } from "@resvg/resvg-js";
|
||||
|
||||
const root = path.join(import.meta.dir, "..");
|
||||
const assets = path.join(root, "assets");
|
||||
|
||||
function renderPng(svg: string, sizePx: number): Uint8Array {
|
||||
const resvg = new Resvg(svg, { fitTo: { mode: "width", value: sizePx } });
|
||||
return resvg.render().asPng();
|
||||
}
|
||||
|
||||
async function writePng(file: string, svg: string, sizePx: number): Promise<void> {
|
||||
await mkdir(path.dirname(file), { recursive: true });
|
||||
await Bun.write(file, renderPng(svg, sizePx));
|
||||
}
|
||||
|
||||
// ---- app icon: iconset rendered per size (crisper than downscaling) ----
|
||||
const logo = await Bun.file(path.join(assets, "logo.svg")).text();
|
||||
await writePng(path.join(assets, "icon.png"), logo, 1024);
|
||||
for (const size of [16, 32, 128, 256, 512]) {
|
||||
await writePng(path.join(assets, "icon.iconset", `icon_${size}x${size}.png`), logo, size);
|
||||
await writePng(path.join(assets, "icon.iconset", `icon_${size}x${size}@2x.png`), logo, size * 2);
|
||||
}
|
||||
|
||||
// ---- tray base (22pt status item @2x) ----
|
||||
const trayGlyph = await Bun.file(path.join(assets, "tray", "tray-glyph.svg")).text();
|
||||
await writePng(path.join(assets, "tray", "tray-44-template.png"), trayGlyph, 44);
|
||||
|
||||
// ---- tray progress frames: faded arrows + centered bar filled to pct ----
|
||||
function progressSvg(pct: number): string {
|
||||
const trackX = 4;
|
||||
const trackW = 16;
|
||||
const fillW = (trackW * pct) / 100;
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<g fill="none" stroke="#000" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" opacity="0.35">
|
||||
<path d="M9.2 9.2 4.6 4.6m0 0v4.2m0-4.2h4.2"/>
|
||||
<path d="m14.8 14.8 4.6 4.6m0 0v-4.2m0 4.2h-4.2"/>
|
||||
</g>
|
||||
<rect x="${trackX}" y="10.7" width="${trackW}" height="2.6" rx="1.3" fill="#000" opacity="0.25"/>
|
||||
${fillW > 0 ? `<rect x="${trackX}" y="10.7" width="${fillW.toFixed(2)}" height="2.6" rx="1.3" fill="#000"/>` : ""}
|
||||
</svg>`;
|
||||
}
|
||||
|
||||
for (let pct = 0; pct <= 100; pct += 5) {
|
||||
await writePng(path.join(assets, "tray", "progress", `p${pct}.png`), progressSvg(pct), 44);
|
||||
}
|
||||
|
||||
console.log("icons regenerated: app iconset, tray template, 21 progress frames");
|
||||
Reference in New Issue
Block a user