janitorial work

This commit is contained in:
2026-02-07 15:12:34 -05:00
parent 7eb49ac1c7
commit 73aa211229
17 changed files with 38 additions and 76 deletions

View File

@@ -1,7 +1,7 @@
import { createSignal, createMemo, ErrorBoundary } from "solid-js";
import { useSelectionHandler } from "@opentui/solid";
import { Layout } from "./Layout";
import { TabNavigation } from "./components/TabNavigation";
import { TabId, TabNavigation } from "./components/TabNavigation";
import { FeedPage } from "@/tabs/Feed/FeedPage";
import { MyShowsPage } from "@/tabs/MyShows/MyShowsPage";
import { LoginScreen } from "@/tabs/Settings/LoginScreen";
@@ -21,7 +21,6 @@ import { useAppKeyboard } from "@/hooks/useAppKeyboard";
import { Clipboard } from "@/utils/clipboard";
import { useToast } from "@/ui/toast";
import { useRenderer } from "@opentui/solid";
import type { TabId } from "@/components/Tab";
import type { AuthScreen } from "@/types/auth";
import type { Episode } from "@/types/episode";

View File

@@ -47,26 +47,13 @@ export function Layout(props: LayoutProps) {
return (
<box
flexDirection="column"
flexDirection="row"
width="100%"
height="100%"
backgroundColor={theme.surface}
>
{/* Header - tab bar */}
<Show when={props.header}>
<box
style={{
height: 3,
backgroundColor: theme.surface ?? theme.backgroundPanel,
}}
>
<box style={{ paddingLeft: 1, paddingTop: 0, paddingBottom: 0 }}>
{props.header}
</box>
</box>
</Show>
{/* Main content: side-by-side panels */}
<box flexDirection="row" style={{ flexGrow: 1 }}>
<For each={props.panels}>
{(panel, index) => (

View File

@@ -72,7 +72,7 @@ export function CodeValidation(props: CodeValidationProps) {
? (currentIndex - 1 + fields.length) % fields.length
: (currentIndex + 1) % fields.length;
setFocusField(fields[nextIndex]);
} else if (key.name === "return" || key.name === "enter") {
} else if (key.name === "return" || key.name === "tab") {
if (focusField() === "submit") {
handleSubmit();
} else if (focusField() === "back" && props.onBack) {

View File

@@ -18,7 +18,14 @@ export const tabs: TabDefinition[] = [
export function TabNavigation(props: TabNavigationProps) {
const { theme } = useTheme();
return (
<box style={{ flexDirection: "column", gap: 1, width: 20 }}>
<box
backgroundColor={theme.surface}
style={{
flexDirection: "column",
width: 10,
flexGrow: 1,
}}
>
<For each={tabs}>
{(tab) => (
<box
@@ -26,16 +33,17 @@ export function TabNavigation(props: TabNavigationProps) {
borderColor={theme.border}
onMouseDown={() => props.onTabSelect(tab.id)}
style={{
padding: 1,
paddingLeft: 2,
backgroundColor:
tab.id == props.activeTab ? theme.primary : "transparent",
}}
>
<text style={{ fg: theme.text }}>
{tab.id == props.activeTab ? "[" : " "}
<text
style={{
fg: tab.id == props.activeTab ? "white" : theme.text,
alignSelf: "center",
}}
>
{tab.label}
{tab.id == props.activeTab ? "]" : " "}
</text>
</box>
)}

View File

@@ -4,11 +4,18 @@
*/
import { useKeyboard, useRenderer } from "@opentui/solid"
import type { TabId } from "../components/Tab"
import type { Accessor } from "solid-js"
const TAB_ORDER: TabId[] = ["feed", "shows", "discover", "search", "player", "settings"]
type TabId =
| "feed"
| "shows"
| "discover"
| "search"
| "player"
| "settings"
type ShortcutOptions = {
activeTab: TabId
onTabChange: (tab: TabId) => void
@@ -53,8 +60,9 @@ export function useAppKeyboard(options: ShortcutOptions) {
return
}
// Return key cycles tabs (equivalent to Tab)
if (key.name === "return") {
options.onAction?.("enter")
options.onTabChange(getNextTab(options.activeTab))
return
}

View File

@@ -1,37 +0,0 @@
import { useKeyboard, useRenderer } from "@opentui/solid"
type ShortcutOptions = {
onSave?: () => void
onQuit?: () => void
onTabNext?: () => void
onTabPrev?: () => void
}
export function useKeyboardShortcuts(options: ShortcutOptions) {
const renderer = useRenderer()
useKeyboard((key) => {
if (key.ctrl && key.name === "q") {
if (options.onQuit) {
options.onQuit()
} else {
renderer.destroy()
}
return
}
if (key.ctrl && key.name === "s") {
options.onSave?.()
return
}
if (key.name === "right") {
options.onTabNext?.()
return
}
if (key.name === "left") {
options.onTabPrev?.()
}
})
}

View File

@@ -38,7 +38,7 @@ export function DiscoverPage(props: DiscoverPageProps) {
}
if (
(key.name === "return" || key.name === "enter") &&
key.name === "return" &&
area === "categories"
) {
setFocusArea("shows");

View File

@@ -57,7 +57,7 @@ export function FeedDetail(props: FeedDetailProps) {
setSelectedIndex((i) => Math.max(0, i - 1));
} else if (key.name === "down" || key.name === "j") {
setSelectedIndex((i) => Math.min(eps.length - 1, i + 1));
} else if (key.name === "return" || key.name === "enter") {
} else if (key.name === "return") {
const episode = eps[selectedIndex()];
if (episode && props.onPlayEpisode) {
props.onPlayEpisode(episode);

View File

@@ -30,7 +30,7 @@ export function FeedFilterComponent(props: FeedFilterProps) {
? (currentIndex - 1 + fields.length) % fields.length
: (currentIndex + 1) % fields.length;
setFocusField(fields[nextIndex]);
} else if (key.name === "return" || key.name === "enter") {
} else if (key.name === "return") {
if (focusField() === "visibility") {
cycleVisibility();
} else if (focusField() === "sort") {

View File

@@ -37,7 +37,7 @@ export function FeedList(props: FeedListProps) {
setSelectedIndex((i) => Math.max(0, i - 1));
} else if (key.name === "down" || key.name === "j") {
setSelectedIndex((i) => Math.min(feeds.length - 1, i + 1));
} else if (key.name === "return" || key.name === "enter") {
} else if (key.name === "return") {
const feed = feeds[selectedIndex()];
if (feed && props.onOpenFeed) {
props.onOpenFeed(feed);

View File

@@ -50,7 +50,7 @@ export function FeedPage(props: FeedPageProps) {
setSelectedIndex((i) => Math.min(episodes.length - 1, i + 1));
} else if (key.name === "up" || key.name === "k") {
setSelectedIndex((i) => Math.max(0, i - 1));
} else if (key.name === "return" || key.name === "enter") {
} else if (key.name === "return") {
const item = episodes[selectedIndex()];
if (item) props.onPlayEpisode?.(item.episode, item.feed);
} else if (key.name === "home" || key.name === "g") {

View File

@@ -63,7 +63,7 @@ export function SearchPage(props: SearchPageProps) {
const area = focusArea();
// Enter to search from input
if ((key.name === "return" || key.name === "enter") && area === "input") {
if (key.name === "return" && area === "input") {
handleSearch();
return;
}

View File

@@ -71,7 +71,7 @@ export function LoginScreen(props: LoginScreenProps) {
? (currentIndex - 1 + fields.length) % fields.length
: (currentIndex + 1) % fields.length;
setFocusField(fields[nextIndex]);
} else if (key.name === "return" || key.name === "enter") {
} else if (key.name === "return") {
if (focusField() === "submit") {
handleSubmit();
} else if (focusField() === "code" && props.onNavigateToCode) {

View File

@@ -26,7 +26,7 @@ export function OAuthPlaceholder(props: OAuthPlaceholderProps) {
? (currentIndex - 1 + fields.length) % fields.length
: (currentIndex + 1) % fields.length;
setFocusField(fields[nextIndex]);
} else if (key.name === "return" || key.name === "enter") {
} else if (key.name === "return") {
if (focusField() === "code" && props.onNavigateToCode) {
props.onNavigateToCode();
} else if (focusField() === "back" && props.onBack) {

View File

@@ -46,7 +46,7 @@ export function PreferencesPanel() {
if (key.name === "right" || key.name === "l") {
stepValue(1);
}
if (key.name === "space" || key.name === "return" || key.name === "enter") {
if (key.name === "space" || key.name === "return") {
toggleValue();
}
};

View File

@@ -62,7 +62,6 @@ export function SourceManager(props: SourceManagerProps) {
setSelectedIndex((i) => Math.min(sources().length - 1, i + 1));
} else if (
key.name === "return" ||
key.name === "enter" ||
key.name === "space"
) {
const source = sources()[selectedIndex()];
@@ -98,7 +97,6 @@ export function SourceManager(props: SourceManagerProps) {
if (focusArea() === "explicit") {
if (
key.name === "enter" ||
key.name === "return" ||
key.name === "space"
) {
@@ -113,7 +111,6 @@ export function SourceManager(props: SourceManagerProps) {
if (focusArea() === "language") {
if (
key.name === "enter" ||
key.name === "return" ||
key.name === "space"
) {

View File

@@ -29,7 +29,7 @@ export function SyncProfile(props: SyncProfileProps) {
? (currentIndex - 1 + fields.length) % fields.length
: (currentIndex + 1) % fields.length;
setFocusField(fields[nextIndex]);
} else if (key.name === "return" || key.name === "enter") {
} else if (key.name === "return") {
if (focusField() === "sync" && props.onManageSync) {
props.onManageSync();
} else if (focusField() === "logout" && props.onLogout) {