From 7eb8e5b8705259dcb7f01a7b8fe7ec73c093eea8 Mon Sep 17 00:00:00 2001 From: Pabloader Date: Wed, 8 Apr 2026 10:00:48 +0000 Subject: [PATCH] Models filter --- .../assets/settings-modal.module.css | 15 +++++ .../components/settings/connection.tsx | 65 ++++++++++++++----- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/games/storywriter/assets/settings-modal.module.css b/src/games/storywriter/assets/settings-modal.module.css index 4de3018..b76986d 100644 --- a/src/games/storywriter/assets/settings-modal.module.css +++ b/src/games/storywriter/assets/settings-modal.module.css @@ -116,6 +116,7 @@ .formGroup { display: flex; flex-direction: column; + gap: 4px; } .formGroupFill { @@ -128,6 +129,20 @@ font-weight: bold; } +.selectMultiline { + flex: 1; + overflow-y: auto; +} + +.selectMultiline optgroup { + padding-block: 4px; +} + +.selectMultiline option { + padding-block: 4px; + padding-inline-start: 16px; +} + .input, .select, .textarea { diff --git a/src/games/storywriter/components/settings/connection.tsx b/src/games/storywriter/components/settings/connection.tsx index 6f50a01..792169a 100644 --- a/src/games/storywriter/components/settings/connection.tsx +++ b/src/games/storywriter/components/settings/connection.tsx @@ -2,6 +2,7 @@ import { useBool } from "@common/hooks/useBool"; import { useQuery } from "@common/hooks/useAsyncState"; import { useInputState } from "@common/hooks/useInputState"; import { useUpdate } from "@common/hooks/useUpdate"; +import clsx from "clsx"; import { useMemo, useRef } from "preact/hooks"; import styles from "../../assets/settings-modal.module.css"; import { useAppState } from "../../contexts/state"; @@ -36,6 +37,8 @@ export const ConnectionSettings = () => { const modelsData = useQuery(fetchModels, connectionToFetch); const isLoadingModels = connectionToFetch != null && modelsData == undefined; + const [modelFilter, setModelFilter] = useInputState(""); + const groupedModels = useMemo(() => { const sorted = (modelsData ?? []).sort((a, b) => { const aWeight = Number(a.support_tools) * 2 + Number(a.support_thinking); @@ -52,6 +55,25 @@ export const ConnectionSettings = () => { .map(([context, models]) => ({ context, models })); }, [modelsData]); + const filteredGroupedModels = useMemo(() => { + if (!modelFilter) return groupedModels; + const query = modelFilter.toLowerCase(); + const fuzzyMatch = (target: string) => { + const t = target.toLowerCase(); + let qi = 0; + for (let ti = 0; ti < t.length && qi < query.length; ti++) { + if (t[ti] === query[qi]) qi++; + } + return qi === query.length; + }; + return groupedModels + .map(({ context, models }) => ({ + context, + models: models.filter(m => m.id === selectedModel || fuzzyMatch(m.id)), + })) + .filter(({ models }) => models.length > 0); + }, [groupedModels, modelFilter, selectedModel]); + const handleBlur = () => { if (url && apiKey) { dispatch({ type: "SET_CONNECTION", connection: { url, apiKey } }); @@ -115,28 +137,37 @@ export const ConnectionSettings = () => { -
+
{connectionToTest ? ( isLoadingModels ? (

Loading models...

) : groupedModels.length > 0 ? ( - + <> + + + ) : (

No models available

)