From b97b24cc5040f0b7318c795cac9d50acd8c109da Mon Sep 17 00:00:00 2001 From: ElwinLiu Date: Sun, 12 Apr 2026 01:01:54 -0400 Subject: [PATCH] fix(settings): preserve overlay position when toggling Persist overlay visibility separately from overlay position so disabling the overlay does not discard the user's placement preference. This keeps existing settings migrated correctly, updates the overlay runtime checks, and wires the new setting through the frontend store and bindings. --- src-tauri/src/lib.rs | 1 + src-tauri/src/overlay.rs | 30 +++++++--- src-tauri/src/settings.rs | 30 +++++++++- src-tauri/src/shortcut/mod.rs | 23 ++++++++ src/bindings.ts | 10 +++- src/components/settings/ShowOverlay.tsx | 73 +++++++++++++++++++------ src/i18n/locales/ar/translation.json | 5 +- src/i18n/locales/cs/translation.json | 5 +- src/i18n/locales/de/translation.json | 5 +- src/i18n/locales/en/translation.json | 5 +- src/i18n/locales/es/translation.json | 5 +- src/i18n/locales/fr/translation.json | 5 +- src/i18n/locales/it/translation.json | 5 +- src/i18n/locales/ja/translation.json | 5 +- src/i18n/locales/ko/translation.json | 5 +- src/i18n/locales/pl/translation.json | 5 +- src/i18n/locales/pt/translation.json | 5 +- src/i18n/locales/ru/translation.json | 5 +- src/i18n/locales/tr/translation.json | 5 +- src/i18n/locales/uk/translation.json | 5 +- src/i18n/locales/vi/translation.json | 5 +- src/i18n/locales/zh-TW/translation.json | 5 +- src/i18n/locales/zh/translation.json | 5 +- src/stores/settingsStore.ts | 2 + 24 files changed, 193 insertions(+), 61 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 482c2be1..8868ba44 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -297,6 +297,7 @@ pub fn run(cli_args: CliArgs) { shortcut::change_autostart_setting, shortcut::change_translate_to_english_setting, shortcut::change_selected_language_setting, + shortcut::change_overlay_enabled_setting, shortcut::change_overlay_position_setting, shortcut::change_debug_mode_setting, shortcut::change_word_correction_threshold_setting, diff --git a/src-tauri/src/overlay.rs b/src-tauri/src/overlay.rs index 3745f3f6..ea14302c 100644 --- a/src-tauri/src/overlay.rs +++ b/src-tauri/src/overlay.rs @@ -349,10 +349,12 @@ struct OverlayPayload<'a> { fn show_overlay_state(app_handle: &AppHandle, state: &str) { // Check if overlay should be shown based on position setting let settings = settings::get_settings(app_handle); - if matches!( - settings.overlay_position, - OverlayPosition::None | OverlayPosition::Notch - ) { + if !settings.overlay_enabled + || matches!( + settings.overlay_position, + OverlayPosition::None | OverlayPosition::Notch + ) + { return; } @@ -427,7 +429,10 @@ fn show_overlay_state(app_handle: &AppHandle, state: &str) { /// Shows the recording overlay window with fade-in animation. pub fn show_recording_overlay(app_handle: &AppHandle) { #[cfg(all(target_os = "macos", target_arch = "aarch64"))] - if settings::get_settings(app_handle).overlay_position == OverlayPosition::Notch { + if { + let settings = settings::get_settings(app_handle); + settings.overlay_enabled && settings.overlay_position == OverlayPosition::Notch + } { crate::notch::update_state(crate::notch::NotchState::Recording); } show_overlay_state(app_handle, "recording"); @@ -436,7 +441,10 @@ pub fn show_recording_overlay(app_handle: &AppHandle) { /// Shows the transcribing overlay window. pub fn show_transcribing_overlay(app_handle: &AppHandle) { #[cfg(all(target_os = "macos", target_arch = "aarch64"))] - if settings::get_settings(app_handle).overlay_position == OverlayPosition::Notch { + if { + let settings = settings::get_settings(app_handle); + settings.overlay_enabled && settings.overlay_position == OverlayPosition::Notch + } { crate::notch::update_state(crate::notch::NotchState::Transcribing); } show_overlay_state(app_handle, "transcribing"); @@ -507,7 +515,10 @@ pub fn emit_levels(app_handle: &AppHandle, levels: &Vec) { // Forward peak level to the native notch indicator (only in notch mode) #[cfg(all(target_os = "macos", target_arch = "aarch64"))] - if settings::get_settings(app_handle).overlay_position == OverlayPosition::Notch { + if { + let settings = settings::get_settings(app_handle); + settings.overlay_enabled && settings.overlay_position == OverlayPosition::Notch + } { let peak = levels.iter().copied().fold(0.0f32, f32::max); crate::notch::update_audio_level(peak); } @@ -568,7 +579,10 @@ pub fn emit_streaming_text(app_handle: &AppHandle, text: &str) { // Forward streaming text to the native notch indicator (only in notch mode) #[cfg(all(target_os = "macos", target_arch = "aarch64"))] - if settings::get_settings(app_handle).overlay_position == OverlayPosition::Notch { + if { + let settings = settings::get_settings(app_handle); + settings.overlay_enabled && settings.overlay_position == OverlayPosition::Notch + } { crate::notch::update_streaming_text(text); } } diff --git a/src-tauri/src/settings.rs b/src-tauri/src/settings.rs index e277e2f7..c89b0108 100644 --- a/src-tauri/src/settings.rs +++ b/src-tauri/src/settings.rs @@ -354,6 +354,8 @@ pub struct AppSettings { pub translate_to_english: bool, #[serde(default = "default_selected_language")] pub selected_language: String, + #[serde(default = "default_overlay_enabled")] + pub overlay_enabled: bool, #[serde(default = "default_overlay_position")] pub overlay_position: OverlayPosition, #[serde(default = "default_debug_mode")] @@ -465,6 +467,17 @@ fn default_selected_language() -> String { "auto".to_string() } +fn default_overlay_enabled() -> bool { + true +} + +fn default_overlay_enabled_for_new_install() -> bool { + #[cfg(target_os = "linux")] + return false; + #[cfg(not(target_os = "linux"))] + return true; +} + fn default_overlay_position() -> OverlayPosition { #[cfg(target_os = "linux")] return OverlayPosition::None; @@ -1118,7 +1131,11 @@ fn recover_settings_from_value(settings_value: JsonValue) -> AppSettings { recover_field!(selected_output_device); recover_field!(translate_to_english); recover_field!(selected_language); + recover_field!(overlay_enabled); recover_field!(overlay_position); + if !object.contains_key("overlay_enabled") { + settings.overlay_enabled = settings.overlay_position != OverlayPosition::None; + } recover_field!(debug_mode); recover_field!(log_level); recover_field!(custom_words); @@ -1258,10 +1275,18 @@ fn read_or_create_app_settings(app: &AppHandle, log_existing: bool) -> AppSettin match serde_json::from_value::(settings_value.clone()) { Ok(mut settings) => { let settings_updated = settings_value.as_object().is_some_and(|object| { - apply_custom_post_process_base_url( + let mut updated = apply_custom_post_process_base_url( &mut settings, configured_custom_post_process_base_url(object), - ) + ); + + if !object.contains_key("overlay_enabled") { + settings.overlay_enabled = + settings.overlay_position != OverlayPosition::None; + updated = true; + } + + updated }); if log_existing { debug!( @@ -1322,6 +1347,7 @@ pub fn get_default_settings() -> AppSettings { selected_output_device: None, translate_to_english: false, selected_language: "auto".to_string(), + overlay_enabled: default_overlay_enabled_for_new_install(), overlay_position: default_overlay_position(), debug_mode: false, log_level: default_log_level(), diff --git a/src-tauri/src/shortcut/mod.rs b/src-tauri/src/shortcut/mod.rs index bd044390..f52eb5d2 100644 --- a/src-tauri/src/shortcut/mod.rs +++ b/src-tauri/src/shortcut/mod.rs @@ -613,6 +613,28 @@ pub fn change_selected_language_setting(app: AppHandle, language: String) -> Res Ok(()) } +#[tauri::command] +#[specta::specta] +pub fn change_overlay_enabled_setting(app: AppHandle, enabled: bool) -> Result<(), String> { + let mut settings = settings::get_settings(&app); + settings.overlay_enabled = enabled; + + if enabled && settings.overlay_position == OverlayPosition::None { + settings.overlay_position = OverlayPosition::Bottom; + } + + settings::write_settings(&app, settings.clone()); + + #[cfg(all(target_os = "macos", target_arch = "aarch64"))] + if !enabled || settings.overlay_position != OverlayPosition::Notch { + crate::notch::update_state(crate::notch::NotchState::Hidden); + } + + crate::utils::update_overlay_position(&app); + + Ok(()) +} + #[tauri::command] #[specta::specta] pub fn change_overlay_position_setting(app: AppHandle, position: String) -> Result<(), String> { @@ -628,6 +650,7 @@ pub fn change_overlay_position_setting(app: AppHandle, position: String) -> Resu } }; settings.overlay_position = parsed; + settings.overlay_enabled = parsed != OverlayPosition::None; settings::write_settings(&app, settings); // Dismiss the notch indicator when switching away from notch mode diff --git a/src/bindings.ts b/src/bindings.ts index cb4265e3..d36a88d1 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -77,6 +77,14 @@ async changeSelectedLanguageSetting(language: string) : Promise> { + try { + return { status: "ok", data: await TAURI_INVOKE("change_overlay_enabled_setting", { enabled }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} +}, async changeOverlayPositionSetting(position: string) : Promise> { try { return { status: "ok", data: await TAURI_INVOKE("change_overlay_position_setting", { position }) }; @@ -926,7 +934,7 @@ async isLaptop() : Promise> { /** user-defined types **/ export type ActivationMode = "toggle" | "hold" | "hold_or_toggle" -export type AppSettings = { bindings?: Partial<{ [key in string]: ShortcutBinding }>; activation_mode?: ActivationMode; audio_feedback_volume?: number; sound_theme?: SoundTheme; start_hidden?: boolean; autostart_enabled?: boolean; update_checks_enabled?: boolean; selected_model?: string; always_on_microphone?: boolean; selected_microphone?: string | null; microphone_priority?: string[]; clamshell_microphone?: string | null; selected_output_device?: string | null; translate_to_english?: boolean; selected_language?: string; overlay_position?: OverlayPosition; debug_mode?: boolean; log_level?: LogLevel; custom_words?: string[]; model_unload_timeout?: ModelUnloadTimeout; word_correction_threshold?: number; history_limit?: number; recording_retention_period?: RecordingRetentionPeriod; paste_method?: PasteMethod; clipboard_handling?: ClipboardHandling; auto_submit?: boolean; auto_submit_key?: AutoSubmitKey; stt_provider_id?: string; stt_providers?: SttProvider[]; stt_api_keys?: Partial<{ [key in string]: string }>; stt_cloud_models?: Partial<{ [key in string]: string }>; post_process_enabled?: boolean; post_process_provider_id?: string; post_process_providers?: PostProcessProvider[]; post_process_api_keys?: Partial<{ [key in string]: string }>; post_process_models?: Partial<{ [key in string]: string }>; post_process_prompts?: LLMPrompt[]; post_process_selected_prompt_id?: string | null; mute_while_recording?: boolean; append_trailing_space?: boolean; app_language?: string; keyboard_implementation?: KeyboardImplementation; show_tray_icon?: boolean; paste_delay_ms?: number; typing_tool?: TypingTool; external_script_path: string | null; app_theme?: AppTheme; stt_verified_providers?: string[]; post_process_verified_providers?: string[]; post_process_input_prices?: Partial<{ [key in string]: number }>; post_process_output_prices?: Partial<{ [key in string]: number }>; stt_cloud_options?: Partial<{ [key in string]: string }>; stt_realtime_enabled?: Partial<{ [key in string]: boolean }>; stats_date_range?: StatsDateRange; dictionary_terms?: string[]; dictionary_context?: string } +export type AppSettings = { bindings?: Partial<{ [key in string]: ShortcutBinding }>; activation_mode?: ActivationMode; audio_feedback_volume?: number; sound_theme?: SoundTheme; start_hidden?: boolean; autostart_enabled?: boolean; update_checks_enabled?: boolean; selected_model?: string; always_on_microphone?: boolean; selected_microphone?: string | null; microphone_priority?: string[]; clamshell_microphone?: string | null; selected_output_device?: string | null; translate_to_english?: boolean; selected_language?: string; overlay_enabled?: boolean; overlay_position?: OverlayPosition; debug_mode?: boolean; log_level?: LogLevel; custom_words?: string[]; model_unload_timeout?: ModelUnloadTimeout; word_correction_threshold?: number; history_limit?: number; recording_retention_period?: RecordingRetentionPeriod; paste_method?: PasteMethod; clipboard_handling?: ClipboardHandling; auto_submit?: boolean; auto_submit_key?: AutoSubmitKey; stt_provider_id?: string; stt_providers?: SttProvider[]; stt_api_keys?: Partial<{ [key in string]: string }>; stt_cloud_models?: Partial<{ [key in string]: string }>; post_process_enabled?: boolean; post_process_provider_id?: string; post_process_providers?: PostProcessProvider[]; post_process_api_keys?: Partial<{ [key in string]: string }>; post_process_models?: Partial<{ [key in string]: string }>; post_process_prompts?: LLMPrompt[]; post_process_selected_prompt_id?: string | null; mute_while_recording?: boolean; append_trailing_space?: boolean; app_language?: string; keyboard_implementation?: KeyboardImplementation; show_tray_icon?: boolean; paste_delay_ms?: number; typing_tool?: TypingTool; external_script_path: string | null; app_theme?: AppTheme; stt_verified_providers?: string[]; post_process_verified_providers?: string[]; post_process_input_prices?: Partial<{ [key in string]: number }>; post_process_output_prices?: Partial<{ [key in string]: number }>; stt_cloud_options?: Partial<{ [key in string]: string }>; stt_realtime_enabled?: Partial<{ [key in string]: boolean }>; stats_date_range?: StatsDateRange; dictionary_terms?: string[]; dictionary_context?: string } export type AppTheme = "dark" | "light" | "system" export type AudioDevice = { index: string; name: string; is_default: boolean } export type AutoSubmitKey = "enter" | "ctrl_enter" | "cmd_enter" diff --git a/src/components/settings/ShowOverlay.tsx b/src/components/settings/ShowOverlay.tsx index ef36e6d2..2bd92042 100644 --- a/src/components/settings/ShowOverlay.tsx +++ b/src/components/settings/ShowOverlay.tsx @@ -1,10 +1,11 @@ import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { platform } from "@tauri-apps/plugin-os"; -import { Dropdown } from "../ui/Dropdown"; import { SettingContainer } from "../ui/SettingContainer"; +import { ToggleSwitch } from "../ui/ToggleSwitch"; import { useSettings } from "../../hooks/useSettings"; import type { OverlayPosition } from "@/bindings"; +import { cn } from "@/lib/utils"; interface ShowOverlayProps { descriptionMode?: "inline" | "tooltip"; @@ -18,7 +19,6 @@ export const ShowOverlay: React.FC = React.memo( const overlayOptions = useMemo(() => { const opts = [ - { value: "none", label: t("settings.advanced.overlay.options.none") }, { value: "bottom", label: t("settings.advanced.overlay.options.bottom"), @@ -36,23 +36,64 @@ export const ShowOverlay: React.FC = React.memo( const selectedPosition = (getSetting("overlay_position") || "bottom") as OverlayPosition; + const overlayEnabled = getSetting("overlay_enabled"); + const isEnabled = overlayEnabled ?? selectedPosition !== "none"; + const effectivePosition = + selectedPosition === "none" ? "bottom" : selectedPosition; + + const isOverlayUpdating = + isUpdating("overlay_enabled") || isUpdating("overlay_position"); return ( - - - updateSetting("overlay_position", value as OverlayPosition) - } - disabled={isUpdating("overlay_position")} + <> + { + if (checked && selectedPosition === "none") { + await updateSetting("overlay_position", "bottom"); + } + + await updateSetting("overlay_enabled", checked); + }} + disabled={isOverlayUpdating} + grouped={grouped} + descriptionMode={descriptionMode} /> - + {isEnabled && ( + +
+ {overlayOptions.map((opt) => ( + + ))} +
+
+ )} + ); }, ); diff --git a/src/i18n/locales/ar/translation.json b/src/i18n/locales/ar/translation.json index c7872698..612ba534 100644 --- a/src/i18n/locales/ar/translation.json +++ b/src/i18n/locales/ar/translation.json @@ -405,8 +405,9 @@ "description": ".عرض أيقونة Handless في شريط النظام" }, "overlay": { - "title": "موقع التراكب", - "description": "عرض تراكب الملاحظات المرئية أثناء التسجيل والتفريغ. على نظام Linux يوصى بـ 'بلا'.", + "title": "تغذية راجعة للتراكب", + "description": "يظهر تراكبًا مرئيًا أثناء التسجيل والتفريغ للحصول على تعليقات فورية حول الحالة.", + "position_label": "الموقع", "options": { "none": "بلا", "bottom": "أسفل", diff --git a/src/i18n/locales/cs/translation.json b/src/i18n/locales/cs/translation.json index 7ca994fd..7eddc5c8 100644 --- a/src/i18n/locales/cs/translation.json +++ b/src/i18n/locales/cs/translation.json @@ -369,8 +369,9 @@ "description": "Zobrazit ikonu Handless v systémové liště." }, "overlay": { - "title": "Pozice překryvu", - "description": "Zobrazovat vizuální překryv během nahrávání a přepisu. Na Linuxu je doporučeno 'Žádné'.", + "title": "Zpětná vazba překryvu", + "description": "Během nahrávání a přepisu zobrazuje vizuální překryv pro okamžitou zpětnou vazbu o stavu.", + "position_label": "Pozice", "options": { "none": "Žádné", "bottom": "Dole", diff --git a/src/i18n/locales/de/translation.json b/src/i18n/locales/de/translation.json index aa9bbe89..c5e095b0 100644 --- a/src/i18n/locales/de/translation.json +++ b/src/i18n/locales/de/translation.json @@ -369,8 +369,9 @@ "description": "Das Handless-Symbol in der Taskleiste anzeigen." }, "overlay": { - "title": "Overlay-Position", - "description": "Visuelles Feedback-Overlay während Aufnahme und Transkription anzeigen. Unter Linux wird 'Keine' empfohlen.", + "title": "Overlay-Feedback", + "description": "Zeigt während der Aufnahme und Transkription ein visuelles Overlay für sofortiges Status-Feedback an.", + "position_label": "Position", "options": { "none": "Keine", "bottom": "Unten", diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index d23fbc1a..294cbb01 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -405,8 +405,9 @@ "description": "Display the Handless icon in the system tray." }, "overlay": { - "title": "Overlay Position", - "description": "Display visual feedback overlay during recording and transcription. On Linux 'None' is recommended.", + "title": "Overlay Feedback", + "description": "Display a visual overlay during recording and transcription for immediate status feedback.", + "position_label": "Position", "options": { "none": "None", "bottom": "Bottom", diff --git a/src/i18n/locales/es/translation.json b/src/i18n/locales/es/translation.json index 54f7f780..3cc724b3 100644 --- a/src/i18n/locales/es/translation.json +++ b/src/i18n/locales/es/translation.json @@ -369,8 +369,9 @@ "description": "Mostrar el icono de Handless en la bandeja del sistema." }, "overlay": { - "title": "Posición de Superposición", - "description": "Mostrar superposición de retroalimentación visual durante la grabación y transcripción. En Linux se recomienda 'Ninguna'.", + "title": "Retroalimentación de Superposición", + "description": "Muestra una superposición visual durante la grabación y la transcripción para obtener comentarios de estado inmediatos.", + "position_label": "Posición", "options": { "none": "Ninguna", "bottom": "Abajo", diff --git a/src/i18n/locales/fr/translation.json b/src/i18n/locales/fr/translation.json index 78358325..ca101484 100644 --- a/src/i18n/locales/fr/translation.json +++ b/src/i18n/locales/fr/translation.json @@ -396,8 +396,9 @@ "description": "Afficher l'icône de Handless dans la barre système." }, "overlay": { - "title": "Position de la fenêtre d'enregistrement", - "description": "Afficher un retour visuel pendant l'enregistrement et la transcription. Sur Linux, 'Aucune' est recommandé.", + "title": "Retour visuel de superposition", + "description": "Affiche une superposition visuelle pendant l’enregistrement et la transcription pour un retour d’état immédiat.", + "position_label": "Position", "options": { "none": "Aucune", "bottom": "Bas", diff --git a/src/i18n/locales/it/translation.json b/src/i18n/locales/it/translation.json index aa7dfb37..13ae3b1c 100644 --- a/src/i18n/locales/it/translation.json +++ b/src/i18n/locales/it/translation.json @@ -369,8 +369,9 @@ "description": "Mostra l'icona di Handless nella barra di sistema." }, "overlay": { - "title": "Posizione della Sovrimpressione", - "description": "Mostra un feedback visivo in sovrimpressione durante la registrazione e la trascrizione. Su Linux si raccomanda 'Nessuna'.", + "title": "Feedback in Sovrimpressione", + "description": "Mostra una sovrimpressione visiva durante la registrazione e la trascrizione per un feedback immediato sullo stato.", + "position_label": "Posizione", "options": { "none": "Nessuna", "bottom": "In basso", diff --git a/src/i18n/locales/ja/translation.json b/src/i18n/locales/ja/translation.json index e65a6b86..a9d6dfcd 100644 --- a/src/i18n/locales/ja/translation.json +++ b/src/i18n/locales/ja/translation.json @@ -369,8 +369,9 @@ "description": "システムトレイにHandlessのアイコンを表示します。" }, "overlay": { - "title": "オーバーレイ位置", - "description": "録音と文字起こし中に視覚的なフィードバックオーバーレイを表示。Linuxでは「なし」を推奨。", + "title": "オーバーレイ・フィードバック", + "description": "録音と文字起こし中に視覚的なオーバーレイを表示し、即座にステータスをフィードバックします。", + "position_label": "位置", "options": { "none": "なし", "bottom": "下", diff --git a/src/i18n/locales/ko/translation.json b/src/i18n/locales/ko/translation.json index ee4c26f2..fc6f1eb4 100644 --- a/src/i18n/locales/ko/translation.json +++ b/src/i18n/locales/ko/translation.json @@ -369,8 +369,9 @@ "description": "시스템 트레이에 Handless 아이콘을 표시합니다." }, "overlay": { - "title": "오버레이 위치", - "description": "녹음 및 전사 중 시각적 피드백 오버레이를 표시합니다. Linux에서는 '없음'을 권장합니다.", + "title": "오버레이 피드백", + "description": "즉각적인 상태 피드백을 위해 녹음 및 전사 중에 시각적 오버레이를 표시합니다.", + "position_label": "위치", "options": { "none": "없음", "bottom": "하단", diff --git a/src/i18n/locales/pl/translation.json b/src/i18n/locales/pl/translation.json index c64081c0..6bf4cc5c 100644 --- a/src/i18n/locales/pl/translation.json +++ b/src/i18n/locales/pl/translation.json @@ -405,8 +405,9 @@ "description": "Wyświetlaj ikonę Handless w zasobniku systemowym." }, "overlay": { - "title": "Pozycja nakładki", - "description": "Wyświetlaj wizualną nakładkę podczas nagrywania i transkrypcji. Na Linuxie zalecane 'Brak'.", + "title": "Informacja zwrotna nakładki", + "description": "Wyświetla wizualną nakładkę podczas nagrywania i transkrypcji w celu natychmiastowej informacji zwrotnej o stanie.", + "position_label": "Pozycja", "options": { "none": "Brak", "bottom": "Dół", diff --git a/src/i18n/locales/pt/translation.json b/src/i18n/locales/pt/translation.json index 4bf33902..4e25b74a 100644 --- a/src/i18n/locales/pt/translation.json +++ b/src/i18n/locales/pt/translation.json @@ -405,8 +405,9 @@ "description": "Exibir o ícone do Handless na bandeja do sistema." }, "overlay": { - "title": "Posição da Sobreposição", - "description": "Exibir sobreposição de feedback visual durante gravação e transcrição. No Linux, 'Nenhum' é recomendado.", + "title": "Feedback de Sobreposição", + "description": "Exibe uma sobreposição visual durante a gravação e transcrição para feedback imediato do status.", + "position_label": "Posição", "options": { "none": "Nenhum", "bottom": "Inferior", diff --git a/src/i18n/locales/ru/translation.json b/src/i18n/locales/ru/translation.json index e617132d..78b350d2 100644 --- a/src/i18n/locales/ru/translation.json +++ b/src/i18n/locales/ru/translation.json @@ -369,8 +369,9 @@ "description": "Отображать значок Handless в системном трее." }, "overlay": { - "title": "Позиция наложения", - "description": "Отображение наложения визуальной обратной связи во время записи и транскрипции. В Linux рекомендуется выбрать «Нет».", + "title": "Обратная связь наложения", + "description": "Отображение визуального наложения во время записи и транскрипции для немедленной обратной связи о статусе.", + "position_label": "Позиция", "options": { "none": "Нет", "bottom": "Снизу", diff --git a/src/i18n/locales/tr/translation.json b/src/i18n/locales/tr/translation.json index 0c5c5f57..7eb75ae0 100644 --- a/src/i18n/locales/tr/translation.json +++ b/src/i18n/locales/tr/translation.json @@ -369,8 +369,9 @@ "description": "Handless simgesini sistem tepsisinde göster." }, "overlay": { - "title": "Overlay Konumu", - "description": "Kayıt ve transkripsiyon sırasında görsel geri bildirim kaplamasını gösterir. Linux'ta 'Yok' önerilir.", + "title": "Overlay Geri Bildirimi", + "description": "Anında durum geri bildirimi için kayıt ve transkripsiyon sırasında görsel bir kaplama görüntüler.", + "position_label": "Konum", "options": { "none": "Yok", "bottom": "Alt", diff --git a/src/i18n/locales/uk/translation.json b/src/i18n/locales/uk/translation.json index 6a1e2129..d25d2d35 100644 --- a/src/i18n/locales/uk/translation.json +++ b/src/i18n/locales/uk/translation.json @@ -369,8 +369,9 @@ "description": "Відображати значок Handless у системному треї." }, "overlay": { - "title": "Позиція оверлею", - "description": "Показувати візуальний оверлей під час запису та транскрипції. На Linux рекомендовано «Немає»", + "title": "Зворотний зв'язок оверлею", + "description": "Відображає візуальний оверлей під час запису та транскрипції для миттєвого зворотного зв'язку про статус.", + "position_label": "Позиція", "options": { "none": "Немає", "bottom": "Внизу", diff --git a/src/i18n/locales/vi/translation.json b/src/i18n/locales/vi/translation.json index a798d424..c13e8506 100644 --- a/src/i18n/locales/vi/translation.json +++ b/src/i18n/locales/vi/translation.json @@ -405,8 +405,9 @@ "description": "Hiển thị biểu tượng Handless trong khay hệ thống." }, "overlay": { - "title": "Vị trí lớp phủ", - "description": "Hiển thị lớp phủ phản hồi trực quan trong quá trình ghi âm và chuyển đổi. Trên Linux, 'Không có' được khuyến nghị.", + "title": "Phản hồi lớp phủ", + "description": "Hiển thị lớp phủ trực quan trong quá trình ghi âm và chuyển đổi để có phản hồi trạng thái ngay lập tức.", + "position_label": "Vị trí", "options": { "none": "Không có", "bottom": "Dưới", diff --git a/src/i18n/locales/zh-TW/translation.json b/src/i18n/locales/zh-TW/translation.json index 97f44dce..fc732d40 100644 --- a/src/i18n/locales/zh-TW/translation.json +++ b/src/i18n/locales/zh-TW/translation.json @@ -369,8 +369,9 @@ "description": "在系統匣中顯示 Handless 圖示" }, "overlay": { - "title": "懸浮窗位置", - "description": "在錄製和轉錄期間顯示視覺回饋懸浮窗。在 Linux 上建議選擇「無」", + "title": "懸浮窗回饋", + "description": "在錄音和轉錄期間顯示視覺懸浮窗,以便即時回饋狀態。", + "position_label": "位置", "options": { "none": "無", "bottom": "底部", diff --git a/src/i18n/locales/zh/translation.json b/src/i18n/locales/zh/translation.json index 787c21c2..1f175207 100644 --- a/src/i18n/locales/zh/translation.json +++ b/src/i18n/locales/zh/translation.json @@ -369,8 +369,9 @@ "description": "在系统托盘中显示 Handless 图标。" }, "overlay": { - "title": "悬浮窗位置", - "description": "在录制和转录期间显示可视反馈悬浮窗。在 Linux 上建议选择「无」。", + "title": "悬浮窗反馈", + "description": "在录音和转录期间显示可视悬浮窗,以便即时反馈状态。", + "position_label": "位置", "options": { "none": "无", "bottom": "底部", diff --git a/src/stores/settingsStore.ts b/src/stores/settingsStore.ts index e887e9c2..b8d65aa0 100644 --- a/src/stores/settingsStore.ts +++ b/src/stores/settingsStore.ts @@ -148,6 +148,8 @@ const settingUpdaters: { commands.changeTranslateToEnglishSetting(value as boolean), selected_language: (value) => commands.changeSelectedLanguageSetting(value as string), + overlay_enabled: (value) => + commands.changeOverlayEnabledSetting(value as boolean), overlay_position: (value) => commands.changeOverlayPositionSetting(value as string), debug_mode: (value) => commands.changeDebugModeSetting(value as boolean),