feat(core,presenter,app-iced): 存档三个写操作(重命名 / 删除 / 备份)+ 行操作区(M247 SAVESOPS)
core::game::saves 新增 write 模块,三个入口的第一句都是 boundary::guard: - rename_world:saves/<old> → saves/<new>,撞名/同名/非法名字各自具名拒绝 - delete_world:递归删(不跟随符号链接、层级上限 64),先过边界校验 - backup_world:流式 zip(限额预检 → 临时文件 → 原子改名), <世界名>-YYYYMMDD-HHMMSS.zip,撞名顺延,绝不覆盖上一份 guard 三道判据(每次写前重做,不信任调用方):名字必须是单段裸名字; saves/ 必须是运行目录的真实直属子目录;世界目录必须是 saves/ 下的真目录 (解析后比父级,不比字符串前缀)。落点目录要求绝对路径(相对路径会落到进程 CWD, 实测过一次)。 presenter:SavesCommand 增 RenameWorld/DeleteWorld/BackupWorld,host 三个后台入口 写成功后重新列一遍目录并把「回执」挂在快照上(SavesOped:改名两端 / 被删的名字 / 备份落点+字节数+跳过的链接数)。SavesFailureView 增 file 与 op,写失败八类一一对应。 SavesState 增 draft / pending / confirm 三样交互态(草稿是行内输入缓冲, pending 与 ModsState::pending 同一条先例,confirm 是删除确认框在等谁)。 app-iced:世界行右侧重命名/备份/删除;行内输入框改名(现成模态队列没有「输入变了」 这一条消息,用输入模态等于重写一套);删除走现成 modal 的 Confirm,主按钮落点接在 app/update/dialog.rs。回执行画在卡片里(备份落点看不见就是静默失败)。 i18n:新增 25 条中英成对 key + 金表同步;删掉 M235 的「这一版只读」那条(写操作接上 之后它是假的)。出图夹具 ULL_SAVES_FIXTURE=rename|confirm|backed-up 三种形态。
This commit is contained in:
1 parent
3e852331f4
commit
c921b9c185
28 files changed
+3016
-216
No files matched your search
@@ -106,7 +106,6 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
|
||||
("InstancesModsReasonCollision", "a file with that name already exists", "同名文件已存在"),
|
||||
("InstancesModsReasonRename", "the rename failed", "改名失败"),
|
||||
("InstancesSavesTitle", "SAVES", "存档"),
|
||||
("InstancesSavesReadOnly", "Read-only in this version: nothing here is moved or deleted.", "这一版只读:这里不移动、也不删除任何东西。"),
|
||||
("InstancesSavesCount", "{worlds} worlds · {shots} screenshots", "{worlds} 个世界 · {shots} 张截图"),
|
||||
("InstancesSavesLoading", "Reading saves/…", "正在读取 saves/…"),
|
||||
("InstancesSavesEmpty", "No worlds or screenshots yet — play once and they show up here.", "还没有世界或截图——玩一次就会出现在这里。"),
|
||||
@@ -125,6 +124,31 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
|
||||
("InstancesSavesReasonDir", "the directory is not usable", "目录不可用"),
|
||||
("InstancesSavesReasonInstance", "the instance is gone", "实例已不存在"),
|
||||
("InstancesSavesReasonOpen", "the file manager did not start", "文件管理器没起来"),
|
||||
("InstancesSavesRename", "Rename", "重命名"),
|
||||
("InstancesSavesBackup", "Back up", "备份"),
|
||||
("InstancesSavesDelete", "Delete", "删除"),
|
||||
("InstancesSavesRenamePlaceholder", "New name for this world", "这个世界的新名字"),
|
||||
("InstancesSavesRenameConfirm", "Rename", "改名"),
|
||||
("InstancesSavesCancel", "Cancel", "取消"),
|
||||
("InstancesSavesBusy", "Working…", "正在处理…"),
|
||||
("InstancesSavesDeleteTitle", "Delete this world?", "删除这个世界?"),
|
||||
("InstancesSavesDeleteBody", "{dir} and everything inside it will be deleted. This cannot be undone.", "{dir} 和它里面的全部内容都会被删除,且不能撤销。"),
|
||||
("InstancesSavesDeleteConfirm", "Delete world", "删除世界"),
|
||||
("InstancesSavesRenamed", "Renamed {from} → {to}.", "已把 {from} 改名为 {to}。"),
|
||||
("InstancesSavesDeleted", "Deleted {dir}.", "已删除 {dir}。"),
|
||||
("InstancesSavesBackedUp", "Backed up {dir} to {path} ({size}).", "已把 {dir} 备份到 {path}({size})。"),
|
||||
("InstancesSavesBackupSkipped", "{count} symlinks skipped", "跳过 {count} 个符号链接"),
|
||||
("InstancesSavesRenameFailed", "Could not rename {file}: {reason}", "重命名 {file} 失败:{reason}"),
|
||||
("InstancesSavesDeleteFailed", "Could not delete {file}: {reason}", "删除 {file} 失败:{reason}"),
|
||||
("InstancesSavesBackupFailed", "Could not back up {file}: {reason}", "备份 {file} 失败:{reason}"),
|
||||
("InstancesSavesReasonUnsafeName", "the name is not usable", "名字不可用"),
|
||||
("InstancesSavesReasonSymlink", "that path is a symbolic link (not followed)", "那个路径是符号链接(不跟随)"),
|
||||
("InstancesSavesReasonMissing", "the world is gone", "那个世界已不在"),
|
||||
("InstancesSavesReasonNotDir", "that is not a directory", "那不是目录"),
|
||||
("InstancesSavesReasonConflict", "a world with that name already exists", "同名世界已存在"),
|
||||
("InstancesSavesReasonBoundary", "that path is outside saves/", "那个路径落在 saves/ 之外"),
|
||||
("InstancesSavesReasonTooLarge", "the world is too large for one zip", "这个世界太大,一个 zip 装不下"),
|
||||
("InstancesSavesReasonWrite", "the write failed", "写盘失败"),
|
||||
];
|
||||
|
||||
/// 金表的**全量**行(本文件 → [`tail`] → [`tail_ai`] → [`tail2`],顺序即 `Key::ALL`)。
|
||||
|
||||
Reference in new issue
Block a user