fix(mobile): fix stale refs in use timer

The timer hook preserved the values of the original local variables,
which caused issues when hiding controls for videos. The callback can be
changed so that it always sees the latest value with useRef, and it can
be simplified significantly using a function rather than state class.
This commit is contained in:
Thomas Way
2026-04-05 04:03:32 +01:00
parent 776b9cbad5
commit 0651612d46
2 changed files with 14 additions and 33 deletions

View File

@@ -74,7 +74,7 @@ class ViewerBottomBar extends ConsumerWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (asset.isVideo) VideoControls(key: ValueKey(asset.heroTag), videoPlayerName: asset.heroTag),
if (asset.isVideo) VideoControls(videoPlayerName: asset.heroTag),
if (!isReadonlyModeEnabled)
Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: actions),
],

View File

@@ -1,36 +1,17 @@
import 'package:async/async.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
RestartableTimer useTimer(Duration duration, void Function() callback) {
return use(_TimerHook(duration: duration, callback: callback));
}
class _TimerHook extends Hook<RestartableTimer> {
final Duration duration;
final void Function() callback;
const _TimerHook({required this.duration, required this.callback});
@override
HookState<RestartableTimer, Hook<RestartableTimer>> createState() => _TimerHookState();
}
class _TimerHookState extends HookState<RestartableTimer, _TimerHook> {
late RestartableTimer timer;
@override
void initHook() {
super.initHook();
timer = RestartableTimer(hook.duration, hook.callback);
}
@override
RestartableTimer build(BuildContext context) {
return timer;
}
@override
void dispose() {
timer.cancel();
super.dispose();
}
RestartableTimer useTimer(Duration duration, VoidCallback callback) {
final latest = useRef(callback);
latest.value = callback;
final timer = useMemoized(
() => RestartableTimer(duration, () => latest.value()),
[duration],
);
useEffect(() => timer.cancel, [timer]);
return timer;
}