feat(app-iced): Ink Cat / Silver Cat 换肤 —— 双色板默认 + 规格卡组件几何(M229)
产品出厂外观从 tone 派生的 `Scheme::baseline` 切到品牌色板:深色 = Ink(淡绿)、 浅色 = Silver(钢蓝),D38 取色链(背景图 / 壁纸)仍然优先,取色失败回落到色板。 主题三档接进设置页「通用 → 主题」:Ink / Silver / 跟随系统(落盘仍是 `appearance.theme_mode` 的 dark / light / auto,不新增配置键)。 组件几何按规格卡对齐(M228 的 `inkcat` 登记项逐条落地): - 卡片圆角 12 → 16;实例元信息卡改用新的 ELEVATED CARD(无描边、SurfaceContainer 底、内距 24、上标注 11/600) - Snackbar 48/4 → 52/16(双行 72) - Checkbox 20/rx2 → 18/rx4;Radio 20 → 18 Ø(内点仍 10) - 按钮加 XS~XL 五档(产品仍只用 S=40),内距改走 ControlSize::pad_x - 新增 FAB 四态(40/56/80/160×56)与图标按钮第四式 outlined - 语言与主题两行 chips 统一成规格卡 chip(32 高 / rx8) `theme.rs` 原本正好 400 行,先把单测纯搬移到 `theme/tests.rs` 再加色板字段; `app/tests.rs`、`settings/general.rs` 同样按纯搬移拆分守 400 行硬线。 验证:cargo fmt --all --check、cargo check -p unlucky-app-iced --all-targets、 cargo test --workspace(除 clippy 前的一轮 flake,见报告)、cargo clippy --workspace --all-targets -- -D warnings、全仓 400 行扫描。视觉矩阵 42 张在 DevDocs/artifacts/m229/(gitignored,不进提交)。
This commit is contained in:
1 parent
a06b7ff4ec
commit
db541c820e
44 files changed
+1439
-300
No files matched your search
@@ -0,0 +1,85 @@
|
||||
//! 主题三档(Ink / Silver / 跟随系统)的落点测试(M229;从 `app/tests.rs` 拆出守 400 行)。
|
||||
//!
|
||||
//! 这一份只管**用户点设置页那三枚 chip 之后**发生的事:换色板、同步设置组状态、落盘。
|
||||
//! `Auto`(跟随系统)那条路在 `app::tests::the_system_theme_never_overrides_an_explicit_one`。
|
||||
|
||||
use crate::app::message::Message;
|
||||
use crate::app::state::App;
|
||||
use crate::cli::Options;
|
||||
use crate::pages;
|
||||
use crate::theme::Families;
|
||||
use unlucky_design::color::SchemeFlavor;
|
||||
use unlucky_presenter::mock::MockBackend;
|
||||
use unlucky_presenter::prefs::ThemeMode;
|
||||
use unlucky_presenter::settings_bridge::SettingsBridge;
|
||||
|
||||
const FAMILIES: Families = Families {
|
||||
text: "Segoe UI",
|
||||
display: "Segoe UI",
|
||||
mono: "Consolas",
|
||||
};
|
||||
|
||||
/// 一个把配置写在临时文件里的 App:测「落盘」必须真的过文件(内存桥读回来永远是出厂值)。
|
||||
fn with_config() -> (App, std::path::PathBuf) {
|
||||
let dir = std::env::temp_dir().join(format!("ull-theme-m229-{}", std::process::id()));
|
||||
std::fs::create_dir_all(dir.join("config")).expect("临时目录");
|
||||
let path = dir.join("config/launcher.json");
|
||||
std::fs::write(&path, "{}").expect("写配置文件");
|
||||
|
||||
let app = App::with_presenter(
|
||||
Options::default(),
|
||||
FAMILIES,
|
||||
SchemeFlavor::Light,
|
||||
Box::new(MockBackend::new()),
|
||||
SettingsBridge::with_path(&path),
|
||||
);
|
||||
(app, dir)
|
||||
}
|
||||
|
||||
/// M229:设置页「通用 → 主题」三档(Ink / Silver / 跟随系统)真的换色板、真的落盘。
|
||||
///
|
||||
/// 抓得住:①`pages::Message::Theme` 没接进 `on_page`(点了没反应)②接了但不换 `Ui`
|
||||
/// (只有选中态变了,界面颜色还是旧的)③同步设置组状态漏了(设置页首帧/刷新后画错档)
|
||||
/// ④落盘漏了(重启回旧值——这里读的是内存桥的 `theme_mode`)。
|
||||
/// 抓不住:色板好不好看、像素级差异(那要截图,见 `DevDocs/artifacts/m229/`)。
|
||||
#[test]
|
||||
fn the_theme_message_switches_the_board_and_persists_it() {
|
||||
let (mut app, dir) = with_config();
|
||||
assert_eq!(app.board_name(), "silver", "首帧是浅色主方案(Silver)");
|
||||
|
||||
// 选 Ink(= 深色主方案)
|
||||
let _ = app.update(Message::Page(pages::Message::Theme(ThemeMode::Dark)));
|
||||
assert_eq!(app.theme_mode(), ThemeMode::Dark);
|
||||
assert_eq!(app.board_name(), "ink", "Ink 深板要真切过去");
|
||||
assert_eq!(app.ui().flavor(), SchemeFlavor::Dark);
|
||||
assert_eq!(
|
||||
app.settings.language_appearance.theme,
|
||||
ThemeMode::Dark,
|
||||
"设置页那一行的档位要跟着改"
|
||||
);
|
||||
// 落盘:真的过了文件(重新打开同一个配置读回来就是 dark)
|
||||
assert_eq!(
|
||||
SettingsBridge::with_path(dir.join("config/launcher.json"))
|
||||
.load()
|
||||
.1,
|
||||
ThemeMode::Dark,
|
||||
"主题档要落盘"
|
||||
);
|
||||
|
||||
// 选 Silver(= 浅色主方案)
|
||||
let _ = app.update(Message::Page(pages::Message::Theme(ThemeMode::Light)));
|
||||
assert_eq!(app.board_name(), "silver");
|
||||
assert_eq!(app.ui().flavor(), SchemeFlavor::Light);
|
||||
assert_eq!(
|
||||
SettingsBridge::with_path(dir.join("config/launcher.json"))
|
||||
.load()
|
||||
.1,
|
||||
ThemeMode::Light
|
||||
);
|
||||
|
||||
// 同一档再点一次:不许白重建
|
||||
let refreshes = app.refreshes;
|
||||
let _ = app.update(Message::Page(pages::Message::Theme(ThemeMode::Light)));
|
||||
assert_eq!(app.refreshes, refreshes, "同一档不该再重建视图模型");
|
||||
std::fs::remove_dir_all(&dir).ok();
|
||||
}
|
||||
Reference in new issue
Block a user