fix(app-iced): 删掉空操作串行门 + 钉住档位贯穿产品启动路径 + 退场起点接当前进度

复审 r2 的三条:
1) 删掉 motion::serialize() 那把串行门:PUMP/LAST_FRAME 都是 thread_local,libtest 每用例
   一线程 ⇒ 它改变不了任何结果(ULL_MOTION=off 下握门照样红)。留一个不起作用的同步原语
   比没有更坏。subscription.rs 与 motion_sync.rs 的 idle_app 恢复原签名。
2) 真实根因是「喂给 configure 的值」:idle_app 先钉 STANDARD,随后 on_boot →
   configure_motion(app/update.rs:276)→ boot_env::motion_scale(..) 再定一次档,把钉住覆盖掉。
   改成 BYPASS_PROBE(bool) → FORCED_SCALE(Cell<Option<MotionScale>>):configure 里钉住优先,
   于是三条定档路径(configure_for_test / on_boot / boot_env 的 env·后端 tier)都穿不过去。
   两条用例钉住它(纯合成 + 真 Message::Boot),删掉「钉住优先」两处都红。
3) P2-2:Modal::Closing 记住起手进度 from,progress = from*(1-eased) —— 进场途中被关掉时
   从当前进度接着缩,不再先跳到 1.0(反向硬跳)。新用例
   closing_during_the_entrance_does_not_jump_to_fully_open,把 from 改回 1.0 即红。
This commit is contained in:
AskaEth committed 2026-11-12 10:50:03 +08:00
1 parent c21c6df51b
commit 787cb16189
4 files changed
+122 -44

No files matched your search

@@ -246,3 +246,70 @@ fn configure_goes_through_the_real_os_probe() {
);
reset();
}
/// **进场途中被关掉**:进度必须从**当前值**接着缩,不许先跳到 1.0 再退(复审 r2 的 P2-2)。
///
/// 抓得住:把 `begin_modal_close` 的起点改回恒 `1.0`(旧实现)⇒ 下面那条
/// `(关掉后首帧)<=(关掉前一帧)` 立刻红——那就是"反向硬跳"。
/// 抓不住:那一帧在真实屏幕上有多刺眼(D30 的观感,不是断言)。
#[test]
fn closing_during_the_entrance_does_not_jump_to_fully_open() {
let mut pump = standard();
assert!(pump.observe_modal(true), "起跑进场");
for _ in 0..3 {
pump.advance(FRAME_MS); // 走到进场的 1/4 左右
}
let before = pump.modal_frame().progress;
assert!(
before > 0.0 && before < 1.0,
"前提:进场走到半路,实测 {before}"
);
assert!(!pump.begin_modal_close(), "有动效 ⇒ 起跑退场");
let first = pump.modal_frame().progress;
assert!(
first <= before + 1.0e-6,
"关掉后的首帧进度不许**变大**({before} → {first} 就是反向硬跳)"
);
assert!(
(first - before).abs() < 0.05,
"起点必须接在当前进度上({before} → {first})"
);
// 之后单调缩到 0,且必须真的走完(交回一次「已关」)
let mut previous = first;
while pump.is_animating() {
pump.advance(FRAME_MS);
let now = pump.modal_frame().progress;
assert!(
now <= previous + 1.0e-6,
"退场必须单调缩小:{previous} → {now}"
);
previous = now;
}
assert_eq!(pump.modal_frame(), ModalFrame::HIDDEN);
assert!(pump.take_modal_closed());
}
/// **钉住的档压过任何来源的取值**(复审 r2 的根因机制)。
///
/// `App::on_boot` 会再调一次 `configure`(`app/update.rs:276`),值来自
/// `boot_env::motion_scale(...)`(本机默认 HALF、`ULL_MOTION=off` 时 NONE)。本用例把那次调用
/// 的**取值**直接喂进来:钉住 STANDARD 之后,`configure(HALF)` / `configure(NONE)` 都改不动它。
///
/// 抓得住:删掉 `configure` 里「`FORCED_SCALE` 优先」那一段 ⇒ 两行断言全红(= r2 之前的真红)。
/// 抓不住:`boot_env` 自己那张分支表(env / 后端 tier 的取值规则,不在本 mission 的 scope)。
#[test]
fn a_pinned_scale_survives_every_later_configure() {
reset();
configure_for_test(MotionScale::STANDARD, None);
configure(MotionScale::HALF, None); // = 本机 ICED_BACKEND 未设时 boot_env 的默认档
assert_eq!(scale(), MotionScale::STANDARD);
configure(MotionScale::NONE, None); // = ULL_MOTION=off 时 boot_env 的取值
assert_eq!(
scale(),
MotionScale::STANDARD,
"钉住的档必须压过 on_boot 的取值"
);
reset();
}