diff --git a/openless-all/app/src-tauri/src/coordinator.rs b/openless-all/app/src-tauri/src/coordinator.rs index 5aaffecc..c3a8ca22 100644 --- a/openless-all/app/src-tauri/src/coordinator.rs +++ b/openless-all/app/src-tauri/src/coordinator.rs @@ -44,13 +44,13 @@ use crate::polish::{ use crate::qa_hotkey::{QaHotkeyError, QaHotkeyEvent, QaHotkeyMonitor}; use crate::recorder::{Recorder, RecorderError}; use crate::selection::capture_selection; +#[cfg(target_os = "windows")] +use crate::types::PasteShortcut; use crate::types::{ CapsulePayload, CapsuleState, ChineseScriptPreference, DictationSession, HotkeyCapability, HotkeyStatus, HotkeyStatusState, InsertStatus, OutputLanguagePreference, PolishMode, }; #[cfg(target_os = "windows")] -use crate::types::{PasteShortcut, WindowsNonTsfFallbackMode}; -#[cfg(target_os = "windows")] use crate::windows_ime_ipc::ImeSubmitTarget; #[cfg(target_os = "windows")] use crate::windows_ime_session::{PreparedWindowsImeSession, WindowsImeSessionController}; @@ -1970,7 +1970,6 @@ async fn insert_with_windows_ime_first( restore_clipboard: bool, allow_non_tsf_insertion_fallback: bool, paste_shortcut: PasteShortcut, - fallback_mode: WindowsNonTsfFallbackMode, ime_target: Option, ) -> InsertStatus { let prepared = { @@ -1983,13 +1982,7 @@ async fn insert_with_windows_ime_first( allow_non_tsf_insertion_fallback, InsertStatus::Failed, ) { - return insert_via_non_tsf_fallback( - inner, - polished, - restore_clipboard, - paste_shortcut, - fallback_mode, - ); + return insert_via_non_tsf_fallback(inner, polished, restore_clipboard, paste_shortcut); } log::warn!("[windows-ime] non-TSF insertion fallback is disabled; failing insert"); return InsertStatus::Failed; @@ -2014,13 +2007,7 @@ async fn insert_with_windows_ime_first( if ime_status == InsertStatus::Inserted { ime_status } else if should_try_non_tsf_insertion_fallback(allow_non_tsf_insertion_fallback, ime_status) { - insert_via_non_tsf_fallback( - inner, - polished, - restore_clipboard, - paste_shortcut, - fallback_mode, - ) + insert_via_non_tsf_fallback(inner, polished, restore_clipboard, paste_shortcut) } else { log::warn!("[windows-ime] TSF did not insert; non-TSF insertion fallback is disabled"); InsertStatus::Failed @@ -2041,27 +2028,6 @@ fn insert_via_non_tsf_fallback( polished: &str, restore_clipboard: bool, paste_shortcut: PasteShortcut, - fallback_mode: WindowsNonTsfFallbackMode, -) -> InsertStatus { - match fallback_mode { - WindowsNonTsfFallbackMode::ClipboardPaste => insert_via_clipboard_first_non_tsf_fallback( - inner, - polished, - restore_clipboard, - paste_shortcut, - ), - WindowsNonTsfFallbackMode::UnicodeKeystrokes => { - insert_via_unicode_first_non_tsf_fallback(inner, polished) - } - } -} - -#[cfg(target_os = "windows")] -fn insert_via_clipboard_first_non_tsf_fallback( - inner: &Arc, - polished: &str, - restore_clipboard: bool, - paste_shortcut: PasteShortcut, ) -> InsertStatus { let mut retried_unicode = false; let status = finish_non_tsf_insertion_fallback( @@ -2105,32 +2071,6 @@ fn insert_via_clipboard_first_non_tsf_fallback( status } -#[cfg(target_os = "windows")] -fn insert_via_unicode_first_non_tsf_fallback(inner: &Arc, polished: &str) -> InsertStatus { - let status = finish_unicode_first_non_tsf_insertion_fallback( - || inner.inserter.insert_via_unicode_keystrokes(polished), - || inner.inserter.copy_fallback(polished), - ); - - match status { - InsertStatus::Inserted => { - log::warn!("[windows-ime] TSF unavailable; inserted via Unicode SendInput fallback"); - } - InsertStatus::CopiedFallback => { - log::warn!( - "[windows-ime] TSF unavailable; Unicode SendInput failed, left text on clipboard" - ); - } - InsertStatus::PasteSent | InsertStatus::Failed => { - log::warn!( - "[windows-ime] TSF unavailable; Unicode SendInput fallback failed and copy fallback failed" - ); - } - } - - status -} - #[cfg(any(target_os = "windows", test))] fn finish_non_tsf_insertion_fallback( mut clipboard_fallback: C, @@ -2153,33 +2093,9 @@ where } } -#[cfg(any(target_os = "windows", test))] -fn finish_unicode_first_non_tsf_insertion_fallback( - mut unicode_fallback: U, - mut copy_fallback: C, -) -> InsertStatus -where - U: FnMut() -> InsertStatus, - C: FnMut() -> InsertStatus, -{ - match unicode_fallback() { - InsertStatus::Inserted => InsertStatus::Inserted, - InsertStatus::PasteSent | InsertStatus::CopiedFallback | InsertStatus::Failed => { - match copy_fallback() { - InsertStatus::CopiedFallback => InsertStatus::CopiedFallback, - InsertStatus::Inserted | InsertStatus::PasteSent | InsertStatus::Failed => { - InsertStatus::Failed - } - } - } - } -} - #[cfg(test)] mod non_tsf_fallback_tests { - use super::{ - finish_non_tsf_insertion_fallback, finish_unicode_first_non_tsf_insertion_fallback, - }; + use super::finish_non_tsf_insertion_fallback; use crate::types::InsertStatus; #[test] @@ -2226,36 +2142,6 @@ mod non_tsf_fallback_tests { assert_eq!(status, InsertStatus::Failed); assert!(unicode_called); } - - #[test] - fn unicode_first_mode_copies_text_when_unicode_fails() { - let mut copy_called = false; - let status = finish_unicode_first_non_tsf_insertion_fallback( - || InsertStatus::Failed, - || { - copy_called = true; - InsertStatus::CopiedFallback - }, - ); - - assert_eq!(status, InsertStatus::CopiedFallback); - assert!(copy_called); - } - - #[test] - fn unicode_first_mode_does_not_copy_after_success() { - let mut copy_called = false; - let status = finish_unicode_first_non_tsf_insertion_fallback( - || InsertStatus::Inserted, - || { - copy_called = true; - InsertStatus::CopiedFallback - }, - ); - - assert_eq!(status, InsertStatus::Inserted); - assert!(!copy_called); - } } // ─────────────────────────── helpers ─────────────────────────── diff --git a/openless-all/app/src-tauri/src/coordinator/dictation.rs b/openless-all/app/src-tauri/src/coordinator/dictation.rs index 648789d7..2c138897 100644 --- a/openless-all/app/src-tauri/src/coordinator/dictation.rs +++ b/openless-all/app/src-tauri/src/coordinator/dictation.rs @@ -1561,8 +1561,6 @@ pub(super) async fn end_session(inner: &Arc) -> Result<(), String> { let restore_clipboard = prefs.restore_clipboard_after_paste; let allow_non_tsf_insertion_fallback = prefs.allow_non_tsf_insertion_fallback; let paste_shortcut = prefs.paste_shortcut; - #[cfg(target_os = "windows")] - let windows_non_tsf_fallback_mode = prefs.windows_non_tsf_fallback_mode; // 流式路径下,字符已经通过 Unicode keystroke 落到光标处,跳过 inserter.insert。 let status = if already_streamed { log::info!( @@ -1582,7 +1580,6 @@ pub(super) async fn end_session(inner: &Arc) -> Result<(), String> { restore_clipboard, allow_non_tsf_insertion_fallback, paste_shortcut, - windows_non_tsf_fallback_mode, ime_target, ) .await diff --git a/openless-all/app/src-tauri/src/types.rs b/openless-all/app/src-tauri/src/types.rs index 9a405b06..737c479a 100644 --- a/openless-all/app/src-tauri/src/types.rs +++ b/openless-all/app/src-tauri/src/types.rs @@ -60,17 +60,6 @@ pub enum PasteShortcut { ShiftInsert, } -/// Windows TSF 不可用时的非 TSF 插入策略。 -/// `ClipboardPaste` 是默认安全路径:避免长文本逐字 SendInput 压垮目标应用; -/// `UnicodeKeystrokes` 保留给会吞掉粘贴快捷键、但接受合成字符输入的应用。 -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)] -#[serde(rename_all = "camelCase")] -pub enum WindowsNonTsfFallbackMode { - #[default] - ClipboardPaste, - UnicodeKeystrokes, -} - /// Auto-update 渠道。决定 Settings → 关于 里展示哪一类版本信息。 /// `Stable` 沿用 `tauri-plugin-updater` 的默认 endpoints(即 `tauri.conf.json` /// 里的 `latest-{{target}}-{{arch}}.json`),与发版 pipeline 对齐。 @@ -555,15 +544,11 @@ pub struct UserPreferences { /// 行为一致,不破坏既有用户。 #[serde(default)] pub paste_shortcut: PasteShortcut, - /// Windows: 是否允许 TSF 失败后继续使用非 TSF 方式兜底。 - /// 具体方式由 `windows_non_tsf_fallback_mode` 决定。 + /// Windows: 是否允许 TSF 失败后继续使用快捷键粘贴 / 剪贴板兜底。 + /// 仅在剪贴板写入失败时才再试 Unicode SendInput,避免长文本注入卡顿。 /// 默认开启以保持可用性;关闭后可验证文本是否真正由 TSF 上屏。 #[serde(default = "default_true")] pub allow_non_tsf_insertion_fallback: bool, - /// Windows: TSF 失败后的非 TSF 插入方式。默认剪贴板粘贴,避免 #491 的长文本 - /// SendInput 压力;少数会吞粘贴快捷键的应用可手动切到 Unicode SendInput。 - #[serde(default)] - pub windows_non_tsf_fallback_mode: WindowsNonTsfFallbackMode, /// 用户的工作语言(多选,原生名)。会作为前提注入 LLM polish/translate 的 system prompt 头部, /// 让模型知道该用户在哪些语言间工作。详见 issue #4。 #[serde(default = "default_working_languages")] @@ -770,8 +755,6 @@ struct UserPreferencesWire { #[serde(default)] paste_shortcut: PasteShortcut, allow_non_tsf_insertion_fallback: bool, - #[serde(default)] - windows_non_tsf_fallback_mode: WindowsNonTsfFallbackMode, working_languages: Vec, translation_target_language: String, chinese_script_preference: ChineseScriptPreference, @@ -846,7 +829,6 @@ impl Default for UserPreferencesWire { restore_clipboard_after_paste: prefs.restore_clipboard_after_paste, paste_shortcut: prefs.paste_shortcut, allow_non_tsf_insertion_fallback: prefs.allow_non_tsf_insertion_fallback, - windows_non_tsf_fallback_mode: prefs.windows_non_tsf_fallback_mode, working_languages: prefs.working_languages, translation_target_language: prefs.translation_target_language, chinese_script_preference: prefs.chinese_script_preference, @@ -922,7 +904,6 @@ impl<'de> Deserialize<'de> for UserPreferences { restore_clipboard_after_paste: wire.restore_clipboard_after_paste, paste_shortcut: wire.paste_shortcut, allow_non_tsf_insertion_fallback: wire.allow_non_tsf_insertion_fallback, - windows_non_tsf_fallback_mode: wire.windows_non_tsf_fallback_mode, working_languages: wire.working_languages, translation_target_language: wire.translation_target_language, chinese_script_preference: wire.chinese_script_preference, @@ -1610,7 +1591,6 @@ impl Default for UserPreferences { restore_clipboard_after_paste: true, paste_shortcut: PasteShortcut::default(), allow_non_tsf_insertion_fallback: true, - windows_non_tsf_fallback_mode: WindowsNonTsfFallbackMode::default(), working_languages: default_working_languages(), translation_target_language: String::new(), chinese_script_preference: ChineseScriptPreference::Auto, @@ -2380,36 +2360,6 @@ mod tests { } } - #[test] - fn windows_non_tsf_fallback_mode_defaults_to_clipboard_paste() { - let prefs = UserPreferences::default(); - assert_eq!( - prefs.windows_non_tsf_fallback_mode, - WindowsNonTsfFallbackMode::ClipboardPaste - ); - - let from_empty: UserPreferences = serde_json::from_str("{}").unwrap(); - assert_eq!( - from_empty.windows_non_tsf_fallback_mode, - WindowsNonTsfFallbackMode::ClipboardPaste - ); - } - - #[test] - fn windows_non_tsf_fallback_mode_round_trips_explicit_values() { - for (raw, expected) in [ - ("clipboardPaste", WindowsNonTsfFallbackMode::ClipboardPaste), - ( - "unicodeKeystrokes", - WindowsNonTsfFallbackMode::UnicodeKeystrokes, - ), - ] { - let json = format!(r#"{{ "windowsNonTsfFallbackMode": "{raw}" }}"#); - let prefs: UserPreferences = serde_json::from_str(&json).unwrap(); - assert_eq!(prefs.windows_non_tsf_fallback_mode, expected, "raw={raw}"); - } - } - #[test] fn legacy_custom_hotkey_without_custom_binding_is_rejected() { let result = serde_json::from_str::( diff --git a/openless-all/app/src/i18n/en.ts b/openless-all/app/src/i18n/en.ts index d96e61d4..943f9880 100644 --- a/openless-all/app/src/i18n/en.ts +++ b/openless-all/app/src/i18n/en.ts @@ -546,11 +546,7 @@ export const en: typeof zhCN = { comboClear: 'Clear', comboConflict: 'This shortcut combination is not available', allowNonTsfFallbackLabel: 'Allow non-TSF fallback', - allowNonTsfFallbackDesc: 'Windows: when TSF insertion fails, allow clipboard paste or Unicode SendInput as a fallback.', - windowsNonTsfFallbackModeLabel: 'Non-TSF fallback method', - windowsNonTsfFallbackModeDesc: 'Default to clipboard paste to avoid long-text stalls; switch to Unicode SendInput for apps that swallow paste shortcuts.', - windowsNonTsfFallbackModeClipboardPaste: 'Clipboard + paste shortcut (default)', - windowsNonTsfFallbackModeUnicodeKeystrokes: 'Unicode SendInput (for paste-blocking apps)', + allowNonTsfFallbackDesc: 'Windows: when TSF insertion fails, try shortcut paste first; only fall back to Unicode SendInput if clipboard write fails.', historyGroupTitle: 'History & context', historyRetentionLabel: 'History retention (days)', historyRetentionDesc: 'Entries older than this are pruned on new writes; 0 = no time-based pruning.', diff --git a/openless-all/app/src/i18n/ja.ts b/openless-all/app/src/i18n/ja.ts index 5841b41e..fa688a09 100644 --- a/openless-all/app/src/i18n/ja.ts +++ b/openless-all/app/src/i18n/ja.ts @@ -548,11 +548,7 @@ export const ja: typeof zhCN = { comboClear: 'クリア', comboConflict: 'このショートカットの組み合わせは使用できません', allowNonTsfFallbackLabel: '非 TSF フォールバックを許可', - allowNonTsfFallbackDesc: 'Windows:TSF 入力が失敗した時に、クリップボード貼り付けまたは Unicode SendInput でフォールバックします。', - windowsNonTsfFallbackModeLabel: '非 TSF フォールバック方式', - windowsNonTsfFallbackModeDesc: '既定では長文の停止を避けるためクリップボード貼り付けを使います。貼り付けショートカットを無視するアプリでは Unicode SendInput に切り替えてください。', - windowsNonTsfFallbackModeClipboardPaste: 'クリップボード + 貼り付けショートカット(既定)', - windowsNonTsfFallbackModeUnicodeKeystrokes: 'Unicode SendInput(貼り付けを無視するアプリ向け)', + allowNonTsfFallbackDesc: 'Windows:TSF 入力が失敗した時は先にショートカット貼り付けを試し、クリップボード書き込みも失敗した時だけ Unicode SendInput に切り替えます。', historyGroupTitle: '履歴とコンテキスト', historyRetentionLabel: '履歴保持期間(日)', historyRetentionDesc: '保持日数を超えた履歴は新規書き込み時に削除されます。0 = 時間で削除しない。', diff --git a/openless-all/app/src/i18n/ko.ts b/openless-all/app/src/i18n/ko.ts index 3db4bd6e..50304f3d 100644 --- a/openless-all/app/src/i18n/ko.ts +++ b/openless-all/app/src/i18n/ko.ts @@ -548,11 +548,7 @@ export const ko: typeof zhCN = { comboClear: '지우기', comboConflict: '이 단축키 조합은 사용할 수 없습니다', allowNonTsfFallbackLabel: '비 TSF 폴백 허용', - allowNonTsfFallbackDesc: 'Windows: TSF 입력이 실패하면 클립보드 붙여넣기 또는 Unicode SendInput으로 폴백합니다.', - windowsNonTsfFallbackModeLabel: '비 TSF 폴백 방식', - windowsNonTsfFallbackModeDesc: '기본값은 긴 텍스트 지연을 피하기 위해 클립보드 붙여넣기를 사용합니다. 붙여넣기 단축키를 무시하는 앱은 Unicode SendInput으로 전환하세요.', - windowsNonTsfFallbackModeClipboardPaste: '클립보드 + 붙여넣기 단축키 (기본값)', - windowsNonTsfFallbackModeUnicodeKeystrokes: 'Unicode SendInput (붙여넣기 차단 앱용)', + allowNonTsfFallbackDesc: 'Windows: TSF 입력이 실패하면 먼저 단축키 붙여넣기를 시도하고, 클립보드 쓰기까지 실패한 경우에만 Unicode SendInput으로 전환.', historyGroupTitle: '기록 및 컨텍스트', historyRetentionLabel: '기록 보관 기간(일)', historyRetentionDesc: '보관 기간을 초과한 기록은 새 항목 작성 시 정리됩니다. 0 = 시간 기반 정리 비활성화.', diff --git a/openless-all/app/src/i18n/zh-CN.ts b/openless-all/app/src/i18n/zh-CN.ts index edb18bb5..11b42ead 100644 --- a/openless-all/app/src/i18n/zh-CN.ts +++ b/openless-all/app/src/i18n/zh-CN.ts @@ -544,11 +544,7 @@ export const zhCN = { comboClear: '清除', comboConflict: '该快捷键组合不可用', allowNonTsfFallbackLabel: '允许非 TSF 兜底', - allowNonTsfFallbackDesc: 'Windows:TSF 失败后允许继续用剪贴板粘贴或 Unicode SendInput 兜底。', - windowsNonTsfFallbackModeLabel: '非 TSF 兜底方式', - windowsNonTsfFallbackModeDesc: '默认用剪贴板粘贴,避免长文本卡顿;如果目标应用会吞粘贴快捷键,可改用 Unicode SendInput。', - windowsNonTsfFallbackModeClipboardPaste: '剪贴板 + 粘贴快捷键(默认)', - windowsNonTsfFallbackModeUnicodeKeystrokes: 'Unicode SendInput(兼容吞粘贴的应用)', + allowNonTsfFallbackDesc: 'Windows:TSF 失败时先改用快捷键粘贴;剪贴板写入失败时才退到 Unicode SendInput。', historyGroupTitle: '历史与上下文', historyRetentionLabel: '历史保留天数', historyRetentionDesc: '超过保留天数的历史在写入新条目时被清理;0 = 不按时间清理。', diff --git a/openless-all/app/src/i18n/zh-TW.ts b/openless-all/app/src/i18n/zh-TW.ts index 1cdfe2f7..40e3334a 100644 --- a/openless-all/app/src/i18n/zh-TW.ts +++ b/openless-all/app/src/i18n/zh-TW.ts @@ -546,11 +546,7 @@ export const zhTW: typeof zhCN = { pasteShortcutCtrlShiftV: 'Ctrl+Shift+V(kitty / alacritty / wezterm / 多數終端)', pasteShortcutShiftInsert: 'Shift+Insert(xterm / urxvt)', allowNonTsfFallbackLabel: '允許非 TSF 兜底', - allowNonTsfFallbackDesc: 'Windows:TSF 失敗後允許繼續用剪貼簿貼上或 Unicode SendInput 兜底。', - windowsNonTsfFallbackModeLabel: '非 TSF 兜底方式', - windowsNonTsfFallbackModeDesc: '默認用剪貼簿貼上,避免長文本卡頓;如果目標應用會吞貼上快捷鍵,可改用 Unicode SendInput。', - windowsNonTsfFallbackModeClipboardPaste: '剪貼簿 + 貼上快捷鍵(默認)', - windowsNonTsfFallbackModeUnicodeKeystrokes: 'Unicode SendInput(兼容吞貼上的應用)', + allowNonTsfFallbackDesc: 'Windows:TSF 失敗時先改用快捷鍵貼上;剪貼簿寫入失敗時才退到 Unicode SendInput。', historyGroupTitle: '歷史與上下文', historyRetentionLabel: '歷史保留天數', historyRetentionDesc: '超過保留天數的歷史在寫入新條目時被清理;0 = 不按時間清理。', diff --git a/openless-all/app/src/lib/ipc.ts b/openless-all/app/src/lib/ipc.ts index 32a7c7a4..fb551d5d 100644 --- a/openless-all/app/src/lib/ipc.ts +++ b/openless-all/app/src/lib/ipc.ts @@ -77,7 +77,6 @@ let mockSettings: UserPreferences = { restoreClipboardAfterPaste: true, pasteShortcut: 'ctrlV', allowNonTsfInsertionFallback: true, - windowsNonTsfFallbackMode: 'clipboardPaste', workingLanguages: ['简体中文'], translationTargetLanguage: '', qaHotkey: defaultQaShortcut(), diff --git a/openless-all/app/src/lib/stylePrefs.test.ts b/openless-all/app/src/lib/stylePrefs.test.ts index d0683428..3f93ca38 100644 --- a/openless-all/app/src/lib/stylePrefs.test.ts +++ b/openless-all/app/src/lib/stylePrefs.test.ts @@ -38,7 +38,6 @@ const previousPrefs: UserPreferences = { restoreClipboardAfterPaste: true, pasteShortcut: 'ctrlV', allowNonTsfInsertionFallback: true, - windowsNonTsfFallbackMode: 'clipboardPaste', workingLanguages: ['简体中文'], translationTargetLanguage: '', chineseScriptPreference: 'auto', diff --git a/openless-all/app/src/lib/types.ts b/openless-all/app/src/lib/types.ts index b293f3cb..21a6a722 100644 --- a/openless-all/app/src/lib/types.ts +++ b/openless-all/app/src/lib/types.ts @@ -119,7 +119,6 @@ export type ComboBinding = ShortcutBinding; * - shiftInsert : xterm / urxvt 等老派 X11 终端 * 详见 issue #360。 */ export type PasteShortcut = 'ctrlV' | 'ctrlShiftV' | 'shiftInsert'; -export type WindowsNonTsfFallbackMode = 'clipboardPaste' | 'unicodeKeystrokes'; export type WindowsImeInstallState = | 'installed' @@ -231,10 +230,8 @@ export interface UserPreferences { * 等终端只接受 Ctrl+Shift+V,硬编码 Ctrl+V 会被吞掉,听写文本只剩在剪贴板里。 * macOS 走 AX 直写不受影响。默认 'ctrlV' 与历史行为一致。 */ pasteShortcut: PasteShortcut; - /** Windows:TSF 失败后是否允许非 TSF 兜底。关闭后可验证是否真实 TSF 上屏。 */ + /** Windows:TSF 失败后是否允许快捷键粘贴 / 剪贴板兜底。仅在剪贴板写失败时才再试 SendInput。关闭后可验证是否真实 TSF 上屏。 */ allowNonTsfInsertionFallback: boolean; - /** Windows:非 TSF 兜底方式。默认剪贴板粘贴;少数吞粘贴快捷键的应用可切到 SendInput。 */ - windowsNonTsfFallbackMode: WindowsNonTsfFallbackMode; /** 用户的工作语言(多选,原生名);作为前提注入 LLM polish/translate prompt 头部。 */ workingLanguages: string[]; /** 翻译模式目标语言(单选,原生名);空串 = 不启用 Shift 翻译。详见 issue #4。 */ diff --git a/openless-all/app/src/pages/Settings.tsx b/openless-all/app/src/pages/Settings.tsx index 25b70dfb..111a40e6 100644 --- a/openless-all/app/src/pages/Settings.tsx +++ b/openless-all/app/src/pages/Settings.tsx @@ -34,7 +34,6 @@ import type { HotkeyTrigger, MicrophoneDevice, PasteShortcut, - WindowsNonTsfFallbackMode, } from '../lib/types'; import { emitSaved } from '../lib/savedEvent'; import { useHotkeySettings } from '../state/HotkeySettingsContext'; @@ -282,8 +281,6 @@ function RecordingSection() { savePrefs({ ...prefs, pasteShortcut }); const onAllowNonTsfFallbackChange = (allowNonTsfInsertionFallback: boolean) => savePrefs({ ...prefs, allowNonTsfInsertionFallback }); - const onWindowsNonTsfFallbackModeChange = (windowsNonTsfFallbackMode: WindowsNonTsfFallbackMode) => - savePrefs({ ...prefs, windowsNonTsfFallbackMode }); // 历史保留 / 对话感知 polish 上下文窗口都用裸 number input;空字符串时回滚到默认值。 // 范围限制:retention 0-365 天,context window 0-60 分钟(再大的值对实际对话场景没意义且白烧 token)。 const clamp = (n: number, min: number, max: number) => Math.max(min, Math.min(max, n)); @@ -510,29 +507,6 @@ function RecordingSection() { /> )} - {capability.adapter === 'windowsLowLevel' && prefs.allowNonTsfInsertionFallback && ( - - onWindowsNonTsfFallbackModeChange(next as WindowsNonTsfFallbackMode)} - options={[ - { - value: 'clipboardPaste', - label: t('settings.recording.windowsNonTsfFallbackModeClipboardPaste'), - }, - { - value: 'unicodeKeystrokes', - label: t('settings.recording.windowsNonTsfFallbackModeUnicodeKeystrokes'), - }, - ]} - ariaLabel={t('settings.recording.windowsNonTsfFallbackModeLabel')} - style={{ ...inputStyle, maxWidth: 260 }} - /> - - )} {/* ─── 历史与上下文(折叠) ────────────────────────────────── */}