mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-08-18 13:26:09 +00:00
feat: add keyboard controls for playback and seeking actions
This commit is contained in:
parent
9381693482
commit
d7545b6924
5 changed files with 65 additions and 17 deletions
|
|
@ -28,8 +28,11 @@ enum class PlayerControlsAction {
|
|||
RevealLockedOverlay,
|
||||
Back,
|
||||
TogglePlayback,
|
||||
KeyboardTogglePlayback,
|
||||
SeekBack,
|
||||
KeyboardSeekBack,
|
||||
SeekForward,
|
||||
KeyboardSeekForward,
|
||||
ResizeMode,
|
||||
Speed,
|
||||
Subtitles,
|
||||
|
|
|
|||
|
|
@ -162,9 +162,11 @@ internal fun PlayerScreenRuntime.togglePlayback() {
|
|||
controlsVisible = true
|
||||
}
|
||||
|
||||
internal fun PlayerScreenRuntime.prepareTogglePlaybackForNativeFallback() {
|
||||
internal fun PlayerScreenRuntime.prepareTogglePlaybackForNativeFallback(revealControls: Boolean = true) {
|
||||
shouldPlay = !playbackSnapshot.isPlaying
|
||||
controlsVisible = true
|
||||
if (revealControls) {
|
||||
controlsVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
internal fun PlayerScreenRuntime.seekBy(offsetMs: Long) {
|
||||
|
|
@ -172,13 +174,21 @@ internal fun PlayerScreenRuntime.seekBy(offsetMs: Long) {
|
|||
applySeekByControlFeedback(offsetMs)
|
||||
}
|
||||
|
||||
internal fun PlayerScreenRuntime.prepareSeekByForNativeFallback(offsetMs: Long) {
|
||||
applySeekByControlFeedback(offsetMs)
|
||||
internal fun PlayerScreenRuntime.prepareSeekByForNativeFallback(
|
||||
offsetMs: Long,
|
||||
revealControls: Boolean = true,
|
||||
) {
|
||||
applySeekByControlFeedback(offsetMs, revealControls)
|
||||
}
|
||||
|
||||
private fun PlayerScreenRuntime.applySeekByControlFeedback(offsetMs: Long) {
|
||||
private fun PlayerScreenRuntime.applySeekByControlFeedback(
|
||||
offsetMs: Long,
|
||||
revealControls: Boolean = true,
|
||||
) {
|
||||
scheduleProgressSyncAfterSeek()
|
||||
controlsVisible = true
|
||||
if (revealControls) {
|
||||
controlsVisible = true
|
||||
}
|
||||
when {
|
||||
offsetMs > 0L -> showSeekFeedback(PlayerSeekDirection.Forward, offsetMs)
|
||||
offsetMs < 0L -> showSeekFeedback(PlayerSeekDirection.Backward, abs(offsetMs))
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ internal fun PlayerScreenRuntime.RenderPlayerRuntimeUi() {
|
|||
isLoading = playbackSnapshot.isLoading,
|
||||
isLocked = playerControlsLocked,
|
||||
lockedOverlayVisible = lockedOverlayVisible,
|
||||
controlsVisible = (controlsVisible || showParentalGuide) && !playerControlsLocked,
|
||||
controlsVisible = controlsVisible && !playerControlsLocked,
|
||||
parentalWarnings = parentalWarnings,
|
||||
showParentalGuide = showParentalGuide,
|
||||
showSubmitIntro = isSeries &&
|
||||
|
|
@ -508,14 +508,26 @@ private fun PlayerScreenRuntime.handlePlayerControlsAction(action: PlayerControl
|
|||
prepareTogglePlaybackForNativeFallback()
|
||||
return false
|
||||
}
|
||||
PlayerControlsAction.KeyboardTogglePlayback -> {
|
||||
prepareTogglePlaybackForNativeFallback(revealControls = false)
|
||||
return false
|
||||
}
|
||||
PlayerControlsAction.SeekBack -> {
|
||||
prepareSeekByForNativeFallback(-10_000L)
|
||||
return false
|
||||
}
|
||||
PlayerControlsAction.KeyboardSeekBack -> {
|
||||
prepareSeekByForNativeFallback(-10_000L, revealControls = false)
|
||||
return false
|
||||
}
|
||||
PlayerControlsAction.SeekForward -> {
|
||||
prepareSeekByForNativeFallback(10_000L)
|
||||
return false
|
||||
}
|
||||
PlayerControlsAction.KeyboardSeekForward -> {
|
||||
prepareSeekByForNativeFallback(10_000L, revealControls = false)
|
||||
return false
|
||||
}
|
||||
PlayerControlsAction.ResizeMode -> cycleResizeMode()
|
||||
PlayerControlsAction.Speed -> cyclePlaybackSpeed()
|
||||
PlayerControlsAction.Subtitles -> {
|
||||
|
|
|
|||
|
|
@ -164,7 +164,8 @@ internal class NativePlayerController(
|
|||
|
||||
private fun handleFallbackAction(action: PlayerControlsAction) {
|
||||
when (action) {
|
||||
PlayerControlsAction.TogglePlayback -> {
|
||||
PlayerControlsAction.TogglePlayback,
|
||||
PlayerControlsAction.KeyboardTogglePlayback -> {
|
||||
val current = handle
|
||||
if (current == 0L) return
|
||||
val isEnded = NativePlayerBridge.isEnded(current)
|
||||
|
|
@ -176,8 +177,10 @@ internal class NativePlayerController(
|
|||
NativePlayerBridge.setPaused(current, !isPaused)
|
||||
}
|
||||
}
|
||||
PlayerControlsAction.SeekBack -> fallbackSeekBy(-10_000L)
|
||||
PlayerControlsAction.SeekForward -> fallbackSeekBy(10_000L)
|
||||
PlayerControlsAction.SeekBack,
|
||||
PlayerControlsAction.KeyboardSeekBack -> fallbackSeekBy(-10_000L)
|
||||
PlayerControlsAction.SeekForward,
|
||||
PlayerControlsAction.KeyboardSeekForward -> fallbackSeekBy(10_000L)
|
||||
PlayerControlsAction.DoubleTapSeekBack -> fallbackSeekBy(-10_000L)
|
||||
PlayerControlsAction.DoubleTapSeekForward -> fallbackSeekBy(10_000L)
|
||||
PlayerControlsAction.Speed -> cycleFallbackSpeed()
|
||||
|
|
@ -432,8 +435,11 @@ private fun String.toPlayerControlsAction(): PlayerControlsAction? =
|
|||
"revealLockedOverlay" -> PlayerControlsAction.RevealLockedOverlay
|
||||
"back" -> PlayerControlsAction.Back
|
||||
"toggle" -> PlayerControlsAction.TogglePlayback
|
||||
"keyboardToggle" -> PlayerControlsAction.KeyboardTogglePlayback
|
||||
"seekBack" -> PlayerControlsAction.SeekBack
|
||||
"keyboardSeekBack" -> PlayerControlsAction.KeyboardSeekBack
|
||||
"seekForward" -> PlayerControlsAction.SeekForward
|
||||
"keyboardSeekForward" -> PlayerControlsAction.KeyboardSeekForward
|
||||
"resize" -> PlayerControlsAction.ResizeMode
|
||||
"speed" -> PlayerControlsAction.Speed
|
||||
"subtitles" -> PlayerControlsAction.Subtitles
|
||||
|
|
|
|||
|
|
@ -166,7 +166,6 @@
|
|||
.player.chrome-hidden .top-gradient,
|
||||
.player.chrome-hidden .bottom-gradient,
|
||||
.player.chrome-hidden .metadata,
|
||||
.player.chrome-hidden .parental-guide,
|
||||
.player.chrome-hidden .header-actions,
|
||||
.player.chrome-hidden .center-controls,
|
||||
.player.chrome-hidden .progress,
|
||||
|
|
@ -226,7 +225,7 @@
|
|||
|
||||
.header {
|
||||
position: absolute;
|
||||
top: calc(var(--vp) / 4 + env(safe-area-inset-top));
|
||||
top: calc(var(--slider-bottom) + env(safe-area-inset-top));
|
||||
left: var(--hp);
|
||||
right: var(--hp);
|
||||
display: flex;
|
||||
|
|
@ -310,7 +309,7 @@
|
|||
|
||||
.parental-guide {
|
||||
position: absolute;
|
||||
top: calc(var(--vp) / 4 + env(safe-area-inset-top));
|
||||
top: calc(var(--slider-bottom) + env(safe-area-inset-top));
|
||||
left: var(--hp);
|
||||
z-index: 5;
|
||||
display: flex;
|
||||
|
|
@ -3090,18 +3089,28 @@
|
|||
switch (event.code) {
|
||||
case "Space":
|
||||
case "KeyK":
|
||||
return "toggle";
|
||||
return "keyboardToggle";
|
||||
case "ArrowLeft":
|
||||
case "KeyJ":
|
||||
return "seekBack";
|
||||
return "keyboardSeekBack";
|
||||
case "ArrowRight":
|
||||
case "KeyL":
|
||||
return "seekForward";
|
||||
return "keyboardSeekForward";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const toggleChrome = () => {
|
||||
if (state.isLocked) {
|
||||
send("revealLockedOverlay", 0);
|
||||
return;
|
||||
}
|
||||
state = { ...state, controlsVisible: !state.controlsVisible };
|
||||
renderChrome();
|
||||
send("toggleChrome", 0);
|
||||
};
|
||||
|
||||
const clearPressedButton = () => {
|
||||
if (!pressedButton) return;
|
||||
pressedButton.classList.remove("is-pressed");
|
||||
|
|
@ -3158,6 +3167,9 @@
|
|||
|
||||
openingOverlay.addEventListener("click", event => {
|
||||
event.stopPropagation();
|
||||
if (!event.target.closest("button,input")) {
|
||||
toggleChrome();
|
||||
}
|
||||
});
|
||||
|
||||
modalElements.forEach(modal => {
|
||||
|
|
@ -3420,7 +3432,7 @@
|
|||
if (event.target.closest("button,input")) return;
|
||||
window.clearTimeout(tapTimer);
|
||||
tapTimer = window.setTimeout(() => {
|
||||
send(state.isLocked ? "revealLockedOverlay" : "toggleChrome");
|
||||
toggleChrome();
|
||||
}, 220);
|
||||
});
|
||||
|
||||
|
|
@ -3439,6 +3451,11 @@
|
|||
focusShortcutRoot();
|
||||
return;
|
||||
}
|
||||
if (event.key === "Escape") {
|
||||
event.preventDefault();
|
||||
send("back", 0);
|
||||
return;
|
||||
}
|
||||
if (activeModal || isTextEntryTarget(event.target)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue