Revert "fix(windows): add Unicode fallback mode"
This reverts commit db6c4bdbda.
This commit is contained in:
1 parent
db6c4bdbda
commit
5bf197c359
12 files changed
+13
-231
No files matched your search
@@ -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<ImeSubmitTarget>,
|
||||
) -> 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<Inner>,
|
||||
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<Inner>, 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<C, U>(
|
||||
mut clipboard_fallback: C,
|
||||
@@ -2153,33 +2093,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "windows", test))]
|
||||
fn finish_unicode_first_non_tsf_insertion_fallback<U, C>(
|
||||
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 ───────────────────────────
|
||||
|
||||
@@ -1561,8 +1561,6 @@ pub(super) async fn end_session(inner: &Arc<Inner>) -> 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<Inner>) -> Result<(), String> {
|
||||
restore_clipboard,
|
||||
allow_non_tsf_insertion_fallback,
|
||||
paste_shortcut,
|
||||
windows_non_tsf_fallback_mode,
|
||||
ime_target,
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -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<String>,
|
||||
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::<UserPreferences>(
|
||||
|
||||
@@ -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.',
|
||||
|
||||
@@ -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 = 時間で削除しない。',
|
||||
|
||||
@@ -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 = 시간 기반 정리 비활성화.',
|
||||
|
||||
@@ -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 = 不按时间清理。',
|
||||
|
||||
@@ -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 = 不按時間清理。',
|
||||
|
||||
@@ -77,7 +77,6 @@ let mockSettings: UserPreferences = {
|
||||
restoreClipboardAfterPaste: true,
|
||||
pasteShortcut: 'ctrlV',
|
||||
allowNonTsfInsertionFallback: true,
|
||||
windowsNonTsfFallbackMode: 'clipboardPaste',
|
||||
workingLanguages: ['简体中文'],
|
||||
translationTargetLanguage: '',
|
||||
qaHotkey: defaultQaShortcut(),
|
||||
|
||||
@@ -38,7 +38,6 @@ const previousPrefs: UserPreferences = {
|
||||
restoreClipboardAfterPaste: true,
|
||||
pasteShortcut: 'ctrlV',
|
||||
allowNonTsfInsertionFallback: true,
|
||||
windowsNonTsfFallbackMode: 'clipboardPaste',
|
||||
workingLanguages: ['简体中文'],
|
||||
translationTargetLanguage: '',
|
||||
chineseScriptPreference: 'auto',
|
||||
|
||||
@@ -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。 */
|
||||
|
||||
@@ -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() {
|
||||
/>
|
||||
</SettingRow>
|
||||
)}
|
||||
{capability.adapter === 'windowsLowLevel' && prefs.allowNonTsfInsertionFallback && (
|
||||
<SettingRow
|
||||
label={t('settings.recording.windowsNonTsfFallbackModeLabel')}
|
||||
desc={t('settings.recording.windowsNonTsfFallbackModeDesc')}
|
||||
>
|
||||
<SelectLite
|
||||
value={prefs.windowsNonTsfFallbackMode}
|
||||
onChange={next => 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 }}
|
||||
/>
|
||||
</SettingRow>
|
||||
)}
|
||||
</Collapsible>
|
||||
|
||||
{/* ─── 历史与上下文(折叠) ────────────────────────────────── */}
|
||||
|
||||
Reference in new issue
Block a user