diff --git a/apps/desktop-client/build/icon.icns b/apps/desktop-client/build/icon.icns new file mode 100644 index 0000000..0c4baab Binary files /dev/null and b/apps/desktop-client/build/icon.icns differ diff --git a/apps/desktop-client/build/icon.ico b/apps/desktop-client/build/icon.ico new file mode 100644 index 0000000..daa925f Binary files /dev/null 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 new file mode 100644 index 0000000..c361203 Binary files /dev/null and b/apps/desktop-client/build/icon.png differ diff --git a/apps/desktop-client/electron.vite.config.ts b/apps/desktop-client/electron.vite.config.ts index c4fbfc3..2d864a8 100644 --- a/apps/desktop-client/electron.vite.config.ts +++ b/apps/desktop-client/electron.vite.config.ts @@ -94,6 +94,9 @@ export default defineConfig({ resolve: { alias: { '@renderer': resolve(rootDir, 'src/renderer'), + // Single source of truth for the brand mark; lives in public/ so the + // main process and electron-builder can read the same file. + '@brand-logo': resolve(rootDir, 'public/logo.svg'), ...workspaceAliases, }, }, diff --git a/apps/desktop-client/package.json b/apps/desktop-client/package.json index 1b992f6..5f888a7 100644 --- a/apps/desktop-client/package.json +++ b/apps/desktop-client/package.json @@ -5,7 +5,7 @@ "description": "省心推客户端 — 连接和管理您的媒体账号,轻松发布和监控内容表现。", "author": { "name": "Liang Xu", - "email": "liangxu@qq.com", + "email": "liangxu0920@qq.com", "url": "https://shengxintui.com" }, "type": "module", @@ -13,6 +13,7 @@ "scripts": { "dev": "electron-vite dev --inspect=9229", "build": "electron-vite build", + "gen:icons": "node scripts/generate-brand-icons.cjs", "obfuscate": "node scripts/obfuscate.cjs", "build:obf": "pnpm run build && pnpm run obfuscate", "package:mac": "pnpm run build:obf && electron-builder --mac --arm64 --universal", diff --git a/apps/desktop-client/public/logo.svg b/apps/desktop-client/public/logo.svg new file mode 100644 index 0000000..d14a919 --- /dev/null +++ b/apps/desktop-client/public/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/desktop-client/scripts/generate-brand-icons.cjs b/apps/desktop-client/scripts/generate-brand-icons.cjs new file mode 100644 index 0000000..af95b35 --- /dev/null +++ b/apps/desktop-client/scripts/generate-brand-icons.cjs @@ -0,0 +1,210 @@ +#!/usr/bin/env node +/* + * Generates every brand icon asset the desktop client needs from the single + * source of truth: public/logo.svg. + * + * Outputs: + * build/icon.icns macOS app icon (electron-builder) + * build/icon.png Linux app icon + Windows/icns fallback (1024x1024) + * build/icon.ico Windows app icon + * src/main/brand-icons.ts base64 icons consumed by the main process + * (tray + dock + window + Windows overlay) + * + * Re-run after changing public/logo.svg: + * node scripts/generate-brand-icons.cjs + * + * Requires `rsvg-convert`, `sips` and `iconutil` (preinstalled on macOS via + * librsvg + the system toolchain). + */ +const { execFileSync } = require('node:child_process') +const fs = require('node:fs') +const os = require('node:os') +const path = require('node:path') + +const APP_DIR = path.resolve(__dirname, '..') +const LOGO_PATH = path.join(APP_DIR, 'public', 'logo.svg') +const BUILD_DIR = path.join(APP_DIR, 'build') +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 LOGO_FILL = '#dfdfdf' // the fill baked into logo.svg + +const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'brand-icons-')) +const cleanup = () => fs.rmSync(tmpDir, { recursive: true, force: true }) + +function rsvg(args) { + return execFileSync('rsvg-convert', args) +} + +/** Extract the inner markup (the elements) and viewBox from logo.svg. */ +function readLogo() { + const raw = fs.readFileSync(LOGO_PATH, 'utf8') + const viewBox = (raw.match(/viewBox="([^"]+)"/) || [])[1] + const inner = (raw.match(/]*>([\s\S]*)<\/svg>/) || [])[1] + if (!viewBox || !inner) { + throw new Error('Could not parse public/logo.svg (missing viewBox or body)') + } + const [, , vbW, vbH] = viewBox.split(/\s+/).map(Number) + return { inner: inner.trim(), width: vbW, height: vbH } +} + +const logo = readLogo() + +/** A square app icon: logo centered on a rounded-rect (squircle-ish) bg. */ +function squareIconSvg(bg) { + const CANVAS = 1024 + // macOS icon grid: 824x824 art area inside a 1024 canvas (100px margin). + const PLATE = 824 + const MARGIN = (CANVAS - PLATE) / 2 + const targetW = PLATE * 0.62 + const scale = targetW / logo.width + const drawnW = logo.width * scale + const drawnH = logo.height * scale + const tx = MARGIN + (PLATE - drawnW) / 2 + const ty = MARGIN + (PLATE - drawnH) / 2 + return ` + + ${logo.inner} +` +} + +/** + * 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 + * bars. Padding keeps the wide/landscape mark from touching the canvas edges. + */ +function trayLogoSvg(fill) { + const CANVAS = 32 // tray asset is 32x32 px + // Glyph height inside the 32px canvas — the single knob for tray size. + // Bump up for a larger glyph, down for a smaller one. + const targetH = 20 + const scale = targetH / logo.height + const drawnW = logo.width * scale + const drawnH = logo.height * scale + const tx = (CANVAS - drawnW) / 2 + const ty = (CANVAS - drawnH) / 2 + const inner = fill ? logo.inner.split(LOGO_FILL).join(fill) : logo.inner + return ` + ${inner} +` +} + +function svgToPng(svg, name, extraArgs = []) { + const svgPath = path.join(tmpDir, `${name}.svg`) + const pngPath = path.join(tmpDir, `${name}.png`) + fs.writeFileSync(svgPath, svg) + rsvg([...extraArgs, '-o', pngPath, svgPath]) + return pngPath +} + +function b64(pngPath) { + return fs.readFileSync(pngPath).toString('base64') +} + +/** Wrap a PNG buffer in a minimal (PNG-payload) .ico container. */ +function pngToIco(pngBuffer) { + const header = Buffer.alloc(6) + header.writeUInt16LE(0, 0) // reserved + header.writeUInt16LE(1, 2) // type: icon + header.writeUInt16LE(1, 4) // image count + const entry = Buffer.alloc(16) + entry.writeUInt8(0, 0) // width (0 => 256) + entry.writeUInt8(0, 1) // height (0 => 256) + entry.writeUInt8(0, 2) // palette + entry.writeUInt8(0, 3) // reserved + entry.writeUInt16LE(1, 4) // color planes + entry.writeUInt16LE(32, 6) // bits per pixel + entry.writeUInt32LE(pngBuffer.length, 8) // size of image data + entry.writeUInt32LE(6 + 16, 12) // offset to image data + return Buffer.concat([header, entry, pngBuffer]) +} + +function buildAppIcons() { + // 1024 master for the normal app icon. + const masterPng = svgToPng(squareIconSvg(BRAND_BLUE), '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 iconset = path.join(tmpDir, 'icon.iconset') + fs.mkdirSync(iconset, { recursive: true }) + const variants = [ + [16, 'icon_16x16.png'], + [32, 'icon_16x16@2x.png'], + [32, 'icon_32x32.png'], + [64, 'icon_32x32@2x.png'], + [128, 'icon_128x128.png'], + [256, 'icon_128x128@2x.png'], + [256, 'icon_256x256.png'], + [512, 'icon_256x256@2x.png'], + [512, 'icon_512x512.png'], + [1024, 'icon_512x512@2x.png'], + ] + for (const [size, file] of variants) { + const dest = path.join(iconset, file) + execFileSync('sips', ['-z', String(size), String(size), masterPng, '--out', dest], { + stdio: 'ignore', + }) + } + execFileSync('iconutil', ['-c', 'icns', iconset, '-o', path.join(BUILD_DIR, 'icon.icns')]) + + // .ico from a 256px render. + const ico256 = svgToPng(squareIconSvg(BRAND_BLUE), 'app-ico', ['-w', '256', '-h', '256']) + fs.writeFileSync(path.join(BUILD_DIR, 'icon.ico'), pngToIco(fs.readFileSync(ico256))) +} + +function buildMainProcessIcons() { + // Tray icons are 32x32 px and loaded @2x in tray.ts (=> ~16pt on retina). + // Glyph size is controlled by targetH in trayLogoSvg(), not by an rsvg -h. + const trayNormal = b64(svgToPng(trayLogoSvg(), 'tray-normal')) + const trayDanger = b64(svgToPng(trayLogoSvg(DANGER_RED), 'tray-danger')) + + // Dock / window icons: logo on the brand plate (normal) and danger plate. + const appNormal = b64(svgToPng(squareIconSvg(BRAND_BLUE), 'dock-normal', ['-w', '512', '-h', '512'])) + const appDanger = b64(svgToPng(squareIconSvg(DANGER_RED), 'dock-danger', ['-w', '512', '-h', '512'])) + + // Windows taskbar overlay: a small danger badge (status cue, not the logo). + const overlaySvg = ` + + + +` + const overlay = b64(svgToPng(overlaySvg, 'win-overlay')) + + const banner = `// AUTO-GENERATED from public/logo.svg by scripts/generate-brand-icons.cjs. +// Do not edit by hand — run \`node scripts/generate-brand-icons.cjs\` instead. +/* eslint-disable */ +/* prettier-ignore-start */` + const body = [ + banner, + '', + '// macOS menu-bar template silhouette (rendered @2x).', + `export const TRAY_ICON_BASE64 =\n '${trayNormal}'`, + '', + '// 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 brand-blue plate.', + `export const APP_ICON_NORMAL_BASE64 =\n '${appNormal}'`, + '', + '// Dock / window icon — logo on a danger plate when issues exist.', + `export const APP_ICON_DANGER_BASE64 =\n '${appDanger}'`, + '', + '// Small Windows taskbar overlay badge signalling account health issues.', + `export const WINDOWS_OVERLAY_ICON_BASE64 =\n '${overlay}'`, + '/* prettier-ignore-end */', + '', + ].join('\n') + fs.writeFileSync(OUT_TS, body) +} + +try { + buildAppIcons() + buildMainProcessIcons() + console.log('✓ build/icon.icns, build/icon.png, build/icon.ico') + console.log('✓ src/main/brand-icons.ts') +} finally { + cleanup() +} diff --git a/apps/desktop-client/src/main/app-issue-indicator.ts b/apps/desktop-client/src/main/app-issue-indicator.ts index 5a7c76d..4984c4a 100644 --- a/apps/desktop-client/src/main/app-issue-indicator.ts +++ b/apps/desktop-client/src/main/app-issue-indicator.ts @@ -2,6 +2,11 @@ import { nativeImage } from 'electron/common' import type { BrowserWindow as ElectronBrowserWindow } from 'electron/main' import { app } from 'electron/main' +import { + APP_ICON_DANGER_BASE64, + APP_ICON_NORMAL_BASE64, + WINDOWS_OVERLAY_ICON_BASE64, +} from './brand-icons' import { createRuntimeSnapshot } from './runtime-snapshot' import { updateTrayIssueIndicator } from './tray' @@ -11,12 +16,6 @@ type AppIndicatorImage = ReturnType const HEALTH_ISSUE_AUTH_STATES = new Set(['expired', 'revoked', 'challenge_required']) const ISSUE_INDICATOR_REFRESH_MS = 15_000 -const APP_ICON_NORMAL_BASE64 = - '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' -const APP_ICON_DANGER_BASE64 = - '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' -const WINDOWS_OVERLAY_ICON_BASE64 = - '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' let refreshTimer: ReturnType | null = null const appIconCache = new Map() diff --git a/apps/desktop-client/src/main/brand-icons.ts b/apps/desktop-client/src/main/brand-icons.ts new file mode 100644 index 0000000..42e9e03 --- /dev/null +++ b/apps/desktop-client/src/main/brand-icons.ts @@ -0,0 +1,25 @@ +// AUTO-GENERATED from public/logo.svg by scripts/generate-brand-icons.cjs. +// Do not edit by hand — run `node scripts/generate-brand-icons.cjs` instead. +/* eslint-disable */ +/* prettier-ignore-start */ + +// macOS menu-bar template silhouette (rendered @2x). +export const TRAY_ICON_BASE64 = + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAACt0lEQVRYhe1WPWgUQRT+3ty6ZqM5jAYvCJqbNTHEwiKkCAiRExvRxspOQbCwiIVoYSGEYCEp/GnEQkgrplEiNrEJWBhEBAnEI97OXC4EEaIgXgzJ7jwLN+GyucvdJppC74OFnffzvW/evP0B6qjjfwfFTchmsy22bb8GcJCZB/L5/L1MJuNvVoCIm2Db9nEAnQAaiWgonU5PaK27t00AEUVzuo0xE1rroUKh4Px1AUEQfALwMyLKYuYbQRB80FqfjMNXdQY8z3tMRJlw+WV+fr6vp6dnGQCmp6eTlmWNAugrSWEAw0KI621tbd+q8VftgBDiBAA3vHpTqVTTiq+jo+M7EY1HUgjAJWPMlFLq/JYFbAEpAE+01qO5XO5QpaA1RzAzM3OAmRsAwBgzJ6VcVEq9BHA6DPns+37atu3DABxjjAXgAYAuAAER7WDm3euKEP0wxtyUUj4kIlNWQD6fP2qMmSyxPZJSXomS5XK5U0KIsRLTMynlOQBgZqG1HgZwocKG3wRBcLm9vX1yxVB6BM2RjuwvxyCE2BfZ3WzJvWHmtxWKA0BvIpEYZ+ZEOQE1gZl5Iz8RNVahmMXvJwUAYK0qEWLKGPOciHaFhUYAQCnVC+BYSF4wxkwAGCUih5l9Zn6nlBoA0EBECWa+WKHwEoC7juPcLp2Dqu8BpVQWwJFQlE9ETVLKxRW/53m3iGiwCs0YM/e7rpuNOqxy0ZViiMhaWFhYk0NEG3EUmPm667pPq5JXQjhYq+tkMhmU+pm5hWhdI5cA3HccZ7C1tbW4EX8tHbiKcAaYec73/Z1KqTtE1MzMTcx8NiL4FTP3Syk/1sAd/39Aa32GmV+sIyKaNcZcc113JA7fZr6GUdHLAIaKxWJX3OJAbUewBrZtv/d9/yuAvXHb/ceglNrjeV7nthato45/Fr8AC58XxWfGw7UAAAAASUVORK5CYII=' + +// Tray icon shown when accounts have health issues (rendered @2x, not a template). +export const TRAY_DANGER_ICON_BASE64 = + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAACl0lEQVRYhe2WS0hUcRTGf+fOdXyUoaVJQREFiQkuZiUERtFG8t6ZFkO7gqBFC1tELVoEg7QIFz02ERK4jVykM5qgLUZokUQJIZjQJhSJoCRTHOdxTwttdK4zjjOYi5oPLtz/Od/5zvd/3AeUUML/Dim0QC2rDow3wBFUQywuPJRoNFmsAaOImtNAI1CFSDfVNeNqWb7dM6CGq0Z9YIyr7e/WYLDy7xvw8BlYdkVNlNvE4h/Vss4VIpf3DKhlPwPOrtG/caihTXp6EgDa3r4P0xsB2jaWoNKLJm7J0NB8Pv1trICcATm+etHKl/nqdGZ4eAF0zF2A6FUMc0o7/Jd2wEDRaEB4rpYdUcs6mouUsQVq24dJlVUAsPR9TqLRmFr2K5D2NcpXkvFjeL0nSEolppo4PAaagBRQBuzN0mcR0Tv4fE8kFHKyGlC//xQOk+mY8FTCA9fdSur3n8dhdEOoXyIDFwE0FDL4MNGLcjnHhN/iGNdk6OXkn8D6FqjWZqyIysGsEikOZDqS2fRsQiEH9F2O5gCtGM6YBoOezQa2CxHdmmBU5VGYpbk5rWGmwyvlU3gTA6juWdVx+gDUsloRTwsAygwpYxxPKoJSiZBEeK92IIRqBeBBnSs5nu448ICV5Xsbz0H+94Dtn0Y5uTZM8utntUSjsfV84C6qXVuryCjidEo4PO3OmNnomQ7U3ODTpL7e3JzPiRmQWxLpf5GLkN8A4rgCKde4LktRHNVHxGNdMjKytJX6dgzcAG1Zu58jkShXy38fqAWqgY4MuvIacTplMPIpv3Yx/wO2fQGVwSxKs6A3JRzuK0SviM+xx206gWo35d6mQpvDtrbAbSAxgXh+APsLXe4dgwYCNWrbjbvatIQS/ln8Bo995P1hCXtRAAAAAElFTkSuQmCC' + +// Dock / window icon — logo on the brand-blue plate. +export const APP_ICON_NORMAL_BASE64 = + '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' + +// Dock / window icon — logo on a danger plate when issues exist. +export const APP_ICON_DANGER_BASE64 = + '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' + +// Small Windows taskbar overlay badge signalling account health issues. +export const WINDOWS_OVERLAY_ICON_BASE64 = + 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAACr0lEQVRYhc2XTU8TURSGn9vyocT4ETEsiBtMVHYOFKPVBX8AaGIKie7QjfELwbggRidGNBrRRKk7XaqkGqnwA9gU3bSNG4mJuEBdQGoUTbQ10ONipnRaDL1ToPCu7szcc94n5965cwbWWUp3ogSDXtLpI+DpQMQPNAA77MffgU8gUTIqQk3VhAqHF1YFQILBzaT+XgDpBbVLk3cWpQaprnyowuE/JQNIW6AT5B5Qr2lcqM8IvWos8sIVgICiPXANkavFIDUkwB2ajX5lmpmiAGKaHmLxZ6A6V2hcqGGajeOFEJ4l02KJgTUwB+gilrheeDOvAvaaD2ul8/ngzGmrwKEQxOI6UQIqqEZHXi4BsHf7B2C3FsCTx1C70xonk9B9SisM+AqZvWp09Dc4lyCd7tE2h5w5QG2tdhhQj/KezV54wD5khItusqxIIr0SDHoXAUjNH3VxyKyG6kjNH84BkOkoozlOz+we8JfdXyxPG0Aayg6g2OMAUNvKDgDbHQDrp+wSzLmOTH5zjJOleP9wAKgp1+GhkAWRTMLQo1IAPgJUWGOJgjrkKjwWh+6TpRjblhKFbAUyKlJ6phLltTwtgJqqCWDWXQIvHGyBFp81dqcZDOMtOL+G7YHLiNzWCq+ogJsDsH+fdT05Cf1XYEGrDwWlLqnXI4PgfA1//ngATGslMA7kzAEaG8EwNM35QnXl4q5dBFDj4ymEPqwWY60kZDjv7JTzDiK7e71VNE08YZU9q/eTkEjo+N9QY5FXeZ5Lppimh1jiKdC1bC6vF5oMq16JRPH1F57jM04UNqUbry3Pi2wLHAO5j5tWLV/TCD2FZdcGAJDW1k1s2XoOpfqAOk3jGeAuv+aG1Ph4armJ+j+npukh9s4PmQ4Ev/09z/2cClN4iIJEaGp6879yb0j9A0Ub4d8dbjwJAAAAAElFTkSuQmCC' +/* prettier-ignore-end */ diff --git a/apps/desktop-client/src/main/tray.ts b/apps/desktop-client/src/main/tray.ts index 95e3ae9..efd3fc5 100644 --- a/apps/desktop-client/src/main/tray.ts +++ b/apps/desktop-client/src/main/tray.ts @@ -2,28 +2,27 @@ import { nativeImage } from 'electron/common' import type { Tray as ElectronTray } from 'electron/main' import { Menu, Tray, app } from 'electron/main' +import { TRAY_DANGER_ICON_BASE64, TRAY_ICON_BASE64 } from './brand-icons' + type TrayIconImage = ReturnType +// The tray PNGs are generated at 2x (see scripts/generate-brand-icons.cjs), so +// they stay crisp on retina menu bars. +const TRAY_ICON_SCALE_FACTOR = 2 + let tray: ElectronTray | null = null let normalTrayIcon: TrayIconImage | null = null let dangerTrayIcon: TrayIconImage | null = null -const TRAY_ICON_BASE64 = - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAAnUlEQVR4nN2UwQmAMAxF360Dee8I' + - 'LuNIxT2cpIv0oJcIEqJGMSIG/qX8fn5/msDfqgcKUIEmqHLW3xHsgAmYTzAJ1+2yOURXNI/77qLo' + - 'VvzQufX8EchAEmQ5s2LZjUCThwMTg8E3IymG07PSzotFqoqUHcJZ3akWSTctOYST0cT3hMOiCGte' + - '2HcjakCIHGmiltDW+eNrU7t/dNF/txaahq+VoZ+VygAAAABJRU5ErkJggg==' - -const TRAY_DANGER_ICON_BASE64 = - 'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABmJLR0QA/wD/AP+gvaeTAAACSUlEQVQ4jd2Uz04TURTGf2dmkG5spwU3mOgKXoCFGlwM0qZpDYEFvoLEPyuN6F4TTYxLWPAKaqILxKZtmMSQ6CvAygUuhNIpLpowt3NcaMt0GkASN/qtbs6533e+e++5B/41yEnJRqmUlsPDMiLTAmMACt9Q3dBz5z6MrK8fnElYJyeHmrncI1FdAjLHcAMReZEJw1fi++ZU4abnudj2W0RunHSaGOoYs5D1/SAetJJOcZw3ZxAFmMFxXqvnOccKN7PZh8BMgriLyFNVnVXVWeAZsJvYk2/Z9oN4oHcVjVIpbYXhV8CN5T9Ztj2fqVT246RWsZiLOp33wPVYODDt9qULm5s/+hyLMTcTot9leHiuK9oqFMZbhcI4QKZS2bdV54G92H53KJUqD16Fqpc43qq7ttYECPL5lUh1K1LdCvL5ZYB0vd4Q1dU+hkhP48jx7z49qqNfuk4V7vTicLfrPLLtzwnOxUHHfxk9YRXZiSdE5ApAplrdFliJ2VrOVKvbAFanczXB6WkcOY4iP1F0sVUs5gDcWu2eJTJhiUxk6/X7AAeeN6oiiwnORq9Id3FMu23aqnPper0RZx943mjHcd4BU7Fw07Tbl7vt1vel9/P5JwLPEy72RHW1+1CW6jVVvQ2M9F0DLLm12ssBxwDqeU7gOB8Z/H2noeYaU4oPo76uEN83GLMA1P5YUqSKMbeSE26g3bK+H7jGlET1MRAk8zE0BZbcMCwnJxucMuh3p6bOD6VS5ciypiWKxn4ZlB1gI2y317sP9X/gJ6o+6LM9+rGLAAAAAElFTkSuQmCC' - function createTrayIcon(tone: 'normal' | 'danger'): TrayIconImage { if (tone === 'danger') { if (dangerTrayIcon) { return dangerTrayIcon } - const icon = nativeImage.createFromBuffer(Buffer.from(TRAY_DANGER_ICON_BASE64, 'base64')) + const icon = nativeImage.createFromBuffer(Buffer.from(TRAY_DANGER_ICON_BASE64, 'base64'), { + scaleFactor: TRAY_ICON_SCALE_FACTOR, + }) icon.setTemplateImage(false) dangerTrayIcon = icon.isEmpty() ? createTrayIcon('normal') : icon return dangerTrayIcon @@ -34,7 +33,7 @@ function createTrayIcon(tone: 'normal' | 'danger'): TrayIconImage { } const buffer = Buffer.from(TRAY_ICON_BASE64, 'base64') - const icon = nativeImage.createFromBuffer(buffer) + const icon = nativeImage.createFromBuffer(buffer, { scaleFactor: TRAY_ICON_SCALE_FACTOR }) if (icon.isEmpty()) { return nativeImage.createEmpty() } diff --git a/apps/desktop-client/src/renderer/brand-logo.d.ts b/apps/desktop-client/src/renderer/brand-logo.d.ts new file mode 100644 index 0000000..610dd28 --- /dev/null +++ b/apps/desktop-client/src/renderer/brand-logo.d.ts @@ -0,0 +1,7 @@ +// Type for the `@brand-logo` alias (electron.vite.config.ts → public/logo.svg). +// Kept in its own ambient (non-module) declaration file so vue-tsc resolves the +// alias the same way Vite does at build time. +declare module '@brand-logo' { + const src: string + export default src +} diff --git a/apps/desktop-client/src/renderer/components/DesktopShell.vue b/apps/desktop-client/src/renderer/components/DesktopShell.vue index 50c9be5..7665aef 100644 --- a/apps/desktop-client/src/renderer/components/DesktopShell.vue +++ b/apps/desktop-client/src/renderer/components/DesktopShell.vue @@ -11,6 +11,7 @@ import { import { computed, onMounted, ref, watch } from 'vue' import { RouterLink, RouterView, useRoute } from 'vue-router' +import brandLogo from '@brand-logo' import { useClientRelease } from '../composables/useClientRelease' import { useDesktopRuntime } from '../composables/useDesktopRuntime' import { useDesktopSession } from '../composables/useDesktopSession' @@ -232,8 +233,7 @@ watch(