refactor: seek via keybind router (< / >), free arrows for navigation

This commit is contained in:
2026-08-10 15:50:51 -04:00
parent fd689aba04
commit 30b7ff57d3
7 changed files with 11 additions and 37 deletions

View File

@@ -18,22 +18,21 @@ const DEBUG = import.meta.env.DEBUG;
export function App() { export function App() {
const nav = useNavigation(); const nav = useNavigation();
const audio = useAudio();
const toast = useToast(); const toast = useToast();
const renderer = useRenderer(); const renderer = useRenderer();
const themeContext = useTheme(); const themeContext = useTheme();
const theme = themeContext.theme; const theme = themeContext.theme;
const keybind = useKeybinds(); const keybind = useKeybinds();
// Multimedia keys (physical play/seek keys) still feed the audio backend // Multimedia keys (physical play/volume/speed keys) still feed the audio
// regardless of the on-screen yazi keybinds. // backend regardless of the on-screen yazi keybinds. Seek lives on the
// keybind router (< / > = shift+, / shift+.), so arrows stay on navigation.
useMultimediaKeys({ useMultimediaKeys({
playerFocused: () => playerFocused: () =>
nav.activeTab() === TABS.PLAYER && nav.mode() !== NavMode.NORMAL nav.activeTab() === TABS.PLAYER && nav.mode() !== NavMode.NORMAL
? true ? true
: false, : false,
inputFocused: () => nav.inputFocused(), inputFocused: () => nav.inputFocused(),
hasEpisode: () => !!audio.currentEpisode(),
}); });
// Mouse text-selection → clipboard (unchanged from the old shell). // Mouse text-selection → clipboard (unchanged from the old shell).

View File

@@ -72,6 +72,6 @@
"audio-toggle": ["P"], // play / pause (shift+p) "audio-toggle": ["P"], // play / pause (shift+p)
"audio-next": ["N"], // next episode (shift+n) "audio-next": ["N"], // next episode (shift+n)
"audio-prev": ["B"], // prev episode (shift+b) "audio-prev": ["B"], // prev episode (shift+b)
"audio-seek-forward": ["shift-."], // seek forward (shift+.) "audio-seek-forward": ["shift-."], // seek forward (> = shift+.)
"audio-seek-backward": ["shift-,"] // seek backward (shift+,) "audio-seek-backward": ["shift-,"] // seek backward (< = shift+,)
} }

View File

@@ -421,14 +421,6 @@ export function useAudio(): AudioControls {
await doSetVolume(Math.max(0, Number((volume() - 0.05).toFixed(2)))); await doSetVolume(Math.max(0, Number((volume() - 0.05).toFixed(2))));
}); });
const unsubMediaSeekFwd = on("media.seekForward", async () => {
await seekRelative(10);
});
const unsubMediaSeekBack = on("media.seekBackward", async () => {
await seekRelative(-10);
});
const unsubMediaSpeed = on("media.speedCycle", async () => { const unsubMediaSpeed = on("media.speedCycle", async () => {
const next = speed() >= 2 ? 0.5 : Number((speed() + 0.25).toFixed(2)); const next = speed() >= 2 ? 0.5 : Number((speed() + 0.25).toFixed(2));
await doSetSpeed(next); await doSetSpeed(next);
@@ -515,8 +507,6 @@ export function useAudio(): AudioControls {
unsubMediaToggle(); unsubMediaToggle();
unsubMediaVolUp(); unsubMediaVolUp();
unsubMediaVolDown(); unsubMediaVolDown();
unsubMediaSeekFwd();
unsubMediaSeekBack();
unsubMediaSpeed(); unsubMediaSpeed();
if (refCount <= 0) { if (refCount <= 0) {

View File

@@ -1,13 +1,14 @@
/** /**
* Global multimedia key handler hook. * Global multimedia key handler hook.
* *
* Captures media-related key events (play/pause, volume, seek, speed) * Captures media-related key events (play/pause, volume, speed)
* regardless of which component is focused. Uses the event bus to * regardless of which component is focused. Uses the event bus to
* decouple key detection from audio control logic. * decouple key detection from audio control logic.
* *
* Volume and speed are app-level settings — adjustable with or without * Volume and speed are app-level settings — adjustable with or without
* an episode loaded (they apply to the next playback and persist). Seek * an episode loaded (they apply to the next playback and persist). Seek
* is playback-dependent, so it still requires a loaded episode. * is NOT handled here: it lives on the yazi keybind router (`<` / `>` =
* shift+, / shift+.), so the arrow keys stay free for navigation.
*/ */
import { useKeyboard } from "@opentui/solid"; import { useKeyboard } from "@opentui/solid";
@@ -17,8 +18,6 @@ export type MediaKeyAction =
| "media.toggle" | "media.toggle"
| "media.volumeUp" | "media.volumeUp"
| "media.volumeDown" | "media.volumeDown"
| "media.seekForward"
| "media.seekBackward"
| "media.speedCycle"; | "media.speedCycle";
export interface MultimediaKeysOptions { export interface MultimediaKeysOptions {
@@ -26,8 +25,6 @@ export interface MultimediaKeysOptions {
playerFocused?: () => boolean; playerFocused?: () => boolean;
/** When true, skip handling (text input has focus) */ /** When true, skip handling (text input has focus) */
inputFocused?: () => boolean; inputFocused?: () => boolean;
/** Whether an episode is currently loaded */
hasEpisode?: () => boolean;
} }
/** /**
@@ -59,16 +56,6 @@ export function useMultimediaKeys(options: MultimediaKeysOptions = {}) {
emit("media.volumeDown", {}); emit("media.volumeDown", {});
break; break;
case "left":
if (!options.hasEpisode?.()) return;
emit("media.seekBackward", {});
break;
case "right":
if (!options.hasEpisode?.()) return;
emit("media.seekForward", {});
break;
case "s": case "s":
emit("media.speedCycle", {}); emit("media.speedCycle", {});
break; break;

View File

@@ -110,7 +110,7 @@ export function PlayerPage() {
<box height={1} /> <box height={1} />
<text fg={muted()}> <text fg={muted()}>
{"P play/pause N next B prev ◀▶ seek h back"} {"P play/pause N next B prev < > seek h back"}
</text> </text>
</box> </box>
); );

View File

@@ -132,8 +132,6 @@ export type AppEvents = {
"media.toggle": {}; "media.toggle": {};
"media.volumeUp": {}; "media.volumeUp": {};
"media.volumeDown": {}; "media.volumeDown": {};
"media.seekForward": {};
"media.seekBackward": {};
"media.speedCycle": {}; "media.speedCycle": {};
}; };

View File

@@ -69,8 +69,8 @@ const DEFAULT_KEYBINDS: KeybindsResolved = {
"audio-toggle": ["P"], "audio-toggle": ["P"],
"audio-next": ["N"], "audio-next": ["N"],
"audio-prev": ["B"], "audio-prev": ["B"],
"audio-seek-forward": ["shift-."], "audio-seek-forward": ["shift-."], // > = shift+.
"audio-seek-backward": ["shift-,"], "audio-seek-backward": ["shift-,"], // < = shift+,
}; };
/** Copy keybinds.jsonc to user config directory on first run */ /** Copy keybinds.jsonc to user config directory on first run */