feat: private feeds, all input fields supersede keyboard nav

This commit is contained in:
2026-08-09 15:39:02 -04:00
parent e1cdd6b2a5
commit db285530b6
7 changed files with 199 additions and 49 deletions

View File

@@ -1,38 +1,55 @@
const createSignal = <T,>(value: T): [() => T, (next: T) => void] => {
let current = value
return [() => current, (next) => {
current = next
}]
}
let current = value;
return [
() => current,
(next) => {
current = next;
},
];
};
import { SyncStatus } from "./SyncStatus"
import { useTheme } from "@/context/ThemeContext"
import { SyncStatus } from "./SyncStatus";
import { useTheme } from "@/context/ThemeContext";
import { useInputFocusNav } from "@/hooks/useInputFocusNav";
export function ExportDialog() {
const { theme } = useTheme();
const filename = createSignal("podcast-sync.json")
const format = createSignal<"json" | "xml">("json")
const { theme } = useTheme();
const filename = createSignal("podcast-sync.json");
const format = createSignal<"json" | "xml">("json");
// Yield navigation keybinds to the Shell router while the input is focused.
const filenameRef = useInputFocusNav();
return (
<box border title="Export" style={{ padding: 1, flexDirection: "column", gap: 1 }}>
<box style={{ flexDirection: "row", gap: 1 }}>
<text fg={theme.text}>File:</text>
<input value={filename[0]()} onInput={filename[1]} style={{ width: 30 }} />
</box>
<box style={{ flexDirection: "row", gap: 1 }}>
<text fg={theme.text}>Format:</text>
<tab_select
options={[
{ name: "JSON", description: "Portable" },
{ name: "XML", description: "Structured" },
]}
onSelect={(index) => format[1](index === 0 ? "json" : "xml")}
/>
</box>
<box border borderColor={theme.border}>
<text fg={theme.text}>Export {format[0]()} to {filename[0]()}</text>
</box>
<SyncStatus />
</box>
)
return (
<box
border
title="Export"
style={{ padding: 1, flexDirection: "column", gap: 1 }}
>
<box style={{ flexDirection: "row", gap: 1 }}>
<text fg={theme.text}>File:</text>
<input
ref={filenameRef}
value={filename[0]()}
onInput={filename[1]}
style={{ width: 30 }}
/>
</box>
<box style={{ flexDirection: "row", gap: 1 }}>
<text fg={theme.text}>Format:</text>
<tab_select
options={[
{ name: "JSON", description: "Portable" },
{ name: "XML", description: "Structured" },
]}
onSelect={(index) => format[1](index === 0 ? "json" : "xml")}
/>
</box>
<box border borderColor={theme.border}>
<text fg={theme.text}>
Export {format[0]()} to {filename[0]()}
</text>
</box>
<SyncStatus />
</box>
);
}