From cbf3be0d50e561006e358bc06fded8566ab32aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=95=E6=9F=8F=E9=9D=92?= Date: Sun, 7 Jun 2026 13:14:31 +0800 Subject: [PATCH] =?UTF-8?q?refactor(coordinator):=20=E5=90=88=E5=B9=B6=20t?= =?UTF-8?q?ake=5F*=5Fcombo=5Fhotkey=5Fon=5Fmain=5Fthread=20=E4=B8=89?= =?UTF-8?q?=E5=A4=84=E5=A4=8D=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit combo_hotkey / translation_hotkey / coding_agent_combo_hotkey 三个 take_*_on_main_thread 的主线程释放(issue #118)marshaling 体逐字相同,仅 take 字段不同。抽出共享 take_combo_monitor_on_main_thread(inner, slot), slot 闭包按 &Arc 取回对应 Mutex> 字段, 三处改为薄封装。action_hotkey 类已用 action_hotkey_slot 单独泛化,不动。 语义不变。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/coordinator/hotkey_supervisors.rs | 29 +++++++++++-------- .../src/coordinator/voice_agent_hotkeys.rs | 10 +------ 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/openless-all/app/src-tauri/src/coordinator/hotkey_supervisors.rs b/openless-all/app/src-tauri/src/coordinator/hotkey_supervisors.rs index fabbc9ac..b186229f 100644 --- a/openless-all/app/src-tauri/src/coordinator/hotkey_supervisors.rs +++ b/openless-all/app/src-tauri/src/coordinator/hotkey_supervisors.rs @@ -593,28 +593,33 @@ pub(crate) fn switch_to_previous_style(inner: &Arc) { } } -pub(crate) fn take_combo_hotkey_on_main_thread(inner: &Arc) { +/// 在主线程上 `.take()` 一个 combo 监听槽。 +/// +/// 这三类 combo 热键(combo / translation / coding-agent)的「拿 app → 有则 +/// `run_on_main_thread` 里 take,无则直接 take」marshaling 语义逐字相同,只是 take +/// 的字段不同(issue #118:监听器必须在主线程释放)。`slot` 闭包按 `&Arc` +/// 取回对应字段,消除三处复制。`action_hotkey` 类已用 `action_hotkey_slot` 单独泛化。 +pub(crate) fn take_combo_monitor_on_main_thread( + inner: &Arc, + slot: impl Fn(&Arc) -> &Mutex> + Send + 'static, +) { let app = inner.app.lock().clone(); if let Some(app) = app { let inner = Arc::clone(inner); let _ = app.run_on_main_thread(move || { - inner.combo_hotkey.lock().take(); + slot(&inner).lock().take(); }); } else { - inner.combo_hotkey.lock().take(); + slot(inner).lock().take(); } } +pub(crate) fn take_combo_hotkey_on_main_thread(inner: &Arc) { + take_combo_monitor_on_main_thread(inner, |inner| &inner.combo_hotkey); +} + pub(crate) fn take_translation_hotkey_on_main_thread(inner: &Arc) { - let app = inner.app.lock().clone(); - if let Some(app) = app { - let inner = Arc::clone(inner); - let _ = app.run_on_main_thread(move || { - inner.translation_hotkey.lock().take(); - }); - } else { - inner.translation_hotkey.lock().take(); - } + take_combo_monitor_on_main_thread(inner, |inner| &inner.translation_hotkey); } pub(crate) fn take_action_hotkey_on_main_thread(inner: &Arc, kind: ActionHotkeyKind) { diff --git a/openless-all/app/src-tauri/src/coordinator/voice_agent_hotkeys.rs b/openless-all/app/src-tauri/src/coordinator/voice_agent_hotkeys.rs index 90f38f2f..597eaa1e 100644 --- a/openless-all/app/src-tauri/src/coordinator/voice_agent_hotkeys.rs +++ b/openless-all/app/src-tauri/src/coordinator/voice_agent_hotkeys.rs @@ -237,15 +237,7 @@ pub(crate) fn take_coding_agent_hotkeys_on_main_thread(inner: &Arc) { } pub(crate) fn take_coding_agent_combo_hotkey_on_main_thread(inner: &Arc) { - let app = inner.app.lock().clone(); - if let Some(app) = app { - let inner = Arc::clone(inner); - let _ = app.run_on_main_thread(move || { - inner.coding_agent_combo_hotkey.lock().take(); - }); - } else { - inner.coding_agent_combo_hotkey.lock().take(); - } + take_combo_monitor_on_main_thread(inner, |inner| &inner.coding_agent_combo_hotkey); } /// 快取用:抓当前选中文本 → Claude 润色 → 回插(替换选区)。全程胶囊反馈。