From 1d97570a9415e1b88fa07688da75a5d18c0254f5 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 2 Feb 2026 16:30:55 +0800 Subject: [PATCH] refactor(terminal): unify terminal selection using global settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove terminal selector from Session Manager page - Backend now reads terminal preference from global settings - Add terminal name mapping (iterm2 → iterm) for compatibility - Add WezTerm support to macOS terminal options - Add WezTerm translations for zh/en/ja --- src-tauri/src/commands/misc.rs | 1 + src-tauri/src/commands/session_manager.rs | 12 +- .../sessions/SessionManagerPage.tsx | 145 ++++-------------- src/components/settings/TerminalSettings.tsx | 1 + src/i18n/locales/en.json | 3 +- src/i18n/locales/ja.json | 3 +- src/i18n/locales/zh.json | 3 +- src/lib/api/sessions.ts | 4 +- 8 files changed, 45 insertions(+), 127 deletions(-) diff --git a/src-tauri/src/commands/misc.rs b/src-tauri/src/commands/misc.rs index 630e2ecda..9a75b0e1c 100644 --- a/src-tauri/src/commands/misc.rs +++ b/src-tauri/src/commands/misc.rs @@ -652,6 +652,7 @@ exec bash --norc --noprofile "alacritty" => launch_macos_open_app("Alacritty", &script_file, true), "kitty" => launch_macos_open_app("kitty", &script_file, false), "ghostty" => launch_macos_open_app("Ghostty", &script_file, true), + "wezterm" => launch_macos_open_app("WezTerm", &script_file, true), _ => launch_macos_terminal_app(&script_file), // "terminal" or default }; diff --git a/src-tauri/src/commands/session_manager.rs b/src-tauri/src/commands/session_manager.rs index 4eb1994a8..8a9f910d8 100644 --- a/src-tauri/src/commands/session_manager.rs +++ b/src-tauri/src/commands/session_manager.rs @@ -26,16 +26,24 @@ pub async fn get_session_messages( #[tauri::command] pub async fn launch_session_terminal( - target: String, command: String, cwd: Option, custom_config: Option, ) -> Result { let command = command.clone(); - let target = target.clone(); let cwd = cwd.clone(); let custom_config = custom_config.clone(); + // Read preferred terminal from global settings + let preferred = crate::settings::get_preferred_terminal(); + // Map global setting terminal names to session terminal names + // Global uses "iterm2", session terminal uses "iterm" + let target = match preferred.as_deref() { + Some("iterm2") => "iterm".to_string(), + Some(t) => t.to_string(), + None => "terminal".to_string(), // Default to Terminal.app on macOS + }; + tauri::async_runtime::spawn_blocking(move || { session_manager::terminal::launch_terminal( &target, diff --git a/src/components/sessions/SessionManagerPage.tsx b/src/components/sessions/SessionManagerPage.tsx index b1201b35f..b446b2e15 100644 --- a/src/components/sessions/SessionManagerPage.tsx +++ b/src/components/sessions/SessionManagerPage.tsx @@ -10,9 +10,7 @@ import { MessageSquare, Clock, FolderOpen, - Terminal, X, - SquareTerminal, } from "lucide-react"; import { useSessionMessagesQuery, useSessionsQuery } from "@/lib/query"; import { sessionsApi } from "@/lib/api"; @@ -24,7 +22,6 @@ import { SelectContent, SelectItem, SelectTrigger, - SelectValue, } from "@/components/ui/select"; import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; import { ScrollArea } from "@/components/ui/scroll-area"; @@ -37,13 +34,6 @@ import { import { extractErrorMessage } from "@/utils/errorUtils"; import { isMac } from "@/lib/platform"; import { ProviderIcon } from "@/components/ProviderIcon"; -import { - AlacrittyIcon, - GhosttyIcon, - ITermIcon, - KittyIcon, - WezTermIcon, -} from "@/components/icons/TerminalIcons"; import { SessionItem } from "./SessionItem"; import { SessionMessageItem } from "./SessionMessageItem"; import { SessionTocDialog, SessionTocSidebar } from "./SessionToc"; @@ -56,16 +46,6 @@ import { getSessionKey, } from "./utils"; -const TERMINAL_TARGET_KEY = "session_manager_terminal_target"; - -type TerminalTarget = - | "terminal" - | "iterm" - | "ghostty" - | "kitty" - | "wezterm" - | "alacritty"; - type ProviderFilter = "all" | "codex" | "claude"; export function SessionManagerPage() { @@ -85,26 +65,6 @@ export function SessionManagerPage() { const [search, setSearch] = useState(""); const [providerFilter, setProviderFilter] = useState("all"); const [selectedKey, setSelectedKey] = useState(null); - const [terminalTarget, setTerminalTarget] = - useState("terminal"); - const [isLoaded, setIsLoaded] = useState(false); - - useEffect(() => { - const storedTarget = window.localStorage.getItem( - TERMINAL_TARGET_KEY - ) as TerminalTarget | null; - if (storedTarget) { - setTerminalTarget(storedTarget); - } - - setIsLoaded(true); - }, []); - - useEffect(() => { - if (isLoaded) { - window.localStorage.setItem(TERMINAL_TARGET_KEY, terminalTarget); - } - }, [terminalTarget, isLoaded]); // 使用 FlexSearch 全文搜索 const { search: searchSessions } = useSessionSearch({ @@ -205,7 +165,6 @@ export function SessionManagerPage() { try { await sessionsApi.launchTerminal({ - target: terminalTarget, command: selectedSession.resumeCommand, cwd: selectedSession.projectDir ?? undefined, }); @@ -493,84 +452,32 @@ export function SessionManagerPage() { {/* 右侧:操作按钮组 */}
{isMac() && ( - <> - - - - - - - - {selectedSession.resumeCommand - ? t("sessionManager.resumeTooltip", { - defaultValue: "在终端中恢复此会话", - }) - : t("sessionManager.noResumeCommand", { - defaultValue: "此会话无法恢复", - })} - - - + + + + + + {selectedSession.resumeCommand + ? t("sessionManager.resumeTooltip", { + defaultValue: "在终端中恢复此会话", + }) + : t("sessionManager.noResumeCommand", { + defaultValue: "此会话无法恢复", + })} + + )}
diff --git a/src/components/settings/TerminalSettings.tsx b/src/components/settings/TerminalSettings.tsx index e1e77d7c5..c1d62a158 100644 --- a/src/components/settings/TerminalSettings.tsx +++ b/src/components/settings/TerminalSettings.tsx @@ -15,6 +15,7 @@ const MACOS_TERMINALS = [ { value: "alacritty", labelKey: "settings.terminal.options.macos.alacritty" }, { value: "kitty", labelKey: "settings.terminal.options.macos.kitty" }, { value: "ghostty", labelKey: "settings.terminal.options.macos.ghostty" }, + { value: "wezterm", labelKey: "settings.terminal.options.macos.wezterm" }, ] as const; const WINDOWS_TERMINALS = [ diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 1053a7cac..4380ea56e 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -300,7 +300,8 @@ "iterm2": "iTerm2", "alacritty": "Alacritty", "kitty": "Kitty", - "ghostty": "Ghostty" + "ghostty": "Ghostty", + "wezterm": "WezTerm" }, "windows": { "cmd": "Command Prompt", diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json index 2a47b5013..b16bb8fd0 100644 --- a/src/i18n/locales/ja.json +++ b/src/i18n/locales/ja.json @@ -300,7 +300,8 @@ "iterm2": "iTerm2", "alacritty": "Alacritty", "kitty": "Kitty", - "ghostty": "Ghostty" + "ghostty": "Ghostty", + "wezterm": "WezTerm" }, "windows": { "cmd": "コマンドプロンプト", diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index e3a504efe..a1a2b3a14 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -300,7 +300,8 @@ "iterm2": "iTerm2", "alacritty": "Alacritty", "kitty": "Kitty", - "ghostty": "Ghostty" + "ghostty": "Ghostty", + "wezterm": "WezTerm" }, "windows": { "cmd": "命令提示符", diff --git a/src/lib/api/sessions.ts b/src/lib/api/sessions.ts index 358d9abc1..3b393c44d 100644 --- a/src/lib/api/sessions.ts +++ b/src/lib/api/sessions.ts @@ -14,14 +14,12 @@ export const sessionsApi = { }, async launchTerminal(options: { - target: string; command: string; cwd?: string | null; customConfig?: string | null; }): Promise { - const { target, command, cwd, customConfig } = options; + const { command, cwd, customConfig } = options; return await invoke("launch_session_terminal", { - target, command, cwd, customConfig,