Files
abode/src/tui/App.tsx
T
2026-06-29 23:07:14 +00:00

112 lines
2.8 KiB
TypeScript

import { Box, useApp, useInput } from "ink";
import { use, useState, type ComponentType, type ReactNode } from "react";
import { ListBox } from "./components/ui/ListBox.js";
import type { DbInterface } from "../db/types/DbInterface.js";
import { DbProvider } from "../react/contexts/Db.js";
import { UsersPanel } from "./components/panels/UsersPanel.js";
import { BgColorContext } from "./contexts/BgColor.js";
import { FocusManager, useActive } from "./contexts/FocusManager.js";
import { Provider } from "../react/store/react.js";
import { createStore, type Store } from "../react/store/store.js";
import { AbodesPanel } from "./components/panels/AbodesPanel.js";
import { LoginPanel } from "./components/panels/LoginPanel.js";
import { PopupManager } from "../react/contexts/PopupManager.js";
function AppWrapper({
children,
db,
store,
bgColor,
}: {
children: ReactNode;
db: DbInterface;
store: Store;
bgColor?: string;
}) {
return (
<FocusManager>
<Provider store={store}>
<DbProvider db={db}>
<BgColorContext value={bgColor ?? use(BgColorContext)}>
<Box flexGrow={1} flexDirection="column">
<Box height={1} />
<Box alignItems="stretch" flexGrow={1}>
<PopupManager>{children}</PopupManager>
</Box>
</Box>
</BgColorContext>
</DbProvider>
</Provider>
</FocusManager>
);
}
export type CollectionType = "users" | "abodes" | "apikeys" | "notes";
const collectionTypes: CollectionType[] = [
"users",
"abodes",
"apikeys",
"notes",
];
const collectionTypeDisplay: Record<CollectionType, string> = {
users: "Users",
abodes: "Abodes",
apikeys: "API Keys",
notes: "Notes",
};
const collections: Record<CollectionType, ComponentType> = {
users: UsersPanel,
abodes: AbodesPanel,
apikeys: () => null,
notes: () => null,
};
function App() {
const app = useApp();
const isActive = useActive();
useInput(
(input, key) => {
if (input === "q" || key.escape) app.exit();
},
{ isActive }
);
const [activeCollection, setActiveCollection] =
useState<CollectionType>("users");
const CollectionPanel = collections[activeCollection];
return (
<Box flexGrow={1} flexDirection="row">
<ListBox
width={13}
title="Collections"
items={collectionTypes}
display={collectionTypeDisplay}
autoFocus
selected={activeCollection}
setSelected={setActiveCollection}
/>
<Box flexGrow={1} flexDirection="column">
<LoginPanel />
<CollectionPanel />
</Box>
</Box>
);
}
export function app({
db,
bgColor,
store = createStore(),
}: {
db: DbInterface;
bgColor?: string;
store?: Store;
}) {
return (
<AppWrapper db={db} store={store} bgColor={bgColor}>
<App />
</AppWrapper>
);
}