diff --git a/src/context/KeybindContext.tsx b/src/context/KeybindContext.tsx index 5f2c781..f396a36 100644 --- a/src/context/KeybindContext.tsx +++ b/src/context/KeybindContext.tsx @@ -18,8 +18,9 @@ export type KeybindsResolved = { inverseModifier: string; leader: string; // will not trigger while focused on input quit: string[]; + select: string[]; // for selecting/activating items "audio-toggle": string[]; - "audio-pause": []; + "audio-pause": string[]; "audio-play": string[]; "audio-next": string[]; "audio-prev": string[]; @@ -36,6 +37,7 @@ export enum KeybindAction { DIVE, OUT, QUIT, + SELECT, AUDIO_TOGGLE, AUDIO_PAUSE, AUDIO_PLAY, @@ -60,6 +62,7 @@ export const { use: useKeybinds, provider: KeybindProvider } = inverseModifier: "", leader: "", quit: [], + select: [], refresh: [], "audio-toggle": [], "audio-pause": [], diff --git a/src/pages/Discover/DiscoverPage.tsx b/src/pages/Discover/DiscoverPage.tsx index ed2f227..e6cb860 100644 --- a/src/pages/Discover/DiscoverPage.tsx +++ b/src/pages/Discover/DiscoverPage.tsx @@ -29,10 +29,9 @@ export function DiscoverPage() { (keyEvent: any) => { const isDown = keybind.match("down", keyEvent); const isUp = keybind.match("up", keyEvent); - const isEnter = keyEvent.name === "Enter" || keyEvent.name === " "; - const isSpace = keyEvent.name === " "; + const isSelect = keybind.match("select", keyEvent); - if (isEnter || isSpace) { + if (isSelect) { const filteredPodcasts = discoverStore.filteredPodcasts(); if (filteredPodcasts.length > 0 && showIndex() < filteredPodcasts.length) { setShowIndex(showIndex() + 1); diff --git a/src/pages/Feed/FeedPage.tsx b/src/pages/Feed/FeedPage.tsx index e9a7976..91455e7 100644 --- a/src/pages/Feed/FeedPage.tsx +++ b/src/pages/Feed/FeedPage.tsx @@ -39,10 +39,9 @@ export function FeedPage() { (keyEvent: any) => { const isDown = keybind.match("down", keyEvent); const isUp = keybind.match("up", keyEvent); - const isEnter = keyEvent.name === "Enter" || keyEvent.name === " "; - const isSpace = keyEvent.name === " "; + const isSelect = keybind.match("select", keyEvent); - if (isEnter || isSpace) { + if (isSelect) { const episodes = allEpisodes(); if (episodes.length > 0 && episodes[focusedIndex()]) { setSelectedEpisodeID(episodes[focusedIndex()].episode.id); diff --git a/src/pages/MyShows/MyShowsPage.tsx b/src/pages/MyShows/MyShowsPage.tsx index dd90a45..cc2bb14 100644 --- a/src/pages/MyShows/MyShowsPage.tsx +++ b/src/pages/MyShows/MyShowsPage.tsx @@ -14,6 +14,7 @@ import { useTheme } from "@/context/ThemeContext"; import { useAudioNavStore, AudioSource } from "@/stores/audio-nav"; import { useNavigation } from "@/context/NavigationContext"; import { LoadingIndicator } from "@/components/LoadingIndicator"; +import { KeybindProvider, useKeybinds } from "@/context/KeybindContext"; enum MyShowsPaneType { SHOWS = 1, @@ -32,16 +33,14 @@ export function MyShowsPage() { const { theme } = useTheme(); const mutedColor = () => theme.muted || theme.text; const nav = useNavigation(); + const keybind = useKeybinds(); onMount(() => { useKeyboard( (keyEvent: any) => { - const isDown = - keyEvent.key === "j" || keyEvent.key === "ArrowDown"; - const isUp = - keyEvent.key === "k" || keyEvent.key === "ArrowUp"; - const isSelect = - keyEvent.key === "Enter" || keyEvent.key === " "; + const isDown = keybind.match("down", keyEvent); + const isUp = keybind.match("up", keyEvent); + const isSelect = keybind.match("select", keyEvent); const shows = feedStore.getFilteredFeeds(); const episodesList = episodes(); diff --git a/src/pages/Player/PlayerPage.tsx b/src/pages/Player/PlayerPage.tsx index 2f43b6c..131cbf5 100644 --- a/src/pages/Player/PlayerPage.tsx +++ b/src/pages/Player/PlayerPage.tsx @@ -4,6 +4,7 @@ import { useAudio } from "@/hooks/useAudio"; import { useAppStore } from "@/stores/app"; import { useTheme } from "@/context/ThemeContext"; import { useNavigation } from "@/context/NavigationContext"; +import { useKeybinds } from "@/context/KeybindContext"; import { useKeyboard } from "@opentui/solid"; import { onMount } from "solid-js"; @@ -17,24 +18,22 @@ export function PlayerPage() { const { theme } = useTheme(); const nav = useNavigation(); + const keybind = useKeybinds(); + onMount(() => { useKeyboard( (keyEvent: any) => { - const isNext = keyEvent.key === "l" || keyEvent.key === "ArrowRight"; - const isPrev = keyEvent.key === "h" || keyEvent.key === "ArrowLeft"; - const isPlayPause = keyEvent.key === " " || keyEvent.key === "Enter"; - - if (isPlayPause) { + if (keybind.match("audio-toggle", keyEvent)) { audio.togglePlayback(); return; } - if (isNext) { + if (keybind.match("audio-seek-forward", keyEvent)) { audio.seek(audio.currentEpisode()?.duration ?? 0); return; } - if (isPrev) { + if (keybind.match("audio-seek-backward", keyEvent)) { audio.seek(0); return; } diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 764ad79..ba615d3 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -11,6 +11,7 @@ import type { SearchResult } from "@/types/source"; import { MyShowsPage } from "../MyShows/MyShowsPage"; import { useTheme } from "@/context/ThemeContext"; import { useNavigation } from "@/context/NavigationContext"; +import { KeybindProvider, useKeybinds } from "@/context/KeybindContext"; enum SearchPaneType { INPUT = 1, @@ -26,16 +27,14 @@ export function SearchPage() { const [historyIndex, setHistoryIndex] = createSignal(0); const { theme } = useTheme(); const nav = useNavigation(); + const keybind = useKeybinds(); onMount(() => { useKeyboard( (keyEvent: any) => { - const isDown = - keyEvent.key === "j" || keyEvent.key === "ArrowDown"; - const isUp = - keyEvent.key === "k" || keyEvent.key === "ArrowUp"; - const isSelect = - keyEvent.key === "Enter" || keyEvent.key === " "; + const isDown = keybind.match("down", keyEvent); + const isUp = keybind.match("up", keyEvent); + const isSelect = keybind.match("select", keyEvent); if (isSelect) { const results = searchStore.results(); diff --git a/src/pages/Settings/SettingsPage.tsx b/src/pages/Settings/SettingsPage.tsx index 82eb6a1..e7cbfa0 100644 --- a/src/pages/Settings/SettingsPage.tsx +++ b/src/pages/Settings/SettingsPage.tsx @@ -6,6 +6,7 @@ import { PreferencesPanel } from "./PreferencesPanel"; import { SyncPanel } from "./SyncPanel"; import { VisualizerSettings } from "./VisualizerSettings"; import { useNavigation } from "@/context/NavigationContext"; +import { KeybindProvider, useKeybinds } from "@/context/KeybindContext"; enum SettingsPaneType { SYNC = 1, @@ -27,6 +28,7 @@ const SECTIONS: Array<{ id: SettingsPaneType; label: string }> = [ export function SettingsPage() { const { theme } = useTheme(); const nav = useNavigation(); + const keybind = useKeybinds(); // Helper function to check if a depth is active const isActive = (depth: SettingsPaneType): boolean => { @@ -36,12 +38,9 @@ export function SettingsPage() { onMount(() => { useKeyboard( (keyEvent: any) => { - const isDown = - keyEvent.key === "j" || keyEvent.key === "ArrowDown"; - const isUp = - keyEvent.key === "k" || keyEvent.key === "ArrowUp"; - const isSelect = - keyEvent.key === "Enter" || keyEvent.key === " "; + const isDown = keybind.match("down", keyEvent); + const isUp = keybind.match("up", keyEvent); + const isSelect = keybind.match("select", keyEvent); if (isSelect) { nav.setActiveDepth((nav.activeDepth() % SettingsPaneCount) + 1); diff --git a/src/utils/keybinds-persistence.ts b/src/utils/keybinds-persistence.ts index f30f2f2..880cdf1 100644 --- a/src/utils/keybinds-persistence.ts +++ b/src/utils/keybinds-persistence.ts @@ -27,6 +27,7 @@ const DEFAULT_KEYBINDS: KeybindsResolved = { right: ["right", "l"], cycle: ["tab"], dive: ["return"], + select: ["return"], out: ["esc"], inverseModifier: "shift", leader: ":",