13 KiB
Kindle Dashboard 多主题切换方案
1. 背景
当前仓库已经具备一条稳定的单主题链路:
calendar/负责渲染仪表盘网页,并导出kindlebg.pngdash/运行在 Kindle 上,按固定 URL 拉取背景图- Kindle 本机每分钟只重画时钟区域,不重新联网渲染整页
当前关键约束如下:
- Kindle 端默认只认识一个背景地址:
BACKGROUND_URL - 背景图文件名固定为
kindlebg.png - 本机时钟素材与时钟区域参数由 Kindle 本地管理
- KUAL 菜单当前只有启动和调试入口,没有切换主题入口
这意味着“多主题”不能只靠改前端样式,还需要把主题标识、产物路径和 Kindle 侧的选择逻辑一起设计出来。
2. 目标
本方案要解决的问题是:
- 访问
calendar网站时,可以通过菜单预览不同主题样式 - 现有日历背景生成流程保持兼容,不因预览主题而被破坏
- 后续如果需要,
calendar/仍能稳定产出多个主题的背景图 - Kindle 能在不改代码、不重新部署整套程序的前提下切换当前主题
- 主题切换后,下一次背景刷新即可生效 SH: 主题切换后,即刻拉取一次
- 后续如果主题不仅改背景,还改表盘素材与时钟区域,也能平滑扩展
非目标:
- 不在 Kindle 上重新渲染整张日历页
- 不引入 Kindle 端复杂主题模板引擎
- 不要求首次版本就支持任意数量主题的自动发现
3. 设计原则
3.1 渲染留在 calendar/
推荐继续保持现有职责边界:
calendar/负责主题样式、布局、导出- Kindle 只负责选择当前主题并拉取对应产物
原因:
- Kindle 算力和调试体验都不适合承载整页主题渲染
- 当前链路已经验证“远端产图 + 本机分钟级叠时钟”可行
- 主题扩展主要发生在样式层,天然更适合留在前端工程里
3.2 Kindle 只保存“当前主题 ID”
Kindle 端不保存复杂主题配置,只保存一个很小的状态:
- 当前主题名,例如
paper
围绕这个主题名决定:
- 去哪个 URL 拉取背景图
- 使用哪套本地表盘素材
- 使用哪份时钟区域配置
3.3 先做“背景主题切换”,再做“完整主题切换”
建议分两阶段:
- 阶段 1:只切换背景主题,保持本地表盘素材不变
- 阶段 2:背景、表盘素材、时钟区域一起切换
这样可以先验证交互链路和配置模型,再扩展到完整主题包。
3.4 预览与导出解耦
主题预览只是 calendar 网站访问时的交互能力,不应反向改变现有导出主流程。
建议明确两条链路:
- 预览链路:用户访问网站,通过菜单切换
theme - 导出链路:脚本继续按当前默认行为生成
calendar/dist/kindlebg.png
只有在后续正式接入 Kindle 多主题切换时,再额外增加“按主题导出”的产物目录。
4. 方案总览
4.1 推荐架构
推荐采用“主题目录 + 当前主题状态文件”的方式。
远端发布结构:
https://shell.biboer.cn:20001/themes/paper/kindlebg.png
https://shell.biboer.cn:20001/themes/paper/dashboard-manifest.json
https://shell.biboer.cn:20001/themes/classic/kindlebg.png
https://shell.biboer.cn:20001/themes/classic/dashboard-manifest.json
Kindle 本地结构:
/mnt/us/dashboard/local/theme.env
/mnt/us/dashboard/local/themes/paper/
/mnt/us/dashboard/local/themes/classic/
其中:
theme.env只记录当前主题 ID- 每个主题目录可以逐步承载本地专属素材
4.2 当前主题状态
建议新增本地状态文件:
export THEME_ID=${THEME_ID:-paper}
优先级建议如下:
/mnt/us/dashboard/local/theme.env/mnt/us/dashboard/local/env.sh中的默认值- 代码里的兜底默认值
这样做的好处是:
- 切换主题不必改主配置文件
- 主题状态和设备级参数可以分开管理
- 后续可以由 KUAL 菜单脚本单独改写
theme.env
5. calendar/ 侧改造建议
5.1 新增 theme URL 参数
当前已有 mode 参数:
/?mode=full/?mode=background/?mode=clock-face
建议扩展为:
/?mode=full&theme=paper/?mode=background&theme=paper/?mode=background&theme=classic
约定:
mode决定页面用途theme决定视觉主题
5.2 网站访问时提供主题预览菜单
主题预览菜单只服务于网站访问场景,不直接参与背景导出。
建议行为:
- 用户访问
/?mode=full时,可以在页面菜单中切换主题 - 菜单切换只更新当前页面的
theme参数 - 可以把当前主题同步到 URL,便于分享和复现
- 可以选择是否额外写入
localStorage,用于下次访问时记住上次预览主题
菜单本身建议只出现在预览页面,不出现在背景导出页面里。
也就是说:
/?mode=full&theme=paper可以显示主题切换菜单/?mode=background&theme=paper只负责导出背景,不显示菜单
5.3 主题定义集中管理
建议在 calendar/src/ 下引入统一主题描述,例如:
type ThemeId = 'paper' | 'classic' | 'minimal';
type DashboardTheme = {
id: ThemeId;
label: string;
clockRegion: {
x: number;
y: number;
width: number;
height: number;
};
managedOnKindle: boolean;
};
主题配置至少要能描述:
- 主题 ID
- 主题显示名
- 时钟区域位置与尺寸
- 是否依赖 Kindle 本地表盘素材
5.4 保持现有导出流程兼容
当前导出主流程建议保持不变:
calendar/dist/kindlebg.png
calendar/dist/dashboard-manifest.json
calendar/dist/clock-region.json
默认规则:
- 如果导出脚本未显式传入
theme,就使用默认主题,例如paper - 继续保留现有
kindlebg.png单产物出口 - 现有部署和 Kindle 拉图流程无需立刻修改
这样可以保证:
- 先落地网站主题预览能力
- 不打断当前背景导出与发布链路
- 后续再增量接入主题化产物
5.5 多主题导出作为附加能力
当需要支持 Kindle 端切换主题时,再额外增加按主题导出的能力,例如:
calendar/dist/themes/paper/kindlebg.png
calendar/dist/themes/paper/dashboard-manifest.json
calendar/dist/themes/paper/clock-region.json
calendar/dist/themes/classic/kindlebg.png
calendar/dist/themes/classic/dashboard-manifest.json
calendar/dist/themes/classic/clock-region.json
这里的重点是“新增”,不是“替换”:
- 原有
calendar/dist/kindlebg.png继续保留 - 主题目录产物只用于多主题发布和 Kindle 切换
- 现有单主题导出脚本不需要被强制改成批量导出
建议后续新增独立命令,例如:
export:background继续生成默认背景export:themes额外生成多个主题目录
5.6 dashboard-manifest.json 增加主题字段
建议每个主题目录下的 manifest 包含:
{
"theme": {
"id": "paper",
"label": "Paper"
},
"background": {
"path": "kindlebg.png",
"url": "https://shell.biboer.cn:20001/themes/paper/kindlebg.png",
"refreshIntervalMinutes": 120
},
"clockRegion": {
"x": 262,
"y": 55,
"width": 220,
"height": 220
},
"clockFace": {
"path": "assets/clock-face.png",
"managedOnKindle": true
}
}
核心变化只有两点:
- 增加
theme.id - 背景 URL 改为带主题目录
6. Kindle 侧改造建议
6.1 拉取路径由主题拼装
不建议继续把 BACKGROUND_URL 写死为单一地址。
建议改成两段式配置:
export BACKGROUND_BASE_URL=${BACKGROUND_BASE_URL:-"https://shell.biboer.cn:20001/themes"}
export THEME_ID=${THEME_ID:-paper}
实际拉取地址在运行时拼成:
$BACKGROUND_BASE_URL/$THEME_ID/kindlebg.png
这样后续新增主题时,不需要再改 Kindle 端脚本逻辑。
6.2 增加切换脚本
建议新增脚本:
/mnt/us/dashboard/switch-theme.sh <theme-id>
行为建议:
- 校验主题 ID 是否在允许列表内
- 写入
/mnt/us/dashboard/local/theme.env - 删除或重置背景更新时间戳
- 可选:立即重启
dash.sh,或等待下一次刷新周期生效
其中第 3 步很重要,因为如果不清空背景更新时间,当前缓存可能会延迟两个小时才被新主题替换。
6.3 KUAL 菜单作为切换入口
推荐在 KUAL 菜单里增加主题项,例如:
Kindle Dashboard
Theme: Paper
Theme: Classic
Theme: Minimal
Dashboard Debug On
Dashboard Debug Off
这样用户在 Kindle 上就能直接切换当前主题,不依赖 SSH。
如果后续主题数量增加到 5 个以上,再考虑改成:
- 一个“循环切换下一个主题”的脚本
- 或由脚本生成菜单 JSON
6.4 完整主题包的本地目录
当主题不只是改背景,而是还改表盘样式时,建议 Kindle 本地按主题存放资源:
/mnt/us/dashboard/local/themes/paper/clock-region.env
/mnt/us/dashboard/local/themes/paper/assets/clock-face.png
/mnt/us/dashboard/local/themes/paper/assets/hour-hand/000.png
/mnt/us/dashboard/local/themes/paper/assets/minute-hand/00.png
/mnt/us/dashboard/local/themes/classic/clock-region.env
/mnt/us/dashboard/local/themes/classic/assets/clock-face.png
切换主题时同时切换:
- 背景拉取路径
- 本地时钟素材根目录
- 时钟区域参数
7. 两种落地级别
7.1 级别 A:只切背景
适用场景:
- 多个主题只改卡片风格、字体、配色、排版
- 所有主题共用同一套 Kindle 本地表盘素材
优点:
- 改动最小
- 风险最低
- 最快落地
限制:
- 不支持不同主题使用不同表盘位置或不同指针样式
7.2 级别 B:完整主题切换
适用场景:
- 不同主题拥有不同表盘造型
- 时钟区域位置和尺寸可能变化
- 指针、刻度、中心点等素材也需要按主题变化
优点:
- 主题能力完整
- 页面视觉更统一
成本:
- Kindle 本地资源管理会更复杂
- 切换时需要同步处理更多状态
8. 推荐实施顺序
建议分四步推进。
第一步:引入主题 ID,但只做单主题兼容
目标:
- 网站访问时支持
theme - 增加主题预览菜单
- 默认主题仍然只有
paper
结果:
- 用户可以在网站上切换预览主题
- 现有背景导出行为保持不变
第二步:产出双主题背景
目标:
- 增加可选的按主题导出能力
calendar/能同时生成两个主题目录- 发布层能稳定提供两组 URL
结果:
- 远端资源准备完成
- 现有默认导出链路仍可继续使用
第三步:Kindle 支持背景主题切换
目标:
- 增加
theme.env - 增加
switch-theme.sh - 增加 KUAL 菜单入口
结果:
- 用户可以在 Kindle 上切换背景主题
第四步:扩展到完整主题包
目标:
- 将时钟素材和时钟区域配置也按主题管理
结果:
- 主题系统从“背景切换”升级为“完整主题切换”
9. 风险与约束
9.1 主题切换后的缓存失效
如果只改了主题 ID,但没有重置背景更新时间戳,Kindle 可能继续显示旧主题缓存。
因此切换脚本必须显式清理以下状态之一:
/mnt/us/dashboard/local/state/background-updated-at- 或缓存背景文件本身
9.2 主题数量增长后的菜单维护
若主题数较多,手写 KUAL 菜单会越来越笨重。
到那时建议:
- 用一个脚本根据主题清单生成菜单
- 或保留“下一个主题”这种单按钮切换方式
9.3 远端发布必须保持目录稳定
一旦 Kindle 端按 /themes/<theme-id>/kindlebg.png 约定拉图,发布层就必须保持目录和文件名稳定,否则会出现主题切换后 404。
10. 推荐结论
推荐采用下面这条路线:
- 保持“
calendar/渲染,Kindle 只拉图和切换主题 ID”的职责边界 - 先实现网站访问时的主题预览菜单,并保持现有导出流程不变
- 再增量接入“背景主题切换”
- 等确认交互和运维链路稳定后,再升级到“完整主题包”
这个路线最符合当前仓库的实际状态:
- 复用现有
mode和导出链路 - 不会打断当前
kindlebg.png生成与发布流程 - 对 Kindle 主循环改动小
- 不会把主题复杂度压到 Kindle 设备上
- 后续也能自然扩展到本地表盘素材切换
11. 待确认问题
进入实现前,建议先明确这几个评审点:
- 网站预览菜单放在哪个区域最合适,是否只在
mode=full显示 - 第一阶段是否只做 2 个主题,例如
paper和classic - 第一阶段主题是否允许改变时钟区域位置
- KUAL 菜单是否接受“每个主题一个菜单项”的交互形式
- 远端发布目录是否可以稳定提供
/themes/<theme-id>/kindlebg.png
如果以上五点都确认,本方案可以直接拆成小步实现。