fix(video): sync first-frame background state

This commit is contained in:
edde746
2026-06-15 12:05:29 +02:00
parent a4c444435f
commit 27723e6f29
2 changed files with 46 additions and 6 deletions
+45 -6
View File
@@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'player/player.dart'; import 'player/player.dart';
@@ -23,8 +24,15 @@ class Video extends StatefulWidget {
final Player player; final Player player;
final Widget Function(BuildContext context)? controls; final Widget Function(BuildContext context)? controls;
final Color backgroundColor; final Color backgroundColor;
final ValueListenable<bool>? hasFirstFrame;
const Video({super.key, required this.player, this.controls, this.backgroundColor = Colors.black}); const Video({
super.key,
required this.player,
this.controls,
this.backgroundColor = Colors.black,
this.hasFirstFrame,
});
@override @override
State<Video> createState() => _VideoState(); State<Video> createState() => _VideoState();
@@ -38,19 +46,50 @@ class _VideoState extends State<Video> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_playbackRestartSubscription = widget.player.streams.playbackRestart.listen((_) { _hasFirstFrame = widget.hasFirstFrame?.value ?? false;
if (!_hasFirstFrame && mounted) { widget.hasFirstFrame?.addListener(_syncExternalFirstFrame);
setState(() => _hasFirstFrame = true); _listenForPlaybackRestart();
} }
});
@override
void didUpdateWidget(covariant Video oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.hasFirstFrame != widget.hasFirstFrame) {
oldWidget.hasFirstFrame?.removeListener(_syncExternalFirstFrame);
widget.hasFirstFrame?.addListener(_syncExternalFirstFrame);
_syncExternalFirstFrame();
}
if (oldWidget.player != widget.player) {
_playbackRestartSubscription?.cancel();
_listenForPlaybackRestart();
_syncExternalFirstFrame();
}
} }
@override @override
void dispose() { void dispose() {
widget.hasFirstFrame?.removeListener(_syncExternalFirstFrame);
_playbackRestartSubscription?.cancel(); _playbackRestartSubscription?.cancel();
super.dispose(); super.dispose();
} }
void _listenForPlaybackRestart() {
_playbackRestartSubscription = widget.player.streams.playbackRestart.listen((_) {
_setHasFirstFrame(true);
});
}
void _syncExternalFirstFrame() {
final external = widget.hasFirstFrame;
if (external == null) return;
_setHasFirstFrame(external.value);
}
void _setHasFirstFrame(bool value) {
if (_hasFirstFrame == value || !mounted) return;
setState(() => _hasFirstFrame = value);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ColoredBox( return ColoredBox(
@@ -256,6 +256,7 @@ extension _VideoPlayerBuildMethods on VideoPlayerScreenState {
return Video( return Video(
player: player!, player: player!,
hasFirstFrame: _hasFirstFrame,
controls: (context) => PlexVideoControls( controls: (context) => PlexVideoControls(
player: player!, player: player!,
metadata: _currentMetadata, metadata: _currentMetadata,