@zhangfengshun/dsh-remote-ssh 2.4.0 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +3 -3
- package/README_EN.md +3 -3
- package/lib/client.js +47 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
本文件的版本号与 `package.json` 的 `version` 保持一致。每个版本对应一个 Cordis Package 快照(`pkg-N`)。
|
|
4
4
|
|
|
5
|
+
## [2.4.2] — 修复设置导航显示器图标「先齿轮后显示器」闪现
|
|
6
|
+
### 修复
|
|
7
|
+
- **图标替换从防抖路径改为同步执行**:此前设置面板挂载后,显示器图标替换走 500ms 防抖定时器,用户会先看到半秒壳层默认齿轮再变成显示器图标。现在在 MutationObserver 回调里**同步原位替换**——回调是微任务、在浏览器绘制前执行,齿轮刚插入 DOM 就被换掉,**第一帧即最终图标**,无闪现。
|
|
8
|
+
- 防抖批量路径保留给工作区地球角标(依赖异步 remoteTitles 数据);语言切换的全量补扫照旧。
|
|
9
|
+
|
|
10
|
+
## [2.4.1] — 设置页「远程连接」选项卡改用真实 SVG 显示器图标
|
|
11
|
+
### 变更
|
|
12
|
+
- **去掉标签文本里的 🖥️ emoji**:`settings.nav` 标签改为纯文本「远程连接 / Remote Connections」,不再以表情文字充当图标。
|
|
13
|
+
- **替换为真实 SVG 图标**:壳层对未知 `settings.section` 一律渲染齿轮兜底,且插槽契约暂不接受自定义图标(壳层注释:Desktop-owned display glyph kept local until the upstream slot accepts icons)。沿既有 DOM 方案把兜底齿轮原位替换为**桌面显示器轮廓图标**(圆角屏幕 + 支架 + 底座,16×16,`currentColor` 跟随主题,与 DSH 原语线稿风格一致)——与 🖥️ 语义最接近的真实图标。
|
|
14
|
+
- `replaceChild` 后 React 仅对已脱离文档的旧齿轮节点做属性更新,无对账冲突;设置面板按需挂载、语言切换、React 重渲染由 MutationObserver + 1s 幂等复检(`data-rssh-monitor` 判据)兜底。
|
|
15
|
+
|
|
5
16
|
## [2.4.0] — 命令级超时 + `remote_ssh_kill` 兜底恢复(issue #5)
|
|
6
17
|
### 新增
|
|
7
18
|
- **命令级超时**:一条挂起的远端命令(网络卡顿 / 远端进程僵死 / 等待 stdin 的 `cat`)此前会永久占用池化会话并阻塞其后所有命令,工具调用永不返回。现在所有 SSH 命令默认 **120 秒**超时:
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
## 截图
|
|
19
19
|
|
|
20
|
-
**设置 →
|
|
20
|
+
**设置 → 远程连接**:连接配置(密钥 / 密码 / ProxyJump 跳板机)· 连接测试 · 从 `~/.ssh/config` 一键导入
|
|
21
21
|
|
|
22
22
|
<p align="center"><img src="assets/settings-remote-connections.png" width="420" alt="设置:远程连接"></p>
|
|
23
23
|
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
## 安装
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
dsh plugin --profile <name> add @zhangfengshun/dsh-remote-ssh@2.4.
|
|
35
|
+
dsh plugin --profile <name> add @zhangfengshun/dsh-remote-ssh@2.4.1
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
> 安装后需**重启 DSH**。`@zhangfengshun/dsh-remote-ssh` 必须在 bundles 列表中排在 `dsh-better-sidebar` **之后**。
|
|
@@ -41,7 +41,7 @@ dsh plugin --profile <name> add @zhangfengshun/dsh-remote-ssh@2.4.0
|
|
|
41
41
|
|
|
42
42
|
## 使用
|
|
43
43
|
|
|
44
|
-
1. **设置 →
|
|
44
|
+
1. **设置 → 远程连接** → 添加连接(主机/端口/用户/密钥)→ 点「测试连接」验证
|
|
45
45
|
2. **添加工作区** → 选「选择远程目录…」→ 选连接 → 浏览并选择远程目录
|
|
46
46
|
3. 打开内置「文件」页签 → 直接显示远程文件,编辑保存直接写回远程
|
|
47
47
|
4. 打开内置「终端」页签 → 自动 SSH 到远程主机(仅密钥认证)
|
package/README_EN.md
CHANGED
|
@@ -17,7 +17,7 @@ A **DSH** plugin like **VSCode Remote-SSH**: connect to remote HPC / servers via
|
|
|
17
17
|
|
|
18
18
|
## Screenshots
|
|
19
19
|
|
|
20
|
-
**Settings →
|
|
20
|
+
**Settings → Remote SSH**: connection profiles (key / password / ProxyJump bastion) · connection test · one-click import from `~/.ssh/config`
|
|
21
21
|
|
|
22
22
|
<p align="center"><img src="assets/settings-remote-connections.png" width="420" alt="Settings: Remote Connections"></p>
|
|
23
23
|
|
|
@@ -32,7 +32,7 @@ A **DSH** plugin like **VSCode Remote-SSH**: connect to remote HPC / servers via
|
|
|
32
32
|
## Installation
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
dsh plugin --profile <name> add @zhangfengshun/dsh-remote-ssh@2.4.
|
|
35
|
+
dsh plugin --profile <name> add @zhangfengshun/dsh-remote-ssh@2.4.1
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
> **Restart DSH** after installation. `@zhangfengshun/dsh-remote-ssh` must come **after** `dsh-better-sidebar` in the bundles list.
|
|
@@ -41,7 +41,7 @@ dsh plugin --profile <name> add @zhangfengshun/dsh-remote-ssh@2.4.0
|
|
|
41
41
|
|
|
42
42
|
## Usage
|
|
43
43
|
|
|
44
|
-
1. **Settings →
|
|
44
|
+
1. **Settings → Remote SSH** → Add a connection (host/port/user/key) → Click "Test Connection"
|
|
45
45
|
2. **Add Workspace** → Choose "Select Remote Directory…" → Pick a connection → Browse and select
|
|
46
46
|
3. Open the built-in **Files** tab → Remote files shown directly, edits save back to remote
|
|
47
47
|
4. Open the built-in **Terminal** tab → Auto SSH to remote host (key auth only)
|
package/lib/client.js
CHANGED
|
@@ -62,7 +62,7 @@ window.__ModuleLoader__.load({
|
|
|
62
62
|
var zh = {
|
|
63
63
|
"tabs.files": "远程文件",
|
|
64
64
|
"tabs.term": "远程终端",
|
|
65
|
-
"settings.nav": "
|
|
65
|
+
"settings.nav": "远程连接",
|
|
66
66
|
"settings.desc": "管理 Remote-SSH 的远程连接配置(SSH 密钥或密码认证)。",
|
|
67
67
|
"settings.empty": "还没有连接配置。请在下方添加。",
|
|
68
68
|
"settings.add": "添加连接",
|
|
@@ -162,7 +162,7 @@ window.__ModuleLoader__.load({
|
|
|
162
162
|
var en = {
|
|
163
163
|
"tabs.files": "Remote Files",
|
|
164
164
|
"tabs.term": "Remote Terminal",
|
|
165
|
-
"settings.nav": "
|
|
165
|
+
"settings.nav": "Remote Connections",
|
|
166
166
|
"settings.desc": "Manage Remote-SSH connection profiles (SSH key or password authentication).",
|
|
167
167
|
"settings.empty": "No connection profiles yet. Add one below.",
|
|
168
168
|
"settings.add": "Add Profile",
|
|
@@ -1109,19 +1109,43 @@ window.__ModuleLoader__.load({
|
|
|
1109
1109
|
return function () { if (el.parentNode) el.parentNode.removeChild(el); };
|
|
1110
1110
|
});
|
|
1111
1111
|
|
|
1112
|
-
// ----
|
|
1112
|
+
// ---- 设置导航「远程连接」条目:把壳层默认齿轮换成真实显示器 SVG 图标 ----
|
|
1113
1113
|
// 壳层对未知 settings.section 一律渲染齿轮图标(IconSettingsOutline16 兜底),
|
|
1114
|
-
//
|
|
1115
|
-
//
|
|
1116
|
-
//
|
|
1114
|
+
// 且 settings.section 插槽契约暂不接受自定义图标(壳层注释:Desktop-owned display
|
|
1115
|
+
// glyph kept local until the upstream slot accepts icons),导航 CSS 类名是构建期哈希
|
|
1116
|
+
// 每版会变。这里沿既有 DOM 方案:按条目文本(settings.nav)定位设置导航按钮,把
|
|
1117
|
+
// 兜底齿轮 svg 原位替换为显示器图标(与 🖥️ 语义最接近的真实 SVG,非文字表情)。
|
|
1118
|
+
// replaceChild 后 React 只会对已脱离文档的旧齿轮节点做属性更新(无冲突),
|
|
1119
|
+
// 设置面板按需挂载、语言切换、React 重渲染由 MutationObserver + 1s 幂等复检兜底。
|
|
1117
1120
|
if (slots) {
|
|
1121
|
+
function monitorIconSvg() {
|
|
1122
|
+
var NS = "http://www.w3.org/2000/svg";
|
|
1123
|
+
var svg = document.createElementNS(NS, "svg");
|
|
1124
|
+
svg.setAttribute("viewBox", "0 0 16 16");
|
|
1125
|
+
svg.setAttribute("width", "16");
|
|
1126
|
+
svg.setAttribute("height", "16");
|
|
1127
|
+
svg.setAttribute("fill", "none");
|
|
1128
|
+
svg.setAttribute("data-rssh-monitor", "1");
|
|
1129
|
+
function add(name, attrs) {
|
|
1130
|
+
var n = document.createElementNS(NS, name);
|
|
1131
|
+
for (var k in attrs) n.setAttribute(k, attrs[k]);
|
|
1132
|
+
svg.appendChild(n);
|
|
1133
|
+
}
|
|
1134
|
+
// 桌面显示器:圆角屏幕外框 + 支架 + 底座(轮廓线风格,与 DSH 原语一致)
|
|
1135
|
+
add("rect", { x: "1.5", y: "2.5", width: "13", height: "9", rx: "1", stroke: "currentColor", "stroke-width": "1.3" });
|
|
1136
|
+
add("path", { d: "M8 11.5v3", stroke: "currentColor", "stroke-width": "1.3", "stroke-linecap": "round" });
|
|
1137
|
+
add("path", { d: "M5.5 14.5h5", stroke: "currentColor", "stroke-width": "1.3", "stroke-linecap": "round" });
|
|
1138
|
+
return svg;
|
|
1139
|
+
}
|
|
1118
1140
|
function checkCell(btn) {
|
|
1119
1141
|
var label = i18n.t("settings.nav");
|
|
1120
1142
|
var text = (btn.textContent || "").trim();
|
|
1121
1143
|
if (text !== label.trim() || text === "") return false;
|
|
1122
1144
|
var icon = btn.querySelector("svg");
|
|
1123
|
-
if (icon)
|
|
1124
|
-
return
|
|
1145
|
+
if (!icon) return false;
|
|
1146
|
+
if (icon.getAttribute("data-rssh-monitor") === "1") return true; // 已替换:幂等
|
|
1147
|
+
try { icon.parentNode.replaceChild(monitorIconSvg(), icon); } catch (e) {}
|
|
1148
|
+
return true;
|
|
1125
1149
|
}
|
|
1126
1150
|
function checkCellIn(root) {
|
|
1127
1151
|
try {
|
|
@@ -1130,7 +1154,7 @@ window.__ModuleLoader__.load({
|
|
|
1130
1154
|
for (var i = 0; i < cells.length; i++) checkCell(cells[i]);
|
|
1131
1155
|
} catch (e) {}
|
|
1132
1156
|
}
|
|
1133
|
-
function
|
|
1157
|
+
function applyRemoteNavIcon() {
|
|
1134
1158
|
try {
|
|
1135
1159
|
var buttons = document.querySelectorAll("button");
|
|
1136
1160
|
for (var i = 0; i < buttons.length; i++) checkCell(buttons[i]);
|
|
@@ -1225,7 +1249,7 @@ window.__ModuleLoader__.load({
|
|
|
1225
1249
|
}
|
|
1226
1250
|
ctx.effect(function () {
|
|
1227
1251
|
if (typeof document === "undefined") return;
|
|
1228
|
-
|
|
1252
|
+
applyRemoteNavIcon();
|
|
1229
1253
|
refreshRemoteTitles();
|
|
1230
1254
|
var titleTimer = setInterval(refreshRemoteTitles, 30000);
|
|
1231
1255
|
var recheckTimer = setInterval(recheckWatched, 1000); // 抵消 React 属性还原
|
|
@@ -1241,11 +1265,12 @@ window.__ModuleLoader__.load({
|
|
|
1241
1265
|
if (document.hidden) return; // 后台页签零开销
|
|
1242
1266
|
if (roots && roots.length) {
|
|
1243
1267
|
// 只扫新增子树:流式聊天期间不做全文档扫描(稳态成本≈0)
|
|
1268
|
+
// (设置导航图标已在 MutationObserver 回调里同步替换,这里只补工作区角标)
|
|
1244
1269
|
for (var i = 0; i < roots.length; i++) {
|
|
1245
|
-
if (roots[i].isConnected)
|
|
1270
|
+
if (roots[i].isConnected) swapWorkspaceIconsIn(roots[i]);
|
|
1246
1271
|
}
|
|
1247
1272
|
} else {
|
|
1248
|
-
|
|
1273
|
+
applyRemoteNavIcon(); // 语言切换等无根场景全量扫一次
|
|
1249
1274
|
swapWorkspaceIconsIn(document.body);
|
|
1250
1275
|
}
|
|
1251
1276
|
}, 500);
|
|
@@ -1253,7 +1278,15 @@ window.__ModuleLoader__.load({
|
|
|
1253
1278
|
var mo = new MutationObserver(function (muts) {
|
|
1254
1279
|
for (var i = 0; i < muts.length; i++) {
|
|
1255
1280
|
var added = muts[i].addedNodes;
|
|
1256
|
-
for (var j = 0; j < added.length; j++)
|
|
1281
|
+
for (var j = 0; j < added.length; j++) {
|
|
1282
|
+
var node = added[j];
|
|
1283
|
+
// 设置导航图标:同步原位替换。MutationObserver 回调是微任务,
|
|
1284
|
+
// 在浏览器绘制前执行 —— 齿轮刚插入 DOM 就被换成显示器图标,
|
|
1285
|
+
// 用户看到的第一帧就是最终图标(2.4.2 修复齿轮闪现)。
|
|
1286
|
+
if (node && node.nodeType === 1 && node.isConnected) checkCellIn(node);
|
|
1287
|
+
// 工作区地球角标依赖异步 remoteTitles,仍走防抖批量路径
|
|
1288
|
+
schedule(node);
|
|
1289
|
+
}
|
|
1257
1290
|
}
|
|
1258
1291
|
});
|
|
1259
1292
|
mo.observe(document.body, { childList: true, subtree: true });
|
|
@@ -1265,7 +1298,7 @@ window.__ModuleLoader__.load({
|
|
|
1265
1298
|
clearInterval(titleTimer);
|
|
1266
1299
|
clearInterval(recheckTimer);
|
|
1267
1300
|
};
|
|
1268
|
-
}, "dsh-remote-ssh: settings
|
|
1301
|
+
}, "dsh-remote-ssh: settings nav monitor icon + remote workspace folder-globe icon");
|
|
1269
1302
|
}
|
|
1270
1303
|
|
|
1271
1304
|
// better-sidebar 0.15+ 的文件上传 UI 把原始字节流 POST 到 /sidebar/upload。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhangfengshun/dsh-remote-ssh",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"description": "DSH web plugin: VSCode Remote-SSH-like remote development (SSH to supercomputers/servers, remote workspace, file explorer, integrated terminal), integrated with dsh-better-sidebar and DSH settings.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|