fix: live tv dvr seek via keyboard/remote

close #789
This commit is contained in:
edde746
2026-04-19 13:13:38 +02:00
parent fd1d187ede
commit f53592f32b
3 changed files with 35 additions and 16 deletions
+12 -8
View File
@@ -1877,19 +1877,23 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen> with WidgetsBindin
receiver.onSeekForward = () async {
if (player == null) return;
final settings = await SettingsService.getInstance();
final target = clampSeekPosition(
player!,
player!.state.position + Duration(seconds: settings.getSeekTimeSmall()),
);
final seekSeconds = settings.getSeekTimeSmall();
if (widget.isLive && _captureBuffer != null) {
await _seekLivePosition(_currentPositionEpoch + seekSeconds);
return;
}
final target = clampSeekPosition(player!, player!.state.position + Duration(seconds: seekSeconds));
await player!.seek(target);
};
receiver.onSeekBackward = () async {
if (player == null) return;
final settings = await SettingsService.getInstance();
final target = clampSeekPosition(
player!,
player!.state.position - Duration(seconds: settings.getSeekTimeSmall()),
);
final seekSeconds = settings.getSeekTimeSmall();
if (widget.isLive && _captureBuffer != null) {
await _seekLivePosition(_currentPositionEpoch - seekSeconds);
return;
}
final target = clampSeekPosition(player!, player!.state.position - Duration(seconds: seekSeconds));
await player!.seek(target);
};
receiver.onVolumeUp = () async {
+19 -8
View File
@@ -139,6 +139,8 @@ class KeyboardShortcutsService {
VoidCallback? onBack,
VoidCallback? onToggleShader,
VoidCallback? onSkipMarker,
int? currentPositionEpoch,
ValueChanged<int>? onLiveSeek,
}) {
if (event is! KeyDownEvent) return KeyEventResult.ignored;
@@ -216,6 +218,8 @@ class KeyboardShortcutsService {
onPreviousChapter,
onToggleShader: onToggleShader,
onSkipMarker: onSkipMarker,
currentPositionEpoch: currentPositionEpoch,
onLiveSeek: onLiveSeek,
);
return KeyEventResult.handled;
}
@@ -235,7 +239,18 @@ class KeyboardShortcutsService {
VoidCallback? onPreviousChapter, {
VoidCallback? onToggleShader,
VoidCallback? onSkipMarker,
int? currentPositionEpoch,
ValueChanged<int>? onLiveSeek,
}) {
void performSeek(int offsetSeconds) {
if (onLiveSeek != null && currentPositionEpoch != null) {
onLiveSeek(currentPositionEpoch + offsetSeconds);
} else {
final target = clampSeekPosition(player, player.state.position + Duration(seconds: offsetSeconds));
unawaited(player.seek(target));
}
}
switch (action) {
case 'play_pause':
player.playOrPause();
@@ -251,20 +266,16 @@ class KeyboardShortcutsService {
_settingsService.setVolume(newVolume);
break;
case 'seek_forward':
final fwdTarget = clampSeekPosition(player, player.state.position + Duration(seconds: _seekTimeSmall));
unawaited(player.seek(fwdTarget));
performSeek(_seekTimeSmall);
break;
case 'seek_backward':
final bwdTarget = clampSeekPosition(player, player.state.position - Duration(seconds: _seekTimeSmall));
unawaited(player.seek(bwdTarget));
performSeek(-_seekTimeSmall);
break;
case 'seek_forward_large':
final fwdLTarget = clampSeekPosition(player, player.state.position + Duration(seconds: _seekTimeLarge));
unawaited(player.seek(fwdLTarget));
performSeek(_seekTimeLarge);
break;
case 'seek_backward_large':
final bwdLTarget = clampSeekPosition(player, player.state.position - Duration(seconds: _seekTimeLarge));
unawaited(player.seek(bwdLTarget));
performSeek(-_seekTimeLarge);
break;
case 'fullscreen_toggle':
onToggleFullscreen?.call();
@@ -1721,6 +1721,8 @@ class _PlexVideoControlsState extends State<PlexVideoControls> with WindowListen
_previousChapter,
onBack: widget.onBack ?? () => Navigator.of(context).pop(true),
onToggleShader: _toggleShader,
currentPositionEpoch: widget.currentPositionEpoch,
onLiveSeek: widget.onLiveSeek,
);
if (result == KeyEventResult.handled) {
_focusNode.requestFocus(); // self-heal focus
@@ -1951,6 +1953,8 @@ class _PlexVideoControlsState extends State<PlexVideoControls> with WindowListen
onBack: widget.onBack ?? () => Navigator.of(context).pop(true),
onToggleShader: _toggleShader,
onSkipMarker: _performAutoSkip,
currentPositionEpoch: widget.currentPositionEpoch,
onLiveSeek: widget.onLiveSeek,
);
// Let non-navigation keys (volume, etc.) pass through to the OS
if (!event.logicalKey.isNavigationKey) return KeyEventResult.ignored;