@zhangfengshun/dsh-remote-ssh 2.3.3 → 2.3.4
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 +5 -0
- package/lib/client.js +45 -25
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
本文件的版本号与 `package.json` 的 `version` 保持一致。每个版本对应一个 Cordis Package 快照(`pkg-N`)。
|
|
4
4
|
|
|
5
|
+
## [2.3.4] — 修复点击会话后图标退化 + 角标加大
|
|
6
|
+
### 修复
|
|
7
|
+
- **图标退化**:点击会话等交互触发 React 重渲染,会把 svg 的 viewBox/children 还原成纯文件夹(属性级变化不触发 childList 观察器),而 2.3.3 的防重入守卫只认 data 标记——标记在即跳过,还原后永不重刷。改为:守卫校验**实际状态**(viewBox 是否为目标帧),不匹配即重新应用;并维护已匹配标题元素清单,**每 1s 幂等复检**(断连清理),任何还原 1 秒内自愈。
|
|
8
|
+
- **角标加大**:地球角标半径 3.1 → 5.2(渲染直径 ≈5px → ≈8.3px,视觉接近翻倍),地球线稿与描边同步放大,位置微调至文件夹左下角不越界。
|
|
9
|
+
|
|
5
10
|
## [2.3.3] — 修复工作区图标替换不生效
|
|
6
11
|
### 修复
|
|
7
12
|
- 2.3.2 的图标替换向上爬找「直接子级含 svg 的祖先」,但壳层工作区行的文件夹 svg 位于标题的**前兄弟槽位**(`projectRow > [slot.folder(svg), …, projectText > title]`),不是任何祖先的直接子级 → 匹配后静默跳过、图标从未被替换。改为:从标题向上最多 4 层,取每层容器的**第一个子元素**,首个含 svg 的即行首文件夹槽位;并将「插入新节点」改为**原位改写**该 svg 的 viewBox/尺寸/内容(不插入/删除节点,避免 React 对账风险;展开态切换重建 svg 后由观察器 500ms 内自动重刷)。
|
package/lib/client.js
CHANGED
|
@@ -1142,6 +1142,7 @@ window.__ModuleLoader__.load({
|
|
|
1142
1142
|
// 定位远程工作区行,找到行首 slot.folder 槽位(标题的前兄弟),把其中的 svg
|
|
1143
1143
|
// 原位改写为「地球角标文件夹」内容 —— 不插入/删除节点,避免 React 对账风险。
|
|
1144
1144
|
var remoteTitles = new Set();
|
|
1145
|
+
var watchedTitles = []; // 已匹配的标题元素:定时幂等复检,抵消 React 重渲染对图标的还原
|
|
1145
1146
|
function refreshRemoteTitles() {
|
|
1146
1147
|
api("listWorkspaces").then(function (r) {
|
|
1147
1148
|
if (!(r && r.ok && Array.isArray(r.workspaces))) return;
|
|
@@ -1154,41 +1155,58 @@ window.__ModuleLoader__.load({
|
|
|
1154
1155
|
swapWorkspaceIconsIn(document.body); // 标题集就绪后补一次全量替换
|
|
1155
1156
|
}).catch(function () {});
|
|
1156
1157
|
}
|
|
1158
|
+
var FOLDER_GLOBE_VIEWBOX = "0 0 20 16";
|
|
1157
1159
|
var FOLDER_GLOBE_INNER =
|
|
1158
1160
|
'<path d="M2.4 4.2c0-1.05.85-1.9 1.9-1.9h3.1c.52 0 1.02.21 1.39.58l1.05 1.05c.28.28.66.44 1.06.44h6.3c1.05 0 1.9.85 1.9 1.9v6.53c0 1.05-.85 1.9-1.9 1.9H4.3c-1.05 0-1.9-.85-1.9-1.9V4.2z" fill="none" stroke="currentColor" stroke-width="1.2"/>' +
|
|
1159
|
-
'<circle cx="6.
|
|
1160
|
-
'<g fill="none" stroke="#ffffff" stroke-width="0.
|
|
1161
|
+
'<circle cx="6.2" cy="10.9" r="5.2" fill="var(--dsw-alias-state-business-primary, #4c6ef5)" stroke="var(--dsw-alias-bg-layer-1, #1b1b1b)" stroke-width="1"/>' +
|
|
1162
|
+
'<g fill="none" stroke="#ffffff" stroke-width="0.9"><circle cx="6.2" cy="10.9" r="3.3"/><ellipse cx="6.2" cy="10.9" rx="1.55" ry="3.3"/><path d="M2.9 10.9h6.6"/></g>';
|
|
1163
|
+
/** 幂等应用:React 重渲染会还原 svg 属性(viewBox 回 16×16、children 回纯文件夹),
|
|
1164
|
+
* 但不感知也不清除我们的 data 标记 —— 守卫必须校验实际状态而非仅 data 标记,
|
|
1165
|
+
* 否则还原后永不重刷(2.3.3 退化 bug 根因)。 */
|
|
1166
|
+
function applyFolderGlobe(slotSvg) {
|
|
1167
|
+
if (slotSvg.getAttribute("data-rssh-folder-globe") === "1" && slotSvg.getAttribute("viewBox") === FOLDER_GLOBE_VIEWBOX) return;
|
|
1168
|
+
slotSvg.setAttribute("data-rssh-folder-globe", "1");
|
|
1169
|
+
slotSvg.setAttribute("viewBox", FOLDER_GLOBE_VIEWBOX);
|
|
1170
|
+
slotSvg.setAttribute("width", "16");
|
|
1171
|
+
slotSvg.setAttribute("height", "16");
|
|
1172
|
+
slotSvg.innerHTML = FOLDER_GLOBE_INNER;
|
|
1173
|
+
}
|
|
1174
|
+
/** 对单个标题元素做行首槽位修复:projectRow > [slot.folder(svg), …, projectText > title],
|
|
1175
|
+
* 文件夹 svg 在标题的前兄弟槽位 —— 向上 ≤4 层取每层容器第一个子元素,首个含 svg 即是。 */
|
|
1176
|
+
function fixRowIconFor(el) {
|
|
1177
|
+
var holder = el;
|
|
1178
|
+
for (var hop = 0; hop < 4 && holder && holder.parentElement; hop++) {
|
|
1179
|
+
var row = holder.parentElement;
|
|
1180
|
+
var first = row.children && row.children[0];
|
|
1181
|
+
if (first && first.querySelector && first.querySelector("svg")) {
|
|
1182
|
+
applyFolderGlobe(first.querySelector("svg"));
|
|
1183
|
+
return true;
|
|
1184
|
+
}
|
|
1185
|
+
holder = row;
|
|
1186
|
+
}
|
|
1187
|
+
return false;
|
|
1188
|
+
}
|
|
1189
|
+
function watchTitle(el) {
|
|
1190
|
+
for (var i = 0; i < watchedTitles.length; i++) { if (watchedTitles[i] === el) return; }
|
|
1191
|
+
watchedTitles.push(el);
|
|
1192
|
+
fixRowIconFor(el);
|
|
1193
|
+
}
|
|
1194
|
+
function recheckWatched() {
|
|
1195
|
+
for (var i = watchedTitles.length - 1; i >= 0; i--) {
|
|
1196
|
+
var el = watchedTitles[i];
|
|
1197
|
+
if (!el || !el.isConnected) { watchedTitles.splice(i, 1); continue; }
|
|
1198
|
+
fixRowIconFor(el);
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1161
1201
|
function swapWorkspaceIconsIn(root) {
|
|
1162
1202
|
if (!remoteTitles.size) return;
|
|
1163
1203
|
try {
|
|
1164
1204
|
var nodes = root.querySelectorAll("span,div,button,a,p");
|
|
1165
1205
|
for (var i = 0; i < nodes.length; i++) {
|
|
1166
1206
|
var el = nodes[i];
|
|
1167
|
-
if (el.getAttribute && el.getAttribute("data-rssh-title-scan") === "1") continue;
|
|
1168
1207
|
var t = (el.textContent || "").trim();
|
|
1169
1208
|
if (!t || !remoteTitles.has(t) || el.childElementCount > 2) continue;
|
|
1170
|
-
el
|
|
1171
|
-
// 行结构:projectRow > [slot.folder(svg), slot.chevron(svg), projectText > span.title, ...]
|
|
1172
|
-
// 从标题元素向上最多 4 层,取每层容器的第一个子元素——首个含 svg 的即行首
|
|
1173
|
-
// 文件夹槽位;将其 svg 原位改写为地球角标文件夹(React 复用同一节点,
|
|
1174
|
-
// 展开态切换会重建 svg,观察器 500ms 内自动重刷)。
|
|
1175
|
-
var holder = el;
|
|
1176
|
-
for (var hop = 0; hop < 4 && holder && holder.parentElement; hop++) {
|
|
1177
|
-
var row = holder.parentElement;
|
|
1178
|
-
var first = row.children && row.children[0];
|
|
1179
|
-
if (first && first.querySelector && first.querySelector("svg")) {
|
|
1180
|
-
var oldSvg = first.querySelector("svg");
|
|
1181
|
-
if (oldSvg.getAttribute("data-rssh-folder-globe") !== "1") {
|
|
1182
|
-
oldSvg.setAttribute("data-rssh-folder-globe", "1");
|
|
1183
|
-
oldSvg.setAttribute("viewBox", "0 0 20 16");
|
|
1184
|
-
oldSvg.setAttribute("width", "16");
|
|
1185
|
-
oldSvg.setAttribute("height", "16");
|
|
1186
|
-
oldSvg.innerHTML = FOLDER_GLOBE_INNER;
|
|
1187
|
-
}
|
|
1188
|
-
break;
|
|
1189
|
-
}
|
|
1190
|
-
holder = row;
|
|
1191
|
-
}
|
|
1209
|
+
watchTitle(el);
|
|
1192
1210
|
}
|
|
1193
1211
|
} catch (e) {}
|
|
1194
1212
|
}
|
|
@@ -1197,6 +1215,7 @@ window.__ModuleLoader__.load({
|
|
|
1197
1215
|
hideRemoteGearIcon();
|
|
1198
1216
|
refreshRemoteTitles();
|
|
1199
1217
|
var titleTimer = setInterval(refreshRemoteTitles, 30000);
|
|
1218
|
+
var recheckTimer = setInterval(recheckWatched, 1000); // 抵消 React 属性还原
|
|
1200
1219
|
var timer = null;
|
|
1201
1220
|
var pendingRoots = null;
|
|
1202
1221
|
var schedule = function (root) {
|
|
@@ -1231,6 +1250,7 @@ window.__ModuleLoader__.load({
|
|
|
1231
1250
|
if (off) off();
|
|
1232
1251
|
if (timer) clearTimeout(timer);
|
|
1233
1252
|
clearInterval(titleTimer);
|
|
1253
|
+
clearInterval(recheckTimer);
|
|
1234
1254
|
};
|
|
1235
1255
|
}, "dsh-remote-ssh: settings gear hide + remote workspace folder-globe icon");
|
|
1236
1256
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhangfengshun/dsh-remote-ssh",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.4",
|
|
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",
|