mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-04-26 01:10:16 +08:00
feat(update-center): add update list icons
This commit is contained in:
214
docs/superpowers/specs/2026-04-10-update-center-icons-design.md
Normal file
214
docs/superpowers/specs/2026-04-10-update-center-icons-design.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# 更新中心列表图标设计
|
||||
|
||||
## 背景
|
||||
|
||||
当前 Electron 更新中心已经可以展示更新项、来源、迁移标记、进度和日志,但更新列表仍然只有文字信息,没有应用图标。对于 APM 包、传统 deb 包和迁移项,纯文字列表会降低识别效率,尤其在批量更新和搜索场景下不够直观。
|
||||
|
||||
仓库现状里已经存在多套可复用的图标来源逻辑:
|
||||
|
||||
1. 主商店卡片通过远程商店 URL 拼接 `icon.png`。
|
||||
2. 已安装应用列表支持本地图标和远程 URL 双来源。
|
||||
3. 旧 Qt 更新器会为 APM 更新项解析 desktop 与 entries/icons,并在无本地图标时继续使用其他数据源。
|
||||
|
||||
目标是在更新中心列表中加入应用图标,同时保持最小改动、兼容当前后端结构,并遵循“本地解析优先,其次远程 URL,最后占位图标”的策略。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 在更新中心列表中为每个更新项展示应用图标。
|
||||
2. 图标来源优先级为:本地解析 > 远程 URL > 前端占位图标。
|
||||
3. 前后端仅增加一个最小公共字段,不引入复杂的图标对象结构。
|
||||
4. 图标缺失或加载失败时,界面仍然保持稳定、整齐、不闪烁。
|
||||
|
||||
## 非目标
|
||||
|
||||
1. 不为图标来源新增额外网络探测请求。
|
||||
2. 不在本次设计中重构应用详情页、已安装列表或主商店卡片的图标逻辑。
|
||||
3. 不在 UI 中展示“图标来源”说明文字。
|
||||
|
||||
## 方案概览
|
||||
|
||||
采用“主进程解析来源、渲染层只展示”的方案:
|
||||
|
||||
1. 更新中心主进程在加载更新项时解析图标来源,并将结果写入更新项的 `icon` 字段。
|
||||
2. 渲染层更新列表只消费 `item.icon`,不参与解析来源。
|
||||
3. 前端负责单次图片加载失败回退到占位图标。
|
||||
|
||||
## 数据结构变化
|
||||
|
||||
### 主进程
|
||||
|
||||
修改:`electron/main/backend/update-center/types.ts`
|
||||
|
||||
为 `UpdateCenterItem` 增加:
|
||||
|
||||
```ts
|
||||
icon?: string;
|
||||
```
|
||||
|
||||
### 渲染层
|
||||
|
||||
修改:`src/global/typedefinition.ts`
|
||||
|
||||
为 `UpdateCenterItem` 增加:
|
||||
|
||||
```ts
|
||||
icon?: string;
|
||||
```
|
||||
|
||||
### Service 映射
|
||||
|
||||
修改:`electron/main/backend/update-center/service.ts`
|
||||
|
||||
在主进程 snapshot -> renderer snapshot 的映射中透传 `icon` 字段。
|
||||
|
||||
## 图标来源策略
|
||||
|
||||
### 优先级
|
||||
|
||||
每个更新项统一按以下顺序取图标:
|
||||
|
||||
1. 本地图标路径
|
||||
2. 远程商店图标 URL
|
||||
3. 前端占位图标
|
||||
|
||||
### 1. 本地图标路径
|
||||
|
||||
#### 传统 deb / Spark 更新项
|
||||
|
||||
优先复用仓库中已有的 desktop 文件扫描与 `Icon=` 解析思路,来源参考:
|
||||
|
||||
- `electron/main/backend/install-manager.ts`
|
||||
|
||||
解析策略:
|
||||
|
||||
1. 从已安装包对应的 desktop 文件中读取 `Icon=`。
|
||||
2. 如果解析结果为绝对路径,直接返回。
|
||||
3. 如果解析结果为图标名,则尝试根据系统图标路径补全。
|
||||
4. 若无法得到有效路径,则继续下一层来源。
|
||||
|
||||
#### APM 更新项
|
||||
|
||||
优先复用旧 Qt 更新器已存在的 APM 图标解析逻辑,来源参考:
|
||||
|
||||
- `spark-update-tool/src/aptssupdater.cpp`
|
||||
|
||||
解析策略:
|
||||
|
||||
1. 查找 APM 包的 `entries/applications/*.desktop`。
|
||||
2. 从 desktop 的 `Icon=` 字段中解析图标。
|
||||
3. 若 `Icon=` 为绝对路径,直接返回。
|
||||
4. 若 `Icon=` 为图标名,则尝试拼接 APM 包内 `entries/icons/...` 路径。
|
||||
5. 若仍无结果,则继续下一层来源。
|
||||
|
||||
### 2. 远程商店图标 URL
|
||||
|
||||
如果本地图标解析失败,则为更新项生成远程图标 URL。
|
||||
|
||||
实现原则:
|
||||
|
||||
1. 不主动探测 URL 是否可用。
|
||||
2. 仅按现有商店规则拼接 URL,并交给浏览器加载。
|
||||
3. 浏览器加载失败后由前端回退占位图标。
|
||||
|
||||
对 Spark/传统 deb:
|
||||
|
||||
1. 使用当前商店已有的远程图标拼接规则。
|
||||
2. 若更新项可以推断出对应 category 和 arch,则拼接:
|
||||
`${APM_STORE_BASE_URL}/${arch}/${category}/${pkgname}/icon.png`
|
||||
|
||||
对 APM:
|
||||
|
||||
1. 若仓库中已有 APM 对应商店资源约定,则使用同样的 `icon.png` 规则。
|
||||
2. 若当前数据无法可靠推断 category,则允许直接跳过远程 URL,进入前端占位图标。
|
||||
|
||||
### 3. 占位图标
|
||||
|
||||
如果主进程未能提供 `icon`,或者前端加载失败,则使用统一占位图标。
|
||||
|
||||
占位规则:
|
||||
|
||||
1. 图标尺寸与正常图标一致。
|
||||
2. 使用仓库现有品牌资源或统一默认应用图标。
|
||||
3. 不因失败状态改变列表布局高度或间距。
|
||||
|
||||
## 模块边界
|
||||
|
||||
新增:
|
||||
|
||||
- `electron/main/backend/update-center/icons.ts`
|
||||
|
||||
职责:
|
||||
|
||||
1. `resolveUpdateItemIcon()`
|
||||
2. `resolveApmIcon()`
|
||||
3. `resolveDesktopIcon()`
|
||||
4. `buildRemoteFallbackIconUrl()`
|
||||
|
||||
该模块只负责“根据更新项得到一个 `icon?: string`”,不参与更新队列、安装、刷新、忽略等逻辑。
|
||||
|
||||
## 数据流
|
||||
|
||||
### 主进程加载更新项
|
||||
|
||||
1. 查询并合并更新项。
|
||||
2. 对每个更新项执行图标解析。
|
||||
3. 将解析到的 `icon` 字段写入 `UpdateCenterItem`。
|
||||
4. 由 `service.ts` 将该字段透传到渲染层 snapshot。
|
||||
|
||||
### 渲染层展示
|
||||
|
||||
1. `UpdateCenterItem.vue` 读取 `item.icon`。
|
||||
2. 如果 `item.icon` 为本地绝对路径,则转成 `file://` URL。
|
||||
3. 如果 `item.icon` 为远程 URL,则直接作为图片地址使用。
|
||||
4. 若图片加载失败,则切换为占位图标,并记住失败状态避免重复尝试。
|
||||
|
||||
## UI 设计
|
||||
|
||||
### 列表项布局
|
||||
|
||||
在更新列表中新增一个固定图标位:
|
||||
|
||||
1. 位置:复选框后、应用信息前。
|
||||
2. 尺寸:`40x40`。
|
||||
3. 样式:圆角矩形,视觉与商店应用卡片图标一致。
|
||||
4. 图标位固定占位,避免有图和无图的项出现布局跳动。
|
||||
|
||||
### 失败回退
|
||||
|
||||
前端仅做一次失败回退:
|
||||
|
||||
1. 优先渲染 `item.icon`。
|
||||
2. 触发 `@error` 后切换为占位图。
|
||||
3. 记录该项失败状态,避免反复向无效地址重新请求。
|
||||
|
||||
## 测试方案
|
||||
|
||||
### 主进程测试
|
||||
|
||||
新增或扩展测试覆盖:
|
||||
|
||||
1. 本地图标优先于远程 URL。
|
||||
2. APM 更新项可解析包内 desktop/icons。
|
||||
3. 传统 deb 更新项可解析 desktop `Icon=`。
|
||||
4. 无本地图标时能生成远程 URL 或返回空值。
|
||||
|
||||
### 组件测试
|
||||
|
||||
扩展 `UpdateCenterItem.vue` 组件测试:
|
||||
|
||||
1. 有 `item.icon` 时渲染图片。
|
||||
2. 图片加载失败时回退到占位图。
|
||||
3. 图标存在时不影响当前状态标签、迁移标签、进度条显示。
|
||||
|
||||
## 风险与约束
|
||||
|
||||
1. 更新项当前不一定总能推断出 category,因此远程 URL 兜底对部分项可能不可用;这是可接受的,因为前端还有占位图兜底。
|
||||
2. 本地图标解析涉及多个来源路径,必须限制在读取路径和拼接路径,不做额外昂贵的同步探测。
|
||||
3. APM 图标路径依赖当前系统安装结构,若个别包结构不标准,应直接退回远程或占位图,而不是阻断更新列表。
|
||||
|
||||
## 决策总结
|
||||
|
||||
1. 更新中心增加单字段 `icon?: string`,不引入复杂图标对象。
|
||||
2. 主进程解析图标来源,渲染层只负责展示和失败回退。
|
||||
3. 图标来源顺序固定为:本地解析 > 远程 URL > 占位图。
|
||||
4. UI 仅新增稳定图标位,不改变现有更新列表信息层级。
|
||||
Reference in New Issue
Block a user