getting keybinds going

This commit is contained in:
2026-02-12 17:39:52 -05:00
parent 0bbb327b29
commit 91fcaa9b9e
4 changed files with 177 additions and 90 deletions

View File

@@ -13,7 +13,8 @@ import { useRenderer } from "@opentui/solid";
import type { AuthScreen } from "@/types/auth";
import type { Episode } from "@/types/episode";
import { DIRECTION, LayerGraph, TABS } from "./utils/navigation";
import { useTheme } from "./context/ThemeContext";
import { useTheme, ThemeProvider } from "./context/ThemeContext";
import { KeybindProvider, useKeybinds } from "./context/KeybindContext";
const DEBUG = import.meta.env.DEBUG;
@@ -34,6 +35,7 @@ export function App() {
const toast = useToast();
const renderer = useRenderer();
const { theme } = useTheme();
const keybind = useKeybinds();
useMultimediaKeys({
playerFocused: () => activeTab() === TABS.PLAYER && layerDepth() > 0,
@@ -62,66 +64,116 @@ export function App() {
});
});
// Handle keyboard input with dynamic keybinds
useKeyboard(
(keyEvent) => {
//handle intra layer navigation
if (keyEvent.name == "up" || keyEvent.name) {
const name = keyEvent.name;
// Navigation: up/down
if (keybind.match("up", keyEvent) || keybind.match("down", keyEvent)) {
// TODO: Implement navigation logic
}
// Navigation: left/right
if (keybind.match("left", keyEvent) || keybind.match("right", keyEvent)) {
// TODO: Implement navigation logic
}
// Cycle through options
if (keybind.match("cycle", keyEvent)) {
// TODO: Implement cycle logic
}
// Dive into content
if (keybind.match("dive", keyEvent)) {
// TODO: Implement dive logic
}
// Out of content
if (keybind.match("out", keyEvent)) {
setActiveDepth((prev) => Math.max(0, prev - 1));
return;
}
// Audio controls
if (keybind.match("audio-toggle", keyEvent)) {
audio.togglePlayback();
return;
}
if (keybind.match("audio-next", keyEvent)) {
audio.seekRelative(30); // Skip forward 30 seconds
return;
}
if (keybind.match("audio-prev", keyEvent)) {
audio.seekRelative(-30); // Skip back 30 seconds
return;
}
// Quit application
if (keybind.match("quit", keyEvent)) {
process.exit(0);
}
},
{ release: false }, // Not strictly necessary
{ release: false },
);
return (
<ErrorBoundary
fallback={(err) => (
<box border padding={2} borderColor={theme.error}>
<text fg={theme.error}>
Error: {err?.message ?? String(err)}
{"\n"}
Press a number key (1-6) to switch tabs.
</text>
</box>
)}
>
{DEBUG && (
<box flexDirection="row" width="100%" height={1}>
<text fg={theme.primary}></text>
<text fg={theme.secondary}></text>
<text fg={theme.accent}></text>
<text fg={theme.error}></text>
<text fg={theme.warning}></text>
<text fg={theme.success}></text>
<text fg={theme.info}></text>
<text fg={theme.text}></text>
<text fg={theme.textMuted}></text>
<text fg={theme.surface}></text>
<text fg={theme.background}></text>
<text fg={theme.border}></text>
<text fg={theme.borderActive}></text>
<text fg={theme.diffAdded}></text>
<text fg={theme.diffRemoved}></text>
<text fg={theme.diffContext}></text>
<text fg={theme.markdownText}></text>
<text fg={theme.markdownHeading}></text>
<text fg={theme.markdownLink}></text>
<text fg={theme.markdownCode}></text>
<text fg={theme.syntaxKeyword}></text>
<text fg={theme.syntaxString}></text>
<text fg={theme.syntaxNumber}></text>
<text fg={theme.syntaxFunction}></text>
</box>
)}
<box flexDirection="row" width="100%" height={1} />
<box
flexDirection="row"
width="100%"
height="100%"
backgroundColor={theme.surface}
>
<TabNavigation activeTab={activeTab()} onTabSelect={setActiveTab} />
{LayerGraph[activeTab()]({ depth: activeDepth })}
{/**TODO: Contextual controls based on tab/depth**/}
</box>
</ErrorBoundary>
<KeybindProvider>
<ThemeProvider mode="dark">
<ErrorBoundary
fallback={(err) => (
<box border padding={2} borderColor={theme.error}>
<text fg={theme.error}>
Error: {err?.message ?? String(err)}
{"\n"}
Press a number key (1-6) to switch tabs.
</text>
</box>
)}
>
{DEBUG && (
<box flexDirection="row" width="100%" height={1}>
<text fg={theme.primary}></text>
<text fg={theme.secondary}></text>
<text fg={theme.accent}></text>
<text fg={theme.error}></text>
<text fg={theme.warning}></text>
<text fg={theme.success}></text>
<text fg={theme.info}></text>
<text fg={theme.text}></text>
<text fg={theme.textMuted}></text>
<text fg={theme.surface}></text>
<text fg={theme.background}></text>
<text fg={theme.border}></text>
<text fg={theme.borderActive}></text>
<text fg={theme.diffAdded}></text>
<text fg={theme.diffRemoved}></text>
<text fg={theme.diffContext}></text>
<text fg={theme.markdownText}></text>
<text fg={theme.markdownHeading}></text>
<text fg={theme.markdownLink}></text>
<text fg={theme.markdownCode}></text>
<text fg={theme.syntaxKeyword}></text>
<text fg={theme.syntaxString}></text>
<text fg={theme.syntaxNumber}></text>
<text fg={theme.syntaxFunction}></text>
</box>
)}
<box flexDirection="row" width="100%" height={1} />
<box
flexDirection="row"
width="100%"
height="100%"
backgroundColor={theme.surface}
>
<TabNavigation activeTab={activeTab()} onTabSelect={setActiveTab} />
{LayerGraph[activeTab()]({ depth: activeDepth })}
{/**TODO: Contextual controls based on tab/depth**/}
</box>
</ErrorBoundary>
</ThemeProvider>
</KeybindProvider>
);
}