diff --git a/apps/desktop/src/components/settings/components/ai/llm-custom-view.tsx b/apps/desktop/src/components/settings/components/ai/llm-custom-view.tsx index 83134049e..bb2800175 100644 --- a/apps/desktop/src/components/settings/components/ai/llm-custom-view.tsx +++ b/apps/desktop/src/components/settings/components/ai/llm-custom-view.tsx @@ -3,6 +3,9 @@ import { fetch as tauriFetch } from "@tauri-apps/plugin-http"; import useDebouncedCallback from "beautiful-react-hooks/useDebouncedCallback"; import { useEffect } from "react"; +import { Trans } from "@lingui/react/macro"; +import { Button } from "@hypr/ui/components/ui/button"; +import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from "@hypr/ui/components/ui/command"; import { Form, FormControl, @@ -13,8 +16,10 @@ import { FormMessage, } from "@hypr/ui/components/ui/form"; import { Input } from "@hypr/ui/components/ui/input"; +import { Popover, PopoverContent, PopoverTrigger } from "@hypr/ui/components/ui/popover"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@hypr/ui/components/ui/select"; import { cn } from "@hypr/ui/lib/utils"; +import { Check, ChevronsUpDown } from "lucide-react"; import { useState } from "react"; import { SharedCustomEndpointProps } from "./shared"; @@ -45,6 +50,60 @@ const openrouterModels = [ "mistralai/mistral-small-3.2-24b-instruct", ]; +interface SearchableModelSelectProps { + models: string[]; + value?: string; + placeholder: string; + onValueChange: (value: string) => void; +} + +function SearchableModelSelect({ models, value, placeholder, onValueChange }: SearchableModelSelectProps) { + const [open, setOpen] = useState(false); + + return ( + + + + + + + + No model found. + + {models.map((model) => ( + { + onValueChange(model); + setOpen(false); + }} + > + + {model} + + ))} + + + + + ); +} + export function LLMCustomView({ customLLMEnabled, selectedLLMModel, @@ -533,21 +592,12 @@ export function LLMCustomView({ Model - + /> @@ -661,21 +711,12 @@ export function LLMCustomView({ ) : othersModels.data && othersModels.data.length > 0 ? ( - + /> ) : ( { + const result = await dbCommands.getConfig(); + return result; + }, + retry: 1, + }); + + useEffect(() => { + const displayLanguage = config.data?.general.display_language; + if (displayLanguage && (displayLanguage === "en" || displayLanguage === "ko")) { + i18n.activate(displayLanguage); + } else { + // Fallback to English for new users, invalid languages, or if config fails to load + i18n.activate("en"); + } + }, [config.data, config.error]); + + // Don't render children until language is initialized + if (config.isLoading) { + return null; + } + + return <>{children}; +} + + const queryClient = new QueryClient({ defaultOptions: { queries: { @@ -128,14 +168,18 @@ if (!rootElement.innerHTML) { - - + + + + + +