fix(tv): hide seek/skip controls during live playback

This commit is contained in:
edde746
2026-02-12 14:21:21 +01:00
parent 80f26b07c0
commit eb644c0194
2 changed files with 88 additions and 80 deletions
@@ -475,41 +475,43 @@ class DesktopVideoControlsState extends State<DesktopVideoControls> {
// Row 2: Playback controls and options
Row(
children: [
// Previous item
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _prevItemFocusNode,
index: 0,
icon: Symbols.skip_previous_rounded,
color: widget.onPrevious != null && widget.canControl ? Colors.white : Colors.white54,
onPressed: widget.canControl ? widget.onPrevious : null,
semanticLabel: t.videoControls.previousButton,
if (!widget.isLive) ...[
// Previous item
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _prevItemFocusNode,
index: 0,
icon: Symbols.skip_previous_rounded,
color: widget.onPrevious != null && widget.canControl ? Colors.white : Colors.white54,
onPressed: widget.canControl ? widget.onPrevious : null,
semanticLabel: t.videoControls.previousButton,
),
),
),
// Previous chapter
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _prevChapterFocusNode,
index: 1,
icon: Symbols.fast_rewind_rounded,
color: widget.chapters.isNotEmpty && widget.canControl ? Colors.white : Colors.white54,
onPressed: widget.canControl && widget.chapters.isNotEmpty ? widget.onSeekToPreviousChapter : null,
semanticLabel: t.videoControls.previousChapterButton,
// Previous chapter
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _prevChapterFocusNode,
index: 1,
icon: Symbols.fast_rewind_rounded,
color: widget.chapters.isNotEmpty && widget.canControl ? Colors.white : Colors.white54,
onPressed: widget.canControl && widget.chapters.isNotEmpty ? widget.onSeekToPreviousChapter : null,
semanticLabel: t.videoControls.previousChapterButton,
),
),
),
// Skip backward
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _skipBackFocusNode,
index: 2,
icon: widget.getReplayIcon(widget.seekTimeSmall),
onPressed: widget.canControl ? widget.onSeekBackward : null,
semanticLabel: t.videoControls.seekBackwardButton(seconds: widget.seekTimeSmall),
// Skip backward
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _skipBackFocusNode,
index: 2,
icon: widget.getReplayIcon(widget.seekTimeSmall),
onPressed: widget.canControl ? widget.onSeekBackward : null,
semanticLabel: t.videoControls.seekBackwardButton(seconds: widget.seekTimeSmall),
),
),
),
],
// Play/Pause
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
@@ -535,41 +537,43 @@ class DesktopVideoControlsState extends State<DesktopVideoControls> {
},
),
),
// Skip forward
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _skipForwardFocusNode,
index: 4,
icon: widget.getForwardIcon(widget.seekTimeSmall),
onPressed: widget.canControl ? widget.onSeekForward : null,
semanticLabel: t.videoControls.seekForwardButton(seconds: widget.seekTimeSmall),
if (!widget.isLive) ...[
// Skip forward
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _skipForwardFocusNode,
index: 4,
icon: widget.getForwardIcon(widget.seekTimeSmall),
onPressed: widget.canControl ? widget.onSeekForward : null,
semanticLabel: t.videoControls.seekForwardButton(seconds: widget.seekTimeSmall),
),
),
),
// Next chapter
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _nextChapterFocusNode,
index: 5,
icon: Symbols.fast_forward_rounded,
color: widget.chapters.isNotEmpty && widget.canControl ? Colors.white : Colors.white54,
onPressed: widget.canControl && widget.chapters.isNotEmpty ? widget.onSeekToNextChapter : null,
semanticLabel: t.videoControls.nextChapterButton,
// Next chapter
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _nextChapterFocusNode,
index: 5,
icon: Symbols.fast_forward_rounded,
color: widget.chapters.isNotEmpty && widget.canControl ? Colors.white : Colors.white54,
onPressed: widget.canControl && widget.chapters.isNotEmpty ? widget.onSeekToNextChapter : null,
semanticLabel: t.videoControls.nextChapterButton,
),
),
),
// Next item
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _nextItemFocusNode,
index: 6,
icon: Symbols.skip_next_rounded,
color: widget.onNext != null && widget.canControl ? Colors.white : Colors.white54,
onPressed: widget.canControl ? widget.onNext : null,
semanticLabel: t.videoControls.nextButton,
// Next item
Opacity(
opacity: widget.canControl ? 1.0 : 0.5,
child: _buildFocusableButton(
focusNode: _nextItemFocusNode,
index: 6,
icon: Symbols.skip_next_rounded,
color: widget.onNext != null && widget.canControl ? Colors.white : Colors.white54,
onPressed: widget.canControl ? widget.onNext : null,
semanticLabel: t.videoControls.nextButton,
),
),
),
],
// Finish time (hidden for live TV and when too narrow to fit)
if (widget.isLive)
const Spacer()
@@ -124,14 +124,16 @@ class MobileVideoControls extends StatelessWidget {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Previous episode button (greyed out when unavailable)
CircularControlButton(
semanticLabel: t.videoControls.previousButton,
icon: Symbols.skip_previous_rounded,
iconSize: 48,
onPressed: onPrevious,
),
const SizedBox(width: 24),
if (!isLive) ...[
// Previous episode button (greyed out when unavailable)
CircularControlButton(
semanticLabel: t.videoControls.previousButton,
icon: Symbols.skip_previous_rounded,
iconSize: 48,
onPressed: onPrevious,
),
const SizedBox(width: 24),
],
CircularControlButton(
semanticLabel: isPlaying ? t.videoControls.pauseButton : t.videoControls.playButton,
icon: isPlaying ? Symbols.pause_rounded : Symbols.play_arrow_rounded,
@@ -146,14 +148,16 @@ class MobileVideoControls extends StatelessWidget {
}
},
),
const SizedBox(width: 24),
// Next episode button (greyed out when unavailable)
CircularControlButton(
semanticLabel: t.videoControls.nextButton,
icon: Symbols.skip_next_rounded,
iconSize: 48,
onPressed: onNext,
),
if (!isLive) ...[
const SizedBox(width: 24),
// Next episode button (greyed out when unavailable)
CircularControlButton(
semanticLabel: t.videoControls.nextButton,
icon: Symbols.skip_next_rounded,
iconSize: 48,
onPressed: onNext,
),
],
],
);
},