dsh-vscode-mode 0.15.4 → 0.15.6
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/README.md +7 -3
- package/lib/client.js +283 -105
- package/lib/client.js.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/compatSummary.ts +77 -0
- package/src/client/externalOpen.ts +21 -3
- package/src/client/index.ts +14 -10
- package/src/client/monaco/lsp/lspClient.ts +26 -5
- package/src/client/monaco/lsp/providers.ts +3 -1
- package/src/client/sidebar/panels/FileExplorer.ts +8 -4
- package/src/client/sidebar/panels/SvnPanel.ts +8 -1
- package/src/client/sidebar/panels/useExplorerSvn.ts +1 -1
- package/src/client/ui/EditorView.ts +2 -2
- package/src/client/ui/FloatingWindow.ts +61 -14
- package/src/client/ui/McpSettings.ts +1 -1
- package/src/client/ui/SvnLogDialog.ts +67 -24
- package/src/svn.ts +8 -1
package/lib/client.js
CHANGED
|
@@ -1258,32 +1258,38 @@ window.__ModuleLoader__.load({
|
|
|
1258
1258
|
//#endregion
|
|
1259
1259
|
//#region src/client/ui/FloatingWindow.ts
|
|
1260
1260
|
/** Shared in-page window chrome, without a mask or focus trap. @author ddj 2026年10月14号 */
|
|
1261
|
-
/** @private @author ddj 2026年10月14号 @param start Originating press. @param rect Initial bounds. @param sizing Resize mode. @param apply Commit bounds. @param done Gesture cleanup notification. @returns Gesture cancellation. */
|
|
1262
|
-
function beginGesture(start, rect, sizing, apply, done) {
|
|
1261
|
+
/** @private @author ddj 2026年10月14号 @param start Originating press. @param rect Initial bounds. @param sizing Resize mode. @param draw Paint live bounds without a render. @param apply Commit bounds once. @param done Gesture cleanup notification. @returns Gesture cancellation. */
|
|
1262
|
+
function beginGesture(start, rect, sizing, draw, apply, done) {
|
|
1263
1263
|
let frame = null;
|
|
1264
1264
|
let next = rect;
|
|
1265
|
-
|
|
1265
|
+
let moved = false;
|
|
1266
|
+
/** @private @author ddj 2026年10月14号 Paint no more than once per frame. */
|
|
1266
1267
|
function paint() {
|
|
1267
1268
|
frame = null;
|
|
1268
|
-
|
|
1269
|
+
draw(next);
|
|
1269
1270
|
}
|
|
1270
1271
|
/** @private @author ddj 2026年10月14号 @param event Pointer motion. Ignore unrelated pointers. */
|
|
1271
1272
|
function move(event) {
|
|
1272
1273
|
if (event.pointerId !== start.pointerId) return;
|
|
1273
1274
|
event.preventDefault();
|
|
1275
|
+
moved = true;
|
|
1274
1276
|
next = moveFloat(rect, event.clientX - start.clientX, event.clientY - start.clientY, sizing, window.innerWidth, window.innerHeight);
|
|
1275
1277
|
if (frame === null) frame = requestAnimationFrame(paint);
|
|
1276
1278
|
}
|
|
1277
|
-
/** @private @author ddj 2026年10月14号 Remove listeners
|
|
1279
|
+
/** @private @author ddj 2026年10月14号 Remove listeners, then commit the settled geometry exactly once. */
|
|
1278
1280
|
function stop() {
|
|
1279
1281
|
if (frame !== null) {
|
|
1280
1282
|
cancelAnimationFrame(frame);
|
|
1281
|
-
|
|
1283
|
+
frame = null;
|
|
1282
1284
|
}
|
|
1283
1285
|
window.removeEventListener("pointermove", move, true);
|
|
1284
1286
|
window.removeEventListener("pointerup", end, true);
|
|
1285
1287
|
window.removeEventListener("pointercancel", end, true);
|
|
1286
1288
|
window.removeEventListener("blur", stop);
|
|
1289
|
+
if (moved) {
|
|
1290
|
+
draw(next);
|
|
1291
|
+
apply(next);
|
|
1292
|
+
}
|
|
1287
1293
|
done();
|
|
1288
1294
|
}
|
|
1289
1295
|
/** @private @author ddj 2026年10月14号 @param event Pointer release. Only end originating gesture. */
|
|
@@ -1296,6 +1302,31 @@ window.__ModuleLoader__.load({
|
|
|
1296
1302
|
window.addEventListener("blur", stop);
|
|
1297
1303
|
return stop;
|
|
1298
1304
|
}
|
|
1305
|
+
const resizeSinks = /* @__PURE__ */ new Set();
|
|
1306
|
+
let resizeFrame = null;
|
|
1307
|
+
/** @private @author ddj 2026年10月14号 Re-clamp every window at most once per frame. */
|
|
1308
|
+
function onViewportResize() {
|
|
1309
|
+
if (resizeFrame !== null) return;
|
|
1310
|
+
resizeFrame = requestAnimationFrame(() => {
|
|
1311
|
+
resizeFrame = null;
|
|
1312
|
+
for (const sink of [...resizeSinks]) sink();
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
/** @private @author ddj 2026年10月14号 @param sink Per-window re-clamp callback. @returns Unsubscribe. */
|
|
1316
|
+
function subscribeResize(sink) {
|
|
1317
|
+
if (resizeSinks.size === 0) window.addEventListener("resize", onViewportResize);
|
|
1318
|
+
resizeSinks.add(sink);
|
|
1319
|
+
return () => {
|
|
1320
|
+
resizeSinks.delete(sink);
|
|
1321
|
+
if (resizeSinks.size === 0) {
|
|
1322
|
+
window.removeEventListener("resize", onViewportResize);
|
|
1323
|
+
if (resizeFrame !== null) {
|
|
1324
|
+
cancelAnimationFrame(resizeFrame);
|
|
1325
|
+
resizeFrame = null;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1299
1330
|
/** @public @author ddj 2026年10月14号 @param props Window contents and lifecycle callbacks. @returns Movable, resizable nonmodal portal. */
|
|
1300
1331
|
function FloatingWindow(props) {
|
|
1301
1332
|
const id = react.default.useId();
|
|
@@ -1306,29 +1337,40 @@ window.__ModuleLoader__.load({
|
|
|
1306
1337
|
const current = react.default.useRef(props.rect ?? bounds);
|
|
1307
1338
|
current.current = props.rect ?? bounds;
|
|
1308
1339
|
const cleanup = react.default.useRef(null);
|
|
1340
|
+
const gesture = react.default.useRef(null);
|
|
1309
1341
|
react.default.useSyncExternalStore(watchFloats, floatVersion, floatVersion);
|
|
1310
1342
|
/** @private @author ddj 2026年10月14号 @param rect Next geometry. Notify controlled owner or retain local geometry. */
|
|
1311
1343
|
function apply(rect) {
|
|
1312
1344
|
if (latest.current.rect) latest.current.onBounds?.(rect);
|
|
1313
1345
|
else setBounds(rect);
|
|
1314
1346
|
}
|
|
1347
|
+
/** @private @author ddj 2026年10月14号 @param rect Live gesture geometry. Write the DOM and hold it until the commit render lands. */
|
|
1348
|
+
function draw(rect) {
|
|
1349
|
+
gesture.current = rect;
|
|
1350
|
+
const node = root.current;
|
|
1351
|
+
if (!node) return;
|
|
1352
|
+
node.style.left = rect.left + "px";
|
|
1353
|
+
node.style.top = rect.top + "px";
|
|
1354
|
+
node.style.width = rect.width + "px";
|
|
1355
|
+
node.style.height = rect.height + "px";
|
|
1356
|
+
}
|
|
1315
1357
|
/** @private @author ddj 2026年10月14号 End any active gesture. */
|
|
1316
1358
|
function cancel() {
|
|
1317
1359
|
cleanup.current?.();
|
|
1318
1360
|
cleanup.current = null;
|
|
1319
1361
|
}
|
|
1320
|
-
/** @private @author ddj 2026年10月14号 Re-clamp after viewport resize. */
|
|
1362
|
+
/** @private @author ddj 2026年10月14号 Re-clamp after viewport resize, preferring the gesture that just settled. */
|
|
1321
1363
|
function resize() {
|
|
1322
1364
|
cancel();
|
|
1323
|
-
apply(clampFloat(current.current, window.innerWidth, window.innerHeight));
|
|
1365
|
+
apply(clampFloat(gesture.current ?? current.current, window.innerWidth, window.innerHeight));
|
|
1324
1366
|
}
|
|
1325
1367
|
react.default.useEffect(() => {
|
|
1326
1368
|
raiseFloat(id);
|
|
1327
|
-
|
|
1369
|
+
const off = subscribeResize(resize);
|
|
1328
1370
|
resize();
|
|
1329
1371
|
return () => {
|
|
1372
|
+
off();
|
|
1330
1373
|
cancel();
|
|
1331
|
-
window.removeEventListener("resize", resize);
|
|
1332
1374
|
dropFloat(id);
|
|
1333
1375
|
};
|
|
1334
1376
|
}, [id]);
|
|
@@ -1347,11 +1389,12 @@ window.__ModuleLoader__.load({
|
|
|
1347
1389
|
if (event.button !== 0 || !event.isPrimary) return;
|
|
1348
1390
|
cancel();
|
|
1349
1391
|
event.preventDefault();
|
|
1350
|
-
cleanup.current = beginGesture(event, current.current, sizing, apply, clear);
|
|
1392
|
+
cleanup.current = beginGesture(event, gesture.current ?? current.current, sizing, draw, apply, clear);
|
|
1351
1393
|
}
|
|
1352
|
-
/** @private @author ddj 2026年10月14号
|
|
1394
|
+
/** @private @author ddj 2026年10月14号 Release the settled geometry once React has committed it. */
|
|
1353
1395
|
function clear() {
|
|
1354
1396
|
cleanup.current = null;
|
|
1397
|
+
gesture.current = null;
|
|
1355
1398
|
}
|
|
1356
1399
|
/** @private @author ddj 2026年10月14号 @param event Title press. Preserve title action buttons. */
|
|
1357
1400
|
function moveStart(event) {
|
|
@@ -1372,7 +1415,8 @@ window.__ModuleLoader__.load({
|
|
|
1372
1415
|
}
|
|
1373
1416
|
props.onKeyDown?.(event);
|
|
1374
1417
|
}
|
|
1375
|
-
const
|
|
1418
|
+
const base = clampFloat(props.rect ?? bounds, window.innerWidth, window.innerHeight);
|
|
1419
|
+
const rect = gesture.current ?? base;
|
|
1376
1420
|
return (0, react_dom.createPortal)(react.default.createElement("div", {
|
|
1377
1421
|
ref: root,
|
|
1378
1422
|
tabIndex: -1,
|
|
@@ -13177,19 +13221,21 @@ window.__ModuleLoader__.load({
|
|
|
13177
13221
|
/**
|
|
13178
13222
|
* 立即同步某文档到 host(首次打开/查询前保证服务器已认识该文档)。
|
|
13179
13223
|
* sessionId 缺失时仍发起请求:host 对唯一活跃会话有兜底解析,弃发会白白丢失文档归属。
|
|
13180
|
-
* @author ddj 2026年08月27号 / 2026年09月11号
|
|
13224
|
+
* @author ddj 2026年08月27号 / 2026年09月11号 / 2026年10月15号
|
|
13181
13225
|
* @param path 工作区相对路径
|
|
13182
|
-
* @param text
|
|
13226
|
+
* @param text 文档全文;传函数表示**发送前才求值**(击键路径用它,避免为被去抖丢弃的中间态取全文)
|
|
13183
13227
|
* @param immediate true 立即发送,false 去抖
|
|
13184
13228
|
*/
|
|
13185
13229
|
async function syncDoc(path, text, immediate = false) {
|
|
13186
|
-
if (!path || typeof text !== "string") return;
|
|
13230
|
+
if (!path || typeof text !== "string" && typeof text !== "function") return;
|
|
13187
13231
|
if (immediate) {
|
|
13188
13232
|
clearPending(path);
|
|
13233
|
+
const value = resolveText(text);
|
|
13234
|
+
if (value === null) return;
|
|
13189
13235
|
await rpc("edrv.lsp.sync", {
|
|
13190
13236
|
sessionId: sessionId$1,
|
|
13191
13237
|
path,
|
|
13192
|
-
text,
|
|
13238
|
+
text: value,
|
|
13193
13239
|
version: nextDocVer(path)
|
|
13194
13240
|
}).catch(() => {});
|
|
13195
13241
|
return;
|
|
@@ -13197,14 +13243,32 @@ window.__ModuleLoader__.load({
|
|
|
13197
13243
|
clearPending(path);
|
|
13198
13244
|
syncTimers.set(path, setTimeout(() => {
|
|
13199
13245
|
syncTimers.delete(path);
|
|
13246
|
+
const value = resolveText(text);
|
|
13247
|
+
if (value === null) return;
|
|
13200
13248
|
rpc("edrv.lsp.sync", {
|
|
13201
13249
|
sessionId: sessionId$1,
|
|
13202
13250
|
path,
|
|
13203
|
-
text,
|
|
13251
|
+
text: value,
|
|
13204
13252
|
version: nextDocVer(path)
|
|
13205
13253
|
}).catch(() => {});
|
|
13206
13254
|
}, SYNC_DEBOUNCE_MS));
|
|
13207
13255
|
}
|
|
13256
|
+
/**
|
|
13257
|
+
* 取本次要同步的文本:字符串原样返回,函数形态在发送前求值。
|
|
13258
|
+
* 取值抛错(model 已销毁)时返回 null 表示**放弃本次同步**——不能退回空串,
|
|
13259
|
+
* 那会把 host 侧文档内容清掉,比漏一次同步严重得多(关闭路径由 closeDoc 负责)。
|
|
13260
|
+
* @author ddj 2026年10月15号
|
|
13261
|
+
* @param text 字符串或惰性取值函数
|
|
13262
|
+
* @returns 待发送文本;无法取值时为 null
|
|
13263
|
+
*/
|
|
13264
|
+
function resolveText(text) {
|
|
13265
|
+
if (typeof text === "string") return text;
|
|
13266
|
+
try {
|
|
13267
|
+
return String(text());
|
|
13268
|
+
} catch (error) {
|
|
13269
|
+
return null;
|
|
13270
|
+
}
|
|
13271
|
+
}
|
|
13208
13272
|
function clearPending(path) {
|
|
13209
13273
|
const timer = syncTimers.get(path);
|
|
13210
13274
|
if (timer) {
|
|
@@ -13677,7 +13741,7 @@ window.__ModuleLoader__.load({
|
|
|
13677
13741
|
if (!model || model.uri.scheme !== "edrv") return;
|
|
13678
13742
|
const path = pathOfModel(model);
|
|
13679
13743
|
if (!path) return;
|
|
13680
|
-
const contentDisposer = model.onDidChangeContent(() => syncDoc(path, model.getValue()));
|
|
13744
|
+
const contentDisposer = model.onDidChangeContent(() => syncDoc(path, () => model.getValue()));
|
|
13681
13745
|
const disposeDisposer = model.onWillDispose(() => {
|
|
13682
13746
|
closeDoc(path);
|
|
13683
13747
|
contentDisposer.dispose();
|
|
@@ -19045,10 +19109,38 @@ window.__ModuleLoader__.load({
|
|
|
19045
19109
|
}, item.copyFrom ? item.copyFrom + "@" + (item.copyFromRev ?? "?") : ""), buttons);
|
|
19046
19110
|
}
|
|
19047
19111
|
/**
|
|
19112
|
+
* 单个数据行:浅比较包装(回调身份由父级 ref 转发保持稳定,故 memo 才可能命中)。
|
|
19113
|
+
* @author ddj 2026年10月14号
|
|
19114
|
+
*/
|
|
19115
|
+
const LogItemRow = react.default.memo(LogItem);
|
|
19116
|
+
/**
|
|
19117
|
+
* 数据行容器(P0-14 上段)。独立 memo:只在条目列表/选中集/工作副本版号变化时重建行元素;
|
|
19118
|
+
* 上段高度拖拽与弹窗缩放只改 LogList 的 height,不再逐帧重建整表(原先每帧 logRowsOf + N 个元素)。
|
|
19119
|
+
* @author ddj 2026年10月14号
|
|
19120
|
+
* @param props.list 过滤排序后的条目(非空)
|
|
19121
|
+
* @param props.selectedRevs 可见选中的 revision 集合
|
|
19122
|
+
* @param props.wcRev 工作副本版号(null = 不加粗)
|
|
19123
|
+
* @param props.onPick 选中回调(event, item)
|
|
19124
|
+
* @param props.onMenu 右键回调(event, item)
|
|
19125
|
+
* @returns 行元素
|
|
19126
|
+
*/
|
|
19127
|
+
const LogRows = react.default.memo(function LogRows(props) {
|
|
19128
|
+
const { list, selectedRevs, wcRev, onPick, onMenu } = props;
|
|
19129
|
+
return react.default.createElement(react.default.Fragment, null, logRowsOf(list).map((row) => react.default.createElement(LogItemRow, {
|
|
19130
|
+
key: row.item.revision + ":" + row.level,
|
|
19131
|
+
item: row.item,
|
|
19132
|
+
on: selectedRevs.has(row.item.revision),
|
|
19133
|
+
wc: wcRev != null && row.item.revision === wcRev,
|
|
19134
|
+
level: row.level,
|
|
19135
|
+
onPick,
|
|
19136
|
+
onMenu
|
|
19137
|
+
})));
|
|
19138
|
+
});
|
|
19139
|
+
/**
|
|
19048
19140
|
* 上窗格列表(列头行 + 数据行 + 「加载更多」;P0-13 宽度受拖拽控制)。
|
|
19049
19141
|
* @author ddj 2026年09月16号 / 2026年09月17号
|
|
19050
19142
|
* @param props.list 过滤排序后的条目(null = 未加载)
|
|
19051
|
-
* @param props.
|
|
19143
|
+
* @param props.selectedRevs 可见选中的 revision 集合(P1-3 多选;由父级按 revision 维护)
|
|
19052
19144
|
* @param props.keyword 过滤词(决定空态文案)
|
|
19053
19145
|
* @param props.busy 加载中
|
|
19054
19146
|
* @param props.truncated 是否可能还有更多
|
|
@@ -19061,19 +19153,17 @@ window.__ModuleLoader__.load({
|
|
|
19061
19153
|
* @returns 列表元素
|
|
19062
19154
|
*/
|
|
19063
19155
|
function LogList(props) {
|
|
19064
|
-
const { list,
|
|
19156
|
+
const { list, selectedRevs, keyword, busy, truncated, sortKey, sortDir, onSort, onSortReset, onPick, onLoadMore, onItemMenu, height, wcRev } = props;
|
|
19065
19157
|
let inner;
|
|
19066
19158
|
if (list === null) inner = react.default.createElement("div", { className: "edrv-tree-loading" }, busy ? "读取日志中…" : "尚未加载");
|
|
19067
19159
|
else if (!list.length) inner = react.default.createElement("div", { className: "edrv-tree-loading" }, keyword ? "无匹配条目" : "无提交历史");
|
|
19068
|
-
else inner =
|
|
19069
|
-
|
|
19070
|
-
|
|
19071
|
-
|
|
19072
|
-
wc: wcRev != null && row.item.revision === wcRev,
|
|
19073
|
-
level: row.level,
|
|
19160
|
+
else inner = react.default.createElement(LogRows, {
|
|
19161
|
+
list,
|
|
19162
|
+
selectedRevs,
|
|
19163
|
+
wcRev,
|
|
19074
19164
|
onPick,
|
|
19075
19165
|
onMenu: onItemMenu
|
|
19076
|
-
})
|
|
19166
|
+
});
|
|
19077
19167
|
const more = truncated ? react.default.createElement("div", { className: "edrv-svnlog-more" }, react.default.createElement("button", {
|
|
19078
19168
|
className: "edrv-svn-act",
|
|
19079
19169
|
disabled: busy,
|
|
@@ -19393,7 +19483,9 @@ window.__ModuleLoader__.load({
|
|
|
19393
19483
|
sortKey,
|
|
19394
19484
|
sortDir
|
|
19395
19485
|
]);
|
|
19396
|
-
const
|
|
19486
|
+
const sortedRevs = react.default.useMemo(() => sorted ? new Set(sorted.map((x) => x.revision)) : null, [sorted]);
|
|
19487
|
+
const visibleSelected = react.default.useMemo(() => sortedRevs ? selected.filter((item) => sortedRevs.has(item.revision)) : selected, [sortedRevs, selected]);
|
|
19488
|
+
const selectedRevs = react.default.useMemo(() => new Set(visibleSelected.map((item) => item.revision)), [visibleSelected]);
|
|
19397
19489
|
const current = visibleSelected.length ? visibleSelected[0] : sorted && sorted.length ? sorted[0] : null;
|
|
19398
19490
|
/** 点列头:同键切换升降,异键回落升序;复位入口在列头行(G10)。 */
|
|
19399
19491
|
const onSort = (key) => {
|
|
@@ -19492,24 +19584,26 @@ window.__ModuleLoader__.load({
|
|
|
19492
19584
|
* @param wantList 目标上段(修订列表)高度
|
|
19493
19585
|
* @param wantMsg 目标中段(提交信息)高度
|
|
19494
19586
|
*/
|
|
19587
|
+
/** @private @author ddj 2026年10月14号 @param nextList 目标上段高度 @param nextMsg 目标中段高度 只在值真正变化时提交。 */
|
|
19588
|
+
const applyFit = (nextList, nextMsg) => {
|
|
19589
|
+
if (nextList !== listH) setListH(nextList);
|
|
19590
|
+
if (nextMsg !== msgH) setMsgH(nextMsg);
|
|
19591
|
+
};
|
|
19495
19592
|
const fitHeights = (wantList, wantMsg) => {
|
|
19496
19593
|
const total = bodyRef.current?.clientHeight ?? 0;
|
|
19497
19594
|
if (!total) {
|
|
19498
|
-
|
|
19499
|
-
setMsgH(wantMsg);
|
|
19595
|
+
applyFit(wantList, wantMsg);
|
|
19500
19596
|
return;
|
|
19501
19597
|
}
|
|
19502
19598
|
const paneOcc = paneRef.current?.offsetHeight ?? -1;
|
|
19503
19599
|
const chrome = paneOcc >= 0 ? Math.max(0, total - listH - msgH - paneOcc) : HSPLIT_TOTAL_PX;
|
|
19504
19600
|
const budget = total - PANE_KEEP_MIN - chrome;
|
|
19505
19601
|
if (budget < 260) {
|
|
19506
|
-
|
|
19507
|
-
setMsgH(Math.min(wantMsg, MSG_H_MIN));
|
|
19602
|
+
applyFit(Math.min(wantList, LIST_H_MIN), Math.min(wantMsg, MSG_H_MIN));
|
|
19508
19603
|
return;
|
|
19509
19604
|
}
|
|
19510
19605
|
if (wantList + wantMsg <= budget) {
|
|
19511
|
-
|
|
19512
|
-
setMsgH(wantMsg);
|
|
19606
|
+
applyFit(wantList, wantMsg);
|
|
19513
19607
|
return;
|
|
19514
19608
|
}
|
|
19515
19609
|
const scale = budget / (wantList + wantMsg);
|
|
@@ -19522,8 +19616,7 @@ window.__ModuleLoader__.load({
|
|
|
19522
19616
|
nextMsg = MSG_H_MIN;
|
|
19523
19617
|
nextList = Math.min(nextList, budget - nextMsg);
|
|
19524
19618
|
}
|
|
19525
|
-
|
|
19526
|
-
setMsgH(nextMsg);
|
|
19619
|
+
applyFit(nextList, nextMsg);
|
|
19527
19620
|
};
|
|
19528
19621
|
const fitRef = react.default.useRef(null);
|
|
19529
19622
|
fitRef.current = () => fitHeights(listH, msgH);
|
|
@@ -19617,6 +19710,15 @@ window.__ModuleLoader__.load({
|
|
|
19617
19710
|
].filter(Boolean)
|
|
19618
19711
|
});
|
|
19619
19712
|
};
|
|
19713
|
+
/** @author ddj 2026年10月14号 */
|
|
19714
|
+
const rowCbs = react.default.useRef({
|
|
19715
|
+
pick: null,
|
|
19716
|
+
menu: null
|
|
19717
|
+
});
|
|
19718
|
+
rowCbs.current.pick = pickWithMods;
|
|
19719
|
+
rowCbs.current.menu = onItemMenu;
|
|
19720
|
+
const pickStable = react.default.useCallback((event, item) => rowCbs.current.pick?.(event, item), []);
|
|
19721
|
+
const menuStable = react.default.useCallback((event, item) => rowCbs.current.menu?.(event, item), []);
|
|
19620
19722
|
/** 下窗格路径行右键菜单(P0-8;G8 目录不可开差异,G9 仓库外不可打开)。 */
|
|
19621
19723
|
const onPathMenu = (event, item, revision) => {
|
|
19622
19724
|
event.preventDefault();
|
|
@@ -19654,7 +19756,7 @@ window.__ModuleLoader__.load({
|
|
|
19654
19756
|
ref: bodyRef
|
|
19655
19757
|
}, react.default.createElement(LogList, {
|
|
19656
19758
|
list: sorted,
|
|
19657
|
-
|
|
19759
|
+
selectedRevs,
|
|
19658
19760
|
keyword: query.trim(),
|
|
19659
19761
|
busy,
|
|
19660
19762
|
truncated,
|
|
@@ -19662,9 +19764,9 @@ window.__ModuleLoader__.load({
|
|
|
19662
19764
|
sortDir,
|
|
19663
19765
|
onSort,
|
|
19664
19766
|
onSortReset,
|
|
19665
|
-
onPick:
|
|
19767
|
+
onPick: pickStable,
|
|
19666
19768
|
onLoadMore,
|
|
19667
|
-
onItemMenu,
|
|
19769
|
+
onItemMenu: menuStable,
|
|
19668
19770
|
height: listH,
|
|
19669
19771
|
wcRev
|
|
19670
19772
|
}), react.default.createElement(Splitter, {
|
|
@@ -26578,17 +26680,7 @@ window.__ModuleLoader__.load({
|
|
|
26578
26680
|
"aria-label": "关闭提示",
|
|
26579
26681
|
onClick: dismissHint
|
|
26580
26682
|
}, "×")) : null;
|
|
26581
|
-
const fullView = (0, react_dom.createPortal)(react.default.createElement("
|
|
26582
|
-
"data-edrv-view": "1",
|
|
26583
|
-
style: {
|
|
26584
|
-
display: "flex",
|
|
26585
|
-
flexDirection: "column",
|
|
26586
|
-
flex: 1,
|
|
26587
|
-
minWidth: 0,
|
|
26588
|
-
minHeight: 0,
|
|
26589
|
-
overflow: "hidden"
|
|
26590
|
-
}
|
|
26591
|
-
}, pathBar, sideHintEl, diskBanner(), editorArea, statusBar), fullHost, "edrv-full-editor");
|
|
26683
|
+
const fullView = (0, react_dom.createPortal)(react.default.createElement(react.default.Fragment, null, pathBar, sideHintEl, diskBanner(), editorArea, statusBar), fullHost, "edrv-full-editor");
|
|
26592
26684
|
const mainCol = react.default.createElement("div", {
|
|
26593
26685
|
className: "edrv-main-col edrv-workbench",
|
|
26594
26686
|
style: {
|
|
@@ -26609,13 +26701,7 @@ window.__ModuleLoader__.load({
|
|
|
26609
26701
|
onBounds: floatBounds,
|
|
26610
26702
|
onFocus: selectGroup,
|
|
26611
26703
|
onReturn: returnPane
|
|
26612
|
-
}, renderGroup(item.group))), dragPreview ? (0, react_dom.createPortal)(react.default.createElement("div", {
|
|
26613
|
-
"data-edrv-view": "1",
|
|
26614
|
-
style: {
|
|
26615
|
-
display: "contents",
|
|
26616
|
-
pointerEvents: "none"
|
|
26617
|
-
}
|
|
26618
|
-
}, dragPreview.rect ? react.default.createElement("div", {
|
|
26704
|
+
}, renderGroup(item.group))), dragPreview ? (0, react_dom.createPortal)(react.default.createElement(react.default.Fragment, null, dragPreview.rect ? react.default.createElement("div", {
|
|
26619
26705
|
className: "edrv-drag-overlay",
|
|
26620
26706
|
style: dragPreview.rect
|
|
26621
26707
|
}, react.default.createElement("span", { className: "edrv-drop-label" }, dragPreview.label)) : null, react.default.createElement("div", {
|
|
@@ -29853,7 +29939,7 @@ window.__ModuleLoader__.load({
|
|
|
29853
29939
|
const warnings = report?.warnings ?? [];
|
|
29854
29940
|
const devForm = report?.devForm;
|
|
29855
29941
|
const versionText = report?.dshVersion ? "(DSH " + report.dshVersion + " · 插件 " + (report?.pluginVersion ?? "") + ")" : report?.pluginVersion ? "(插件版本 " + report.pluginVersion + ")" : "";
|
|
29856
|
-
return react.default.createElement("section", { className: "vsm-general-page" }, react.default.createElement("h2", null, "兼容性"), react.default.createElement("p", null, "检测与其他插件 / DSH 版本的适配状态与已知问题。" + versionText), error && react.default.createElement("div", { className: "vsm-mcp-error vsm-mcp-banner" }, error), devForm?.enabled && group("开发形态", react.default.createElement("div", { className: "vsm-compat-item ok" }, react.default.createElement("span", { className: "vsm-compat-name" }, "开发形态开启(工作区链接安装)"), react.default.createElement("span", { className: "vsm-compat-note" }, devForm.path))), group("版本适配", renderItems(report?.adapters)), group("外部插件与服务", renderItems(report?.external)), group("客户端适配", renderItems(getSummary?.() ?? [])), group("护栏", renderItems(report?.guards)), group("警告", warnings.length ? warnings.map((w, index) => react.default.createElement("div", {
|
|
29942
|
+
return react.default.createElement("section", { className: "vsm-general-page" }, react.default.createElement("h2", null, "兼容性"), react.default.createElement("p", null, "检测与其他插件 / DSH 版本的适配状态与已知问题。" + versionText), error && react.default.createElement("div", { className: "vsm-mcp-error vsm-mcp-banner" }, error), devForm?.enabled && group("开发形态", react.default.createElement("div", { className: "vsm-compat-item ok" }, react.default.createElement("span", { className: "vsm-compat-name" }, "开发形态开启(工作区链接安装)"), react.default.createElement("span", { className: "vsm-compat-note" }, devForm.path))), group("版本适配", renderItems(report?.adapters)), group("外部插件与服务", renderItems(report?.external)), group("客户端适配", renderItems(getSummary?.(report?.dshVersion ?? "") ?? [])), group("护栏", renderItems(report?.guards)), group("警告", warnings.length ? warnings.map((w, index) => react.default.createElement("div", {
|
|
29857
29943
|
key: index,
|
|
29858
29944
|
className: "vsm-mcp-error vsm-mcp-banner"
|
|
29859
29945
|
}, w)) : react.default.createElement("div", { className: "vsm-compat-item ok" }, react.default.createElement("span", { className: "vsm-compat-name" }, "未检测到兼容性问题"), react.default.createElement("span", { className: "vsm-compat-note" }, ""))));
|
|
@@ -30741,6 +30827,12 @@ window.__ModuleLoader__.load({
|
|
|
30741
30827
|
/** 深链移交轮询周期(兼活跃心跳)。 */
|
|
30742
30828
|
const HANDOFF_POLL_MS = 3e3;
|
|
30743
30829
|
/**
|
|
30830
|
+
* 页面隐藏时的降频倍数(3s × 5 = 15s)。
|
|
30831
|
+
* 必须仍短于 host 租约(src/externalHandoff.ts 的 LEASE_MS = 30s):心跳一旦超期,
|
|
30832
|
+
* host 判定该页面已死,launcher 会重复开新页——比多几次 RPC 更糟。
|
|
30833
|
+
*/
|
|
30834
|
+
const HIDDEN_POLL_EVERY = 5;
|
|
30835
|
+
/**
|
|
30744
30836
|
* 装配外部深链:深链参数缺失时仅保持移交轮询(零额外开销)。
|
|
30745
30837
|
* @author ddj 2026年09月07号
|
|
30746
30838
|
* @param ctx 客户端根上下文(sessions/workspaces 服务)
|
|
@@ -30763,9 +30855,10 @@ window.__ModuleLoader__.load({
|
|
|
30763
30855
|
return dispose;
|
|
30764
30856
|
}
|
|
30765
30857
|
/**
|
|
30766
|
-
*
|
|
30858
|
+
* 深链移交轮询:可见时每 3s 向 host 领取待打开请求(兼活跃心跳,launcher 据此决定是否开新页);
|
|
30859
|
+
* 页面隐藏时降到 15s 一次——无人看页面时移交不必保持 3s 精度,但心跳不能停(超期会让 host 判页面已死)。
|
|
30767
30860
|
* 页面级单例(window 标记防 HMR 重复);领取到即执行打开规则。
|
|
30768
|
-
* @author ddj 2026年09月08号
|
|
30861
|
+
* @author ddj 2026年09月08号 / 2026年10月15号
|
|
30769
30862
|
* @param ctx 客户端根上下文
|
|
30770
30863
|
*/
|
|
30771
30864
|
function startPresencePoll(ctx) {
|
|
@@ -30776,6 +30869,20 @@ window.__ModuleLoader__.load({
|
|
|
30776
30869
|
let disposed = false;
|
|
30777
30870
|
let polling = false;
|
|
30778
30871
|
let executing = false;
|
|
30872
|
+
let ticks = 0;
|
|
30873
|
+
/**
|
|
30874
|
+
* 页面隐藏时按倍数跳轮;可见时每次都跑并清零计数。
|
|
30875
|
+
* @author ddj 2026年10月15号
|
|
30876
|
+
* @returns 是否跳过本轮
|
|
30877
|
+
*/
|
|
30878
|
+
function hiddenSkip() {
|
|
30879
|
+
if (typeof document === "undefined" || document.visibilityState !== "hidden") {
|
|
30880
|
+
ticks = 0;
|
|
30881
|
+
return false;
|
|
30882
|
+
}
|
|
30883
|
+
ticks += 1;
|
|
30884
|
+
return ticks % HIDDEN_POLL_EVERY !== 0;
|
|
30885
|
+
}
|
|
30779
30886
|
/** @private @author ddj 2026年09月28号 Open all requested paths before acknowledging this exact lease. */
|
|
30780
30887
|
async function execute(open) {
|
|
30781
30888
|
executing = true;
|
|
@@ -30807,6 +30914,7 @@ window.__ModuleLoader__.load({
|
|
|
30807
30914
|
}
|
|
30808
30915
|
}
|
|
30809
30916
|
const timer = window.setInterval(() => {
|
|
30917
|
+
if (hiddenSkip()) return;
|
|
30810
30918
|
tick().catch(() => {});
|
|
30811
30919
|
}, HANDOFF_POLL_MS);
|
|
30812
30920
|
/** @private @author ddj 2026年09月28号 Stop heartbeats and fail outstanding editor waits on plugin disposal. */
|
|
@@ -30882,6 +30990,80 @@ window.__ModuleLoader__.load({
|
|
|
30882
30990
|
setTimeout(() => toast.remove(), TOAST_MS);
|
|
30883
30991
|
}
|
|
30884
30992
|
//#endregion
|
|
30993
|
+
//#region src/client/compatSummary.ts
|
|
30994
|
+
/**
|
|
30995
|
+
* Classify the API generation without importing the host's node-only version probe.
|
|
30996
|
+
* @private @author ddj 2026年10月13号
|
|
30997
|
+
* @param input Running DSH version from the compat RPC.
|
|
30998
|
+
* @param patch First supported 0.1.x patch (alpha.1).
|
|
30999
|
+
* @returns Whether that API generation is expected; undefined for unknown versions.
|
|
31000
|
+
*/
|
|
31001
|
+
function apiExpected(input, patch) {
|
|
31002
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*))?(?:\+[0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*)?$/.exec(input.trim());
|
|
31003
|
+
if (!match) return void 0;
|
|
31004
|
+
const major = Number(match[1]);
|
|
31005
|
+
const minor = Number(match[2]);
|
|
31006
|
+
const current = Number(match[3]);
|
|
31007
|
+
if (major !== 0) return major > 0;
|
|
31008
|
+
if (minor !== 1) return minor > 1;
|
|
31009
|
+
if (current !== patch) return current > patch;
|
|
31010
|
+
const pre = match[4];
|
|
31011
|
+
if (!pre) return true;
|
|
31012
|
+
const parts = pre.split(".");
|
|
31013
|
+
if (/^\d+$/.test(parts[0])) return false;
|
|
31014
|
+
if (parts[0] !== "alpha") return parts[0] > "alpha";
|
|
31015
|
+
return parts.length > 1 && (/^\d+$/.test(parts[1]) ? Number(parts[1]) >= 1 : true);
|
|
31016
|
+
}
|
|
31017
|
+
/**
|
|
31018
|
+
* Build only applicable diagnostics; explicit legacy choices still expose missing capabilities.
|
|
31019
|
+
* @public @author ddj 2026年10月13号
|
|
31020
|
+
* @param state Actual client installation facts and user selection.
|
|
31021
|
+
* @param version Running DSH version; unknown versions retain conservative diagnostics.
|
|
31022
|
+
* @returns Visible adapters, without changing routing or installation.
|
|
31023
|
+
*/
|
|
31024
|
+
function clientSummary(state, version = "") {
|
|
31025
|
+
const remoteExpected = apiExpected(version, 3);
|
|
31026
|
+
const officialExpected = apiExpected(version, 5);
|
|
31027
|
+
const official = state.officialSidebar;
|
|
31028
|
+
const legacyChosen = state.selected === SIDEBAR_PLUGIN;
|
|
31029
|
+
const items = [{
|
|
31030
|
+
name: "设置桥",
|
|
31031
|
+
active: state.settingsReady,
|
|
31032
|
+
note: state.settingsReady ? "使用 " + state.settingsService + " 桥" : "未绑定设置服务(持久化不可用,晚到重试窗口内自愈)"
|
|
31033
|
+
}];
|
|
31034
|
+
if (remoteExpected !== true && !state.remoteReady && !official) items.push({
|
|
31035
|
+
name: "文件打开路由(workspaces.openPath)",
|
|
31036
|
+
active: state.openPathReady,
|
|
31037
|
+
note: "旧版对话文件链接路由,失败回退系统打开"
|
|
31038
|
+
});
|
|
31039
|
+
if (remoteExpected !== false || state.remoteReady) items.push({
|
|
31040
|
+
name: "会话文件链接路由(remote.session.openWorkspacePath)",
|
|
31041
|
+
active: state.remoteReady,
|
|
31042
|
+
note: state.remoteReady ? "会话文件链接走插件打开器,失败回退系统打开" : "适用路由未安装(服务缺失或补丁失败)"
|
|
31043
|
+
});
|
|
31044
|
+
if (legacyChosen || state.sidebarOpener || !official && officialExpected !== true) items.push({
|
|
31045
|
+
name: "侧边栏打开器(dsh-better-sidebar)",
|
|
31046
|
+
active: state.sidebarOpener,
|
|
31047
|
+
note: state.sidebarOpener ? "已注册(优先级 80)" : "未检测到侧边栏打开能力"
|
|
31048
|
+
});
|
|
31049
|
+
if (official || officialExpected !== false) items.push({
|
|
31050
|
+
name: "侧边栏编辑区(官方 Sidebar)",
|
|
31051
|
+
active: official,
|
|
31052
|
+
note: official ? "编辑区=官方右侧 Sidebar Tab(对话+编辑同屏)" : "官方侧边栏服务未探测到"
|
|
31053
|
+
});
|
|
31054
|
+
if (!official && (state.legacySidebar || officialExpected !== true)) items.push({
|
|
31055
|
+
name: "侧边栏编辑区(dsh-better-sidebar,归档)",
|
|
31056
|
+
active: state.legacySidebar,
|
|
31057
|
+
note: state.legacySidebar ? "编辑区=旧版侧边栏 Tab" : "旧版侧边栏回退能力未检测到"
|
|
31058
|
+
});
|
|
31059
|
+
if (state.fileClaim || state.claimWanted && (official || officialExpected !== false)) items.push({
|
|
31060
|
+
name: "文件链接官方认领(dsh-resource://file)",
|
|
31061
|
+
active: state.fileClaim,
|
|
31062
|
+
note: state.fileClaim ? "聊天文件链接转发进单一编辑器页签" : "官方文件链接认领未安装"
|
|
31063
|
+
});
|
|
31064
|
+
return items;
|
|
31065
|
+
}
|
|
31066
|
+
//#endregion
|
|
30885
31067
|
//#region src/client/ui/SideEditorTab.ts
|
|
30886
31068
|
/**
|
|
30887
31069
|
* dsh-vscode-mode client — SideEditorTab:betterSidebar「文件编辑」Tab 的组件包装。
|
|
@@ -31973,7 +32155,7 @@ window.__ModuleLoader__.load({
|
|
|
31973
32155
|
...remote,
|
|
31974
32156
|
local: snapshot?.view.marks ?? null,
|
|
31975
32157
|
remote: snapshot ? remote.remote : null,
|
|
31976
|
-
message: localMessage(snapshot?.view) + (remote.message ? ";" + remote.message : ""),
|
|
32158
|
+
message: ready ? localMessage(snapshot?.view) + (remote.message ? ";" + remote.message : "") : "",
|
|
31977
32159
|
canCheck: ready && snapshot !== null,
|
|
31978
32160
|
refreshLocal
|
|
31979
32161
|
};
|
|
@@ -32527,6 +32709,11 @@ window.__ModuleLoader__.load({
|
|
|
32527
32709
|
separator: item.separator,
|
|
32528
32710
|
onClick: () => item.run(menu.target, ctx)
|
|
32529
32711
|
})) : [];
|
|
32712
|
+
/** @private @author ddj 2026年10月15号 Open the existing update window for the current project root. */
|
|
32713
|
+
function updateProject() {
|
|
32714
|
+
ctx?.openSvnUpdate?.("");
|
|
32715
|
+
}
|
|
32716
|
+
const updateHint = !ctx?.svn?.svnCli ? "SVN CLI 不可用" : !ctx?.openSvnUpdate ? "SVN 更新窗口不可用" : "更新项目(打开 SVN 更新窗口)";
|
|
32530
32717
|
const errorList = Object.entries(errors);
|
|
32531
32718
|
const errorText = errorList.length ? errorList[0][1] : null;
|
|
32532
32719
|
return react.default.createElement("div", {
|
|
@@ -32538,11 +32725,11 @@ window.__ModuleLoader__.load({
|
|
|
32538
32725
|
}, rootName), react.default.createElement("span", { style: { flex: 1 } }), ctx?.svn?.managed ? react.default.createElement(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
32539
32726
|
variant: "toolbar",
|
|
32540
32727
|
size: "sm",
|
|
32541
|
-
disabled: !svn.
|
|
32542
|
-
title:
|
|
32543
|
-
onClick:
|
|
32544
|
-
"aria-label": "
|
|
32545
|
-
},
|
|
32728
|
+
disabled: !ctx.svn.svnCli || !ctx.openSvnUpdate,
|
|
32729
|
+
title: updateHint,
|
|
32730
|
+
onClick: updateProject,
|
|
32731
|
+
"aria-label": "更新项目"
|
|
32732
|
+
}, "↓") : null, react.default.createElement("button", {
|
|
32546
32733
|
className: "edrv-side-btn",
|
|
32547
32734
|
title: "刷新目录树",
|
|
32548
32735
|
onClick: () => emitRefresh({
|
|
@@ -35008,6 +35195,11 @@ window.__ModuleLoader__.load({
|
|
|
35008
35195
|
revert: onRevert
|
|
35009
35196
|
})
|
|
35010
35197
|
});
|
|
35198
|
+
/** @private @author ddj 2026年10月15号 Open the shared update window independently of selection and local changes. */
|
|
35199
|
+
function updateProject() {
|
|
35200
|
+
ctxRef.current?.openSvnUpdate?.("");
|
|
35201
|
+
}
|
|
35202
|
+
const updateHint = !managed ? "SVN CLI 或工作副本不可用" : !ctx?.openSvnUpdate ? "SVN 更新窗口不可用" : "更新项目(打开 SVN 更新窗口)";
|
|
35011
35203
|
const rootName = ctx?.svn?.wcRoot ? String(ctx.svn.wcRoot).split(/[\\/]/).pop() || ctx.svn.wcRoot : "";
|
|
35012
35204
|
const remoteEl = remote === null ? null : react.default.createElement("div", { className: "edrv-svn-hintbar" + (remote.failed ? " edrv-svn-hintbar-warn" : "") }, react.default.createElement("span", { style: { flex: 1 } }, remote.failed ? "远端检查失败(网络不可达或超时;可用 ⟳ 或「检查远端」重试)" : remote.outdated.length ? "远端有 " + remote.outdated.length + " 个更新(against r" + (remote.againstRev ?? "?") + "),其中本地已改 " + remote.outdated.filter((item) => item.path && versionedPathSet.has(item.path)).length + " 个;更新前请先提交或还原" : "远端无更新(against r" + (remote.againstRev ?? "?") + ")"), react.default.createElement("button", {
|
|
35013
35205
|
className: "edrv-svn-act",
|
|
@@ -35043,6 +35235,12 @@ window.__ModuleLoader__.load({
|
|
|
35043
35235
|
className: "edrv-side-root",
|
|
35044
35236
|
title: ctx?.svn?.wcRoot || ""
|
|
35045
35237
|
}, rootName), react.default.createElement("span", { style: { flex: 1 } }), react.default.createElement("span", { className: "edrv-svn-head-icons" }, react.default.createElement("button", {
|
|
35238
|
+
className: "edrv-side-btn",
|
|
35239
|
+
title: updateHint,
|
|
35240
|
+
"aria-label": "更新项目",
|
|
35241
|
+
disabled: !managed || !ctx?.openSvnUpdate,
|
|
35242
|
+
onClick: updateProject
|
|
35243
|
+
}, "↓"), react.default.createElement("button", {
|
|
35046
35244
|
className: "edrv-side-btn",
|
|
35047
35245
|
title: "检查远端更新(svn status -u;约数秒,离线自动降级)",
|
|
35048
35246
|
onClick: checkRemote
|
|
@@ -37841,44 +38039,24 @@ window.__ModuleLoader__.load({
|
|
|
37841
38039
|
let claimDisposer = null;
|
|
37842
38040
|
/** 「添加到对话」动作集:编辑区/Tab 右键菜单注入文件引用与代码块(conversation 服务缺失时各动作安全降级)。 */
|
|
37843
38041
|
const addToConversation = createAddToConversation(ctx);
|
|
37844
|
-
/**
|
|
37845
|
-
|
|
37846
|
-
|
|
37847
|
-
|
|
37848
|
-
|
|
37849
|
-
|
|
37850
|
-
|
|
37851
|
-
|
|
37852
|
-
|
|
37853
|
-
|
|
37854
|
-
|
|
37855
|
-
|
|
37856
|
-
|
|
37857
|
-
|
|
37858
|
-
|
|
37859
|
-
|
|
37860
|
-
|
|
37861
|
-
|
|
37862
|
-
name: "侧边栏打开器(dsh-better-sidebar)",
|
|
37863
|
-
active: registry.get(SIDEBAR_PLUGIN) !== void 0,
|
|
37864
|
-
note: registry.get("dsh-better-sidebar") !== void 0 ? "已注册(优先级 80)" : "未检测到侧边栏打开能力"
|
|
37865
|
-
},
|
|
37866
|
-
{
|
|
37867
|
-
name: "侧边栏编辑区(官方 Sidebar)",
|
|
37868
|
-
active: officialService !== void 0,
|
|
37869
|
-
note: officialService !== void 0 ? "编辑区=官方右侧 Sidebar Tab(对话+编辑同屏,DSH 0.1.5+)" : "官方侧边栏服务未探测到(DSH < 0.1.5-alpha.1 时属预期)"
|
|
37870
|
-
},
|
|
37871
|
-
{
|
|
37872
|
-
name: "侧边栏编辑区(dsh-better-sidebar,归档)",
|
|
37873
|
-
active: sideService !== void 0,
|
|
37874
|
-
note: sideService !== void 0 ? "编辑区=侧边栏 Tab(旧版 DSH 回退形态)" : "未检测到;DSH ≥ 0.1.5 优先官方侧边栏,旧版可安装(" + SIDEBAR_INSTALL_CMD + ")"
|
|
37875
|
-
},
|
|
37876
|
-
{
|
|
37877
|
-
name: "文件链接官方认领(dsh-resource://file)",
|
|
37878
|
-
active: claimDisposer !== null,
|
|
37879
|
-
note: claimDisposer !== null ? "聊天文件链接转发进单一编辑器页签(文件分页归编辑器自带页签栏)" : "链接走官方查看器或旧版路由(未认领)"
|
|
37880
|
-
}
|
|
37881
|
-
];
|
|
38042
|
+
/**
|
|
38043
|
+
* Build applicable client diagnostics from live installation state.
|
|
38044
|
+
* @private @author ddj 2026年10月13号
|
|
38045
|
+
* @param version Running DSH version supplied by the compat RPC.
|
|
38046
|
+
* @returns Applicable adapters; routing behavior is unchanged.
|
|
38047
|
+
*/
|
|
38048
|
+
const compatSummary = (version = "") => clientSummary({
|
|
38049
|
+
settingsService: bridge.service(),
|
|
38050
|
+
settingsReady: bridge.scope() !== void 0,
|
|
38051
|
+
openPathReady: Boolean(workspaces?.openPath),
|
|
38052
|
+
remoteReady: remoteOpenInstalled,
|
|
38053
|
+
sidebarOpener: registry.get(SIDEBAR_PLUGIN) !== void 0,
|
|
38054
|
+
legacySidebar: sideService !== void 0,
|
|
38055
|
+
officialSidebar: officialService !== void 0,
|
|
38056
|
+
fileClaim: claimDisposer !== null,
|
|
38057
|
+
claimWanted: shouldClaimFiles(selected),
|
|
38058
|
+
selected
|
|
38059
|
+
}, version);
|
|
37882
38060
|
ctx.provide("fileOpeners", registry);
|
|
37883
38061
|
ctx.effect(() => registry.register(vscodeOpener()), "vscode-mode: file opener");
|
|
37884
38062
|
const sidebarPanels = createSidebarPanelRegistry();
|