fix(video): release scrub chrome hold

close #1340
This commit is contained in:
edde746
2026-06-14 18:34:12 +02:00
parent b23ba4c839
commit 5e2bd4efa8
8 changed files with 122 additions and 5 deletions
+77 -1
View File
@@ -425,6 +425,8 @@ void main() {
required List<Duration> seekEnds,
Duration duration = const Duration(minutes: 10),
bool enabled = true,
VoidCallback? onScrubStart,
VoidCallback? onScrubEnd,
Widget Function(Widget child)? wrap,
}) async {
Widget slider = SizedBox(
@@ -437,6 +439,8 @@ void main() {
enabled: enabled,
onSeek: seeks.add,
onSeekEnd: seekEnds.add,
onScrubStart: onScrubStart,
onScrubEnd: onScrubEnd,
),
);
if (wrap != null) slider = wrap(slider);
@@ -450,7 +454,15 @@ void main() {
testWidgets('touch drag survives tooltip appearance and finalizes once', (tester) async {
final seeks = <Duration>[];
final seekEnds = <Duration>[];
await pumpScrubSlider(tester, seeks: seeks, seekEnds: seekEnds);
var scrubStarts = 0;
var scrubEnds = 0;
await pumpScrubSlider(
tester,
seeks: seeks,
seekEnds: seekEnds,
onScrubStart: () => scrubStarts++,
onScrubEnd: () => scrubEnds++,
);
// Down at the center (200/400 → 5min), drag +100px (→ 7.5min). The
// first scrub event makes the tooltip appear; the drag must keep
@@ -466,9 +478,73 @@ void main() {
expect(seeks, isNotEmpty);
expect(seekEnds, hasLength(1));
expect(scrubStarts, 1);
expect(scrubEnds, 1);
expect(seekEnds.single.inMilliseconds, closeTo(const Duration(minutes: 7, seconds: 30).inMilliseconds, 2000));
});
testWidgets('keyboard input does not start a scrub lifecycle', (tester) async {
final focusNode = FocusNode();
addTearDown(focusNode.dispose);
var scrubStarts = 0;
var scrubEnds = 0;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: SizedBox(
width: 400,
child: TimelineSlider(
position: const Duration(minutes: 1),
duration: const Duration(minutes: 10),
chapters: const [],
chaptersLoaded: true,
focusNode: focusNode,
onKeyEvent: (_, event) => KeyEventResult.handled,
onSeek: (_) {},
onSeekEnd: (_) {},
onScrubStart: () => scrubStarts++,
onScrubEnd: () => scrubEnds++,
),
),
),
),
);
focusNode.requestFocus();
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
await tester.pump();
expect(scrubStarts, 0);
expect(scrubEnds, 0);
});
testWidgets('disposing mid-drag ends the scrub lifecycle', (tester) async {
final seeks = <Duration>[];
final seekEnds = <Duration>[];
var scrubStarts = 0;
var scrubEnds = 0;
await pumpScrubSlider(
tester,
seeks: seeks,
seekEnds: seekEnds,
onScrubStart: () => scrubStarts++,
onScrubEnd: () => scrubEnds++,
);
final gesture = await tester.startGesture(tester.getCenter(find.byType(TimelineSlider)));
await tester.pump();
expect(scrubStarts, 1);
expect(scrubEnds, 0);
await tester.pumpWidget(const SizedBox.shrink());
await tester.pump();
await gesture.cancel();
expect(scrubEnds, 1);
});
testWidgets('tap seeks to the tapped position', (tester) async {
final seeks = <Duration>[];
final seekEnds = <Duration>[];