AskaEth
35345f3399
Merge branch 'feat/p4-iced-component-base-buttons-gallery-h'
2026-11-02 04:51:10 +08:00
AskaEth
4d7b198822
fix(app-iced): M75 r6 —— probe 删 19 行重复块 + 补第 8 行(icon·tonal) + 三处注释按 visual-r4 P2-2 更正
...
① 19 行重复块(第 4 次报):probe.rs 218-236 与 198-216 逐字重复(on_primary/left_ink 双层循环/
icon_pad/assert 各两遍,靠 shadowing 编过),已删;粘在一起的注释头随之消失。
滑动窗口脚本:改前 'DUP at 199 and 219' → 改后 'no 19-line duplicate'。
② 逐行护栏补到 8 行:(7, OnSurface, true, "icon·tonal");汇总打印 '8 行通过'。
变异(该行墨迹涂回满档色)→ probe 红。
③ 三处过期注释按 review 的 §P2-2 逐条改:
- probe 模块文档 药丸顶行宽 ≈9 → 左内缩 ≈14;
- 圆角推导改成像素中心闭式 inset(k)=r−√(r²−(r−k−0.5)²),r=20,k=1 给 12.40;
- gallery/mod.rs 列宽注释 132 → 160(cell_width 的实际值)。
2026-11-02 04:51:07 +08:00
AskaEth
4954ba3463
chore(app-iced): M75 r5 —— 删掉被 count_in 取代的 count_pixels(clippy dead_code)
2026-11-02 04:51:06 +08:00
AskaEth
b563c6ac44
docs(app-iced): M75 r5 —— 三处过期注释按 A1 更正(会被四条家族线当规格抄)
...
- buttons/mod.rs 表行 1.8:禁用内容角色「按变体」(Variant::disabled_content),容器 α 注明 A1 是 10%
- buttons/mod.rs 表行 2.7:IconButton 禁用内容 = OnSurface@38%(A1),落点改到 disabled_content_over_role
- interaction α 表 / disabled_colors 文档:容器 0.12 与 A1 的 0.10f 差异点名 D8;内容默认为 OnSurfaceVariant
- overlay_color 的 content 说明从 OnSurface 改成 OnSurfaceVariant(与 A1 一致)
2026-11-02 04:51:04 +08:00
AskaEth
eed1c9d3f7
fix(app-iced): M75 r5 —— 禁用内容角色按变体(A1)+ 删 probe 重复块 + 逐行护栏
...
1) A1 逐变体(AAR javap):Filled/Elevated/Outlined/Text = OnSurfaceVariant@0.38 ;
FilledTonal = OnSurface@0.38 (FilledTonalButtonTokens.DisabledLabelTextColor);
Standard/Filled IconButton = OnSurface@0.38 (*IconButtonTokens.DisabledColor)。
新增 Variant::disabled_content() / IconVariant::disabled_content(),
interaction::disabled_content_over_role(ui, role, on_container) 成唯一入口。
2) probe.rs 删掉被两个 reviewer 点名的重复块(disabled_colors 调用两次、
disabled_container 绑定两次),并补 grep 证据。
3) 护栏改成**逐行**:矩阵 7 个有内容的变体行各自断言 disabled 列的 38% 墨迹 > 40 px
(浅/深同一套阈值,单行回退就会红),取代原来按浅色标定的全局 500 阈值。
6) 删掉 interaction/mod.rs 里挂在 mod tests 头上的悬挂文档。
2026-11-02 04:51:03 +08:00
AskaEth
b31a758cda
test(app-iced): M75 r4b —— 无容器禁用墨迹的护栏收窄到 disabled 列 + 阈值 500(变异实测会红)
...
整图计数会把别处抗锯齿像素算进来(正常 800/1966 px,涂回满档色后仍剩 348 px),
护栏实际上拦不住 code-r2 说的「text/standard 那两行」。改为只在矩阵最右 1/3 列内计数,
阈值 500(浅 800 / 深 1966 正常,变异后 348)——变异实测:红。
2026-11-02 04:51:02 +08:00
AskaEth
a878fc6a58
refactor(app-iced): M75 r4 —— interaction 拆成 mod.rs(287) + tracker.rs(159),恢复被压掉的文档
...
interaction.rs 连压三笔才回到 400 行(靠删文档腾空间),而它会被四条家族线各扩一次。
- interaction/mod.rs:五态枚举 + overlay_color / disabled_colors / disabled_content_over(态→颜色)
- interaction/tracker.rs:事件→态的状态机 + 它的两条单测;Tracker 用法示例(ignore 代码块)恢复
- 对外路径不变:components::interaction::* 照旧(mod.rs 里再导出 Tracker)
- 两份文件都写了「加东西前先看行数余额」
顺带修两处门禁:注释里去掉 hex 色值(守门连注释一起扫)、再导出显式 allow。
2026-11-02 04:51:01 +08:00
AskaEth
ab5f5802a8
test(app-iced): M75 r3f —— 去掉一条与上一行重复的断言,interaction.rs 400 行
2026-11-02 04:50:59 +08:00
AskaEth
95a6f56060
docs(app-iced): M75 r3d —— interaction.rs 再收 2 行,确保 ≤400
2026-11-02 04:50:58 +08:00
AskaEth
a3b3c9eba7
docs(app-iced): M75 r3c —— interaction.rs 文档收口(Tracker 用法/α 表压行,回到 400 行内)
2026-11-02 04:50:57 +08:00
AskaEth
86f7a31d9a
fix(app-iced): M75 r3b —— IconButton 高度断言按抗锯齿实测改为 39..=40 + interaction.rs 收回到 400 行内
...
exact-color 的连通块高度会排除底部抗锯齿行,实测 40×39;宽度仍精确 40。
区间收到 39..=40 仍能抓住 ±2px 回归(42→41、38→37 都落区间外)。
2026-11-02 04:50:55 +08:00
AskaEth
5fd1f3ca26
fix(app-iced): M75 r3 —— 禁用内容角色按 A1 改 OnSurfaceVariant + 两项语汇 + probe 双色护栏
...
A1 定案(本机 gradle 缓存 material3.aar + javap):
FilledButtonTokens.<clinit>: DisabledContainerColor=OnSurface, DisabledContainerOpacity=0.1f
DisabledIconColor/DisabledLabelTextColor=OnSurfaceVariant, 两者 Opacity=0.38f
OutlinedButtonTokens/TextButtonTokens: LabelTextColor=OnSurfaceVariant(12b §1.9 原本就对)
据此:
- interaction::disabled_content_over / disabled_colors 的内容角色从 OnSurface 改成
OnSurfaceVariant(α 仍取令牌 DISABLED_CONTENT_ALPHA=0.38);设计层 color::state::disabled_content()
用的是 OnSurface,与 A1 不符 —— 令牌线修好前这里按 A1 直接求值,已登记。
- content_color 的「底」按有无容器分开:有容器叠 12% 容器、无容器叠 surface(视觉 r2 P2-1)。
- probe 加第二条护栏:无容器三式的 38% 墨迹单独计数,避免只护住有容器那四式(code r2 p2-1)。
- gallery 样例图标改描边(Download + ChevronRight),并加单测钉「同控件不混用 Fill/Stroke」(P2-3)。
- 滚动条:透明轨 + OutlineVariant thumb(P2-4;宽度 10px 是 iced 内部常量,只能改颜色)。
- probe 文档修好被 //! 打断的命令、shot_path 注释归位、去掉空转的重复断言(P2-5)。
2026-11-02 04:50:54 +08:00
AskaEth
d075feb77d
test(app-iced): M75 复审 P1-B —— 渲层断言收紧到 2px 级(变异实测会红)
...
- 高度断言改 assert_eq!(true_height, 40):变异成 42 实测变红(证据 target/m75/evidence.sh)
- 补「带图标左内边距 16」断言:墨迹 ≈21(16→21 / 24→29 / 8→13 三档互不重叠)
- 分隔线:行数 2..=4 + 单条墨量覆盖率 0.8..=1.3(1.5dp 会到 ~1.5),
只统计「连续非底色 > 900」的长横线行,避免把文字墨量算进去
- 两条判据都踩过误报:白色与浅色页面底色在容差内(padding 量出 3)、
圆角透出的底色被当成满档 OnPrimary;已改成「内带 + nearer 判定」并注明原因
2026-11-02 04:50:52 +08:00
AskaEth
e905fa3922
fix(app-iced): M75 复审 P1-A/P1-B/P2 —— 内容色跟态走 + 断言收紧 + 矩阵排版
...
P1-A 禁用内容色没下发(视觉 reviewer:text/standard 的 enabled 与 disabled 逐像素相同):
assemble 里内容色恒取 ui.color(content) 再被 text().color() 钉死,Style.text_color 的 38%
永远下发不出去。新增 assemble::content_color(ui, forced, content),文字按钮与 IconButton
共用;probe 补两条像素断言(禁用 38% 墨迹必须存在、禁用容器内不得有满档 OnPrimary)。
P1-B 渲染层断言抓不住 2px 级回归(reviewer 变异验证:高度 42 仍绿):
高度改成精确 == 40;补「带图标左内边距 16(墨迹 ≈21)」断言;分隔线从「行数」改成
「墨量覆盖率 ≈1.0」(1.5dp 会到 ≈1.5)。
P2-1 probe 给了图却读不到时硬失败(只有完全没给 ULL_GALLERY_SHOT 才跳过)。
P2-2 Geometry::stroke 真正接到 Border.width;IconGeometry::icon 改由 side−2×padding 推导。
P2-3 矩阵 cell 宽 192→160(总宽 1040<1180,disabled 列不再被裁);禁用格保留前后图标。
P2-4 补注:snap 仅 wgpu 实现,CPU 验收图不受它影响。
2026-11-02 04:50:51 +08:00
AskaEth
8072f1cc7e
test(app-iced): M75 —— probe 分隔线判据改为「非底色长横线」+ 修 forced 改成 Option 后的两处测试
...
线在 fractional y 上被抗锯齿摊到两行,按精确 OutlineVariant 色匹配抓不到(实测 0 行);
改为「非 Surface 的长横线」计数,断言 2..=6 行(两条线 × 各 1~2 行)。
2026-11-02 04:50:49 +08:00
AskaEth
5f85891e7e
fix(app-iced): M75 —— 截图取证必须能强制「静息」态(光标污染修掉)
...
StyleSpec.forced 从 Interaction 改成 Option<Interaction>:Some(Enabled) 与 None 语义不同——
前者强制画静息,后者才跟随 button::Status。修前光标恰好停在某个格子上时,gallery 的
enabled 列会被画成 hover(表现为 text 行出现不该有的灰底容器,看着像 Text 按钮自带容器)。
2026-11-02 04:50:47 +08:00
AskaEth
5861881073
refactor(app-iced): M75 —— probe 拆出 scan 工具 + clippy 全绿 + 三个字面/生命周期修正
...
- gallery/{probe,scan}.rs 拆分:像素扫描(连通块/外接框/顶行宽度)与判据分离,
后续四条家族线可以自带 probe 复用扫描逻辑
- probe 的实心块判据跳过字形割出的小碎片(area < 800),阈值写明原因
- app.rs / gallery::mod 的 clippy 修正(needless_lifetime / field_reassign_with_default / collapsible_if)
- cargo test -p unlucky-app-iced 与 cargo clippy --all-targets -D warnings 已绿(见报告)
2026-11-02 04:50:46 +08:00
AskaEth
4774e7b788
WIP(app-iced): M75 组件基座 checkpoint —— 组件骨架/按钮五式/分隔线/gallery harness
...
已落地:
- components/{mod,interaction,layout,divider,gate}.rs + buttons/{mod,geometry,assemble,tests}.rs
- gallery/{mod,buttons,probe,scan}.rs + 四个家族桩(selection/inputs/feedback/navigation)
- cli.rs: --screen=shell|gallery + capture_flavor(截图默认 Light,删掉等系统主题的闸门)
- app.rs: gallery 路由 + DemoMessage 接线(400 行)
待办(下一个 commit):编译/测试全绿、浅深矩阵出图、1:1 并排与数值表。
2026-11-02 04:50:44 +08:00
AskaEth
22ddc74784
Merge branch 'feat/p4-iced-page-frame-layout-system-breakpo'
2026-11-02 04:44:53 +08:00
AskaEth
831bd00620
docs(app-iced): SIM 常量口径精确化(字符最多行 402 / 全段最宽行 411)
...
视觉 r3 的不计入裁决的精度提醒:`SIM_SAFE_MAX_INK = 402` 其实是**字符最多**那一行的 ink,
全段**墨迹最宽**的行是 411px(渲染 410),所以「余量 22px」实际是 13px。
- 拆成两个常量并分别断言:`SIM_SAFE_MAX_CHARS_INK = 402`(67 字符那行)、
`SIM_SAFE_WIDEST_INK = 411`(墨迹最宽那行,新加断言 `cap >= 411`,并在失败信息里打印余量);
- 文档写明「两者不是同一行:402 那行字符多但字形窄」。
证据:`cargo test -p unlucky-app-iced --no-default-features`
→ `test result: ok. 86 passed; 0 failed` / `test result: ok. 6 passed; 0 failed`。
2026-11-02 04:10:05 +08:00
AskaEth
589f51f4fb
docs(app-iced): 订正测试注释(1180 上限是 424,不是 435)
...
r3 复审:`layout/tests.rs` 的注释说「现在必须是 435」,同一函数的断言却是 424。
证据:`grep -n 435 crates/app-iced/src/pages/layout/tests.rs`
- 第 229 行(旧):`// 1180 —— M68 就是在这条上翻的车(712px),现在必须是 435` → 改成 **424**;
- 剩下两处 435 都是**平均口径上界**的正确引用,不是残留:
第 176 行注释「不是『平均步进 × 72』的算术值 435」、
第 180 行 `assert_eq!(measure_average_bound_px(), 435.0)`。
2026-11-02 03:52:28 +08:00
AskaEth
87d5dd8f67
docs(app-iced): 订正 meta_grid 注释(1180 与 900 都是 2 列)
...
r3 复审:`meta_grid` 的文档还写着「1180 → 3 列,900 → 2 列」,但本轮起两者都是 2 列。
证据:`grep -n "3 列" crates/app-iced/src/pages/instances.rs`
- 旧:`/// 元信息网格:列数由 [...] 决定(1180 → 3 列,900 → 2 列)。`
- 新:写明「1180 与 900 都是 2 列;3 列需要 3×160 + 2×12 = 504px > 行宽上限 424,数学上不可行;
硬塞回 3 列会让 NeoForge 20.4.237(118px)折行、同排卡底不齐」。
- 现在文件里唯一出现「3 列」的地方就是这条「不可行」的说明(第 275/276 行)。
2026-11-02 03:52:24 +08:00
AskaEth
0de8e63ad6
fix(app-iced): 必修1 跟进 —— 旧断言 435→424 + clippy 常量断言
...
必修1 改完 cap 之后跑门禁抓到的两处自身的漏改:
1. `settings_pane_keeps_the_drawer_width_and_a_readable_form_column` 里还留着
`assert_eq!(measure_cap_px(), 435.0)`(P2-1 轮加的锚点),cap 收到 424 后它必红。
已改 424 —— 这正是「锚点断言」该有的行为:常量一改就红,而不是悄悄跟着漂。
2. clippy `assertions_on_constants`:`assert!(SIM_SAFE_MAX_CHARS <= MAX_MEASURE_CHARS)`
两边都是 const,改成 `const { assert!(..) }`。
门禁(本机私有 target,CPU 档):86 lib passed + 6 集成 passed;clippy -D warnings 干净。
2026-11-02 02:42:58 +08:00
AskaEth
c5c543ba43
docs(app-iced): 必修3 504→435 一轮留下的三处文档漂移
...
视觉 r2 逐条点出来的三处「偏离登记与对外口径没跟着改」:
1. `pages/mod.rs` 偏离 #1:详情列右缘写 976 / 分歧 180px —— 行宽收到 424 后实测是
页头右缘 **1156**、详情列右缘 **896**(472 + 424),分歧 **260px**;
2. `pages/mod.rs` 偏离 #3:单列页占比写 48%(435/1044)—— 现在是 **40.6%(424/1044)**;
3. `frame/pieces.rs` 的 `scroll_style` 函数头仍写「滑块 `Outline`、尺寸取 iced 默认」——
实现早已是 `OutlineVariant` + 6px 轨 + 2px 内缩,文档跟上。
三处都在 D30 要求「逐条写清」的偏离登记/口径里,属于对外承诺,不是内部注释。
2026-11-02 02:04:32 +08:00
AskaEth
ddf6937b2b
fix(app-iced): 必修1 「72 字符」改成逐行口径,上限 435 → 424
...
代码 r2 的复核:`435 / 6.0526 = 71.9` 是**整段平均步进**换来的数,不是每行都 ≤72;
它实测交付图里就有 **73 字符**行(`guess. Nothing on this page is wired to real data yet: the layout is, the`,
ink 428px)。上一轮是系数错,这一轮是**把平均当成了逐行上界**。
选 **(a)**:不变式改成逐行可验证,cap 跟着压到能满足它的地方。依据是 FreeType 量宽 + 贪心词折行的模拟表
(同一段 361 字符正文扫列宽):
| 列宽 | 最长一行 | 该行 ink | 判定 |
|---|---|---|---|
| 435(= 平均口径上界) | 73 字符 | 428px | ✗ |
| 428 | 73 字符 | 428px | ✗ |
| 426 | 71 字符 | 426px | ✓ 只剩 1 字符余量 |
| **424**(4px 栅格) | **67 字符** | **402px** | ✓ 取这个 |
- `measure_cap_px()` = `min(逐行安全宽 424, 平均口径上界 435)` = **424**;平均口径另立
`measure_average_bound_px()`(435)并在文档里标明「只是上界,不是取值」。
- 单测 `line_length_is_capped_at_72_characters` 改成**两侧夹逼**:`402 ≤ cap < 428` ——
放大到 428 会重新出现 73 字符行(红),压到 402 以下白丢宽度(也红);另断言
`cap < measure_average_bound_px()`,防止有人把平均口径当上限。
- §3 新增「逐行口径」小节:模拟表 + **作用域**(承诺只覆盖 14px 正文;12px 辅助文案是 1~2 行短句,
不做逐行承诺;CJK 全角 1em 另行定)。
- 四页文档与 `pages/mod.rs` 的 ≤435 同步改 424。
2026-11-02 02:04:23 +08:00
AskaEth
a650f8184b
fix(app-iced): 必修2 元信息卡最小宽改由内容推(136 → 160),1180 下网格 2 列
...
视觉 r2 抓到的回归:上一轮为塞进三列把 `META_CARD_MIN_WIDTH` 收到 136,只算外框、忘了
`card_padding = 20`,卡内只剩 96px —— demo 里 `NeoForge 20.4.237`(实测 118px)与
`NeoForge 21.1.72`(110px)都会按词折成两行,同排另两张卡仍一行 → **卡底不齐**。
- 最小宽改由**卡内最长内容**反推:118(Segoe UI 14px 实测)+ 2×20(令牌 `card_padding`)= 158
→ 取 4px 栅格 **160**(值上等于最初的 160,但这次是内容推出来的,不是凑上限凑出来的)。
- 于是元信息网格在 1180 宽落到 **2 列**(2×160 + 12 = 332;3 列要 504 > 行宽上限),
卡内可排 **166px** ≥ 118,所有值单行放下;6 格 = 3 行 2 列。
- 新增单测 `meta_card_is_wide_enough_for_the_longest_value`(此前 39 条 pages 测试没有一条覆盖它):
① 夹具 `NeoForge 20.4.237` 必须仍在 DEMO 里(数据变了就红,提醒重新量);
② `META_CARD_MIN_WIDTH − 2×card_padding ≥ 118`;③ 实际两列布局下每卡内宽也 ≥ 118。
- `meta_grid_drops_columns_as_the_detail_narrows` 跟着改成「上限处 2 列」(1180 与 900 同为 2 列,
差别落在详情列宽 435 vs 404)。
2026-11-02 02:04:04 +08:00
AskaEth
dc67be529d
docs(app-iced): P2-2 r2 712 是 ink 不是列宽 + 补偏离登记
...
代码 reviewer 把 P2-2 说得更准,我上一轮只改了数字没改算式,这里按它的复核改到底:
- **712 是那一行的墨迹宽度,不是列宽**。早期文档写「1180 − 88 − 2×24 = 712」,这个减法得 **1044**;
M68 的卡片是 x=112..1156(1044px),卡片内文本区 **1004px**,那一行 ink 才是 712px(x=133..845)。
- 交叉验算对上了:137 字符 × 5.19px(12px × 实测 0.4323em)= **711px** ≈ ink 712。
所以事故是「1004px 的文本区里,一行排了 137 字符」,不是「列宽 712」。
- 订正记录改成两条(① 712 是 ink ② 字符数按实测),并写明早期口径的错法。
顺带把视觉 reviewer 的「请登记」落地:`pages/mod.rs` 新增**偏离登记表** 6 条
(页头右缘与详情右缘 180px 分歧、空态标题比页标题大、单列页只用 48% 内容宽、空态字形 40、
返回入口无箭头、实例空详情态未出图),每条写了「为什么」与「什么时候收口」。
2026-11-02 01:05:27 +08:00
AskaEth
c495fccd6c
fix(app-iced): 视觉 P2-2/3 滚动条变细变淡 + 图标语汇统一成描边
...
视觉复审两条:
- **P2-2 滚动条偏重**:原来直接用 iced 默认 10px 轨 + `Role::Outline`(那份灰绿在浅色下压过列表内容)。
改 **6px 轨 + 2px 外边距 + `Role::OutlineVariant` 滑块**(比 `Outline` 弱一档的容器描边角色),
圆角由 full 按 6px 折算成 3。功能不变(仍是列表列独立滚动、仍只有这一条 scrollable)。
- **P2-3 图标线宽语汇不一致**:设置页「Java」分组用的是令牌里的 `Play`——它是**填充**字形,
同屏其它图标都是描边。改成描边的 `IconKind::Folder`(Java 分组讲的是运行时安装位置,语义也对),
并在 `pieces.rs` 写明规矩:页面骨架**只用描边图标**,将来若要「主操作允许实心图标」,
由 `components/` 统一定义并只留一处。守门见上一条 commit 的 `pages_use_only_stroked_icons`。
2026-11-02 00:39:58 +08:00
AskaEth
a0ccf79b2b
test(app-iced): P2-3 尺寸硬编码守门扩到 pages/(并补图标语汇守门)
...
代码 reviewer 指出:`no_hardcoded_tokens` 的**尺寸**守门只扫 `src/shell`,`pages/` 是新增目录、
**根本没被扫到**,页面里写 `.width(24)` 没人会发现(颜色守门扫全 `src/**`,所以颜色那条是覆盖的)。
- `shell_takes_every_size_from_tokens` → `layout_sources_take_every_size_from_tokens`:
扫描面改成 `src/shell` + `src/pages`,并把「至少 2 个文件」的哨兵断言提到 **≥10 个**(防扫描逻辑坏掉)。
- 实测结果:**扩了之后 `pages/` 是干净的(0 处)**——所有尺寸都走 `layout::*` 常量 / `LayoutMetrics` /
`Space` / `TypeStyle`,没有需要修的违规。
- 顺带补 `pages_use_only_stroked_icons`:`pages/` 里不许出现令牌层的填充字形(`Play`/`Stop`/`More`),
这是视觉 P2-3「图标语汇不一致」的机器化守门(修法见下一条 commit)。
- 文件顶到 403 行 → 压到 399(仓库硬限 400)。
2026-11-02 00:39:48 +08:00
AskaEth
367100848a
docs(app-iced): P2-2 M68 事故口径订正(实测 137 字符,不再引用估算值)
...
代码 reviewer 指出:712px ≈ 「118 字符」的那个数本身不是实测,是拿 0.5em 估的步进换算的,
和 P2-1 是同一个根因(高估了步进)。按实测重写事故描述:
- M68 那张卡里的正文是 `BodySmall` **12px**,步进 = 14px 实测值 6.0526 × 12/14 = **5.19px/字符**,
所以 712px **实测 137 字符**(不是 118);
- 补一条**订正记录**说明早期数错在哪:既高估了步进、也对错了字号,两条叠加把事故说轻了 16%;
- `pages/mod.rs` 的历史判词同步改成 712px + 137 字符;
- 全 `pages/` 已无「118 字符」这个数(`grep` 为空)。
2026-11-02 00:13:42 +08:00
AskaEth
fae1b61d9e
fix(app-iced): P2-1 「72 字符」改成实测口径(上限 504 → 435)
...
两位 reviewer 都量到:`CHAR_ADVANCE_EM = 0.5` 是估的,14 × 0.5 × 72 = 504px 实际能放 83 字符,
「72 字符」只活在名字里。改成实测:
- 口径:`BodyMedium` 14px / Segoe UI Regular / 无 letter-spacing(iced 0.14 不支持字距),
样本 = 实例页详情那段正文(361 字符,大小写/标点/空格/`→` 混排),FreeType getlength
实测 **2185.00px / 361 = 6.0526 px/字符 = 0.43233em**(旧 0.5 高估 15.7%);
交叉验证:同段首行 78 字符渲染墨迹 484px,FreeType 对同一串 479px,差 1%(抗锯齿外扩)。
- `CHAR_ADVANCE_EM` 0.5 → **0.43233**;`measure_cap_px()` 加 **floor** → **435**
(435.79 四舍五入成 436 就会让最后一两个字符挤不进 72 字符的承诺);下限 315 → 272。
- 版面连带重算:`META_CARD_MIN_WIDTH` 160 → **136**(3×136 + 2×12 = 432 ≤ 435,否则 1180 宽下
元信息网格会从 3 列掉到 2 列)。**816 / 720 两个两列阈值不受影响**(它们由 LIST/DETAIL/FORM 宽度算,
与行宽上限无关),单测里的绝对值断言原样成立。
- 单测:`line_length_is_capped_at_72_characters` 里新增 tower 要求的断言 —— 用**实测步进**
(样本字符数 + 实测宽度,独立于常量)反算「上限列宽能放多少字符」≤ 72(实际 71.87),
并加一条回归护栏:同一实测步进下旧口径 504px = 83.3 字符,改回 0.5em 立刻红。
- 文档:`layout.rs` §3 补「怎么重新量」(字体、样本、工具、交叉验证、CJK 不适用)与全部数字;
`mod.rs` / 四页文档里的 ≤504 同步改 435。
2026-11-02 00:13:20 +08:00
AskaEth
2c442585b1
feat(app-iced): M84 页面骨架与布局系统(断点 / 行宽上限 / 三种版面)
...
视觉复审在 M68 的判词是不能把「全宽单卡」当页面模板(1180 宽下正文单行 712px ≈ 118 字符)。
本 mission 把它落成一套**布局系统**,四个页面只是它的用例:
- `pages/layout.rs`:官方 600 / 840 两个档位 → 三种版面(单列 / supporting-pane / list-detail),
阈值由列宽和算出(设置 240+24+320 → 720;实例 336+24+320 → 816 ≤ 840),行宽硬上限
14 × 0.5em × 72 = **504px**,全部是纯函数,`pages/layout/tests.rs` 用绝对值和边界表钉死。
- `pages/frame.rs`:页头(56 / 两行 84)+ 内容列(≤504)+ 两列骨架 + 空态位;
`pages/frame/pieces.rs` 是占位控件(卡片 / 分隔线 / 文本按钮 / 图标),令牌驱动、无完整状态机,
待 M75 的 components 家族合入后替换。
- 四页:实例(list-detail,列表列 336 独立滚动,窄窗退化成整页切换)、
设置(supporting-pane,240 分组导航 + ≤504 表单列)、下载 / 日志(单列,两行页头)。
- `pages/harness.rs` + `examples/pages_demo.rs`:自带 `--screen/--width/--screenshot-theme`,
不碰 `cli.rs` / `app.rs`(M75 在改)。
偏离与说明:
- 布局用「页边距 16/24」而非 16/24/32,官方 expanded 也是 24(少一条偏离登记);
- 实例空详情态一屏会有 5 档字号(22/16/24/12 + 14 的操作按钮),未截图的状态,已知并登记;
- `lib.rs` 只加一行 `pub mod pages;`。
2026-11-01 23:27:28 +08:00
AskaEth
352dd7937e
Merge branch 'feat/p4-core-platform-wallpaper-source-detect'
2026-11-01 21:18:02 +08:00
AskaEth
69d0025d09
fix(core): M73 r1 —— Windows 壁纸来源改为「当前主题优先」,通配主题包降为末档
...
复审 p2-1(medium):Win10+ 上 `%APPDATA%\Microsoft\Windows\Themes\` 通常只有
`TranscodedWallpaper`,一个 `.theme` 都没有;当前生效的主题记在
`HKCU\Software\Microsoft\Windows\CurrentVersion\Themes` 的 `CurrentTheme` 值里,
指向 `%LOCALAPPDATA%\Microsoft\Windows\Themes\Custom.theme`。
- 新增第二步 `windows-current-theme`:`reg.exe query ... /v CurrentTheme` →
归一化(含 `%LOCALAPPDATA%` 展开)→ 读该 `.theme` 的 `Wallpaper=`;
- `%APPDATA%\...\Themes\*.theme` 通配扫描从「第二步」降为第四步兜底,
evidence 如实标注「用户另存的主题包,可能未启用」;
- 新顺序:TranscodedWallpaper → CurrentTheme → 注册表 WallPaper → 另存主题包;
- `HostRoots` 增加 `local_app_data`(`%LOCALAPPDATA%`,退 `~/AppData/Local`)。
复审 p2-2(low):`transcoded_wallpaper_hit_comes_first` 补一条字面量路径断言,
防止夹具与生产代码用同一构造函数一起拼错。
复审 p2-3(low):`HostIo::run` 现在检查退出码(`!output.status.success()` 也返回
`None`),与四处「非零退出 → 失败」的文案对齐;`io.rs` 补一条夹具用例
(有 stdout 但退出码非零)证明旧行为会被挡掉。
行长:`windows.rs` 371 → 拆出纯解析到 `wallpaper/windows/parse.rs`(100 行),
全部 7 个文件 ≤400 行。真机复跑 `detect()`:第 1 条 transcoded、第 2 条
`windows-current-theme` → `C:\Windows\web\wallpaper\Windows\img0.jpg`(与注册表同源,
去重后只剩一条),`%APPDATA%` 下无主题包的 note 照旧。
2026-11-01 21:17:55 +08:00
AskaEth
d3e9a62b21
feat(core): M73 桌面壁纸路径探测(D38 第②级输入)
...
新增 platform::wallpaper:只做「桌面壁纸可能是哪个文件」的路径探测,
不解码图片、不取色(莫奈取色与三级降级留给 crates/design 的后续 mission)。
- 唯一入口 detect() / 注入式 detect_with(io, env, platform):返回有序候选列表
+ 各步失败原因,全部找不到时是空列表而不是错误;
- Windows 三步:TranscodedWallpaper(无扩展名,靠魔数认)→ *.theme 的
Wallpaper= → reg.exe query HKCU\Control Panel\Desktop /v WallPaper;
- Linux 四步:gsettings picture-uri(-dark) → KDE Image= → hyprpaper/sway
配置 → XFCE xfce4-desktop.xml,每步失败不影响下一步;
- macOS 两步:com.apple.wallpaper/Store/Index.plist 字符串扫描(不引 plist
依赖,兼容 bplist00)→ defaults read com.apple.desktop Background;
代码与文档明确标注「未在真机验证」;
- 零 unsafe / 零 FFI(core 是 #![forbid(unsafe_code)]),文件读取与子进程
全部经 ProbeIo 注入,环境变量表经 EnvSource 注入;三平台采集逻辑不带 cfg,
CI 的 Linux 上也能跑 Windows / macOS 夹具用例;
- 不新增第三方依赖;6 个文件均 ≤400 行,32 条单测覆盖三平台的
正常命中 / 多候选 / 全部失败。
2026-11-01 21:17:52 +08:00
AskaEth
614bd253c8
Merge branch 'feat/docs-remove-affiliation-disclaimer-foote'
2026-11-01 20:26:14 +08:00
AskaEth
9e30d2cf15
docs(readme): 删掉文末「与 Mojang / Microsoft 无关联」免责脚注
...
中英两份都删,不补替代句;文件以感谢段落 + 单个换行结束。
2026-11-01 20:24:14 +08:00
AskaEth
6cfac9c823
Merge branch 'feat/docs-tone-pass-remove-defensive-wording'
2026-11-01 20:02:10 +08:00
AskaEth
4069204379
docs(readme): 复审收尾两处——ull 行补回分发状态,平台独立性改正面陈述
...
- bin 表 `ull` 行:State 列补回「未随 v0.1.0 资产分发」/ "not in the v0.1.0 assets",
只看表格的人也读得到分发状态
- 平台基线末条:去掉「而非独立产物链」这半句对没人提的质疑的反驳,
改为「每个平台跑各自的测试矩阵」/ "Each platform runs its own test matrix"
2026-11-01 20:00:41 +08:00
AskaEth
0cb1454067
docs(readme): 致谢改为平实感谢,去掉「欠人情」的债务叙事
...
原段落把作者写成亏欠方(「这个项目欠它们一份很大的人情」/ "exists very much in
their debt"),并把 HMCL / PCL2 称作 "old-timers"。两者都是 GPL-3.0 开源项目,
阅读与借鉴本就在许可之内,不需要愧疚来偿付。
- 债务词全部移除:欠 / 人情 / debt / owe / old-timers / enormous amount
- 保留感谢本身,改成「它们做得久 + 本项目从中受益」两句话
- 中文补一次断行以保持 ≤100 显示列
2026-11-01 19:55:55 +08:00
AskaEth
aca280fd30
docs(readme): 删掉「合规声明」整节,账户信息归位到特性表
...
这是项目的 README,不是审核材料:把单独开列的合规节去掉,信息放回它该在的位置。
- 删除整节 `## Compliance statement` / `## 合规声明`(含 5 条 bullet)
- 「Microsoft 账户登录 + OAuth device code → XBL → XSTS → Minecraft Services + 令牌只存本机」
并入特性表新增的「账户 / Accounts」一条(功能说明,不是专项保证)
- 「不分发游戏文件」「联机需账户与权益」两条删除(常识范围 / 与前一句重复)
- 「与 Mojang、Microsoft 无关联」降为文末一行普通脚注
- 平台基线:标准工具链那条去掉三重「无」,改为平铺陈述
- 平台基线:删掉与「构建 → 渲染开关」重复的渲染兜底条目(第三处),
文件内不再出现「完整界面」/ "the full UI"
- bin 表:`ull` 状态列去掉与 Track A bullet 重复的「未随资产分发」,保留「同源同版本构建」
- UI 一条:「驱动真实引擎」→「由 core 引擎驱动」/ "drive the real engine" → "run on the core engine"
2026-11-01 19:54:50 +08:00
AskaEth
5a44870de5
docs(readme): 语气体检——去掉「正版登录」及同类防御腔与自我声明
...
- zh 模块表 auth 行:「Microsoft 正版登录」→「Microsoft 账户登录」,与英文 "Microsoft sign-in" 对齐
- zh/en:CLI 行去掉「完整可用」/ "is fully usable"(要读者相信的形容词)
- zh/en:CPU 软渲染兜底不再承诺「完整界面」/ "the full UI",改为陈述渲染结果
- zh/en:轨道 B 首句去掉「没有任何…任何下载都拿不到它」/ "Nothing…no download contains it" 的双重否认,
并与紧邻的「只能自己从源码编」合并为一句
- zh:轨道 A 小标题去掉「真能」的强调语气
2026-11-01 19:51:46 +08:00
AskaEth
a426cb5dcb
Merge branch 'feat/docs-refresh-readme-for-iced-rewrite-and'
2026-11-01 19:49:27 +08:00
AskaEth
9d9ab3e7e0
docs(readme): 合规段第一条去掉防御腔 —— 平静陈述「用 Microsoft 账户登录」
...
- 英文:Microsoft sign-in only → Sign-in with your Microsoft account;删掉 There is no other
account provider(过度否认本身是信号)
- 中文:只走 Microsoft 正版登录 → 用 Microsoft 账户登录;删掉「没有别家账户通道」,
并避开「正版」这个词(中文圈里该词天然与「破解」对照,带防御姿态)
- 事实不变:device code → XBL → XSTS → api.minecraftservices.com,用玩家自己的账户与权益
- 第三条「联机游玩需要 Microsoft 账户与有效权益」保留独立一条(事实陈述,非否认)
2026-11-01 19:49:08 +08:00
AskaEth
d0d24d42e7
docs(readme): 按用户令删除全部离线档案描述;门禁口径改为 main 推送 + PR
...
- 合规条里「Offline profiles cannot play online / 本地离线档案仅限本地与隔离网络测试」整条删除,
只保留正面陈述「联机游玩需要 Microsoft 账户与有效的游戏权益」
- 模块地图 auth 行去掉「local offline profiles / 本地离线档案」,只留 Microsoft 正版登录全链路
- 全文 grep offline|离线|隔离网络 零命中;不做「不支持离线」的反向承诺,也不暗示别的账户通道
- 顺手修 nit:CI 段「Every push」→「Every push to main and every pull request」
(ci.yml on.push 限 main 分支,非 main 且无 PR 时门禁不跑)
2026-11-01 19:47:40 +08:00
AskaEth
a4bd4d2b38
docs(readme): r1 复审修复 —— 去掉 ull 随包分发的假话、macOS 探针降级为 advisory、离线档案正面陈述、合规段提到第一屏
...
- P1: ull 与 v0.1.0 同源同版本但发布资产只有 GUI 单文件(make_artifacts.py 只搬 launcher、
release.yml assets 只 glob unlucky-launcher-*)→ 4 处改为「自行 cargo build --release --bin ull」
- P2-1: macOS 运行期探针 if workflow_dispatch + continue-on-error,属 advisory → 与 Linux 冒烟拆句
- P2-2: 离线档案去掉「不能连校验账户的服务器」这种可反读的限定,标题改「联机游玩必须使用 Microsoft 账户」
- P2-3: 合规声明挪到引言之后、特性 bullet 之前(第一屏可见),文字不变
- nit: 三份合规文本每个 Release 都挂(Windows 因 exe 装不下才并列);Slint 版无显式探测,改为两套栈
各自回退到 CPU 的准确表述
2026-11-01 19:44:07 +08:00
AskaEth
2a0493c3eb
docs(readme): 两份 README 改写为 iced/M3 Expressive 现状(双 bin 并存 + 两轨 Status)
...
- UI 描述:已发布 v0.1.0 = Slint + Metro;下一代 = iced 0.14 + Material 3 Expressive,dev 上施工中
- 双 bin 并存逐条讲清:unlucky-launcher(Slint,v0.1.0 已发布)/ unlucky-launcher-iced(施工中)
/ ull(CLI),并说明翻牌前不改名的原因(同 target 目录不能同名 bin)
- 模块地图补 crates/design(真 HCT 令牌、零 UI 依赖)与 crates/app-iced;crates/app 保留到等价验收
- Status 重写为两轨:Track A 已发布(含 v0.1.0 资产范围与 CLI 命令集,取自 release.yml 与 cli/help.rs)
/ Track B 施工中(已完成=令牌+骨架;未完成=组件库/页面/i18n,页面全是占位)
- 删除全部过期统计数字(983+ tests 等),改为行为性门禁表述;无测试数、无产物体积
- 合规段落只留 Microsoft 正版登录 / 凭据只存本机且 AI 不可访 / 离线不能联机 / 不分发不镜像不代理
/ 与 Mojang-Microsoft 无关联;无第三方账户服务字样
- 许可:Slint RF 2.0 归属保留并补 iced(MIT)、MCU(Apache-2.0)、其余主要依赖
- 致谢 HMCL / PCL2 改为口语化语气,不加粗、不撇清
- 开头保留 GitHub 官方主页行(英文自指、中文醒目指引 + Releases 链接),全文无 gitea 地址
- 平台基线补 macOS 未签名需清 Gatekeeper 隔离标记
2026-11-01 18:53:26 +08:00
AskaEth
cf52751124
Merge branch 'feat/p4-design-cool-sky-blue-default-seed-can'
2026-11-01 18:13:28 +08:00
AskaEth
40864d93d0
fix(design): M70 r4 —— 偏离登记补齐「neutral-variant 8→14」+ 文档口径与 pin 可读性
...
复审 P2-1:neutral-variant 的那一半偏离漏登记,且文档把 nv 说成官方相对式。
- `color/mod.rs`:标题改「两处有意偏离(同一处偏离的两半)」;偏离登记把
neutral 6→12 与 neutral-variant 8→14 分列,写明官方 `getNeutralVariantPalette`
是**绝对值 8**(不是 neutral+2)、影响角色含 outline/outline-variant/surface-variant,
以及「nv 钉回 8 会让表面(12)比中性变体(8)更有色」的倒挂理由
- `palettes.rs`:`NEUTRAL_VARIANT_OFFSET` 文档改述为「官方绝对值 8,本实现相对式=有意偏离」;
`DEFAULT_NEUTRAL_CHROMA` 的矛盾区间改正为「数值安全区间 6..=13(14 才撞 secondary),产品取 12」;
`from_seed_with_neutral_chroma` 加调用方约束(越界静默退化:<0/NaN → 彩度 0;≥14 → nv 撞 secondary);
新增 `product_default_neutral_chroma_is_a_registered_deviation`(钉 neutral 12 / nv 14,官方锚点仍 6/8)
- nit1:`sky_seed_candidates_meet_wcag_aa` 的「三档」→「四档(208 项)」
- nit2:`product_default_is_the_adopted_candidate` 改成比 hex 文案,失败时可直读「期望 #3C8DBC、实测 #87CEEB(③)」
- nit4:`lib.rs` 的 `DesignTokens::baseline` 文档改准(产品默认 ④ 天蓝,官方口径走 `Scheme::official_baseline`)
无物理行为变更:算法、tone 表、gamut、所有色值一个没动。
2026-11-01 18:09:14 +08:00
AskaEth
e37b452345
feat(design): M70 r2 —— 出厂默认定为 ④ 天蓝 #3C8DBC(用户 2026-11-01 拍板)
...
- `palettes::DEFAULT_SEED`:`#87CEEB`(③ 浅冷蓝)→ `#3C8DBC`(④ 天蓝,主色 `#236488`);
`DEFAULT_NEUTRAL_CHROMA` 保持 12
- `tests/skyseed_candidates.rs`:`product_default_is_the_recommended_candidate` →
`product_default_is_the_adopted_candidate`,绑定 `CANDIDATES[3]`(④);四档 pin 不变
- 文档:`color/mod.rs` / `palettes.rs` 的「临时默认 ③ / 待用户确认」全部换成
「出厂默认 ④(用户 2026-11-01 拍板)」,③ 标注为备选(值仍 pin 住,可一行换回)
- 文档新增定位(D38):这两个常量只定义「**莫奈关闭时的出厂预选色卡**」(配色来源第三级),
不再代表唯一配色来源;背景图/壁纸取色与内置色卡库都不在本 crate、尚未实现
2026-11-01 18:09:14 +08:00