diff --git a/src/components/settings/models/ModelsSettings.tsx b/src/components/settings/models/ModelsSettings.tsx index 3833338df..29b27e6bd 100644 --- a/src/components/settings/models/ModelsSettings.tsx +++ b/src/components/settings/models/ModelsSettings.tsx @@ -1,12 +1,16 @@ import React, { useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { ask } from "@tauri-apps/plugin-dialog"; -import { ChevronDown, Globe } from "lucide-react"; +import { ChevronDown, Globe, Search, X } from "lucide-react"; import type { ModelCardStatus } from "@/components/onboarding"; import { ModelCard } from "@/components/onboarding"; import { useModelStore } from "@/stores/modelStore"; import { LANGUAGES } from "@/lib/constants/languages.ts"; import type { ModelInfo } from "@/bindings"; +import { + getTranslatedModelDescription, + getTranslatedModelName, +} from "@/lib/utils/modelTranslation"; // check if model supports a language based on its supported_languages list const modelSupportsLanguage = (model: ModelInfo, langCode: string): boolean => { @@ -19,8 +23,10 @@ export const ModelsSettings: React.FC = () => { const [languageFilter, setLanguageFilter] = useState("all"); const [languageDropdownOpen, setLanguageDropdownOpen] = useState(false); const [languageSearch, setLanguageSearch] = useState(""); + const [modelSearchQuery, setModelSearchQuery] = useState(""); const languageDropdownRef = useRef(null); const languageSearchInputRef = useRef(null); + const searchInputRef = useRef(null); const { models, currentModel, @@ -153,15 +159,26 @@ export const ModelsSettings: React.FC = () => { } }; - // Filter models based on language filter + // Filter models based on language filter and search query const filteredModels = useMemo(() => { return models.filter((model: ModelInfo) => { if (languageFilter !== "all") { if (!modelSupportsLanguage(model, languageFilter)) return false; } + const query = modelSearchQuery.trim().toLowerCase(); + if (query) { + const name = getTranslatedModelName(model, t).toLowerCase(); + const description = getTranslatedModelDescription( + model, + t, + ).toLowerCase(); + if (!name.includes(query) && !description.includes(query)) { + return false; + } + } return true; }); - }, [models, languageFilter]); + }, [models, languageFilter, modelSearchQuery, t]); // Split filtered models into downloaded (including custom) and available sections const { downloadedModels, availableModels } = useMemo(() => { @@ -215,122 +232,148 @@ export const ModelsSettings: React.FC = () => { {t("settings.models.description")}

- {filteredModels.length > 0 ? ( -
- {/* Downloaded Models Section — header always visible so filter stays accessible */} -
-
-

- {t("settings.models.yourModels")} -

- {/* Language filter dropdown */} -
+ + {/* Search and Filter Bar */} +
+ {/* Search Input */} +
+ + setModelSearchQuery(e.target.value)} + placeholder={t("settings.models.searchPlaceholder")} + className="w-full pl-9 pr-9 py-2 text-sm bg-mid-gray/10 border border-mid-gray/40 rounded-lg text-text placeholder:text-text/40 transition-all duration-200 hover:bg-mid-gray/15 hover:border-mid-gray/60 focus:outline-none focus:bg-mid-gray/20 focus:border-logo-primary focus:ring-1 focus:ring-logo-primary/30" + /> + {modelSearchQuery && ( + + )} +
+ + {/* Language filter dropdown */} +
+ + + {languageDropdownOpen && ( +
+
+ setLanguageSearch(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter" && filteredLanguages.length > 0) { + setLanguageFilter(filteredLanguages[0].value); + setLanguageDropdownOpen(false); + setLanguageSearch(""); + } else if (e.key === "Escape") { + setLanguageDropdownOpen(false); + setLanguageSearch(""); + } + }} + placeholder={t("settings.general.language.searchPlaceholder")} + className="w-full px-2 py-1 text-sm bg-mid-gray/10 border border-mid-gray/40 rounded-md focus:outline-none focus:ring-1 focus:ring-logo-primary" + /> +
+
- - {languageDropdownOpen && ( -
-
- setLanguageSearch(e.target.value)} - onKeyDown={(e) => { - if ( - e.key === "Enter" && - filteredLanguages.length > 0 - ) { - setLanguageFilter(filteredLanguages[0].value); - setLanguageDropdownOpen(false); - setLanguageSearch(""); - } else if (e.key === "Escape") { - setLanguageDropdownOpen(false); - setLanguageSearch(""); - } - }} - placeholder={t( - "settings.general.language.searchPlaceholder", - )} - className="w-full px-2 py-1 text-sm bg-mid-gray/10 border border-mid-gray/40 rounded-md focus:outline-none focus:ring-1 focus:ring-logo-primary" - /> -
-
- - {filteredLanguages.map((lang) => ( - - ))} - {filteredLanguages.length === 0 && ( -
- {t("settings.general.language.noResults")} -
- )} -
+ {filteredLanguages.map((lang) => ( + + ))} + {filteredLanguages.length === 0 && ( +
+ {t("settings.general.language.noResults")}
)}
- {downloadedModels.map((model: ModelInfo) => ( - - ))} -
+ )} +
+
+ + {filteredModels.length > 0 ? ( +
+ {/* Downloaded Models Section */} + {downloadedModels.length > 0 && ( +
+

+ {t("settings.models.yourModels")} +

+ {downloadedModels.map((model: ModelInfo) => ( + + ))} +
+ )} {/* Available Models Section */} {availableModels.length > 0 && ( diff --git a/src/i18n/locales/ar/translation.json b/src/i18n/locales/ar/translation.json index 81f7a14ec..028fd5009 100644 --- a/src/i18n/locales/ar/translation.json +++ b/src/i18n/locales/ar/translation.json @@ -523,6 +523,7 @@ "models": { "title": "نماذج النسخ", "description": "اختر نموذج نسخ أو قم بتنزيل نماذج إضافية. تقدم النماذج المختلفة مستويات متفاوتة من الدقة والسرعة.", + "searchPlaceholder": "Search models...", "yourModels": "النماذج المحمّلة", "availableModels": "متاح للتنزيل", "downloaded": "تم التنزيل", @@ -569,6 +570,7 @@ "update": "تحديث", "close": "إغلاق", "open": "فتح", + "clear": "Clear", "default": "افتراضي", "enabled": "ممكن", "disabled": "معطل", diff --git a/src/i18n/locales/bg/translation.json b/src/i18n/locales/bg/translation.json index 2cb5d79dc..28bf6cb26 100644 --- a/src/i18n/locales/bg/translation.json +++ b/src/i18n/locales/bg/translation.json @@ -200,6 +200,7 @@ "models": { "title": "Модели за транскрипция", "description": "Изберете модел за транскрипция или изтеглете допълнителни. Различните модели предлагат различна точност и скорост.", + "searchPlaceholder": "Search models...", "yourModels": "Изтеглени модели", "availableModels": "Налични за изтегляне", "downloaded": "Изтеглен", @@ -569,6 +570,7 @@ "update": "Обновяване", "close": "Затваряне", "open": "Отваряне", + "clear": "Clear", "default": "По подразбиране", "enabled": "Включено", "disabled": "Изключено", diff --git a/src/i18n/locales/cs/translation.json b/src/i18n/locales/cs/translation.json index aa93251c5..92548e89b 100644 --- a/src/i18n/locales/cs/translation.json +++ b/src/i18n/locales/cs/translation.json @@ -158,6 +158,7 @@ "models": { "title": "Modely přepisu", "description": "Vyberte model přepisu nebo stáhněte další modely. Různé modely nabízejí různé úrovně přesnosti a rychlosti.", + "searchPlaceholder": "Search models...", "downloaded": "Staženo", "available": "K dispozici ke stažení", "deleteConfirm": "Opravdu chcete smazat {{modelName}}? Pro opětovné použití jej budete muset znovu stáhnout.", @@ -569,6 +570,7 @@ "update": "Aktualizovat", "close": "Zavřít", "open": "Otevřít", + "clear": "Clear", "default": "Výchozí", "enabled": "Zapnuto", "disabled": "Vypnuto", diff --git a/src/i18n/locales/de/translation.json b/src/i18n/locales/de/translation.json index 821b94463..d82053aa8 100644 --- a/src/i18n/locales/de/translation.json +++ b/src/i18n/locales/de/translation.json @@ -158,6 +158,7 @@ "models": { "title": "Transkriptionsmodelle", "description": "Wähle ein Transkriptionsmodell aus oder lade zusätzliche Modelle herunter. Verschiedene Modelle bieten unterschiedliche Genauigkeits- und Geschwindigkeitsstufen.", + "searchPlaceholder": "Modelle suchen...", "downloaded": "Heruntergeladen", "available": "Zum Download verfügbar", "deleteConfirm": "Bist du sicher, dass du {{modelName}} löschen möchtest? Du musst es erneut herunterladen, um es zu verwenden.", @@ -569,6 +570,7 @@ "update": "Aktualisieren", "close": "Schließen", "open": "Öffnen", + "clear": "Leeren", "default": "Standard", "enabled": "Aktiviert", "disabled": "Deaktiviert", diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index eef96e5be..7765a3514 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -200,6 +200,7 @@ "models": { "title": "Transcription Models", "description": "Select a transcription model or download additional models. Different models offer varying levels of accuracy and speed.", + "searchPlaceholder": "Search models...", "yourModels": "Downloaded Models", "availableModels": "Available to Download", "downloaded": "Downloaded", @@ -569,6 +570,7 @@ "update": "Update", "close": "Close", "open": "Open", + "clear": "Clear", "default": "Default", "enabled": "Enabled", "disabled": "Disabled", diff --git a/src/i18n/locales/es/translation.json b/src/i18n/locales/es/translation.json index e33d5cb41..a8b043b71 100644 --- a/src/i18n/locales/es/translation.json +++ b/src/i18n/locales/es/translation.json @@ -158,6 +158,7 @@ "models": { "title": "Modelos de Transcripción", "description": "Selecciona un modelo de transcripción o descarga modelos adicionales. Diferentes modelos ofrecen distintos niveles de precisión y velocidad.", + "searchPlaceholder": "Buscar modelos...", "downloaded": "Descargados", "available": "Disponibles para Descargar", "deleteConfirm": "¿Estás seguro de que deseas eliminar {{modelName}}? Necesitarás descargarlo de nuevo para usarlo.", @@ -569,6 +570,7 @@ "update": "Actualizar", "close": "Cerrar", "open": "Abrir", + "clear": "Limpiar", "default": "Predeterminado", "enabled": "Habilitado", "disabled": "Deshabilitado", diff --git a/src/i18n/locales/fr/translation.json b/src/i18n/locales/fr/translation.json index 479d00c49..3b3db5074 100644 --- a/src/i18n/locales/fr/translation.json +++ b/src/i18n/locales/fr/translation.json @@ -158,6 +158,7 @@ "models": { "title": "Modèles de Transcription", "description": "Sélectionnez un modèle de transcription ou téléchargez des modèles supplémentaires. Différents modèles offrent différents niveaux de précision et de vitesse.", + "searchPlaceholder": "Rechercher des modeles...", "downloaded": "Téléchargés", "available": "Disponibles au Téléchargement", "deleteConfirm": "Êtes-vous sûr de vouloir supprimer {{modelName}} ? Vous devrez le télécharger à nouveau pour l'utiliser.", @@ -569,6 +570,7 @@ "update": "Mettre à jour", "close": "Fermer", "open": "Ouvrir", + "clear": "Effacer", "default": "Par défaut", "enabled": "Activé", "disabled": "Désactivé", diff --git a/src/i18n/locales/he/translation.json b/src/i18n/locales/he/translation.json index 9b0518d39..54bd49b5b 100644 --- a/src/i18n/locales/he/translation.json +++ b/src/i18n/locales/he/translation.json @@ -200,6 +200,7 @@ "models": { "title": "מודלי תמלול", "description": "בחר מודל תמלול או הורד מודלים נוספים. מודלים שונים מציעים רמות שונות של דיוק ומהירות.", + "searchPlaceholder": "Search models...", "yourModels": "מודלים שהורדו", "availableModels": "זמינים להורדה", "downloaded": "הורד", @@ -569,6 +570,7 @@ "update": "עדכן", "close": "סגור", "open": "פתח", + "clear": "Clear", "default": "ברירת מחדל", "enabled": "פעיל", "disabled": "כבוי", diff --git a/src/i18n/locales/it/translation.json b/src/i18n/locales/it/translation.json index 6f7cd035e..77893d058 100644 --- a/src/i18n/locales/it/translation.json +++ b/src/i18n/locales/it/translation.json @@ -158,6 +158,7 @@ "models": { "title": "Modelli di Trascrizione", "description": "Seleziona un modello di trascrizione o scarica modelli aggiuntivi. Diversi modelli offrono diversi livelli di accuratezza e velocità.", + "searchPlaceholder": "Cerca modelli...", "downloaded": "Scaricati", "available": "Disponibili per il Download", "deleteConfirm": "Sei sicuro di voler eliminare {{modelName}}? Dovrai scaricarlo di nuovo per usarlo.", @@ -569,6 +570,7 @@ "update": "Aggiorna", "close": "Chiudi", "open": "Apri", + "clear": "Cancella", "default": "Predefinito", "enabled": "Abilitato", "disabled": "Disabilitato", diff --git a/src/i18n/locales/ja/translation.json b/src/i18n/locales/ja/translation.json index a9aad4ed4..700edb9a1 100644 --- a/src/i18n/locales/ja/translation.json +++ b/src/i18n/locales/ja/translation.json @@ -158,6 +158,7 @@ "models": { "title": "転写モデル", "description": "転写モデルを選択するか、追加のモデルをダウンロードします。異なるモデルは精度と速度のレベルが異なります。", + "searchPlaceholder": "モデルを検索...", "downloaded": "ダウンロード済み", "available": "ダウンロード可能", "deleteConfirm": "{{modelName}}を削除してもよろしいですか?再度使用するにはダウンロードが必要です。", @@ -569,6 +570,7 @@ "update": "更新", "close": "閉じる", "open": "開く", + "clear": "クリア", "default": "デフォルト", "enabled": "有効", "disabled": "無効", diff --git a/src/i18n/locales/ko/translation.json b/src/i18n/locales/ko/translation.json index 4e168d2b0..3971564dc 100644 --- a/src/i18n/locales/ko/translation.json +++ b/src/i18n/locales/ko/translation.json @@ -223,6 +223,7 @@ "models": { "title": "음성 인식 모델", "description": "음성 인식 모델을 선택하거나 추가 모델을 다운로드하세요. 모델마다 정확도와 속도가 다릅니다.", + "searchPlaceholder": "모델 검색...", "yourModels": "다운로드된 모델", "availableModels": "다운로드 가능", "downloaded": "다운로드됨", @@ -569,6 +570,7 @@ "update": "업데이트", "close": "닫기", "open": "열기", + "clear": "지우기", "default": "기본값", "enabled": "활성화됨", "disabled": "비활성화됨", diff --git a/src/i18n/locales/pl/translation.json b/src/i18n/locales/pl/translation.json index ed064221e..066d3221f 100644 --- a/src/i18n/locales/pl/translation.json +++ b/src/i18n/locales/pl/translation.json @@ -158,6 +158,7 @@ "models": { "title": "Modele transkrypcji", "description": "Wybierz model transkrypcji lub pobierz dodatkowe modele. Różne modele oferują różne poziomy dokładności i szybkości.", + "searchPlaceholder": "Search models...", "downloaded": "Pobrane", "available": "Dostępne do pobrania", "deleteConfirm": "Czy na pewno chcesz usunąć {{modelName}}? Będziesz musiał pobrać go ponownie, aby go użyć.", @@ -569,6 +570,7 @@ "update": "Aktualizuj", "close": "Zamknij", "open": "Otwórz", + "clear": "Clear", "default": "Domyślne", "enabled": "Włączone", "disabled": "Wyłączone", diff --git a/src/i18n/locales/pt/translation.json b/src/i18n/locales/pt/translation.json index a85436f47..2ebe50824 100644 --- a/src/i18n/locales/pt/translation.json +++ b/src/i18n/locales/pt/translation.json @@ -200,6 +200,7 @@ "models": { "title": "Modelos de Transcrição", "description": "Selecione um modelo de transcrição ou baixe modelos adicionais. Diferentes modelos oferecem diferentes níveis de precisão e velocidade.", + "searchPlaceholder": "Buscar modelos...", "downloaded": "Baixados", "available": "Disponíveis para Download", "deleteConfirm": "Tem certeza de que deseja excluir {{modelName}}? Você precisará baixá-lo novamente para usá-lo.", @@ -569,6 +570,7 @@ "update": "Atualizar", "close": "Fechar", "open": "Abrir", + "clear": "Limpar", "default": "Padrão", "enabled": "Habilitado", "disabled": "Desabilitado", diff --git a/src/i18n/locales/ru/translation.json b/src/i18n/locales/ru/translation.json index b196a329a..8b3d4956b 100644 --- a/src/i18n/locales/ru/translation.json +++ b/src/i18n/locales/ru/translation.json @@ -158,6 +158,7 @@ "models": { "title": "Модели транскрипции", "description": "Выберите модель транскрипции или загрузите дополнительные модели. Разные модели предлагают разные уровни точности и скорости.", + "searchPlaceholder": "Поиск моделей...", "downloaded": "Загружено", "available": "Доступные для загрузки", "deleteConfirm": "Вы уверены, что хотите удалить {{modelName}}? Вам нужно будет загрузить её снова, чтобы использовать.", @@ -569,6 +570,7 @@ "update": "Обновлять", "close": "Закрывать", "open": "Открыть", + "clear": "Очистить", "default": "По умолчанию", "enabled": "Включено", "disabled": "Неполноценный", diff --git a/src/i18n/locales/sv/translation.json b/src/i18n/locales/sv/translation.json index de731efc5..38c920faa 100644 --- a/src/i18n/locales/sv/translation.json +++ b/src/i18n/locales/sv/translation.json @@ -200,6 +200,7 @@ "models": { "title": "Transkriptionsmodeller", "description": "Välj en transkriptionsmodell eller ladda ner ytterligare modeller. Olika modeller erbjuder varierande nivåer av noggrannhet och hastighet.", + "searchPlaceholder": "Search models...", "yourModels": "Nedladdade modeller", "availableModels": "Tillgängliga att ladda ner", "downloaded": "Nedladdad", @@ -569,6 +570,7 @@ "update": "Uppdatera", "close": "Stäng", "open": "Öppna", + "clear": "Clear", "default": "Standard", "enabled": "Aktiverad", "disabled": "Inaktiverad", diff --git a/src/i18n/locales/tr/translation.json b/src/i18n/locales/tr/translation.json index e4cc4e2e7..a8487563f 100644 --- a/src/i18n/locales/tr/translation.json +++ b/src/i18n/locales/tr/translation.json @@ -158,6 +158,7 @@ "models": { "title": "Transkripsiyon Modelleri", "description": "Bir transkripsiyon modeli seçin veya ek modeller indirin. Farklı modeller değişen doğruluk ve hız seviyeleri sunar.", + "searchPlaceholder": "Model ara...", "downloaded": "İndirildi", "available": "İndirilebilir", "deleteConfirm": "{{modelName}} modelini silmek istediğinizden emin misiniz? Kullanmak için tekrar indirmeniz gerekecek.", @@ -569,6 +570,7 @@ "update": "Güncelle", "close": "Kapat", "open": "Aç", + "clear": "Temizle", "default": "Varsayılan", "enabled": "Etkin", "disabled": "Devre Dışı", diff --git a/src/i18n/locales/uk/translation.json b/src/i18n/locales/uk/translation.json index 825c1ee15..c4d89b2fc 100644 --- a/src/i18n/locales/uk/translation.json +++ b/src/i18n/locales/uk/translation.json @@ -200,6 +200,7 @@ "models": { "title": "Моделі транскрипції", "description": "Виберіть модель транскрипції або завантажте додаткові моделі. Різні моделі пропонують різні рівні точності та швидкості.", + "searchPlaceholder": "Search models...", "downloaded": "Завантажено", "available": "Доступні для завантаження", "deleteConfirm": "Ви впевнені, що хочете видалити {{modelName}}? Вам потрібно буде завантажити її знову, щоб використовувати.", @@ -569,6 +570,7 @@ "update": "Оновити", "close": "Закрити", "open": "Відкрити", + "clear": "Clear", "default": "За замовчуванням", "enabled": "Увімкнено", "disabled": "Вимкнено", diff --git a/src/i18n/locales/vi/translation.json b/src/i18n/locales/vi/translation.json index b6bfe7c96..830a60660 100644 --- a/src/i18n/locales/vi/translation.json +++ b/src/i18n/locales/vi/translation.json @@ -158,6 +158,7 @@ "models": { "title": "Mô hình chuyển đổi", "description": "Chọn mô hình chuyển đổi hoặc tải thêm mô hình. Các mô hình khác nhau có mức độ chính xác và tốc độ khác nhau.", + "searchPlaceholder": "Search models...", "downloaded": "Đã tải xuống", "available": "Có thể tải xuống", "deleteConfirm": "Bạn có chắc chắn muốn xóa {{modelName}}? Bạn sẽ cần tải lại để sử dụng.", @@ -569,6 +570,7 @@ "update": "Cập nhật", "close": "Đóng", "open": "Mở", + "clear": "Clear", "default": "Mặc định", "enabled": "Đã bật", "disabled": "Đã tắt", diff --git a/src/i18n/locales/zh-TW/translation.json b/src/i18n/locales/zh-TW/translation.json index 6eee9637a..b4cdd110a 100644 --- a/src/i18n/locales/zh-TW/translation.json +++ b/src/i18n/locales/zh-TW/translation.json @@ -200,6 +200,7 @@ "models": { "title": "轉錄模型", "description": "選擇轉錄模型或下載其他模型。不同模型提供不同的準確度和速度", + "searchPlaceholder": "搜尋模型...", "yourModels": "已下載的模型", "availableModels": "可供下載", "downloaded": "已下載", @@ -569,6 +570,7 @@ "update": "更新", "close": "關閉", "open": "開啟", + "clear": "清除", "default": "預設", "enabled": "已啟用", "disabled": "已停用", diff --git a/src/i18n/locales/zh/translation.json b/src/i18n/locales/zh/translation.json index 7dd690c54..0f86b972d 100644 --- a/src/i18n/locales/zh/translation.json +++ b/src/i18n/locales/zh/translation.json @@ -158,6 +158,7 @@ "models": { "title": "转录模型", "description": "选择转录模型或下载其他模型。不同模型提供不同的准确度和速度。", + "searchPlaceholder": "搜索模型...", "downloaded": "已下载", "available": "可下载", "deleteConfirm": "确定要删除 {{modelName}} 吗?您需要重新下载才能使用。", @@ -569,6 +570,7 @@ "update": "更新", "close": "关闭", "open": "打开", + "clear": "清除", "default": "默认", "enabled": "已启用", "disabled": "已禁用",