Feat: Implement intelligent right-click copy/paste and add missing translations

This commit is contained in:
TomZz
2026-06-12 02:27:09 +08:00
parent 890ce85cfc
commit 58fd03386a
6 changed files with 90 additions and 5 deletions
+1
View File
@@ -16,6 +16,7 @@ The brand-new v0.3 introduces comprehensive upgrades to both architecture and us
-**Persistent Workspace State**: Your sidebar width adjustments, terminal themes, font settings, and file visibility preferences are completely restored upon your next launch!
-**Intelligent SSH Disconnect/Reconnect**: Greatly enhanced SSH connection resilience. Provides a beautiful and localized overlay for one-click re-connection on unexpected disconnections.
-**Hot-Swappable i18n System**: Deeply optimized internationalization. Switch instantly between English and Simplified Chinese without restarting the application.
-**Smart Right-Click Actions**: Added intelligent right-click copy and paste for the terminal, featuring a dedicated settings toggle and OS-native keyboard shortcut hints.
## Download
+1
View File
@@ -16,6 +16,7 @@
-**持久化工作区记忆**:您对侧边栏的尺寸拖拽、终端主题、字体、隐藏文件开关等一切设置都会在下次启动时原样恢复!
-**智能断线重连与状态感知**:全面增强的 SSH 网络异常处理机制,断线后直接提供美观的覆盖层用于一键重连或关闭。
-**多语言热切换增强**:深度优化的 i18n 系统,包含中文与英文在内的所有界面文案现在均支持热切换。
-**智能右键快捷操作**:新增终端右键智能复制与粘贴功能,提供专属设置项自由控制开关,并支持根据不同操作系统自适应显示原生快捷键提示。
## 下载
+4 -1
View File
@@ -91,4 +91,7 @@ failed: "Failed"
cancelled: "Cancelled"
session: "Session"
software_builtin: "Built-in"
software_builtin: "Built-in"
retry: "Retry"
right_click_copy_paste: "Right-click Copy/Paste"
copy_paste_hint: "Tip: Regardless of this switch, you can always use %{key} + C/V to copy/paste."
+4 -1
View File
@@ -91,4 +91,7 @@ failed: "失败"
cancelled: "已取消"
session: "会话"
software_builtin: "软件内置"
software_builtin: "软件内置"
retry: "重试"
right_click_copy_paste: "右键复制/粘贴"
copy_paste_hint: "提示:不管是否开启此开关,都可以使用 %{key} + C/V 快捷键进行复制和粘贴。"
+10
View File
@@ -109,6 +109,8 @@ pub struct ConfigFile {
pub terminal_font_size: f32,
#[serde(default = "default_ui_font_size")]
pub ui_font_size: f32,
#[serde(default)]
pub right_click_copy_paste: bool,
#[serde(default = "default_ui_font_family")]
pub ui_font_family: String,
#[serde(default = "default_terminal_font_family")]
@@ -302,6 +304,14 @@ impl ConfigStore {
self.cache.ui_font_family = family.to_string();
}
pub fn right_click_copy_paste(&self) -> bool {
self.cache.right_click_copy_paste
}
pub fn set_right_click_copy_paste(&mut self, val: bool) {
self.cache.right_click_copy_paste = val;
}
pub fn terminal_font_family(&self) -> &str {
if self.cache.terminal_font_family.is_empty() {
"Maple Mono NF CN"
+70 -3
View File
@@ -26,6 +26,7 @@ use gpui_component::{
ThemeRegistry, WindowExt as _,
button::{Button, ButtonVariants as _},
checkbox::Checkbox,
switch::Switch,
dialog::Dialog,
h_flex,
input::{Input, InputEvent, InputState},
@@ -939,7 +940,7 @@ impl Ashell {
self.selector_selection = self.default_selector_index();
window.open_dialog(cx, move |dialog: Dialog, _window, _| {
dialog
.title("Open Session")
.title(t!("open_session").to_string())
.w(px(520.))
.on_ok({
let view = view.clone();
@@ -1616,6 +1617,34 @@ impl Ashell {
),
),
)
.child(
v_flex()
.gap_1()
.child(
h_flex()
.items_center()
.gap_3()
.child(div().w(px(240.)).child(t!("right_click_copy_paste").to_string()))
.child(
Switch::new("right-click-copy-paste")
.checked(view.read(cx).config.right_click_copy_paste())
.on_click(window.listener_for(
&view,
|this, checked, _, cx| {
this.config.set_right_click_copy_paste(*checked);
let _ = this.config.save();
cx.notify();
},
)),
)
)
.child(
div()
.text_size(rems(0.85))
.text_color(cx.theme().muted_foreground)
.child(t!("copy_paste_hint", key = if cfg!(target_os = "macos") { "Command" } else { "Ctrl" }).to_string())
)
)
.child(
h_flex()
.items_center()
@@ -2499,6 +2528,43 @@ impl Ashell {
cx.notify();
}
fn on_terminal_right_click(
&mut self,
_event: &MouseDownEvent,
window: &mut Window,
cx: &mut Context<Self>,
) {
if !self.config.right_click_copy_paste() {
return;
}
let mut handled = false;
if let Some(text) = self.active_terminal_selection_text() {
if !text.is_empty() {
cx.write_to_clipboard(gpui::ClipboardItem::new_string(text));
let active_id = self.active_tab.clone();
if let Some(active_id) = active_id {
if let Some(tab) = self.tabs.iter_mut().find(|tab| tab.id == active_id) {
tab.clear_selection();
}
}
cx.notify();
handled = true;
}
}
if !handled {
if let Some(clipboard_item) = cx.read_from_clipboard() {
if let Some(text) = clipboard_item.text() {
if !text.is_empty() {
self.paste_into_terminal(&text, window, cx);
}
}
}
}
}
fn begin_terminal_selection(&mut self, event: &MouseDownEvent, cx: &mut Context<Self>) {
let click_count = event.click_count.max(1);
let selection_type = match click_count {
@@ -3913,6 +3979,7 @@ impl Render for Ashell {
.track_focus(&self.focus_handle)
.key_context(TERMINAL_KEY_CONTEXT)
.on_mouse_down(MouseButton::Left, cx.listener(Self::focus_terminal))
.on_mouse_down(MouseButton::Right, cx.listener(Self::on_terminal_right_click))
.on_mouse_move(cx.listener(Self::on_terminal_mouse_move))
.on_mouse_up(MouseButton::Left, cx.listener(Self::on_terminal_mouse_up))
.on_key_down(cx.listener(Self::on_terminal_key_down))
@@ -4082,14 +4149,14 @@ impl Render for Ashell {
.child(
Button::new("ssh-connect-progress-retry")
.primary()
.label("retry")
.label(t!("retry").to_string())
.on_click(cx.listener(|this, _, _, cx| {
this.retry_connection_progress(cx)
})),
)
.child(
Button::new("ssh-connect-progress-close")
.label("cancel")
.label(t!("cancel").to_string())
.on_click(cx.listener(|this, _, _, cx| {
this.cancel_connection_progress(cx)
})),