fix(app-iced): 补回被变异回滚误删的两处修复(钉住档位 + 退场起点)
上一提交把一个中间态(BYPASS_PROBE + serialize 未删、Modal::Closing 无 from)提交了:
变异实验后我用 git checkout -- 复原,而那些修复当时还没入库,于是被一起抹掉,
直接用例把这件事抓了出来(3 条恒定红)。现在按正确内容重做:
- delete motion::serialize()(空操作)
- FORCED_SCALE: Cell<Option<MotionScale>>,configure 里钉住优先
- Modal::Closing { start_ms, from },退场从当前进度连续缩到 0
(教训记在报告:变异只在已提交的树上做,别在未提交的树里 checkout。)
This commit is contained in:
1 parent
787cb16189
commit
b6127b4735
2 files changed
+27
-28
No files matched your search
@@ -84,21 +84,22 @@ thread_local! {
|
||||
/// 上次收到帧的时刻(`advance` 用它把「帧到达」换算成流逝毫秒)。
|
||||
#[allow(clippy::missing_const_for_thread_local)]
|
||||
static LAST_FRAME: Cell<Option<Instant>> = const { Cell::new(None) };
|
||||
/// **测试专用**:置真后 [`configure`] 不再读系统偏好(见 [`configure_for_test`])。
|
||||
/// **测试专用**:`Some(档)` = 钉住这个档,[`configure`] 既不再读系统偏好、也不吃传入值。
|
||||
#[allow(clippy::missing_const_for_thread_local)]
|
||||
static BYPASS_PROBE: Cell<bool> = const { Cell::new(false) };
|
||||
static FORCED_SCALE: Cell<Option<MotionScale>> = const { Cell::new(None) };
|
||||
}
|
||||
|
||||
/// 定档:`on_boot` 调一次(截图档给 `NONE`,CPU 档给 `HALF`,见 `app/update/boot_env.rs`)。
|
||||
///
|
||||
/// **系统「减少动效」在这里合成**(见模块文档的表):`Reduced` ⇒ `NONE`;`Unknown` ⇒ 不动。
|
||||
pub fn configure(scale: MotionScale, pin: Option<f64>) {
|
||||
// 用例走 `configure_for_test` 置位旁路:**产品启动路径**(`on_boot` → 这里)也会重新定档,
|
||||
// 只挡调用点是不够的。
|
||||
let scale = if BYPASS_PROBE.with(Cell::get) {
|
||||
scale
|
||||
} else {
|
||||
effective_scale(scale, ReduceMotion::probe(), pin.is_some())
|
||||
// 三条定档路径**都汇到这里**:①测试/`on_boot` 直接调;②`App::on_boot` → `configure_motion`
|
||||
// → 这里(`app/update.rs:276`);③`boot_env::motion_scale(..)` 算出的 env / 后端 tier 也是经②
|
||||
// 喂进来的。所以「钉住某个档」必须在这个函数里生效——堵调用点或堵 `boot_env` 都会被后一次
|
||||
// `on_boot` 覆盖(r2 复审实测:`idle_app()` 先钉 STANDARD,Boot 之后变 HALF/NONE)。
|
||||
let scale = match FORCED_SCALE.with(Cell::get) {
|
||||
Some(forced) => forced,
|
||||
None => effective_scale(scale, ReduceMotion::probe(), pin.is_some()),
|
||||
};
|
||||
PUMP.with(|pump| pump.borrow_mut().configure(scale, pin));
|
||||
}
|
||||
@@ -111,7 +112,7 @@ pub fn configure(scale: MotionScale, pin: Option<f64>) {
|
||||
/// 这条判据悄悄删掉。
|
||||
#[cfg(test)]
|
||||
pub fn configure_for_test(scale: MotionScale, pin: Option<f64>) {
|
||||
BYPASS_PROBE.with(|flag| flag.set(true));
|
||||
FORCED_SCALE.with(|forced| forced.set(Some(scale)));
|
||||
configure(scale, pin);
|
||||
}
|
||||
|
||||
@@ -131,18 +132,6 @@ pub fn scale() -> MotionScale {
|
||||
PUMP.with(|pump| pump.borrow().scale())
|
||||
}
|
||||
|
||||
/// **测试专用**:动效全局态的串行门(复审 P2-5 的第二半)。
|
||||
///
|
||||
/// `Pump` 与「旁路探针」都是 thread-local,正常并行用例本就互不干扰;但用例会读**产品启动路径**
|
||||
/// 写下的档位,而 libtest 允许 `--test-threads=1`(届时所有用例同线程)。凡是会改写动效全局态的
|
||||
/// 用例都先取这把锁,把时序固定下来——**跨模块共用的只有这一把**(`subscription.rs` 与
|
||||
/// `motion_sync.rs` 都从这里取)。
|
||||
#[cfg(test)]
|
||||
pub fn serialize() -> std::sync::MutexGuard<'static, ()> {
|
||||
static GATE: std::sync::Mutex<()> = std::sync::Mutex::new(());
|
||||
GATE.lock().unwrap_or_else(|poisoned| poisoned.into_inner())
|
||||
}
|
||||
|
||||
/// 已推进的帧数。
|
||||
pub fn samples() -> u64 {
|
||||
PUMP.with(|pump| pump.borrow().samples())
|
||||
@@ -258,8 +247,8 @@ pub fn shifted<'a, M: 'a>(
|
||||
pub fn reset() {
|
||||
PUMP.with(|pump| *pump.borrow_mut() = pump::Pump::new());
|
||||
LAST_FRAME.with(|last| last.set(None));
|
||||
// 旁路也要清:「故意走真探针」的那条用例靠 `reset()` 回到未旁路状态。
|
||||
BYPASS_PROBE.with(|flag| flag.set(false));
|
||||
// 钉住也要清:「故意走真探针」的那条用例靠 `reset()` 回到未钉住状态。
|
||||
FORCED_SCALE.with(|forced| forced.set(None));
|
||||
}
|
||||
|
||||
/// 测试专用:按给定毫秒推进(`advance` 读真实时钟,单元测试不能等它)。
|
||||
|
||||
@@ -24,8 +24,9 @@ pub(crate) enum Modal {
|
||||
Opening { start_ms: f64 },
|
||||
/// 完全展开(稳态,不占帧)。
|
||||
Open,
|
||||
/// 退场中。
|
||||
Closing { start_ms: f64 },
|
||||
/// 退场中。`from` = 起手那一刻的进度:进场途中被关掉时它是**当前进度**,不是 1.0
|
||||
/// (否则会先跳到完全展开再往回缩 = 反向硬跳)。
|
||||
Closing { start_ms: f64, from: f32 },
|
||||
}
|
||||
|
||||
impl Pump {
|
||||
@@ -72,8 +73,16 @@ impl Pump {
|
||||
self.close_pending = false;
|
||||
return true;
|
||||
}
|
||||
// 已经在退场 ⇒ 保持原样(重复的关闭请求不该重算起点)。
|
||||
if matches!(self.modal, Modal::Closing { .. }) {
|
||||
return false;
|
||||
}
|
||||
// **起点是当前进度**:进场走到 20% 就关 ⇒ 从 0.20 往回缩;已展开 ⇒ 从 1.0 缩。
|
||||
// 不这么做就是「先跳到 1.0 再退」的反向硬跳(复审 r2 的 P2-2)。
|
||||
let from = self.modal_frame().progress;
|
||||
self.modal = Modal::Closing {
|
||||
start_ms: self.start_now(),
|
||||
from,
|
||||
};
|
||||
false
|
||||
}
|
||||
@@ -107,7 +116,7 @@ impl Pump {
|
||||
progress: spec.enter.easing.sample(t),
|
||||
}
|
||||
}
|
||||
Modal::Closing { start_ms } => {
|
||||
Modal::Closing { start_ms, from } => {
|
||||
let spec = modal_spec();
|
||||
let t = leg_fraction(
|
||||
self.elapsed_ms() - start_ms,
|
||||
@@ -115,8 +124,9 @@ impl Pump {
|
||||
);
|
||||
ModalFrame {
|
||||
visible: true,
|
||||
// 退场是**反向**走同一条线:1 → 0(与进场共用 `modal_scale` 的映射)。
|
||||
progress: 1.0 - spec.exit.easing.sample(t),
|
||||
// 从起手进度**连续**缩到 0:`from * (1 - eased)`。`from = 1.0` 时与改造前
|
||||
// 逐帧等价;进场途中关则是"从半开接着缩"。
|
||||
progress: from * (1.0 - spec.exit.easing.sample(t)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user