fix: re-anchor effects clock when ticker drains (stale-clock freeze)

After Ticker.stop(), elapsed resets to zero on the next start(). _now was
left frozen at the old elapsed, so effects added after a drain captured a
stale start time and their progress() clamped to 0 forever — ticker never
stopped, second batch broken. Fix: reset _now = Duration.zero on drain.
Adds @visibleForTesting getters and a regression test that catches the
stale value directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 22:16:51 +09:00
parent 8c3c2ae9a9
commit f1b8052f77
2 changed files with 78 additions and 1 deletions
+12 -1
View File
@@ -60,11 +60,22 @@ class EffectsOverlayState extends State<EffectsOverlay>
_ticker = createTicker(_tick);
}
@visibleForTesting
Ticker get ticker => _ticker;
@visibleForTesting
Duration get now => _now;
void _tick(Duration elapsed) {
setState(() {
_now = elapsed;
_fx.removeWhere((e) => e.done(elapsed));
if (_fx.isEmpty) _ticker.stop();
if (_fx.isEmpty) {
_ticker.stop();
// Ticker elapsed restarts from zero after stop(); re-anchor so
// effects added later don't inherit a stale clock.
_now = Duration.zero;
}
});
}