Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ class AudioQueueDialog extends ConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
final playbackInfo = ref.watch(mediaPlaybackProvider);
final currentModel = ref.watch(playBackModel);
final player = ref.watch(videoPlayerProvider);

final shouldWrap = playbackInfo.repeatMode == AudioRepeatMode.all;
// Only depend on repeatMode here; watching the whole model rebuilt the
// entire dialog (and re-mapped the queue) on every position tick.
final shouldWrap = ref.watch(mediaPlaybackProvider.select((value) => value.repeatMode == AudioRepeatMode.all));
final items = player.audioQueueForDisplay(wrapAround: shouldWrap);
final currentItem = currentModel?.item;
final tempStart = player.temporaryQueueStartInDisplay(wrapAround: shouldWrap);
Expand Down
5 changes: 3 additions & 2 deletions lib/screens/video_player/components/video_player_queue.dart
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,11 @@ class VideoPlayerQueue extends ConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
final playbackInfo = ref.watch(mediaPlaybackProvider);
final player = ref.watch(videoPlayerProvider);

final shouldWrap = playbackInfo.repeatMode == AudioRepeatMode.all;
// Only depend on repeatMode here; watching the whole model rebuilt the
// entire queue (and re-mapped it) on every position tick.
final shouldWrap = ref.watch(mediaPlaybackProvider.select((value) => value.repeatMode == AudioRepeatMode.all));
final providerItems = player.audioQueueForDisplay(wrapAround: shouldWrap);
final items = providerItems.isNotEmpty ? providerItems : this.items;
final tempStart = player.temporaryQueueStartInDisplay(wrapAround: shouldWrap);
Expand Down
5 changes: 4 additions & 1 deletion lib/screens/video_player/components/video_progress_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,10 @@ class _ChapterProgressSliderState extends ConsumerState<VideoProgressBar> {
),
),
if (!widget.buffering) ...[
chapterCard(context, position, isVisible),
// Only build the scrub-preview card while it is actually visible
// (hovering/dragging the bar). Otherwise it would build + lay out
// its image/trickplay subtree on every frame behind opacity 0.
if (isVisible) chapterCard(context, position, isVisible),
Positioned(
left: (constraints.maxWidth / (widget.duration.inMilliseconds / position.inMilliseconds))
.clamp(1, constraints.maxWidth),
Expand Down
38 changes: 29 additions & 9 deletions lib/screens/video_player/video_player_controls.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {

final fadeDuration = const Duration(milliseconds: 350);
bool showOverlay = true;

/// Whether the overlay controls are kept in the widget tree. They are
/// unmounted once the hide animation finishes so their position-driven
/// Consumers stop rebuilding while the user is just watching.
bool _overlayMounted = true;
bool wasPlaying = false;
SystemUiMode? _currentSystemUiMode;

Expand Down Expand Up @@ -171,13 +176,23 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
child: AnimatedOpacity(
duration: fadeDuration,
opacity: showOverlay ? 1 : 0,
child: Column(
children: [
topButtons(context),
const Spacer(),
bottomButtons(context),
],
),
onEnd: () {
// Once fully faded out, drop the controls from the tree so
// their position-driven Consumers stop rebuilding while
// the overlay is hidden.
if (!showOverlay && _overlayMounted) {
setState(() => _overlayMounted = false);
}
},
child: _overlayMounted
? Column(
children: [
topButtons(context),
const Spacer(),
bottomButtons(context),
],
)
: const SizedBox.shrink(),
),
),
VideoPlayerSeekIndicator(controller: _seekController),
Expand Down Expand Up @@ -747,8 +762,13 @@ class _DesktopControlsState extends ConsumerState<DesktopControls> {
}

void toggleOverlay({bool? value}) {
if (showOverlay == (value ?? !showOverlay)) return;
setState(() => showOverlay = (value ?? !showOverlay));
final newValue = value ?? !showOverlay;
if (showOverlay == newValue) return;
setState(() {
showOverlay = newValue;
// Remount the controls before fading them back in.
if (newValue) _overlayMounted = true;
});
resetTimer();

final desiredMode = showOverlay ? SystemUiMode.edgeToEdge : SystemUiMode.immersiveSticky;
Expand Down
Loading