diff --git a/src-tauri/src/settings.rs b/src-tauri/src/settings.rs index a9855843..e277e2f7 100644 --- a/src-tauri/src/settings.rs +++ b/src-tauri/src/settings.rs @@ -1345,7 +1345,7 @@ pub fn get_default_settings() -> AppSettings { post_process_models: default_post_process_models(), post_process_prompts: default_post_process_prompts(), post_process_selected_prompt_id: default_post_process_selected_prompt_id(), - mute_while_recording: false, + mute_while_recording: true, append_trailing_space: false, app_language: default_app_language(), keyboard_implementation: KeyboardImplementation::default(), diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 2748d686..2c9bac88 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -4,6 +4,7 @@ import { motion, LayoutGroup } from "motion/react"; import { DragRegion } from "./ui/DragRegion"; import { House, + GearSix, Command, Cube, Book, @@ -14,6 +15,7 @@ import { import { useSettings } from "../hooks/useSettings"; import { GeneralSettings, + AdvancedSettings, ShortcutsSettings, HistorySettings, DebugSettings, @@ -77,6 +79,12 @@ export const SECTIONS_CONFIG = { component: HistorySettings, enabled: () => true, }, + advanced: { + labelKey: "sidebar.advanced", + icon: GearSix, + component: AdvancedSettings, + enabled: () => true, + }, debug: { labelKey: "sidebar.debug", icon: Bug, diff --git a/src/components/settings/MuteWhileRecording.tsx b/src/components/settings/MuteWhileRecording.tsx index b3e81542..359ab856 100644 --- a/src/components/settings/MuteWhileRecording.tsx +++ b/src/components/settings/MuteWhileRecording.tsx @@ -13,7 +13,7 @@ export const MuteWhileRecording: React.FC = const { t } = useTranslation(); const { getSetting, updateSetting, isUpdating } = useSettings(); - const muteEnabled = getSetting("mute_while_recording") ?? false; + const muteEnabled = getSetting("mute_while_recording") ?? true; return ( { + const { t } = useTranslation(); + const version = useAppVersion(); + + return ( +
+

{t("sidebar.advanced")}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* eslint-disable-next-line i18next/no-literal-string */} + v{version} + + + + + + + {t("settings.about.acknowledgments.handy.details")} + + + +
+ ); +}; diff --git a/src/components/settings/general/GeneralSettings.tsx b/src/components/settings/general/GeneralSettings.tsx index da487ac3..61014b77 100644 --- a/src/components/settings/general/GeneralSettings.tsx +++ b/src/components/settings/general/GeneralSettings.tsx @@ -1,35 +1,13 @@ import React from "react"; import { useTranslation } from "react-i18next"; -import { openUrl } from "@tauri-apps/plugin-opener"; -import { useAppVersion } from "@/hooks/useAppVersion"; import { MicrophoneSelector } from "../MicrophoneSelector"; import { SettingsGroup } from "../../ui/SettingsGroup"; -import { SettingContainer } from "../../ui/SettingContainer"; -import { Button } from "../../ui/Button"; import { VolumeSlider } from "../VolumeSlider"; import { OutputDeviceSelector } from "../OutputDeviceSelector"; -import { MuteWhileRecording } from "../MuteWhileRecording"; import { ShowOverlay } from "../ShowOverlay"; -import { ModelUnloadTimeoutSetting } from "../ModelUnloadTimeout"; -import { StartHidden } from "../StartHidden"; -import { AutostartToggle } from "../AutostartToggle"; -import { ShowTrayIcon } from "../ShowTrayIcon"; -import { ThemeSelector } from "../ThemeSelector"; -import { PasteMethodSetting } from "../PasteMethod"; -import { TypingToolSetting } from "../TypingTool"; -import { ClipboardHandlingSetting } from "../ClipboardHandling"; -import { AutoSubmit } from "../AutoSubmit"; -import { KeyboardImplementationSelector } from "../debug/KeyboardImplementationSelector"; -import { ExportImportSettings } from "../advanced/ExportImportSettings"; -import { ConfigFileSettings } from "../advanced/ConfigFileSettings"; -import { AppLanguageSelector } from "../AppLanguageSelector"; -import { AppDataDirectory } from "../AppDataDirectory"; -import { AppendTrailingSpace } from "../AppendTrailingSpace"; -import { LogDirectory } from "../debug"; export const GeneralSettings: React.FC = () => { const { t } = useTranslation(); - const version = useAppVersion(); return (
@@ -37,71 +15,12 @@ export const GeneralSettings: React.FC = () => { - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* eslint-disable-next-line i18next/no-literal-string */} - v{version} - - - - - - - {t("settings.about.acknowledgments.handy.details")} - -
); diff --git a/src/components/settings/index.ts b/src/components/settings/index.ts index 29ef7cbf..29882d08 100644 --- a/src/components/settings/index.ts +++ b/src/components/settings/index.ts @@ -1,5 +1,6 @@ // Settings section components export { GeneralSettings } from "./general/GeneralSettings"; +export { AdvancedSettings } from "./advanced/AdvancedSettings"; export { ShortcutsSettings } from "./shortcuts/ShortcutsSettings"; export { DebugSettings } from "./debug/DebugSettings"; export { HistorySettings } from "./history/HistorySettings"; diff --git a/src/i18n/locales/ar/translation.json b/src/i18n/locales/ar/translation.json index a6bfa459..c7872698 100644 --- a/src/i18n/locales/ar/translation.json +++ b/src/i18n/locales/ar/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "عام", + "advanced": "Advanced", "shortcuts": "اختصارات", "dictionary": "القاموس", "postProcessing": "معالجة لاحقة", diff --git a/src/i18n/locales/cs/translation.json b/src/i18n/locales/cs/translation.json index 2b70298d..7ca994fd 100644 --- a/src/i18n/locales/cs/translation.json +++ b/src/i18n/locales/cs/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Obecné", + "advanced": "Advanced", "shortcuts": "Zkratky", "models": "Modely", "dictionary": "Slovník", diff --git a/src/i18n/locales/de/translation.json b/src/i18n/locales/de/translation.json index 9cb9cb73..aa9bbe89 100644 --- a/src/i18n/locales/de/translation.json +++ b/src/i18n/locales/de/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Allgemein", + "advanced": "Advanced", "shortcuts": "Tastenkürzel", "models": "Modelle", "dictionary": "Wörterbuch", diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index da9e285a..d23fbc1a 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "General", + "advanced": "Advanced", "shortcuts": "Shortcuts", "models": "Models", "dictionary": "Dictionary", diff --git a/src/i18n/locales/es/translation.json b/src/i18n/locales/es/translation.json index f31b932e..54f7f780 100644 --- a/src/i18n/locales/es/translation.json +++ b/src/i18n/locales/es/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "General", + "advanced": "Advanced", "shortcuts": "Atajos", "models": "Modelos", "dictionary": "Diccionario", diff --git a/src/i18n/locales/fr/translation.json b/src/i18n/locales/fr/translation.json index 08c7cb3f..78358325 100644 --- a/src/i18n/locales/fr/translation.json +++ b/src/i18n/locales/fr/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Général", + "advanced": "Advanced", "shortcuts": "Raccourcis", "models": "Modèles", "dictionary": "Dictionnaire", diff --git a/src/i18n/locales/it/translation.json b/src/i18n/locales/it/translation.json index 8af20f8c..aa7dfb37 100644 --- a/src/i18n/locales/it/translation.json +++ b/src/i18n/locales/it/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Generale", + "advanced": "Advanced", "shortcuts": "Scorciatoie", "models": "Modelli", "dictionary": "Dizionario", diff --git a/src/i18n/locales/ja/translation.json b/src/i18n/locales/ja/translation.json index bac7948e..e65a6b86 100644 --- a/src/i18n/locales/ja/translation.json +++ b/src/i18n/locales/ja/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "一般", + "advanced": "Advanced", "shortcuts": "ショートカット", "models": "モデル", "dictionary": "辞書", diff --git a/src/i18n/locales/ko/translation.json b/src/i18n/locales/ko/translation.json index 4231f60e..ee4c26f2 100644 --- a/src/i18n/locales/ko/translation.json +++ b/src/i18n/locales/ko/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "일반", + "advanced": "Advanced", "shortcuts": "단축키", "models": "모델", "dictionary": "사전", diff --git a/src/i18n/locales/pl/translation.json b/src/i18n/locales/pl/translation.json index 39e24c98..c64081c0 100644 --- a/src/i18n/locales/pl/translation.json +++ b/src/i18n/locales/pl/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Ogólne", + "advanced": "Advanced", "shortcuts": "Skróty", "models": "Modele", "dictionary": "Słownik", diff --git a/src/i18n/locales/pt/translation.json b/src/i18n/locales/pt/translation.json index 8cecfbd6..4bf33902 100644 --- a/src/i18n/locales/pt/translation.json +++ b/src/i18n/locales/pt/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Geral", + "advanced": "Advanced", "shortcuts": "Atalhos", "models": "Modelos", "dictionary": "Dicionário", diff --git a/src/i18n/locales/ru/translation.json b/src/i18n/locales/ru/translation.json index 5fdf0eff..e617132d 100644 --- a/src/i18n/locales/ru/translation.json +++ b/src/i18n/locales/ru/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Общие", + "advanced": "Advanced", "shortcuts": "Горячие клавиши", "models": "Модели", "dictionary": "Словарь", diff --git a/src/i18n/locales/tr/translation.json b/src/i18n/locales/tr/translation.json index 9813f4d7..0c5c5f57 100644 --- a/src/i18n/locales/tr/translation.json +++ b/src/i18n/locales/tr/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Genel", + "advanced": "Advanced", "shortcuts": "Kısayollar", "models": "Modeller", "dictionary": "Sözlük", diff --git a/src/i18n/locales/uk/translation.json b/src/i18n/locales/uk/translation.json index c4f81442..6a1e2129 100644 --- a/src/i18n/locales/uk/translation.json +++ b/src/i18n/locales/uk/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Загальні", + "advanced": "Advanced", "shortcuts": "Гарячі клавіші", "models": "Моделі", "dictionary": "Dictionary", diff --git a/src/i18n/locales/vi/translation.json b/src/i18n/locales/vi/translation.json index f6db6d22..a798d424 100644 --- a/src/i18n/locales/vi/translation.json +++ b/src/i18n/locales/vi/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "Chung", + "advanced": "Advanced", "shortcuts": "Phím tắt", "models": "Mô hình", "dictionary": "Từ điển", diff --git a/src/i18n/locales/zh-TW/translation.json b/src/i18n/locales/zh-TW/translation.json index 5d604c4c..97f44dce 100644 --- a/src/i18n/locales/zh-TW/translation.json +++ b/src/i18n/locales/zh-TW/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "一般", + "advanced": "Advanced", "shortcuts": "快捷鍵", "models": "模型", "dictionary": "字典", diff --git a/src/i18n/locales/zh/translation.json b/src/i18n/locales/zh/translation.json index dc9bdf13..787c21c2 100644 --- a/src/i18n/locales/zh/translation.json +++ b/src/i18n/locales/zh/translation.json @@ -10,6 +10,7 @@ }, "sidebar": { "general": "通用", + "advanced": "Advanced", "shortcuts": "快捷键", "models": "模型", "dictionary": "词典", diff --git a/src/overlay/RecordingOverlay.css b/src/overlay/RecordingOverlay.css index bb3b3225..36ea0149 100644 --- a/src/overlay/RecordingOverlay.css +++ b/src/overlay/RecordingOverlay.css @@ -79,6 +79,15 @@ clip-path 280ms cubic-bezier(0.16, 1, 0.3, 1); } +/* Inline streaming text needs its final width immediately, otherwise the + first scrollHeight measurement is taken while the pill is still narrow. */ +.recording-overlay.has-inline-text, +.recording-overlay.fade-in.has-inline-text { + transition: + opacity 180ms ease-out, + transform 280ms cubic-bezier(0.34, 1.56, 0.64, 1); +} + /* Fade-in any new content block (exclude absolutely-positioned buttons) */ .recording-overlay > *:not(.overlay-btn):not(.postprocess-dismiss) { animation: content-enter 200ms ease-out; diff --git a/src/overlay/RecordingOverlay.tsx b/src/overlay/RecordingOverlay.tsx index 97a68676..7f432cfd 100644 --- a/src/overlay/RecordingOverlay.tsx +++ b/src/overlay/RecordingOverlay.tsx @@ -130,18 +130,18 @@ const RecordingOverlay: React.FC = () => { const buttonsExtra = showButtons ? BUTTON_AREA_WIDTH * 2 : 0; // Toggle mode: text floats above waveform bars instead of replacing them const showTextAboveBars = hasStreamingText && activationMode === "toggle"; + const showInlineStreamingText = hasStreamingText && !showTextAboveBars; // Compute overlay dimensions — pill never changes shape in toggle mode const overlayWidth = (() => { if (!isVisible) return 33; - if (hasStreamingText && !showTextAboveBars) - return STREAMING_WIDTH + buttonsExtra; + if (showInlineStreamingText) return STREAMING_WIDTH + buttonsExtra; return 70 + buttonsExtra; })(); const overlayHeight = (() => { if (!isVisible) return 33; - if (hasStreamingText && !showTextAboveBars && contentHeight > 0) { + if (showInlineStreamingText && contentHeight > 0) { const maxTextHeight = STREAMING_LINE_HEIGHT * MAX_LINES; const clampedHeight = Math.min(contentHeight, maxTextHeight); return Math.max(33, clampedHeight + OVERLAY_PADDING); @@ -149,8 +149,8 @@ const RecordingOverlay: React.FC = () => { return 33; })(); - const overlayRadius = hasStreamingText && !showTextAboveBars ? 14 : 999; - const buttonRadius = hasStreamingText && !showTextAboveBars ? 8 : 13; + const overlayRadius = showInlineStreamingText ? 14 : 999; + const buttonRadius = showInlineStreamingText ? 8 : 13; // Track words (runs before paint to avoid flicker) useLayoutEffect(() => { @@ -487,7 +487,7 @@ const RecordingOverlay: React.FC = () => { borderRadius: overlayRadius, clipPath: `inset(0 round ${overlayRadius}px)`, }} - className={`recording-overlay ${isVisible ? "fade-in" : ""} ${showButtons ? "has-buttons" : ""}`} + className={`recording-overlay ${isVisible ? "fade-in" : ""} ${showButtons ? "has-buttons" : ""} ${showInlineStreamingText ? "has-inline-text" : ""}`} > {state === "recording" && ( <> @@ -499,7 +499,7 @@ const RecordingOverlay: React.FC = () => { >