主机右键菜单增加复制 IP 地址

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
XuzandClaude Opus 5.5 committed 2026-10-02 20:23:21 +08:00
1 parent ee8441e301
commit a20b3bae3b
3 files changed
+37 -12

No files matched your search

+1 -1
View File
@@ -34,7 +34,7 @@ ShellRS 同一时间只运行一个:已经开着时再打开一次,会把已
对话框最后是「备注」,可以写多行(回车换行),记下机器的用途、负责人、到期时间之类,只保存在本地数据库里,不影响连接。
鼠标停在主机上,行的右侧会显示 `用户@地址:端口`,主机有备注时下面接着显示备注(太长的只显示前 6 行)。右键主机可连接、打开 SFTP、编辑、复制、复制 ID 或删除。「复制 ID」复制的是主机的 16 位随机标识(形如 `Jwg5rHvXCxw89paM`),供其他工具标识这台主机:它在主机创建时生成,改名、改地址都不变,复制出来的主机得到新的 ID,删掉的 ID 不会再分配。没有打开任何标签时,中间区显示「最近连接」列表,双击或回车连接;右键其中的主机弹出同一个菜单,并选中该主机。
鼠标停在主机上,行的右侧会显示 `用户@地址:端口`,主机有备注时下面接着显示备注(太长的只显示前 6 行)。右键主机可连接、打开 SFTP、编辑、复制、复制 IP 地址(地址是域名时叫「复制主机名」)、复制 ID 或删除。「复制 ID」复制的是主机的 16 位随机标识(形如 `Jwg5rHvXCxw89paM`),供其他工具标识这台主机:它在主机创建时生成,改名、改地址都不变,复制出来的主机得到新的 ID,删掉的 ID 不会再分配。没有打开任何标签时,中间区显示「最近连接」列表,双击或回车连接;右键其中的主机弹出同一个菜单,并选中该主机。
拖动分组或主机到同类项目的上侧 / 下侧可调整同级顺序;主机拖到分组会移入该分组,分组拖到另一个分组的中部会成为子分组。拖到列表空白处可移回根层级。分组始终排在同级主机之前,顺序与分组的展开状态会保存到本地数据库。搜索时暂停拖动排序。
+30 -8
View File
@@ -21,15 +21,16 @@ use gpui_kit::prelude::FluentBuilder as _;
use gpui_kit::*;
use crate::app::{
CatalogIcon, CollapseAllGroups, ConnectGroup, ConnectHost, ConnectSelected, CopyHostId,
DeleteGroup, DeleteHost, DuplicateHost, EditHost, ExpandAllGroups, HOST_PANEL_CONTEXT,
MoveHostNode, NewChildGroup, NewGroup, NewHost, NewHostInGroup, OpenExplorer, RenameGroup,
CatalogIcon, CollapseAllGroups, ConnectGroup, ConnectHost, ConnectSelected, CopyHostAddress,
CopyHostId, DeleteGroup, DeleteHost, DuplicateHost, EditHost, ExpandAllGroups,
HOST_PANEL_CONTEXT, MoveHostNode, NewChildGroup, NewGroup, NewHost, NewHostInGroup,
OpenExplorer, RenameGroup,
};
use crate::shared::{HostMark, RowTooltip, RowTooltips};
use super::{
GroupId, HostId, HostNode, HostOs, HostStore, NodeDrop, host_tree_items, matches_query,
GroupId, Host, HostId, HostNode, HostOs, HostStore, NodeDrop, host_tree_items, matches_query,
};
/// The host list of the left dock: a searchable, grouped tree of hosts.
@@ -506,7 +507,12 @@ impl Render for HostPanel {
},
)
})
.context_menu(move |menu, _, _| build_context_menu(clicked_menu.get(), menu)),
.context_menu({
let store = self.store.clone();
move |menu, _, cx| {
build_context_menu(clicked_menu.get(), store.read(cx), menu)
}
}),
)
.child(self.row_tooltips.overlay())
}
@@ -778,7 +784,15 @@ fn valid_drop(
/// The menu of one host, wherever it is listed: the host tree and the
/// start page's recent hosts both build it here, so they cannot drift.
pub fn host_menu(menu: PopupMenu, id: HostId) -> PopupMenu {
/// Built as it opens, from the host as it is then.
pub fn host_menu(menu: PopupMenu, host: &Host) -> PopupMenu {
let id = host.id;
// Named after what the address is, as in the tabs' menus.
let copy_address = if host.address_is_ip() {
"复制 IP 地址"
} else {
"复制主机名"
};
menu.menu_with_icon(
"连接",
Icon::new(CatalogIcon::Plug),
@@ -801,6 +815,11 @@ pub fn host_menu(menu: PopupMenu, id: HostId) -> PopupMenu {
Box::new(DuplicateHost(id)),
)
.separator()
.menu_with_icon(
copy_address,
Icon::new(CatalogIcon::ClipboardCopy),
Box::new(CopyHostAddress(id)),
)
.menu_with_icon(
"复制 ID",
Icon::new(CatalogIcon::ClipboardCopy),
@@ -814,9 +833,12 @@ pub fn host_menu(menu: PopupMenu, id: HostId) -> PopupMenu {
)
}
fn build_context_menu(node: Option<HostNode>, menu: PopupMenu) -> PopupMenu {
fn build_context_menu(node: Option<HostNode>, store: &HostStore, menu: PopupMenu) -> PopupMenu {
match node {
Some(HostNode::Host(id)) => host_menu(menu, id),
Some(HostNode::Host(id)) => match store.host(id) {
Some(host) => host_menu(menu, host),
None => menu,
},
Some(HostNode::Group(id)) => menu
.menu_with_icon(
"连接组内主机",
+6 -3
View File
@@ -144,9 +144,12 @@ impl RecentHosts {
.gap_1()
.capture_any_mouse_down(move |_, _, _| clear_hit.set(None))
.children(rows.into_iter().map(|row| self.render_row(row, cx)))
.context_menu(move |menu, _, _| match menu_hit.get() {
Some(id) => host_menu(menu, id),
None => menu,
.context_menu({
let store = self.store.clone();
move |menu, _, cx| match menu_hit.get().and_then(|id| store.read(cx).host(id)) {
Some(host) => host_menu(menu, host),
None => menu,
}
})
}