Feat/snapshot resources - #1104
Conversation
… rebinding - Collect currently referenced avatar/background/bubble/font resources for all character cards, character groups and the global user avatar. - Copy only referenced files into payload/resources/ (owner dirs + readable names), record originalUri/snapshotPath mapping in manifest.resources. - Skip re-copying referenced source files in raw files/external_files scan. - On restore, rebind each snapshot resource back to its original app-private path. - Keep includeTerminalData/databases/shared_prefs/datastore behaviour unchanged.
Theme media (user/ai/group avatars, background, bubble images and custom fonts) are persisted as flat files in filesDir root with known prefixes. Only files currently referenced by a character card/group or the global user avatar are kept (they live once under payload/resources); any other file matching those prefixes is now excluded from the raw files copy so historical media no longer bloats the snapshot. Logs and non-theme data are intentionally left untouched.
The built-in default_character persona is not returned by getAllCharacterCards(), so its background / user avatar / ai avatar (stored under character_card_theme_default_character_* keys) were never collected. They were therefore treated as unreferenced history and pruned, leaving the exported snapshot without the current main-chat resources. Collect the default scope explicitly so those files are kept under payload/resources and restored.
CATMIAOZHI
left a comment
There was a problem hiding this comment.
BLOCK:3 项 P2,触发条件、后果和建议见行内评论。
审计提交:fb264c39d6c4cb96791d30820c20e18b2d3071b4,目标分支 dev。已先请求 CATMIAOZHI review,再完成独立工作树全 diff、运行调用链和独立 agent 复核;git diff --check 通过。
验证范围:上游仓库该 HEAD 的 check-runs 为 0,审计前无 review 线程或普通评论。已核对工作流内容:PR workflow 仅匹配 development,本 PR 目标为 dev;构建/单测 push workflow 匹配 main。已核对 Actions Variables(GITEE_OWNER、GITEE_REPO)。PR 引用的 Android Build 确实成功,但提交是 2b71f5f,与本次 HEAD 不同;未获得当前 HEAD 的构建或单测成功证据。遵守目标仓库 AGENTS.md,本次未执行本地编译、测试、Lint 或真机验证,未修改源码。
备份与恢复仅做静态调用链核查,未执行任何真实数据导出、覆盖、恢复或清理操作。
| snapshot: ThemePreferenceSnapshot, | ||
| owner: RawSnapshotResourceOwner, | ||
| ) { | ||
| if (snapshot.useBackgroundImage) { |
There was a problem hiding this comment.
[P2] 保留已保存但暂时关闭的主题媒体引用
选择背景或字体后关闭显示开关,设置页只改布尔值,仍保存对应 URI,用户随后可以直接重新启用。但这里因开关关闭不收集文件,RawSnapshotBackupManager 又将剩余匹配前缀的媒体从原始 files 备份中排除。恢复快照时 replaceDirContents 会移除原文件,重新启用背景/字体便找不到资源。请按保存的 URI 收集引用;显示开关关闭不等于资源已不再被配置引用。气泡图片和字体的同类判断也需一致处理。
| RawSnapshotResourceKind.AI_AVATAR, | ||
| userPreferences.getAiAvatarForCharacterGroupFlow(group.id).first(), | ||
| ) | ||
| addThemeReferences( |
There was a problem hiding this comment.
[P2] 群组也需要收集自定义用户头像
群组主题使用同一编辑器,可以保存 custom_user_avatar_uri,聊天气泡也实际优先显示该头像。这里群组只收 AI 头像和 addThemeReferences,后者没有用户头像;customUserAvatarUri 仅在角色卡路径收集。群组独有的 user_avatar_* 文件因此会被后续未引用媒体筛选排除,备份恢复后丢失。请从群组的 ThemePreferenceSnapshot 同样收集 customUserAvatarUri。
| val sharedPrefsDir = File(dataDir, "shared_prefs") | ||
| val datastoreDir = File(dataDir, "datastore") | ||
| val databasesDir = File(dataDir, "databases") | ||
| val resourceReferences = DefaultRawSnapshotResourceReferenceProvider(context).collectReferences() |
There was a problem hiding this comment.
[P2] 保留不依赖偏好解析的原始救援导出能力
数据救援页也调用此导出函数。现在必须先完成 collectReferences,其中直接 first() 读取 display DataStore、角色卡和主题配置;当 display_preferences 损坏或配置 schema 高于当前版本时,这些读取会抛异常并直接终止导出,救援页只得到失败而没有原始快照。旧路径仅复制原始文件,还明确容忍数据库 checkpoint 失败,能保全无法解析的数据。请让救援原始导出独立于成功解析偏好,避免资源整理阻断故障数据归档。
变更说明 / Description
本 PR 改进原始快照备份中的主题媒体资源管理,包括当前引用资源收集、资源目录整理、历史媒体排除,以及日志导出控制。
背景与动机 / Context and motivation
原始快照会把
files目录中的历史头像、背景图和字体一并打包,导致快照体积较大(本人实际体验中,391MB大小的快照文件中有131MB是字体和图片资源,大约33.5%的空间占用全都是无效资源)。同时,当前仍在使用的主题媒体资源与普通应用文件混在一起,难以人工检查和迁移。本次改动将当前引用的主题媒体资源单独保存到快照中的可读目录,并排除明确属于历史遗留且未被当前配置引用的主题媒体文件。
改动范围 / Changes
default_character的主题资源。payload/resources/character_cards/<角色名_角色ID>/payload/resources/character_groups/<群组名_群组ID>/payload/resources/global/files目录时,跳过已经单独写入payload/resources/的当前引用媒体,避免重复打包。files根目录下明确匹配主题媒体命名规则、且未被当前配置引用的历史图片和字体文件。files/logs/external_files/anr_reports/兼容性与风险 / Compatibility and risks
file:URI。content://等外部授权 URI 不属于本次资源文件路径恢复范围。关联 Issue / Related issue
暂无。
验证方式 / Verification