# 唯一源
`client/electron/src/icons/agentmail.svg` 是图标唯一源(24×24 视图框,`currentColor`
跟随文字色)。此前各端用的都是占位物:Electron 的窗口/托盘指向一个**不存在**的
`src/icons/tray-icon.png`(`nativeImage` 拿到空图,托盘不可见),
HarmonyOS 的 `startIcon/foreground/background` 是 1×1 PNG,
Web 端根本没有 favicon。
# 为什么带生成脚本
PNG/ICO 是二进制的,换一次配色要重出十几个尺寸,手工做必然出现
「Web 是旧的、Harmony 是新的」这种不一致,而且没人能复核。
`generate.py` 只认上面那一份源,所有变体都由它推导(本机无 rsvg/ImageMagick,
用 cairosvg + Pillow)。改图标只需改源文件再跑一次脚本。
# 各端产物
- **Web**:`public/assets/{agentmail.svg,favicon.ico,apple-touch-icon.png}` + `index.html` 引用。
放 `assets/` 下而非根目录,是因为 Gateway 只把 `/assets/*` 与 `/` 交给静态处理器
(`server/cmd/server/main.go`),放根下会 404。已实测本机与 LAN 均 200。
- **Electron**:应用图标 `icon.png`(512) / `icon.ico`(16–256) / 各尺寸 PNG /
托盘 `tray-icon.png`(32),`package.json` 里 `win.icon` 与 `linux.icon` 指过去。
托盘用品牌色字形而非白色 —— 浅色面板下白色会消失。
- **HarmonyOS**:`startIcon.png`(512) 用完整应用图标(启动页底色浅 `#FFF` /
深 `#000`,白底蓝图标两套都立得住);分层图标的 `background` 是品牌色整块、
`foreground` 是白色字形并留 12% 安全区,避免被系统圆角裁掉。
- **应用内**:新增 `BrandMarkIcon`(fill 型,与现有描边图标集不同族),
替换登录页与初始化页品牌位的占位 `MailboxIcon`;后者已无引用,一并删除。
图标色 `#2563eb` 与门户 Dashy 主题主色一致。
# 验证
- 前端 typecheck 与 196 项测试全绿;`npm run build` 产物含三个图标文件
- Gateway 重新部署后 `/assets/{agentmail.svg,favicon.ico,apple-touch-icon.png}`
在本机与 `192.168.2.60:8180` 都返回 200,Content-Type 正确
- 所有 PNG/ICO 用 Pillow 复核尺寸与 alpha 边界(合成失败会表现为全透明,
已用 getbbox 排除)
55 lines
2.2 KiB
HTML
55 lines
2.2 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta
|
||
name="viewport"
|
||
content="width=device-width, initial-scale=1.0, viewport-fit=cover, interactive-widget=resizes-content"
|
||
/>
|
||
<!--
|
||
图标放在 public/assets/ 而不是 public/ 根下:Gateway 只把 /assets/* 和 /
|
||
挂给了静态处理器(见 server/cmd/server/main.go 的静态段),放在根下会 404。
|
||
Vite 原样拷贝 public/ 到 dist/,所以开发态与内嵌后 URL 都是 /assets/…。
|
||
品牌源文件与其生成脚本:client/electron/src/icons/。
|
||
-->
|
||
<link rel="icon" type="image/svg+xml" href="/assets/agentmail.svg" />
|
||
<link rel="alternate icon" type="image/x-icon" href="/assets/favicon.ico" />
|
||
<link rel="apple-touch-icon" href="/assets/apple-touch-icon.png" />
|
||
<meta name="theme-color" content="#2563eb" />
|
||
<title>AgentMail</title>
|
||
<script>
|
||
/*
|
||
* 首帧防闪屏。
|
||
*
|
||
* JS bundle 有几百 KB,从 HTML 解析完到 React 挂载之间有一段空窗 ——
|
||
* 那段时间里页面是 body 的默认底色。深色偏好的用户会被闪一下白屏,
|
||
* 而且是每次刷新都闪。
|
||
*
|
||
* 这段脚本必须**内联且同步**:外链或 defer 都会晚于首次绘制。
|
||
* 逻辑与 themeStore 的 readStored/resolveTheme 一致,
|
||
* 改那边的键名或取值时这里要同步。
|
||
*/
|
||
(function () {
|
||
try {
|
||
var p = localStorage.getItem("agentmail.theme") || "system";
|
||
var dark =
|
||
p === "dark" ||
|
||
(p === "system" &&
|
||
window.matchMedia &&
|
||
window.matchMedia("(prefers-color-scheme: dark)").matches);
|
||
if (dark) {
|
||
document.documentElement.classList.add("dark");
|
||
document.documentElement.style.colorScheme = "dark";
|
||
}
|
||
} catch (e) {
|
||
/* localStorage 不可用(隐私模式)时退回浅色,不阻塞渲染 */
|
||
}
|
||
})();
|
||
</script>
|
||
</head>
|
||
<body class="bg-gray-50 text-gray-900 antialiased">
|
||
<div id="root"></div>
|
||
<script type="module" src="/src/main.tsx"></script>
|
||
</body>
|
||
</html>
|