import { useEffect } from "preact/hooks";
import { t } from "../../i18n";
import { closeCust, custTab } from "../../features/customize/actions";
import {
CUST_LOAD_TIMEOUT_MS,
markCustomizeTimedOut,
} from "../../features/customize/load";
import {
customizeGeneration,
customizeLoad,
customizeOpen,
customizeTab,
nestedEditor,
} from "../../features/customize/state";
import { CUST_TABS, CUST_TAB_I18N, type CustTab } from "../../features/customize/tabs";
import { Icon } from "./icons";
import { GeneralTab } from "./GeneralTab";
import { SkillsTab } from "./SkillsTab";
import { SpecialistsTab } from "./SpecialistsTab";
import { ConnectorsTab } from "./ConnectorsTab";
import { ComputeTab } from "./ComputeTab";
import { PermissionsTab } from "./PermissionsTab";
import { NetworkTab } from "./NetworkTab";
import { MemoryTab } from "./MemoryTab";
import { ModelsTab } from "./ModelsTab";
import { NestedEditor } from "./NestedEditor";
import "./customize.css";
function ActiveTab() {
switch (customizeTab.value) {
case "general":
return ;
case "skills":
return ;
case "specialists":
return ;
case "connectors":
return ;
case "compute":
return ;
case "permissions":
return ;
case "network":
return ;
case "memory":
return ;
case "models":
return ;
}
}
/**
* The bounded-load annotation above the tab body. "Loading…" while the tab's
* first fetch is pending; after CUST_LOAD_TIMEOUT_MS with no answer, or when
* the fetch failed, a Retry that reloads the tab (a new generation). The tab
* body stays mounted underneath: a control the user is already using is
* annotated, never discarded.
*/
function LoadStatus({ tab, generation }: { tab: CustTab; generation: number }) {
const load = customizeLoad.value;
useEffect(() => {
const timer = setTimeout(() => markCustomizeTimedOut(generation), CUST_LOAD_TIMEOUT_MS);
return () => clearTimeout(timer);
}, [generation]);
if (load.generation !== generation || load.state === "ready") return null;
if (load.state === "loading") {
return (
{t("common.loading")}
);
}
return (
{load.state === "timeout" && load.error ? (
{load.error}
) : null}
);
}
export function Customize() {
const open = customizeOpen.value;
const tab = customizeTab.value;
const gen = customizeGeneration.value;
const loading = customizeLoad.value.generation === gen && customizeLoad.value.state === "loading";
useEffect(() => {
const onKey = (e: KeyboardEvent) => {
if (e.key !== "Escape") return;
if (!customizeOpen.value) return;
if (nestedEditor.value) {
nestedEditor.value = null;
e.preventDefault();
return;
}
e.preventDefault();
closeCust();
};
document.addEventListener("keydown", onKey);
return () => document.removeEventListener("keydown", onKey);
}, []);
return (
{
if ((e.target as HTMLElement).id === "cust") closeCust();
}}
>