diff --git a/apps/desktop-client/build/icon.ico b/apps/desktop-client/build/icon.ico index 1f1bec9..3628c79 100644 Binary files a/apps/desktop-client/build/icon.ico and b/apps/desktop-client/build/icon.ico differ diff --git a/apps/desktop-client/build/icon.png b/apps/desktop-client/build/icon.png index dbb1868..9315a39 100644 Binary files a/apps/desktop-client/build/icon.png and b/apps/desktop-client/build/icon.png differ diff --git a/apps/desktop-client/scripts/generate-brand-icons.cjs b/apps/desktop-client/scripts/generate-brand-icons.cjs index 9d1bd79..792f9c8 100644 --- a/apps/desktop-client/scripts/generate-brand-icons.cjs +++ b/apps/desktop-client/scripts/generate-brand-icons.cjs @@ -32,12 +32,6 @@ const OUT_TS = path.join(APP_DIR, 'src', 'main', 'brand-icons.ts') // Brand palette — keep in sync with the renderer (#1677ff is Ant Design blue). const BRAND_BLUE = '#1677ff' const DANGER_RED = '#ff4d4f' -const MAC_APP_ICON_PLATE = 824 -const MAC_APP_ICON_LOGO_RATIO = 0.62 -const APP_PNG_PLATE = 896 -const APP_PNG_LOGO_RATIO = 0.72 -const WINDOWS_ICO_PLATE = 1024 -const WINDOWS_ICO_LOGO_RATIO = 1 const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'brand-icons-')) const cleanup = () => fs.rmSync(tmpDir, { recursive: true, force: true }) @@ -218,36 +212,19 @@ function forceLogoColor(source, fill) { } /** A square app icon: logo centered on a rounded-rect (squircle-ish) bg. */ -function squareIconSvg(bg, logoSource = logo, boundsSource = logoBounds, options = {}) { +function squareIconSvg(bg, logoSource = logo, boundsSource = logoBounds) { const CANVAS = 1024 - const PLATE = options.plate ?? MAC_APP_ICON_PLATE - const LOGO_RATIO = options.logoRatio ?? MAC_APP_ICON_LOGO_RATIO - const radius = options.radius ?? Math.round(PLATE * 0.225) + // macOS icon grid: 824x824 art area inside a 1024 canvas (100px margin). + const PLATE = 824 const MARGIN = (CANVAS - PLATE) / 2 - const target = PLATE * LOGO_RATIO + const target = PLATE * 0.62 const { scale, tx, ty } = fitLogo(boundsSource, target, target, MARGIN + PLATE / 2, MARGIN + PLATE / 2) return ` - + ${logoSource.inner} ` } -function windowsIcoIconSvg(bg, logoSource = windowsTrayLogo, boundsSource = windowsTrayLogoBounds) { - // Windows .ico taskbar layers are tiny in practice; this denser composition - // keeps the foreground mark legible at 24-32px without changing icon.png. - return squareIconSvg(bg, logoSource, boundsSource, { - plate: WINDOWS_ICO_PLATE, - logoRatio: WINDOWS_ICO_LOGO_RATIO, - }) -} - -function appPngIconSvg(bg, logoSource = windowsTrayLogo, boundsSource = windowsTrayLogoBounds) { - return squareIconSvg(bg, logoSource, boundsSource, { - plate: APP_PNG_PLATE, - logoRatio: APP_PNG_LOGO_RATIO, - }) -} - /** * Tray glyph: the logo centered (with padding) inside a 32px square canvas. * tray.ts loads it with scaleFactor 2, so it shows at ~16pt on retina menu @@ -307,19 +284,12 @@ function pngsToIco(pngBuffers) { } function buildAppIcons() { - fs.mkdirSync(BUILD_DIR, { recursive: true }) - // 1024 master for the normal app icon. - const appPng = svgToPng(appPngIconSvg('#ffffff'), 'app-normal', ['-w', '1024', '-h', '1024']) - fs.copyFileSync(appPng, path.join(BUILD_DIR, 'icon.png')) + const masterPng = svgToPng(squareIconSvg('#ffffff', windowsTrayLogo, windowsTrayLogoBounds), 'app-normal', ['-w', '1024', '-h', '1024']) + fs.mkdirSync(BUILD_DIR, { recursive: true }) + fs.copyFileSync(masterPng, path.join(BUILD_DIR, 'icon.png')) // .icns via an .iconset downscaled with sips. - const macMasterPng = svgToPng(squareIconSvg('#ffffff', windowsTrayLogo, windowsTrayLogoBounds), 'app-normal-mac', [ - '-w', - '1024', - '-h', - '1024', - ]) const iconset = path.join(tmpDir, 'icon.iconset') fs.mkdirSync(iconset, { recursive: true }) const variants = [ @@ -336,7 +306,7 @@ function buildAppIcons() { ] for (const [size, file] of variants) { const dest = path.join(iconset, file) - execFileSync('sips', ['-z', String(size), String(size), macMasterPng, '--out', dest], { + execFileSync('sips', ['-z', String(size), String(size), masterPng, '--out', dest], { stdio: 'ignore', }) } @@ -345,7 +315,7 @@ function buildAppIcons() { // .ico with every size Windows asks for (taskbar/Explorer/Alt-Tab/tiles). const icoSizes = [16, 24, 32, 48, 64, 128, 256] const icoPngs = icoSizes.map((s) => - fs.readFileSync(svgToPng(windowsIcoIconSvg('#ffffff'), `app-ico-${s}`, ['-w', String(s), '-h', String(s)])), + fs.readFileSync(svgToPng(squareIconSvg('#ffffff', windowsTrayLogo, windowsTrayLogoBounds), `app-ico-${s}`, ['-w', String(s), '-h', String(s)])), ) fs.writeFileSync(path.join(BUILD_DIR, 'icon.ico'), pngsToIco(icoPngs)) } @@ -386,7 +356,7 @@ function buildMainProcessIcons() { '// Tray icon shown when accounts have health issues (rendered @2x, not a template).', `export const TRAY_DANGER_ICON_BASE64 =\n '${trayDanger}'`, '', - '// Dock / window icon — logo on the white plate, tuned for Windows taskbar visibility.', + '// Dock / window icon — logo on the brand-blue plate.', `export const APP_ICON_NORMAL_BASE64 =\n '${appNormal}'`, '', '// Dock / window icon — logo on a danger plate when issues exist.',