more keyboard handling

This commit is contained in:
2026-02-21 00:46:36 -05:00
parent b45e7bf538
commit c9a370a424
8 changed files with 30 additions and 32 deletions

View File

@@ -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": [],

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -27,6 +27,7 @@ const DEFAULT_KEYBINDS: KeybindsResolved = {
right: ["right", "l"],
cycle: ["tab"],
dive: ["return"],
select: ["return"],
out: ["esc"],
inverseModifier: "shift",
leader: ":",