@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 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
- **设置 → 🖥️ 远程连接**:连接配置(密钥 / 密码 / ProxyJump 跳板机)· 连接测试 · 从 `~/.ssh/config` 一键导入
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.0
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 → 🖥️ Remote SSH**: connection profiles (key / password / ProxyJump bastion) · connection test · one-click import from `~/.ssh/config`
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.0
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 → 🖥️ Remote SSH** → Add a connection (host/port/user/key) → Click "Test Connection"
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": "🖥️ Remote Connections",
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
- // 且导航 CSS 类名是构建期哈希(VOzbGW_*、zOa2rq_* 每版都会变),CSS 选择器跨版本
1115
- // 不可靠。这里改为按条目文本(settings.nav)定位设置导航按钮,隐藏其 svg 图标;
1116
- // 设置面板按需挂载、语言会切换,用 MutationObserver + 语言订阅自动重跑。
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) { icon.style.display = "none"; return true; }
1124
- return false;
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 hideRemoteGearIcon() {
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
- hideRemoteGearIcon();
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) { checkCellIn(roots[i]); swapWorkspaceIconsIn(roots[i]); }
1270
+ if (roots[i].isConnected) swapWorkspaceIconsIn(roots[i]);
1246
1271
  }
1247
1272
  } else {
1248
- hideRemoteGearIcon(); // 语言切换等无根场景全量扫一次
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++) schedule(added[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 gear hide + remote workspace folder-globe icon");
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.0",
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",