diff --git a/src-tauri/src/settings.rs b/src-tauri/src/settings.rs index 2d3580739..f82aa4c45 100644 --- a/src-tauri/src/settings.rs +++ b/src-tauri/src/settings.rs @@ -117,6 +117,14 @@ pub struct AppSettings { /// Skill 同步方式:auto(默认,优先 symlink)、symlink、copy #[serde(default)] pub skill_sync_method: SyncMethod, + + // ===== 终端设置 ===== + /// 首选终端应用(可选,默认使用系统默认终端) + /// - macOS: "terminal" | "iterm2" | "warp" | "alacritty" | "kitty" | "ghostty" + /// - Windows: "cmd" | "powershell" | "wt" (Windows Terminal) + /// - Linux: "gnome-terminal" | "konsole" | "xfce4-terminal" | "alacritty" | "kitty" | "ghostty" + #[serde(default, skip_serializing_if = "Option::is_none")] + pub preferred_terminal: Option, } fn default_show_in_tray() -> bool { @@ -147,6 +155,7 @@ impl Default for AppSettings { current_provider_gemini: None, current_provider_opencode: None, skill_sync_method: SyncMethod::default(), + preferred_terminal: None, } } } @@ -417,3 +426,17 @@ pub fn get_skill_sync_method() -> SyncMethod { }) .skill_sync_method } + +// ===== 终端设置管理函数 ===== + +/// 获取首选终端应用 +pub fn get_preferred_terminal() -> Option { + settings_store() + .read() + .unwrap_or_else(|e| { + log::warn!("设置锁已毒化,使用恢复值: {e}"); + e.into_inner() + }) + .preferred_terminal + .clone() +} diff --git a/src/components/settings/SettingsPage.tsx b/src/components/settings/SettingsPage.tsx index 915773d05..1167110fd 100644 --- a/src/components/settings/SettingsPage.tsx +++ b/src/components/settings/SettingsPage.tsx @@ -36,6 +36,7 @@ import { ThemeSettings } from "@/components/settings/ThemeSettings"; import { WindowSettings } from "@/components/settings/WindowSettings"; import { AppVisibilitySettings } from "@/components/settings/AppVisibilitySettings"; import { SkillSyncMethodSettings } from "@/components/settings/SkillSyncMethodSettings"; +import { TerminalSettings } from "@/components/settings/TerminalSettings"; import { DirectorySettings } from "@/components/settings/DirectorySettings"; import { ImportExportSection } from "@/components/settings/ImportExportSection"; import { AboutSection } from "@/components/settings/AboutSection"; @@ -256,6 +257,12 @@ export function SettingsPage({ handleAutoSave({ skillSyncMethod: method }) } /> + + handleAutoSave({ preferredTerminal: terminal }) + } + /> ) : null} diff --git a/src/components/settings/TerminalSettings.tsx b/src/components/settings/TerminalSettings.tsx new file mode 100644 index 000000000..e1e77d7c5 --- /dev/null +++ b/src/components/settings/TerminalSettings.tsx @@ -0,0 +1,111 @@ +import { useTranslation } from "react-i18next"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { isMac, isWindows, isLinux } from "@/lib/platform"; + +// Terminal options per platform +const MACOS_TERMINALS = [ + { value: "terminal", labelKey: "settings.terminal.options.macos.terminal" }, + { value: "iterm2", labelKey: "settings.terminal.options.macos.iterm2" }, + { value: "alacritty", labelKey: "settings.terminal.options.macos.alacritty" }, + { value: "kitty", labelKey: "settings.terminal.options.macos.kitty" }, + { value: "ghostty", labelKey: "settings.terminal.options.macos.ghostty" }, +] as const; + +const WINDOWS_TERMINALS = [ + { value: "cmd", labelKey: "settings.terminal.options.windows.cmd" }, + { + value: "powershell", + labelKey: "settings.terminal.options.windows.powershell", + }, + { value: "wt", labelKey: "settings.terminal.options.windows.wt" }, +] as const; + +const LINUX_TERMINALS = [ + { + value: "gnome-terminal", + labelKey: "settings.terminal.options.linux.gnomeTerminal", + }, + { value: "konsole", labelKey: "settings.terminal.options.linux.konsole" }, + { + value: "xfce4-terminal", + labelKey: "settings.terminal.options.linux.xfce4Terminal", + }, + { value: "alacritty", labelKey: "settings.terminal.options.linux.alacritty" }, + { value: "kitty", labelKey: "settings.terminal.options.linux.kitty" }, + { value: "ghostty", labelKey: "settings.terminal.options.linux.ghostty" }, +] as const; + +// Get terminals for the current platform +function getTerminalOptions() { + if (isMac()) { + return MACOS_TERMINALS; + } + if (isWindows()) { + return WINDOWS_TERMINALS; + } + if (isLinux()) { + return LINUX_TERMINALS; + } + // Fallback to macOS options + return MACOS_TERMINALS; +} + +// Get default terminal for the current platform +function getDefaultTerminal(): string { + if (isMac()) { + return "terminal"; + } + if (isWindows()) { + return "cmd"; + } + if (isLinux()) { + return "gnome-terminal"; + } + return "terminal"; +} + +export interface TerminalSettingsProps { + value?: string; + onChange: (value: string) => void; +} + +export function TerminalSettings({ value, onChange }: TerminalSettingsProps) { + const { t } = useTranslation(); + const terminals = getTerminalOptions(); + const defaultTerminal = getDefaultTerminal(); + + // Use value or default + const currentValue = value || defaultTerminal; + + return ( +
+
+

{t("settings.terminal.title")}

+

+ {t("settings.terminal.description")} +

+
+ +

+ {t("settings.terminal.fallbackHint")} +

+
+ ); +} diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index ccbf27089..2e40fbf9d 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -289,6 +289,33 @@ "copy": "Copy Files", "symlinkHint": "Symlinks save disk space and enable real-time sync. Note: May require admin privileges or Developer Mode on Windows" }, + "terminal": { + "title": "Preferred Terminal", + "description": "Choose which terminal app to use when clicking the terminal button", + "fallbackHint": "If the selected terminal is unavailable, the system default will be used", + "options": { + "macos": { + "terminal": "Terminal.app", + "iterm2": "iTerm2", + "alacritty": "Alacritty", + "kitty": "Kitty", + "ghostty": "Ghostty" + }, + "windows": { + "cmd": "Command Prompt", + "powershell": "PowerShell", + "wt": "Windows Terminal" + }, + "linux": { + "gnomeTerminal": "GNOME Terminal", + "konsole": "Konsole", + "xfce4Terminal": "Xfce4 Terminal", + "alacritty": "Alacritty", + "kitty": "Kitty", + "ghostty": "Ghostty" + } + } + }, "configDirectoryOverride": "Configuration Directory Override (Advanced)", "configDirectoryDescription": "When using Claude Code or Codex in environments like WSL, you can manually specify the configuration directory to the one in WSL to keep provider data consistent with the main environment.", "appConfigDir": "CC Switch Configuration Directory", diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json index 1b04d6fda..9e367cc51 100644 --- a/src/i18n/locales/ja.json +++ b/src/i18n/locales/ja.json @@ -289,6 +289,33 @@ "copy": "ファイルコピー", "symlinkHint": "シンボリックリンクはディスク容量を節約し、リアルタイム同期を有効にします。注意:Windowsでは管理者権限または開発者モードが必要な場合があります" }, + "terminal": { + "title": "優先ターミナル", + "description": "ターミナルボタンをクリックした時に使用するターミナルアプリを選択", + "fallbackHint": "選択したターミナルが利用できない場合、システムのデフォルトが使用されます", + "options": { + "macos": { + "terminal": "Terminal.app", + "iterm2": "iTerm2", + "alacritty": "Alacritty", + "kitty": "Kitty", + "ghostty": "Ghostty" + }, + "windows": { + "cmd": "コマンドプロンプト", + "powershell": "PowerShell", + "wt": "Windows Terminal" + }, + "linux": { + "gnomeTerminal": "GNOME Terminal", + "konsole": "Konsole", + "xfce4Terminal": "Xfce4 Terminal", + "alacritty": "Alacritty", + "kitty": "Kitty", + "ghostty": "Ghostty" + } + } + }, "configDirectoryOverride": "設定ディレクトリの上書き(詳細)", "configDirectoryDescription": "WSL などで Claude Code や Codex を使う場合、ここで設定ディレクトリを WSL 側に合わせるとデータを揃えられます。", "appConfigDir": "CC Switch 設定ディレクトリ", diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index 4f492857d..0634f91aa 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -289,6 +289,33 @@ "copy": "文件复制", "symlinkHint": "软连接节省磁盘空间并支持实时同步。注意:Windows 可能需要管理员权限或开启开发者模式" }, + "terminal": { + "title": "首选终端", + "description": "选择点击终端按钮时使用的终端应用", + "fallbackHint": "如果选择的终端不可用,将自动使用系统默认终端", + "options": { + "macos": { + "terminal": "Terminal.app", + "iterm2": "iTerm2", + "alacritty": "Alacritty", + "kitty": "Kitty", + "ghostty": "Ghostty" + }, + "windows": { + "cmd": "命令提示符", + "powershell": "PowerShell", + "wt": "Windows Terminal" + }, + "linux": { + "gnomeTerminal": "GNOME Terminal", + "konsole": "Konsole", + "xfce4Terminal": "Xfce4 Terminal", + "alacritty": "Alacritty", + "kitty": "Kitty", + "ghostty": "Ghostty" + } + } + }, "configDirectoryOverride": "配置目录覆盖(高级)", "configDirectoryDescription": "在 WSL 等环境使用 Claude Code 或 Codex 的时候,可手动指定为 WSL 里的配置目录,供应商数据与主环境保持一致。", "appConfigDir": "CC Switch 配置目录", diff --git a/src/types.ts b/src/types.ts index dc2c1a3c3..b13b21ddf 100644 --- a/src/types.ts +++ b/src/types.ts @@ -191,6 +191,13 @@ export interface Settings { // ===== Skill 同步设置 ===== // Skill 同步方式:auto(默认,优先 symlink)、symlink、copy skillSyncMethod?: SkillSyncMethod; + + // ===== 终端设置 ===== + // 首选终端应用(可选,默认使用系统默认终端) + // macOS: "terminal" | "iterm2" | "warp" | "alacritty" | "kitty" | "ghostty" + // Windows: "cmd" | "powershell" | "wt" + // Linux: "gnome-terminal" | "konsole" | "xfce4-terminal" | "alacritty" | "kitty" | "ghostty" + preferredTerminal?: string; } // MCP 服务器连接参数(宽松:允许扩展字段)