From 2a8ee12f7c50f77a1863d497a20ba9f89684ebb2 Mon Sep 17 00:00:00 2001 From: Sashank Bhamidi Date: Mon, 25 Aug 2025 20:41:23 +0530 Subject: [PATCH 1/4] fix: load language from user settings instead of hardcoding - Replace hardcoded i18n.activate("en") with dynamic language loading - Add LanguageInitializer component to read user preferences from config - Support English and Korean languages with proper fallback - Handle loading states and error conditions gracefully - Validates language codes to prevent invalid configurations Resolves TODO comment in main.tsx line 35 --- apps/desktop/src/main.tsx | 56 +++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/apps/desktop/src/main.tsx b/apps/desktop/src/main.tsx index 4150b7fee..8e91e4a6c 100644 --- a/apps/desktop/src/main.tsx +++ b/apps/desktop/src/main.tsx @@ -3,9 +3,9 @@ import "./styles/globals.css"; import { i18n } from "@lingui/core"; import { I18nProvider } from "@lingui/react"; -import { QueryClient, QueryClientProvider, useQueries, useQueryClient } from "@tanstack/react-query"; +import { QueryClient, QueryClientProvider, useQueries, useQuery, useQueryClient } from "@tanstack/react-query"; import { CatchBoundary, createRouter, ErrorComponent, RouterProvider } from "@tanstack/react-router"; -import { useEffect } from "react"; +import { type ReactNode, useEffect } from "react"; import ReactDOM from "react-dom/client"; import { recordingStartFailedToast } from "@/components/toast/shared"; @@ -32,8 +32,34 @@ i18n.load({ ko: koMessages, }); -// TODO: load language from user settings -i18n.activate("en"); +// Language initialization component +function LanguageInitializer({ children }: { children: ReactNode }) { + const config = useQuery({ + queryKey: ["config", "general"], + queryFn: async () => { + 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: { @@ -137,16 +163,18 @@ if (!rootElement.innerHTML) { - - - - + + + + + + From 9327a8794672615bdc1ec9b643d7ed460aaf8ba4 Mon Sep 17 00:00:00 2001 From: Sashank Bhamidi Date: Mon, 25 Aug 2025 20:41:58 +0530 Subject: [PATCH 2/4] feat: add search functionality to model selection dropdowns - Add SearchableModelSelect component with real-time filtering - Apply to "Others" section where users configure custom endpoints - Also apply to "OpenRouter" section for consistency - Show dynamic model count in search placeholder - Handle empty search results gracefully - Maintain accessibility with proper ARIA attributes - Use existing UI components (Command, Popover, Button) Resolves #1386 - Users can now search through ~100 models instead of scrolling manually --- .../components/ai/llm-custom-view.tsx | 91 +++++++++++++------ 1 file changed, 65 insertions(+), 26 deletions(-) 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 c012b1c64..a1b2c1158 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 @@ -4,6 +4,8 @@ import { fetch as tauriFetch } from "@tauri-apps/plugin-http"; import useDebouncedCallback from "beautiful-react-hooks/useDebouncedCallback"; import { useEffect } from "react"; +import { Button } from "@hypr/ui/components/ui/button"; +import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from "@hypr/ui/components/ui/command"; import { Form, FormControl, @@ -14,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"; @@ -46,6 +50,59 @@ 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, @@ -534,21 +591,12 @@ export function LLMCustomView({ Model - + /> @@ -664,21 +712,12 @@ export function LLMCustomView({ ) : othersModels.data && othersModels.data.length > 0 ? ( - + /> ) : ( Date: Mon, 25 Aug 2025 21:01:30 +0530 Subject: [PATCH 3/4] fix: address code review feedback - Fix CSS variable to use var(--radix-popper-anchor-width) - Add internationalization to 'No model found' message - Improve accessibility with aria-label on model selector button --- .../components/settings/components/ai/llm-custom-view.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 a1b2c1158..42fc3f219 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 @@ -67,16 +67,17 @@ function SearchableModelSelect({ models, value, placeholder, onValueChange }: Se variant="outline" role="combobox" aria-expanded={open} + aria-label={value ? `Selected model: ${value}` : placeholder} className="w-full justify-between" > {value || placeholder} - + - No model found. + No model found. {models.map((model) => ( Date: Mon, 6 Oct 2025 13:21:38 +0530 Subject: [PATCH 4/4] fix: add missing Trans import for i18n --- .../src/components/settings/components/ai/llm-custom-view.tsx | 1 + 1 file changed, 1 insertion(+) 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 fb185e201..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,7 @@ 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 {