Revert "feat: update app icon generation for improved Windows and macOS support"
Desktop Client Build / Resolve Build Metadata (push) Successful in 26s
Desktop Client Build / Build Desktop Client (push) Successful in 22m27s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 30s

This reverts commit 8b3a5c3442.
This commit is contained in:
Xu Liang
2026-06-01 00:01:27 +08:00
parent 0575578c8e
commit b2ec8cc9fc
3 changed files with 11 additions and 41 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 30 KiB

@@ -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 `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${CANVAS}" height="${CANVAS}" viewBox="0 0 ${CANVAS} ${CANVAS}">
<rect x="${MARGIN}" y="${MARGIN}" width="${PLATE}" height="${PLATE}" rx="${radius}" ry="${radius}" fill="${bg}"/>
<rect x="${MARGIN}" y="${MARGIN}" width="${PLATE}" height="${PLATE}" rx="185" ry="185" fill="${bg}"/>
<g transform="translate(${tx.toFixed(2)},${ty.toFixed(2)}) scale(${scale.toFixed(6)})">${logoSource.inner}</g>
</svg>`
}
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.',