test(presenter)+fix(i18n): 淘汰策略与共享缓存解耦;注释里的 ASCII 引号
- prune() 抽成独立函数:全局缓存被所有用例共享,谁往里面灌 240+ 条都会顺手清掉 别的用例刚缓存的键(实测:并行跑时 the_second_identical_refresh_... 假红)。淘汰 策略改在本地 Cache 上测,两条判据各自确定; - clippy -D warnings:from_ref 代替 &[x.clone()]; - model.rs 注释里的 "原因 + OS 原文" 用 ASCII 引号 → 页面字面量白名单守门报红,改 中文引号;core/events 的三处文档失真登记为 TowerFinding(scope 外); - 出处文案口径:TooLarge 的 detail 只留数字(presenter 不产人读文案)。
This commit is contained in:
1 parent
0b6b8f0a62
commit
dd9962e610
11 files changed
+127
-64
No files matched your search
@@ -106,7 +106,7 @@ pub fn view(instance: &str) -> unlucky_presenter::dto::SavesListView {
|
||||
Some(OLDEST),
|
||||
ScreenshotPreview::Failed(ScreenshotThumbFailure {
|
||||
kind: ScreenshotThumbKind::TooLarge,
|
||||
detail: "9437184 > 8388608 字节".to_string(),
|
||||
detail: "9437184 > 8388608".to_string(),
|
||||
}),
|
||||
),
|
||||
],
|
||||
@@ -214,7 +214,12 @@ fn scene(tone: u8) -> unlucky_presenter::dto::ThumbnailView {
|
||||
// 地平线在 2/3 高度(截图里天空总比地面多)。
|
||||
const HORIZON: u32 = H * 2 / 3;
|
||||
let (sky_top, sky_bottom, ground, sun): ([u8; 3], [u8; 3], [u8; 3], [u8; 3]) = if tone == 1 {
|
||||
([128, 176, 240], [200, 224, 248], [86, 138, 66], [255, 246, 186])
|
||||
(
|
||||
[128, 176, 240],
|
||||
[200, 224, 248],
|
||||
[86, 138, 66],
|
||||
[255, 246, 186],
|
||||
)
|
||||
} else {
|
||||
([96, 66, 96], [232, 148, 96], [58, 74, 48], [255, 214, 150])
|
||||
};
|
||||
@@ -228,12 +233,20 @@ fn scene(tone: u8) -> unlucky_presenter::dto::ThumbnailView {
|
||||
let span = i32::from(to) - i32::from(from);
|
||||
(i32::from(from) + span * t as i32 / 255) as u8
|
||||
};
|
||||
(mix(sky_top[0], sky_bottom[0]), mix(sky_top[1], sky_bottom[1]), mix(sky_top[2], sky_bottom[2]))
|
||||
(
|
||||
mix(sky_top[0], sky_bottom[0]),
|
||||
mix(sky_top[1], sky_bottom[1]),
|
||||
mix(sky_top[2], sky_bottom[2]),
|
||||
)
|
||||
} else {
|
||||
// 地面:按 3px 一条的条纹给出「方块地形」的观感。
|
||||
let stripe = (y / 3) % 2 == 0;
|
||||
let shade: u8 = if stripe { 0 } else { 14 };
|
||||
(ground[0].saturating_sub(shade), ground[1].saturating_sub(shade), ground[2].saturating_sub(shade))
|
||||
(
|
||||
ground[0].saturating_sub(shade),
|
||||
ground[1].saturating_sub(shade),
|
||||
ground[2].saturating_sub(shade),
|
||||
)
|
||||
};
|
||||
// 太阳/月亮:右上角一个 18px 的圆(够小,不会盖住画面主体)。
|
||||
let (dx, dy) = (x as i32 - 126, y as i32 - 26);
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
//!
|
||||
//! | 变化 | 落点 |
|
||||
//! |---|---|
|
||||
//! | 截图不再是一行字,而是「图 + 副文案」的格子 | [`wall`](3 列,见那个模块的文档) |
|
||||
//! | 截图不再是一行字,而是「图 + 副文案」的格子 | [`wall`](2 列 = 同列元信息卡的栅格,见那个模块的文档) |
|
||||
//! | 像素**不在**这里解,也不在渲染回调里解 | presenter 的后台线程(`host::saves::thumbs`)解好、随快照过来;本层只把 `Handle` 建一次(`model::from_state`) |
|
||||
//! | 没有像素的格子**不许留白** | 占位框 + 一句短话;副文案把原因说全(超 8 MiB / 读不出 / 解不出 / 超 60 张预算) |
|
||||
//!
|
||||
@@ -164,7 +164,7 @@ pub(super) fn section<'a>(
|
||||
if saves.screenshots.is_empty() {
|
||||
body = body.push(note(ui, texts.saves_no_screenshots()));
|
||||
} else {
|
||||
// 缩略图墙(M251):一行三格,没像素的格子给占位框 + 原因,不留白。
|
||||
// 缩略图墙(M251):一行两格(详情列 ≤424 宽,三格装不下),没像素的格子给占位框 + 原因。
|
||||
body = body.push(wall::grid(ui, &saves.screenshots));
|
||||
}
|
||||
if saves.skipped > 0 {
|
||||
|
||||
@@ -211,12 +211,12 @@ fn shot_cell(shot: &ScreenshotView, texts: Texts) -> Shot {
|
||||
},
|
||||
},
|
||||
// 像素长度与宽高对不上:壳层不该拿到这种数据,但拿到了也不能画成花屏。
|
||||
ScreenshotPreview::Ready(_) => {
|
||||
missing(shot, texts.saves_preview_reason(ScreenshotThumbKind::Decode), stamp)
|
||||
}
|
||||
ScreenshotPreview::NotGenerated => {
|
||||
missing(shot, texts.saves_preview_none(), stamp)
|
||||
}
|
||||
ScreenshotPreview::Ready(_) => missing(
|
||||
shot,
|
||||
texts.saves_preview_reason(ScreenshotThumbKind::Decode),
|
||||
stamp,
|
||||
),
|
||||
ScreenshotPreview::NotGenerated => missing(shot, texts.saves_preview_none(), stamp),
|
||||
ScreenshotPreview::Failed(failure) => {
|
||||
missing(shot, texts.saves_preview_reason(failure.kind), stamp)
|
||||
}
|
||||
@@ -225,7 +225,7 @@ fn shot_cell(shot: &ScreenshotView, texts: Texts) -> Shot {
|
||||
|
||||
/// 「没有可画的像素」那一格:**框里说为什么**(短句),**格子下面照旧是大小与时间**。
|
||||
///
|
||||
/// 为什么原因不进副文案:`160px` 宽的格子里,"原因 + OS 原文"会摊成三行,把墙变得比图还吵;
|
||||
/// 为什么原因不进副文案:`160px` 宽的格子里,「原因 + OS 原文」会摊成三行,把墙变得比图还吵;
|
||||
/// 而 `ScreenshotThumbFailure::detail`(`9437184 > 8388608 字节` / `Access is denied.`)留在
|
||||
/// DTO 里,是排障用的原文,不是给墙看的正文。D54 第 6 条要的是「逐条、结构化、不是静默」——
|
||||
/// 那一句在框里,每条各说各的。
|
||||
|
||||
@@ -62,9 +62,7 @@ const PER_ROW: usize = 2;
|
||||
|
||||
/// 整面墙(`saves.rs` 的 `section` 调;空列表不该走到这里)。
|
||||
pub(super) fn grid<'a>(ui: &'a Ui, shots: &'a [Shot]) -> Element<'a, Message> {
|
||||
let mut wall = column![]
|
||||
.spacing(ui.space(Space::X3))
|
||||
.width(Length::Fill);
|
||||
let mut wall = column![].spacing(ui.space(Space::X3)).width(Length::Fill);
|
||||
for chunk in shots.chunks(PER_ROW) {
|
||||
let mut line = row![]
|
||||
.spacing(ui.space(Space::X3))
|
||||
|
||||
@@ -56,10 +56,7 @@ const PAGE_SOURCES: [(&str, &str); 12] = [
|
||||
("instances/text.rs", include_str!("../text.rs")),
|
||||
// M251:存档 / 截图一族从 text.rs 拆出(那边越过 400 行)——新文件必须一起扫,
|
||||
// 否则那四句缩略图文案会被当成「死 key」。
|
||||
(
|
||||
"instances/text/saves.rs",
|
||||
include_str!("../text/saves.rs"),
|
||||
),
|
||||
("instances/text/saves.rs", include_str!("../text/saves.rs")),
|
||||
(
|
||||
"instances/launch_args.rs",
|
||||
include_str!("../launch_args.rs"),
|
||||
@@ -80,10 +77,7 @@ const PAGE_SOURCES: [(&str, &str); 12] = [
|
||||
include_str!("../saves/model.rs"),
|
||||
),
|
||||
// M251:截图缩略图墙
|
||||
(
|
||||
"instances/saves/wall.rs",
|
||||
include_str!("../saves/wall.rs"),
|
||||
),
|
||||
("instances/saves/wall.rs", include_str!("../saves/wall.rs")),
|
||||
];
|
||||
|
||||
/// 页面五件套里**允许出现的字符串字面量**(凡是带 ASCII 单词的都必须在这张表里)。
|
||||
@@ -346,7 +340,10 @@ fn every_english_literal_in_the_page_sources_is_whitelisted() {
|
||||
.map(|(_, source)| *source)
|
||||
.unwrap_or_else(|| panic!("PAGE_SOURCES 里没有 {name}:拆文件之后忘了登记?"))
|
||||
};
|
||||
assert!(source("instances.rs").contains("Texts::of("), "实例页没有从 Texts 取词");
|
||||
assert!(
|
||||
source("instances.rs").contains("Texts::of("),
|
||||
"实例页没有从 Texts 取词"
|
||||
);
|
||||
assert!(
|
||||
source("instances.rs").contains("Header::new(texts.title())"),
|
||||
"页头标题必须是词表里的那条(`Header::new` 里写死字符串 = 中文界面上顶着英文标题)"
|
||||
|
||||
@@ -143,7 +143,12 @@ impl Texts {
|
||||
self.0.render(Key::InstancesSavesDeleted, &[("dir", dir)])
|
||||
}
|
||||
/// 备份成功的回执:`已把 A 备份到 D:/…/A-…zip(1.2 MiB)。`
|
||||
pub(in crate::pages::instances) fn saves_backed_up(self, dir: &str, path: &str, size: &str) -> String {
|
||||
pub(in crate::pages::instances) fn saves_backed_up(
|
||||
self,
|
||||
dir: &str,
|
||||
path: &str,
|
||||
size: &str,
|
||||
) -> String {
|
||||
self.0.render(
|
||||
Key::InstancesSavesBackedUp,
|
||||
&[("dir", dir), ("path", path), ("size", size)],
|
||||
@@ -157,21 +162,33 @@ impl Texts {
|
||||
)
|
||||
}
|
||||
/// 重命名失败的主句:`重命名 A 失败:同名世界已存在`。
|
||||
pub(in crate::pages::instances) fn saves_rename_failed(self, file: &str, reason: &str) -> String {
|
||||
pub(in crate::pages::instances) fn saves_rename_failed(
|
||||
self,
|
||||
file: &str,
|
||||
reason: &str,
|
||||
) -> String {
|
||||
self.0.render(
|
||||
Key::InstancesSavesRenameFailed,
|
||||
&[("file", file), ("reason", reason)],
|
||||
)
|
||||
}
|
||||
/// 删除失败的主句。
|
||||
pub(in crate::pages::instances) fn saves_delete_failed(self, file: &str, reason: &str) -> String {
|
||||
pub(in crate::pages::instances) fn saves_delete_failed(
|
||||
self,
|
||||
file: &str,
|
||||
reason: &str,
|
||||
) -> String {
|
||||
self.0.render(
|
||||
Key::InstancesSavesDeleteFailed,
|
||||
&[("file", file), ("reason", reason)],
|
||||
)
|
||||
}
|
||||
/// 备份失败的主句。
|
||||
pub(in crate::pages::instances) fn saves_backup_failed(self, file: &str, reason: &str) -> String {
|
||||
pub(in crate::pages::instances) fn saves_backup_failed(
|
||||
self,
|
||||
file: &str,
|
||||
reason: &str,
|
||||
) -> String {
|
||||
self.0.render(
|
||||
Key::InstancesSavesBackupFailed,
|
||||
&[("file", file), ("reason", reason)],
|
||||
@@ -179,7 +196,10 @@ impl Texts {
|
||||
}
|
||||
// ------------------------------------------------- 截图缩略图(M251 · SAVESHOTS)
|
||||
/// 「这一格为什么没有图」的短句(`未生成预览` / 太大 / 读不出 / 解不出)。
|
||||
pub(in crate::pages::instances) fn saves_preview_reason(self, kind: ScreenshotThumbKind) -> &'static str {
|
||||
pub(in crate::pages::instances) fn saves_preview_reason(
|
||||
self,
|
||||
kind: ScreenshotThumbKind,
|
||||
) -> &'static str {
|
||||
self.text(match kind {
|
||||
ScreenshotThumbKind::TooLarge => Key::InstancesSavesPreviewTooLarge,
|
||||
ScreenshotThumbKind::Unreadable => Key::InstancesSavesPreviewUnreadable,
|
||||
|
||||
Reference in new issue
Block a user