dsh-vscode-mode 0.26.0 → 0.27.0
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 +23 -11
- package/lib/client.js +487 -35
- package/lib/client.js.map +2 -2
- package/lib/index.js +398 -183
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/compatSummary.ts +4 -0
- package/src/client/contextMenusOfficial.ts +80 -0
- package/src/client/forgeBridge.ts +28 -0
- package/src/client/index.ts +18 -3
- package/src/client/monaco/lsp/lspClient.ts +25 -7
- package/src/client/officialSidebar.ts +15 -3
- package/src/client/sidebar/menuItems.ts +6 -0
- package/src/client/sidebar/panels/FileExplorer.ts +26 -1
- package/src/client/sidebar/types.ts +3 -0
- package/src/client/state/recordsFeed.ts +40 -3
- package/src/client/state/reviewFeed.ts +9 -2
- package/src/client/tabMenu.ts +5 -0
- package/src/client/ui/ClaimRouter.ts +11 -5
- package/src/client/ui/EditorPane.ts +9 -1
- package/src/client/ui/EditorView.ts +47 -10
- package/src/client/ui/OfficialSideTab.ts +13 -5
- package/src/pending/capture.ts +96 -47
- package/src/pending/store.ts +95 -57
- package/src/pendingCompat.ts +21 -29
- package/src/pendingRpc.ts +5 -6
- package/src/reviewCapture.ts +64 -23
- package/src/reviewEvidence.ts +1 -1
- package/src/reviewRpc.ts +6 -7
- package/src/toolTargets.ts +63 -0
package/lib/client.js
CHANGED
|
@@ -414,6 +414,16 @@ window.__ModuleLoader__.load({
|
|
|
414
414
|
}
|
|
415
415
|
/** @private @author ddj 2026年10月14号 @param event Keyboard activation. */
|
|
416
416
|
function key(event) {
|
|
417
|
+
if (event.key === "ContextMenu" || event.shiftKey && event.key === "F10") {
|
|
418
|
+
event.preventDefault();
|
|
419
|
+
event.stopPropagation();
|
|
420
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
421
|
+
props.onMenu(tab.path, {
|
|
422
|
+
clientX: rect.left,
|
|
423
|
+
clientY: rect.bottom
|
|
424
|
+
});
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
417
427
|
if (event.key === "Enter" || event.key === " ") {
|
|
418
428
|
event.preventDefault();
|
|
419
429
|
props.onSelect(group.id, tab.path);
|
|
@@ -3469,11 +3479,23 @@ window.__ModuleLoader__.load({
|
|
|
3469
3479
|
*/
|
|
3470
3480
|
function refreshFeed(sessionId, skipStale = false) {
|
|
3471
3481
|
const entry = entryOf(sessionId);
|
|
3482
|
+
entry.queuedSkipStale = entry.queuedSkipStale === void 0 ? skipStale : entry.queuedSkipStale && skipStale;
|
|
3483
|
+
if (typeof document !== "undefined" && document.hidden) {
|
|
3484
|
+
entry.queued = true;
|
|
3485
|
+
return Promise.resolve();
|
|
3486
|
+
}
|
|
3487
|
+
if (entry.inflight) {
|
|
3488
|
+
entry.queued = true;
|
|
3489
|
+
return entry.request ?? Promise.resolve();
|
|
3490
|
+
}
|
|
3491
|
+
skipStale = entry.queuedSkipStale ?? skipStale;
|
|
3492
|
+
entry.queuedSkipStale = void 0;
|
|
3472
3493
|
const current = ++entry.seq;
|
|
3473
3494
|
entry.inflight = true;
|
|
3495
|
+
entry.controller = new AbortController();
|
|
3474
3496
|
const payload = { sessionId };
|
|
3475
3497
|
if (skipStale) payload.skipStale = true;
|
|
3476
|
-
|
|
3498
|
+
entry.request = rpc("edrv.list", payload, entry.controller.signal).then((res) => {
|
|
3477
3499
|
if (current !== entry.seq) return;
|
|
3478
3500
|
if (!res || !res.ok || !Array.isArray(res.records)) return;
|
|
3479
3501
|
entry.records = res.records;
|
|
@@ -3485,8 +3507,14 @@ window.__ModuleLoader__.load({
|
|
|
3485
3507
|
listener(message);
|
|
3486
3508
|
} catch {}
|
|
3487
3509
|
}).finally(() => {
|
|
3488
|
-
if (current
|
|
3510
|
+
if (current !== entry.seq) return;
|
|
3511
|
+
entry.inflight = false;
|
|
3512
|
+
if (entry.queued) {
|
|
3513
|
+
entry.queued = false;
|
|
3514
|
+
if (feeds$1.get(sessionId) === entry) return refreshFeed(sessionId, entry.queuedSkipStale ?? false);
|
|
3515
|
+
}
|
|
3489
3516
|
});
|
|
3517
|
+
return entry.request;
|
|
3490
3518
|
}
|
|
3491
3519
|
/**
|
|
3492
3520
|
* 确保该会话的定时器与 refresh 事件监听已就绪(首个订阅者到来时启动)。
|
|
@@ -3496,12 +3524,26 @@ window.__ModuleLoader__.load({
|
|
|
3496
3524
|
*/
|
|
3497
3525
|
function ensureTimer$1(sessionId, entry) {
|
|
3498
3526
|
if (entry.timer === null) entry.timer = setInterval(() => {
|
|
3527
|
+
if (typeof document !== "undefined" && document.hidden) return;
|
|
3499
3528
|
const tickers = Array.from(entry.tickers);
|
|
3500
3529
|
for (const tick of tickers) try {
|
|
3501
3530
|
tick();
|
|
3502
3531
|
} catch {}
|
|
3503
3532
|
if (entry.listeners.size > 0 || entry.errorListeners.size > 0) refreshFeed(sessionId);
|
|
3504
3533
|
}, FEED_INTERVAL_MS);
|
|
3534
|
+
if (!entry.onVisible && typeof document !== "undefined") {
|
|
3535
|
+
entry.onVisible = () => {
|
|
3536
|
+
if (document.hidden) return;
|
|
3537
|
+
for (const tick of entry.tickers) try {
|
|
3538
|
+
tick();
|
|
3539
|
+
} catch {}
|
|
3540
|
+
if (entry.listeners.size || entry.errorListeners.size) {
|
|
3541
|
+
entry.queued = false;
|
|
3542
|
+
refreshFeed(sessionId);
|
|
3543
|
+
}
|
|
3544
|
+
};
|
|
3545
|
+
document.addEventListener("visibilitychange", entry.onVisible);
|
|
3546
|
+
}
|
|
3505
3547
|
if (entry.onRefresh === null) {
|
|
3506
3548
|
const handler = () => {
|
|
3507
3549
|
refreshFeed(sessionId);
|
|
@@ -3518,12 +3560,16 @@ window.__ModuleLoader__.load({
|
|
|
3518
3560
|
* @param entry 订阅槽位
|
|
3519
3561
|
*/
|
|
3520
3562
|
function releaseIfIdle(sessionId, entry) {
|
|
3521
|
-
if (entry.listeners.size || entry.tickers.size || entry.errorListeners.size) return;
|
|
3563
|
+
if (feeds$1.get(sessionId) !== entry || entry.listeners.size || entry.tickers.size || entry.errorListeners.size) return;
|
|
3522
3564
|
if (entry.timer !== null) clearInterval(entry.timer);
|
|
3523
3565
|
if (entry.onRefresh !== null) {
|
|
3524
3566
|
const target = win();
|
|
3525
3567
|
if (target) target.removeEventListener("edrv:refresh", entry.onRefresh);
|
|
3526
3568
|
}
|
|
3569
|
+
entry.seq++;
|
|
3570
|
+
entry.queued = false;
|
|
3571
|
+
entry.controller?.abort();
|
|
3572
|
+
if (entry.onVisible && typeof document !== "undefined") document.removeEventListener("visibilitychange", entry.onVisible);
|
|
3527
3573
|
feeds$1.delete(sessionId);
|
|
3528
3574
|
}
|
|
3529
3575
|
/**
|
|
@@ -3588,6 +3634,10 @@ window.__ModuleLoader__.load({
|
|
|
3588
3634
|
/** @private @author ddj 2026年10月26号 @param sessionId Scope. @param entry Current generation. @returns First-page metadata update; no overlap or late publication. */
|
|
3589
3635
|
async function refresh(sessionId, entry, force = false) {
|
|
3590
3636
|
if (entry.controller.signal.aborted) return;
|
|
3637
|
+
if (typeof document !== "undefined" && document.hidden) {
|
|
3638
|
+
entry.again = true;
|
|
3639
|
+
return;
|
|
3640
|
+
}
|
|
3591
3641
|
if (entry.loading) {
|
|
3592
3642
|
entry.again = true;
|
|
3593
3643
|
return;
|
|
@@ -3641,17 +3691,25 @@ window.__ModuleLoader__.load({
|
|
|
3641
3691
|
};
|
|
3642
3692
|
feeds.set(sessionId, entry);
|
|
3643
3693
|
if (typeof window !== "undefined") window.addEventListener("edrv:refresh", onRefresh);
|
|
3694
|
+
if (typeof document !== "undefined") {
|
|
3695
|
+
const current = entry;
|
|
3696
|
+
entry.onVisible = () => {
|
|
3697
|
+
if (!document.hidden) refresh(sessionId, current);
|
|
3698
|
+
};
|
|
3699
|
+
document.addEventListener("visibilitychange", entry.onVisible);
|
|
3700
|
+
}
|
|
3644
3701
|
refresh(sessionId, entry);
|
|
3645
3702
|
}
|
|
3646
3703
|
entry.listeners.add(listener);
|
|
3647
3704
|
listener(entry.value);
|
|
3648
3705
|
return () => {
|
|
3649
3706
|
entry.listeners.delete(listener);
|
|
3650
|
-
if (entry.listeners.size) return;
|
|
3707
|
+
if (entry.listeners.size || feeds.get(sessionId) !== entry) return;
|
|
3651
3708
|
entry.controller.abort();
|
|
3652
3709
|
clearTimeout(entry.timer);
|
|
3653
3710
|
feeds.delete(sessionId);
|
|
3654
3711
|
if (typeof window !== "undefined") window.removeEventListener("edrv:refresh", entry.onRefresh);
|
|
3712
|
+
if (entry.onVisible && typeof document !== "undefined") document.removeEventListener("visibilitychange", entry.onVisible);
|
|
3655
3713
|
};
|
|
3656
3714
|
}
|
|
3657
3715
|
/** @public @author ddj 2026年10月26号 @param sessionId Refresh metadata after a decision; does not alter legacy or disk. */
|
|
@@ -376726,9 +376784,15 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
376726
376784
|
*/
|
|
376727
376785
|
function resolveNavLine(params) {
|
|
376728
376786
|
const line = (params ?? {})?.line;
|
|
376729
|
-
if (typeof line !== "number" || !Number.isFinite(line) || line
|
|
376787
|
+
if (typeof line !== "number" || !Number.isFinite(line) || line < 1) return void 0;
|
|
376730
376788
|
return Math.floor(line);
|
|
376731
376789
|
}
|
|
376790
|
+
/** @public @author ddj 2026年11月04号 @param params Plugin navigation extension. @returns Positive column only alongside a valid line; official line-only callers remain unchanged. */
|
|
376791
|
+
function resolveNavColumn(params) {
|
|
376792
|
+
if (!resolveNavLine(params)) return void 0;
|
|
376793
|
+
const column = params?.column;
|
|
376794
|
+
return typeof column === "number" && Number.isFinite(column) && column >= 1 ? Math.floor(column) : void 0;
|
|
376795
|
+
}
|
|
376732
376796
|
/** 逐段 component 解码(失败返回 null,对齐官方 parseFileAddress 的容错语义)。 */
|
|
376733
376797
|
function decodeSegment(raw) {
|
|
376734
376798
|
if (raw === void 0) return null;
|
|
@@ -376749,7 +376813,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
376749
376813
|
*/
|
|
376750
376814
|
function parseOfficialFileAddress(address) {
|
|
376751
376815
|
if (typeof address !== "string" || !address.startsWith("dsh-resource://file/")) return null;
|
|
376752
|
-
const [scope, ...tail] = address.slice(20).split("/");
|
|
376816
|
+
const [scope, ...tail] = address.split(/[?#]/, 1)[0].slice(20).split("/");
|
|
376753
376817
|
const kind = decodeSegment(scope);
|
|
376754
376818
|
if (kind === "session") {
|
|
376755
376819
|
const sessionId = decodeSegment(tail[0]);
|
|
@@ -376817,10 +376881,16 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
376817
376881
|
* @param preview 可选 Markdown 渲染模式(行号导航优先源码)
|
|
376818
376882
|
* @returns 转发是否成功(openTab 抛错返回 false,由调用方决定重试或兜底)
|
|
376819
376883
|
*/
|
|
376820
|
-
function forwardToEditor(service, path, line, preview) {
|
|
376884
|
+
function forwardToEditor(service, path, line, preview, column) {
|
|
376821
376885
|
if (!service || typeof service.openTab !== "function" || !path) return false;
|
|
376822
376886
|
const params = { openPath: path };
|
|
376823
|
-
|
|
376887
|
+
const validLine = resolveNavLine({ line });
|
|
376888
|
+
if (validLine !== void 0) params.line = validLine;
|
|
376889
|
+
const validColumn = resolveNavColumn({
|
|
376890
|
+
line: validLine,
|
|
376891
|
+
column
|
|
376892
|
+
});
|
|
376893
|
+
if (validColumn !== void 0) params.column = validColumn;
|
|
376824
376894
|
if (preview !== void 0) params.preview = preview;
|
|
376825
376895
|
try {
|
|
376826
376896
|
service.openTab(OFFICIAL_TAB_KIND, { params });
|
|
@@ -386122,6 +386192,8 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
386122
386192
|
at: 0
|
|
386123
386193
|
};
|
|
386124
386194
|
let progressListeners = /* @__PURE__ */ new Set();
|
|
386195
|
+
let statusRequest = null;
|
|
386196
|
+
let statusEpoch = 0;
|
|
386125
386197
|
/** 会话 id 变更通知(EditorView 持有权威 sessionId,经窗口事件回填)。 */
|
|
386126
386198
|
const SESSION_EVENT = "edrv:lsp-session";
|
|
386127
386199
|
/** 上报可见状态(复用 EditorView 的状态通道;失败不再静默)。 */
|
|
@@ -386141,6 +386213,11 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
386141
386213
|
syncTimers.clear();
|
|
386142
386214
|
docVersions.clear();
|
|
386143
386215
|
sessionId$1 = id;
|
|
386216
|
+
statusEpoch++;
|
|
386217
|
+
statusCache = {
|
|
386218
|
+
servers: [],
|
|
386219
|
+
at: 0
|
|
386220
|
+
};
|
|
386144
386221
|
refreshStatus();
|
|
386145
386222
|
}
|
|
386146
386223
|
/**
|
|
@@ -386400,17 +386477,35 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
386400
386477
|
if (!res || !res.tokens || !Array.isArray(res.tokens.data)) return null;
|
|
386401
386478
|
return res.tokens;
|
|
386402
386479
|
}
|
|
386403
|
-
/**
|
|
386480
|
+
/** @public @author ddj 2026年11月04号 @param force Bypass cached data, not the in-flight guard. @returns Current-session server status; stale responses never publish. */
|
|
386404
386481
|
async function refreshStatus(force = false) {
|
|
386482
|
+
if (statusRequest) {
|
|
386483
|
+
const pending = statusRequest;
|
|
386484
|
+
await pending.promise;
|
|
386485
|
+
if (pending.epoch !== statusEpoch) return refreshStatus(force);
|
|
386486
|
+
return statusCache.servers;
|
|
386487
|
+
}
|
|
386488
|
+
if (typeof document !== "undefined" && document.hidden) return statusCache.servers;
|
|
386405
386489
|
if (!force && Date.now() - statusCache.at < 1500) return statusCache.servers;
|
|
386406
|
-
const
|
|
386407
|
-
const
|
|
386408
|
-
|
|
386409
|
-
|
|
386410
|
-
at: Date.now()
|
|
386490
|
+
const epoch = statusEpoch, owner = sessionId$1;
|
|
386491
|
+
const request = {
|
|
386492
|
+
epoch,
|
|
386493
|
+
promise: rpc("edrv.lsp.status", { sessionId: owner }).catch(() => null)
|
|
386411
386494
|
};
|
|
386412
|
-
|
|
386413
|
-
|
|
386495
|
+
statusRequest = request;
|
|
386496
|
+
try {
|
|
386497
|
+
const res = await request.promise;
|
|
386498
|
+
if (epoch !== statusEpoch || owner !== sessionId$1) return statusCache.servers;
|
|
386499
|
+
const servers = res && res.ok && Array.isArray(res.servers) ? res.servers : [];
|
|
386500
|
+
statusCache = {
|
|
386501
|
+
servers,
|
|
386502
|
+
at: Date.now()
|
|
386503
|
+
};
|
|
386504
|
+
publishProgress();
|
|
386505
|
+
return servers;
|
|
386506
|
+
} finally {
|
|
386507
|
+
if (statusRequest === request) statusRequest = null;
|
|
386508
|
+
}
|
|
386414
386509
|
}
|
|
386415
386510
|
/** file:// 或已转 edrv:// 的 LSP location → Monaco Location(edrv:// uri + 1-based range)。 */
|
|
386416
386511
|
function toClientLocation(loc) {
|
|
@@ -389483,6 +389578,13 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
389483
389578
|
label: "添加到对话",
|
|
389484
389579
|
disabled: !(hasSession && canAddToConversation)
|
|
389485
389580
|
},
|
|
389581
|
+
...state.forgeReady ? [{
|
|
389582
|
+
id: "forge-open",
|
|
389583
|
+
label: "打开 Forge"
|
|
389584
|
+
}, {
|
|
389585
|
+
id: "forge-local",
|
|
389586
|
+
label: "查看本地变更(Forge)"
|
|
389587
|
+
}] : [],
|
|
389486
389588
|
{
|
|
389487
389589
|
id: "close",
|
|
389488
389590
|
label: "关闭",
|
|
@@ -394409,9 +394511,11 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
394409
394511
|
page: null,
|
|
394410
394512
|
error: ""
|
|
394411
394513
|
});
|
|
394412
|
-
if (!sessionId) return void 0;
|
|
394413
|
-
return subscribeReview(sessionId, setReview);
|
|
394414
394514
|
}, [sessionId]);
|
|
394515
|
+
react$1.default.useEffect(() => {
|
|
394516
|
+
if (!sessionId || props.visible === false) return void 0;
|
|
394517
|
+
return subscribeReview(sessionId, setReview);
|
|
394518
|
+
}, [sessionId, props.visible]);
|
|
394415
394519
|
const [tabs, setTabs] = react$1.default.useState([]);
|
|
394416
394520
|
const [active, setDiskActive] = react$1.default.useState(null);
|
|
394417
394521
|
const [planTabs, setPlanTabs] = react$1.default.useState([]);
|
|
@@ -395720,7 +395824,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
395720
395824
|
});
|
|
395721
395825
|
};
|
|
395722
395826
|
react$1.default.useEffect(() => {
|
|
395723
|
-
if (!sessionId) return void 0;
|
|
395827
|
+
if (!sessionId || props.visible === false) return void 0;
|
|
395724
395828
|
const offRecords = subscribeRecords(sessionId, applyRecords);
|
|
395725
395829
|
const offErrors = subscribeErrors(sessionId, (message) => setError("list异常:" + message));
|
|
395726
395830
|
refreshRecords();
|
|
@@ -395728,7 +395832,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
395728
395832
|
offRecords();
|
|
395729
395833
|
offErrors();
|
|
395730
395834
|
};
|
|
395731
|
-
}, [sessionId]);
|
|
395835
|
+
}, [sessionId, props.visible]);
|
|
395732
395836
|
/**
|
|
395733
395837
|
* 展示外部同步提示(按路径+类型去重:同一文件重复回调不重置已关闭的提示)。
|
|
395734
395838
|
* @author ddj 2026年09月15号
|
|
@@ -395847,17 +395951,31 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
395847
395951
|
onDiskChange: (change) => diskChangeRef.current?.(change)
|
|
395848
395952
|
});
|
|
395849
395953
|
react$1.default.useEffect(() => {
|
|
395850
|
-
|
|
395954
|
+
let alive = true;
|
|
395955
|
+
let loading = false;
|
|
395956
|
+
const publishLsp = (servers) => {
|
|
395957
|
+
if (alive) setLspServers(Array.isArray(servers) ? servers : []);
|
|
395958
|
+
};
|
|
395959
|
+
const refreshLsp = async () => {
|
|
395960
|
+
if (loading || props.visible === false || document.hidden) return;
|
|
395961
|
+
loading = true;
|
|
395962
|
+
try {
|
|
395963
|
+
publishLsp(await refreshStatus(true));
|
|
395964
|
+
} finally {
|
|
395965
|
+
loading = false;
|
|
395966
|
+
}
|
|
395967
|
+
};
|
|
395851
395968
|
const unsubscribe = onLspProgress(publishLsp);
|
|
395852
|
-
|
|
395853
|
-
const timer = setInterval(
|
|
395854
|
-
|
|
395855
|
-
}, 1500);
|
|
395969
|
+
refreshLsp();
|
|
395970
|
+
const timer = setInterval(refreshLsp, 1500);
|
|
395971
|
+
document.addEventListener("visibilitychange", refreshLsp);
|
|
395856
395972
|
return () => {
|
|
395973
|
+
alive = false;
|
|
395857
395974
|
unsubscribe();
|
|
395858
395975
|
clearInterval(timer);
|
|
395976
|
+
document.removeEventListener("visibilitychange", refreshLsp);
|
|
395859
395977
|
};
|
|
395860
|
-
}, [sessionId]);
|
|
395978
|
+
}, [sessionId, props.visible]);
|
|
395861
395979
|
react$1.default.useEffect(() => {
|
|
395862
395980
|
if (!sessionId) return;
|
|
395863
395981
|
setSession(sessionId);
|
|
@@ -395907,6 +396025,9 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
395907
396025
|
const fileOpenRef = react$1.default.useRef(null);
|
|
395908
396026
|
/** @private @author ddj 2026年10月08号 @param e Routed file request. Always uses the current workspace and save/preview callbacks. */
|
|
395909
396027
|
fileOpenRef.current = (e) => {
|
|
396028
|
+
if (e?.detail?.sessionId && e.detail.sessionId !== sessionId) return;
|
|
396029
|
+
if (e?.detail?.ownerId && e.detail.ownerId !== props?.ownerId) return;
|
|
396030
|
+
if (!e?.detail?.ownerId && props?.visible === false) return;
|
|
395910
396031
|
const p = e?.detail?.path;
|
|
395911
396032
|
if (!p) return;
|
|
395912
396033
|
const normalized = tabPath(p);
|
|
@@ -398670,6 +398791,8 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
398670
398791
|
}
|
|
398671
398792
|
const tabMenuActions = (path) => ({
|
|
398672
398793
|
"add-to-conversation": () => addRefToChat(path),
|
|
398794
|
+
"forge-open": () => props.forge?.open(sessionId),
|
|
398795
|
+
"forge-local": () => props.forge?.open(sessionId, true),
|
|
398673
398796
|
"split-left": () => splitTab(path, "left"),
|
|
398674
398797
|
"split-right": () => splitTab(path, "right"),
|
|
398675
398798
|
"split-top": () => splitTab(path, "top"),
|
|
@@ -398716,6 +398839,7 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
398716
398839
|
cwd,
|
|
398717
398840
|
hasSession: Boolean(sessionId),
|
|
398718
398841
|
canAddToConversation: Boolean(addToConversation),
|
|
398842
|
+
forgeReady: props.forge?.available() === true,
|
|
398719
398843
|
canSplit: workbench.groups.length < 8 && !workbench.floats.some((item) => item.group === ownerOf(workbench, tabMenu.path)?.id),
|
|
398720
398844
|
canFloat: workbench.groups.length < 8,
|
|
398721
398845
|
canReturn: ownerOf(workbench, tabMenu.path)?.id !== MAIN_GROUP,
|
|
@@ -399098,6 +399222,48 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
399098
399222
|
y: event.clientY
|
|
399099
399223
|
});
|
|
399100
399224
|
}
|
|
399225
|
+
const menuOwner = react$1.default.useRef({
|
|
399226
|
+
sessionId,
|
|
399227
|
+
scope,
|
|
399228
|
+
alive: true
|
|
399229
|
+
});
|
|
399230
|
+
menuOwner.current.sessionId = sessionId;
|
|
399231
|
+
menuOwner.current.scope = scope;
|
|
399232
|
+
const menuValid = react$1.default.useRef(null);
|
|
399233
|
+
react$1.default.useEffect(() => {
|
|
399234
|
+
menuOwner.current.alive = props.visible !== false;
|
|
399235
|
+
return () => {
|
|
399236
|
+
menuOwner.current.alive = false;
|
|
399237
|
+
if (menuValid.current) props.officialMenus?.invalidate(menuValid.current);
|
|
399238
|
+
};
|
|
399239
|
+
}, [
|
|
399240
|
+
sessionId,
|
|
399241
|
+
scope,
|
|
399242
|
+
props.visible,
|
|
399243
|
+
props.officialMenus
|
|
399244
|
+
]);
|
|
399245
|
+
react$1.default.useEffect(() => {
|
|
399246
|
+
if (!tabMenu || !props.officialMenus || !sessionId) return;
|
|
399247
|
+
const capturedSession = sessionId;
|
|
399248
|
+
const capturedScope = scope;
|
|
399249
|
+
const path = tabMenu.path;
|
|
399250
|
+
const groupId = ownerOf(benchRef.current, path)?.id;
|
|
399251
|
+
const valid = () => menuOwner.current.alive && menuOwner.current.sessionId === capturedSession && menuOwner.current.scope === capturedScope && ownerOf(benchRef.current, path)?.id === groupId && tabsRef.current.some((tab) => tab.path === path);
|
|
399252
|
+
menuValid.current = valid;
|
|
399253
|
+
const items = tabMenuEntries().map((entry) => ({
|
|
399254
|
+
...entry,
|
|
399255
|
+
run: entry.onClick ?? (() => {})
|
|
399256
|
+
}));
|
|
399257
|
+
if (props.officialMenus.open("tab", sessionId, path, {
|
|
399258
|
+
x: tabMenu.x,
|
|
399259
|
+
y: tabMenu.y
|
|
399260
|
+
}, items, valid)) setTabMenu(null);
|
|
399261
|
+
}, [
|
|
399262
|
+
tabMenu,
|
|
399263
|
+
props.officialMenus,
|
|
399264
|
+
sessionId,
|
|
399265
|
+
scope
|
|
399266
|
+
]);
|
|
399101
399267
|
/** @private @author ddj 2026年10月14号 @param group Auxiliary group. Return documents rather than closing them. */
|
|
399102
399268
|
function returnPane(group) {
|
|
399103
399269
|
acceptLayout(returnGroup(benchRef.current, group));
|
|
@@ -399877,6 +400043,9 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
399877
400043
|
editor: () => editorRef.current,
|
|
399878
400044
|
outlineSources: props.outlineSources,
|
|
399879
400045
|
fileMenuItems: props.fileMenuItems,
|
|
400046
|
+
officialMenus: props.officialMenus,
|
|
400047
|
+
visible: props.visible,
|
|
400048
|
+
forge: props.forge,
|
|
399880
400049
|
addToConversation,
|
|
399881
400050
|
svn: svnStatus,
|
|
399882
400051
|
svnChanges,
|
|
@@ -403933,6 +404102,144 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
403933
404102
|
return new McpSessionState(fetchStatus, document);
|
|
403934
404103
|
}
|
|
403935
404104
|
//#endregion
|
|
404105
|
+
//#region src/client/forgeBridge.ts
|
|
404106
|
+
/** @public @author ddj 2026年11月04号 @param ctx Client capabilities. @param current Current session reader. @returns Capability-gated official navigation, with no polling or writes. */
|
|
404107
|
+
function forgeBridge(ctx, current) {
|
|
404108
|
+
const capabilities = () => {
|
|
404109
|
+
try {
|
|
404110
|
+
return {
|
|
404111
|
+
tabs: ctx.get("sidebarRightTabs"),
|
|
404112
|
+
service: ctx.get("sidebarRight")
|
|
404113
|
+
};
|
|
404114
|
+
} catch {
|
|
404115
|
+
return;
|
|
404116
|
+
}
|
|
404117
|
+
};
|
|
404118
|
+
return {
|
|
404119
|
+
available() {
|
|
404120
|
+
const capabilitiesNow = capabilities();
|
|
404121
|
+
return Boolean(capabilitiesNow?.tabs?.get?.("forge-panel") && capabilitiesNow.tabs.get("forge-changes") && capabilitiesNow.service?.openTab && capabilitiesNow.service.openResource);
|
|
404122
|
+
},
|
|
404123
|
+
open(sessionId, local = false) {
|
|
404124
|
+
if (!sessionId || current() !== sessionId || !this.available()) return false;
|
|
404125
|
+
const service = capabilities().service;
|
|
404126
|
+
try {
|
|
404127
|
+
if (local) service.openResource("dsh-resource://forge-changes/" + encodeURIComponent(sessionId) + "/local", { kind: "forge-changes" });
|
|
404128
|
+
else service.openTab("forge-panel");
|
|
404129
|
+
return true;
|
|
404130
|
+
} catch {
|
|
404131
|
+
return false;
|
|
404132
|
+
}
|
|
404133
|
+
}
|
|
404134
|
+
};
|
|
404135
|
+
}
|
|
404136
|
+
//#endregion
|
|
404137
|
+
//#region src/client/contextMenusOfficial.ts
|
|
404138
|
+
let ownerSeq = 0;
|
|
404139
|
+
/** @public @author ddj 2026年11月04号 @param ctx Optional service context. @returns Retry-on-use bridge for late service registration, with legacy fallback. */
|
|
404140
|
+
function lazyMenus(ctx) {
|
|
404141
|
+
let bridge;
|
|
404142
|
+
let stopped = false;
|
|
404143
|
+
return {
|
|
404144
|
+
open(...args) {
|
|
404145
|
+
if (stopped) return false;
|
|
404146
|
+
bridge ??= officialMenus(ctx);
|
|
404147
|
+
return bridge?.open(...args) ?? false;
|
|
404148
|
+
},
|
|
404149
|
+
invalidate(valid) {
|
|
404150
|
+
bridge?.invalidate(valid);
|
|
404151
|
+
},
|
|
404152
|
+
dispose() {
|
|
404153
|
+
stopped = true;
|
|
404154
|
+
bridge?.dispose();
|
|
404155
|
+
bridge = void 0;
|
|
404156
|
+
}
|
|
404157
|
+
};
|
|
404158
|
+
}
|
|
404159
|
+
/** @public @author ddj 2026年11月04号 @param ctx Optional service context. @returns Scoped bridge or no capability, preserving the existing popup. */
|
|
404160
|
+
function officialMenus(ctx) {
|
|
404161
|
+
let service;
|
|
404162
|
+
try {
|
|
404163
|
+
service = ctx.get("contextMenus");
|
|
404164
|
+
} catch {
|
|
404165
|
+
return;
|
|
404166
|
+
}
|
|
404167
|
+
if (!service || typeof service.register !== "function" || typeof service.open !== "function" || typeof service.close !== "function") return void 0;
|
|
404168
|
+
const owner = "edrv-menu-" + ++ownerSeq;
|
|
404169
|
+
let current;
|
|
404170
|
+
let revision = 0;
|
|
404171
|
+
let stopped = false;
|
|
404172
|
+
const disposers = [];
|
|
404173
|
+
try {
|
|
404174
|
+
for (const kind of ["resource", "tab"]) disposers.push(service.register({
|
|
404175
|
+
id: owner + "-" + kind,
|
|
404176
|
+
target: "edrv." + kind,
|
|
404177
|
+
order: 30,
|
|
404178
|
+
resolve: (target, signal) => {
|
|
404179
|
+
const opening = current;
|
|
404180
|
+
if (stopped || target.owner !== owner || !opening || !opening.valid() || signal.aborted) return [];
|
|
404181
|
+
return opening.items.map((item) => ({
|
|
404182
|
+
id: item.id,
|
|
404183
|
+
label: item.label,
|
|
404184
|
+
disabled: item.disabled,
|
|
404185
|
+
danger: item.danger,
|
|
404186
|
+
separatorBefore: item.separator,
|
|
404187
|
+
commandId: item.commandId,
|
|
404188
|
+
run: async () => {
|
|
404189
|
+
if (stopped || opening.revision !== revision || !opening.valid() || item.disabled) return;
|
|
404190
|
+
await item.run();
|
|
404191
|
+
}
|
|
404192
|
+
}));
|
|
404193
|
+
}
|
|
404194
|
+
}));
|
|
404195
|
+
} catch {
|
|
404196
|
+
for (const dispose of disposers) dispose();
|
|
404197
|
+
return;
|
|
404198
|
+
}
|
|
404199
|
+
/** @private @author ddj 2026年11月04号 Close only this bridge's active shared popup. */
|
|
404200
|
+
function closeOwned() {
|
|
404201
|
+
const active = service.active?.getSnapshot();
|
|
404202
|
+
if (active?.value?.owner === owner && (active.kind === "edrv.resource" || active.kind === "edrv.tab")) service.close();
|
|
404203
|
+
}
|
|
404204
|
+
return {
|
|
404205
|
+
open(kind, sessionId, path, point, items, valid) {
|
|
404206
|
+
if (stopped || !sessionId || !valid()) return false;
|
|
404207
|
+
current = {
|
|
404208
|
+
items,
|
|
404209
|
+
valid,
|
|
404210
|
+
revision: ++revision
|
|
404211
|
+
};
|
|
404212
|
+
try {
|
|
404213
|
+
service.open({
|
|
404214
|
+
kind: "edrv." + kind,
|
|
404215
|
+
value: {
|
|
404216
|
+
owner,
|
|
404217
|
+
sessionId,
|
|
404218
|
+
path
|
|
404219
|
+
}
|
|
404220
|
+
}, point);
|
|
404221
|
+
return true;
|
|
404222
|
+
} catch {
|
|
404223
|
+
current = void 0;
|
|
404224
|
+
return false;
|
|
404225
|
+
}
|
|
404226
|
+
},
|
|
404227
|
+
invalidate(valid) {
|
|
404228
|
+
if (current?.valid !== valid) return;
|
|
404229
|
+
revision++;
|
|
404230
|
+
current = void 0;
|
|
404231
|
+
closeOwned();
|
|
404232
|
+
},
|
|
404233
|
+
dispose() {
|
|
404234
|
+
stopped = true;
|
|
404235
|
+
revision++;
|
|
404236
|
+
current = void 0;
|
|
404237
|
+
closeOwned();
|
|
404238
|
+
for (const dispose of disposers) dispose();
|
|
404239
|
+
}
|
|
404240
|
+
};
|
|
404241
|
+
}
|
|
404242
|
+
//#endregion
|
|
403936
404243
|
//#region src/client/ui/McpSessionStatus.ts
|
|
403937
404244
|
/** Official session-row slots; no DOM patching or session activation. @author ddj 2026年10月20号 */
|
|
403938
404245
|
const labels = {
|
|
@@ -404271,6 +404578,16 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
404271
404578
|
active: state.fileClaim,
|
|
404272
404579
|
note: state.fileClaim ? "聊天文件链接转发进单一编辑器页签" : "官方文件链接认领未安装"
|
|
404273
404580
|
});
|
|
404581
|
+
if (state.officialMenus !== void 0) items.push({
|
|
404582
|
+
name: "官方右键菜单",
|
|
404583
|
+
active: state.officialMenus,
|
|
404584
|
+
note: state.officialMenus ? "插件动作接入共享菜单" : "服务缺失或装配失败,保留插件菜单"
|
|
404585
|
+
});
|
|
404586
|
+
if (state.forge !== void 0) items.push({
|
|
404587
|
+
name: "Forge 导航",
|
|
404588
|
+
active: state.forge,
|
|
404589
|
+
note: state.forge ? "导航至官方面板与本地变更;PR 保持官方审查" : "官方 Forge 未安装或未启用,不自动启用"
|
|
404590
|
+
});
|
|
404274
404591
|
return items;
|
|
404275
404592
|
}
|
|
404276
404593
|
//#endregion
|
|
@@ -404339,8 +404656,12 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
404339
404656
|
const sessionId = props?.sessionId;
|
|
404340
404657
|
const useTabInfo = props?.useTabInfo;
|
|
404341
404658
|
let navigation;
|
|
404659
|
+
let tab;
|
|
404660
|
+
let visible = true;
|
|
404342
404661
|
if (typeof useTabInfo === "function") try {
|
|
404343
|
-
|
|
404662
|
+
tab = useTabInfo()?.tab;
|
|
404663
|
+
navigation = tab?.navigation;
|
|
404664
|
+
visible = tab?.visible !== false;
|
|
404344
404665
|
} catch {
|
|
404345
404666
|
navigation = void 0;
|
|
404346
404667
|
}
|
|
@@ -404371,19 +404692,25 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
404371
404692
|
if (revision <= 0) return;
|
|
404372
404693
|
const fileHit = parseOfficialFileAddress(navigation?.address);
|
|
404373
404694
|
if (fileHit) {
|
|
404374
|
-
const line = navigation?.params
|
|
404695
|
+
const line = resolveNavLine(navigation?.params);
|
|
404375
404696
|
window.dispatchEvent(new CustomEvent("edrv:open-editor", { detail: {
|
|
404697
|
+
sessionId,
|
|
404698
|
+
ownerId: tab?.id,
|
|
404376
404699
|
path: fileHit.path,
|
|
404377
|
-
line
|
|
404700
|
+
line,
|
|
404701
|
+
column: resolveNavColumn(navigation?.params),
|
|
404378
404702
|
preview: navigation?.params?.preview
|
|
404379
404703
|
} }));
|
|
404380
404704
|
return;
|
|
404381
404705
|
}
|
|
404382
404706
|
const request = resolveNavOpen(navigation?.params);
|
|
404383
404707
|
window.dispatchEvent(new CustomEvent("edrv:open-editor", { detail: {
|
|
404708
|
+
sessionId,
|
|
404709
|
+
ownerId: tab?.id,
|
|
404384
404710
|
path: request.path,
|
|
404385
404711
|
focusDiff: request.focusDiff,
|
|
404386
404712
|
line: resolveNavLine(navigation?.params),
|
|
404713
|
+
column: resolveNavColumn(navigation?.params),
|
|
404387
404714
|
preview: navigation?.params?.preview
|
|
404388
404715
|
} }));
|
|
404389
404716
|
});
|
|
@@ -404391,11 +404718,15 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
404391
404718
|
key: sessionId,
|
|
404392
404719
|
sessionId,
|
|
404393
404720
|
layout: "side",
|
|
404721
|
+
visible,
|
|
404722
|
+
ownerId: tab?.id,
|
|
404394
404723
|
schedule: props?.schedule,
|
|
404395
404724
|
addToConversation: props?.addToConversation,
|
|
404396
404725
|
sidebarPanels: props?.sidebarPanels,
|
|
404397
404726
|
outlineSources: props?.outlineSources,
|
|
404398
404727
|
fileMenuItems: props?.fileMenuItems,
|
|
404728
|
+
officialMenus: props?.officialMenus,
|
|
404729
|
+
forge: props?.forge,
|
|
404399
404730
|
fileOpeners: props?.fileOpeners,
|
|
404400
404731
|
sessions: props?.sessions
|
|
404401
404732
|
});
|
|
@@ -404462,17 +404793,27 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
404462
404793
|
const [failed, setFailed] = react$1.default.useState(false);
|
|
404463
404794
|
const doneRef = react$1.default.useRef(-1);
|
|
404464
404795
|
react$1.default.useEffect(() => {
|
|
404465
|
-
|
|
404466
|
-
|
|
404796
|
+
const intent = JSON.stringify([
|
|
404797
|
+
props?.sessionId,
|
|
404798
|
+
tab?.id,
|
|
404799
|
+
revision,
|
|
404800
|
+
navigation?.address
|
|
404801
|
+
]);
|
|
404802
|
+
if (intent === doneRef.current) return;
|
|
404467
404803
|
const parsed = parseOfficialFileAddress(navigation?.address);
|
|
404468
404804
|
if (!parsed) {
|
|
404469
404805
|
setFailed(true);
|
|
404470
404806
|
return;
|
|
404471
404807
|
}
|
|
404472
404808
|
const line = resolveNavLine(navigation?.params);
|
|
404809
|
+
const column = resolveNavColumn(navigation?.params);
|
|
404810
|
+
let alive = true;
|
|
404811
|
+
setFailed(false);
|
|
404473
404812
|
let left = FORWARD_ATTEMPTS;
|
|
404474
404813
|
const attempt = () => {
|
|
404475
|
-
if (
|
|
404814
|
+
if (!alive || tab?.signal?.aborted) return;
|
|
404815
|
+
if (forwardToEditor(typeof tab?.actions?.openTab === "function" ? tab.actions : service, parsed.path, line, navigation?.params?.preview, column)) {
|
|
404816
|
+
doneRef.current = intent;
|
|
404476
404817
|
closeTab(tab);
|
|
404477
404818
|
return;
|
|
404478
404819
|
}
|
|
@@ -404481,7 +404822,15 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
404481
404822
|
else setFailed(true);
|
|
404482
404823
|
};
|
|
404483
404824
|
attempt();
|
|
404484
|
-
|
|
404825
|
+
return () => {
|
|
404826
|
+
alive = false;
|
|
404827
|
+
};
|
|
404828
|
+
}, [
|
|
404829
|
+
revision,
|
|
404830
|
+
props?.sessionId,
|
|
404831
|
+
tab?.id,
|
|
404832
|
+
navigation?.address
|
|
404833
|
+
]);
|
|
404485
404834
|
if (!failed || typeof fallback !== "function") return null;
|
|
404486
404835
|
return react$1.default.createElement(fallback, props);
|
|
404487
404836
|
}
|
|
@@ -408716,13 +409065,26 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
408716
409065
|
function menu(event) {
|
|
408717
409066
|
onContext(path, type, event);
|
|
408718
409067
|
}
|
|
409068
|
+
/** @private @author ddj 2026年11月04号 @param event Keyboard context trigger anchored to the focused row. */
|
|
409069
|
+
function menuKey(event) {
|
|
409070
|
+
if (event.key !== "ContextMenu" && !(event.shiftKey && event.key === "F10")) return;
|
|
409071
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
409072
|
+
onContext(path, type, {
|
|
409073
|
+
preventDefault: () => event.preventDefault(),
|
|
409074
|
+
stopPropagation: () => event.stopPropagation(),
|
|
409075
|
+
clientX: rect.left,
|
|
409076
|
+
clientY: rect.bottom
|
|
409077
|
+
});
|
|
409078
|
+
}
|
|
408719
409079
|
return react$1.default.createElement("div", {
|
|
408720
409080
|
className: "edrv-tree-row" + (active ? " edrv-tree-active" : "") + (context ? " edrv-tree-context" : "") + (reveal ? " edrv-tree-reveal" : "") + (mark?.stale ? " edrv-tree-stale" : ""),
|
|
408721
409081
|
title: path + (mark?.stale ? ";SVN 状态陈旧,等待确认" : ""),
|
|
408722
409082
|
"data-edrv-path": path,
|
|
408723
409083
|
style: { paddingLeft: 6 + depth * 14 },
|
|
409084
|
+
tabIndex: 0,
|
|
408724
409085
|
onClick: select,
|
|
408725
|
-
onContextMenu: menu
|
|
409086
|
+
onContextMenu: menu,
|
|
409087
|
+
onKeyDown: menuKey
|
|
408726
409088
|
}, react$1.default.createElement("span", { className: "edrv-tree-chev" }, isDir ? isOpen ? "▾" : "▸" : ""), react$1.default.createElement("span", { className: "edrv-tree-iconbox" }, rowIconEl({ name }, isDir, isOpen), svnOverlayEl(viewOverlayOf(mark), remote)), react$1.default.createElement("span", { className: "edrv-tree-name" + (type === "other" ? " edrv-tree-dim" : "") }, name), pending > 0 ? react$1.default.createElement("span", { className: "edrv-tree-badge" }, String(pending)) : null);
|
|
408727
409089
|
}
|
|
408728
409090
|
const ExplorerRow = react$1.default.memo(rowView);
|
|
@@ -409182,6 +409544,54 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
409182
409544
|
if (menu && !menuValid) setMenu(null);
|
|
409183
409545
|
}
|
|
409184
409546
|
react$1.default.useEffect(closeLostMenu, [menu, menuValid]);
|
|
409547
|
+
const liveMenu = react$1.default.useRef({
|
|
409548
|
+
scope,
|
|
409549
|
+
treeRows,
|
|
409550
|
+
sessionId: ctx?.sessionId,
|
|
409551
|
+
alive: true
|
|
409552
|
+
});
|
|
409553
|
+
const openingValid = react$1.default.useRef(null);
|
|
409554
|
+
liveMenu.current = {
|
|
409555
|
+
scope,
|
|
409556
|
+
treeRows,
|
|
409557
|
+
sessionId: ctx?.sessionId,
|
|
409558
|
+
alive: liveMenu.current.alive
|
|
409559
|
+
};
|
|
409560
|
+
react$1.default.useEffect(() => {
|
|
409561
|
+
liveMenu.current.alive = ctx?.visible !== false;
|
|
409562
|
+
return () => {
|
|
409563
|
+
liveMenu.current.alive = false;
|
|
409564
|
+
if (openingValid.current) ctx?.officialMenus?.invalidate(openingValid.current);
|
|
409565
|
+
};
|
|
409566
|
+
}, [
|
|
409567
|
+
scope,
|
|
409568
|
+
ctx?.sessionId,
|
|
409569
|
+
ctx?.officialMenus,
|
|
409570
|
+
ctx?.visible
|
|
409571
|
+
]);
|
|
409572
|
+
react$1.default.useEffect(() => {
|
|
409573
|
+
if (!menuValid || !ctx?.officialMenus || !ctx.sessionId) return;
|
|
409574
|
+
const target = { ...menu.target };
|
|
409575
|
+
const sessionId = ctx.sessionId;
|
|
409576
|
+
const valid = () => liveMenu.current.alive && liveMenu.current.sessionId === sessionId && liveMenu.current.scope === menu.scope && (target.path === "" || liveMenu.current.treeRows.some((row) => row.e?.path === target.path));
|
|
409577
|
+
openingValid.current = valid;
|
|
409578
|
+
const items = buildTreeMenu(ctx.fileMenuItems, target, ctx).map((item) => ({
|
|
409579
|
+
id: item.id,
|
|
409580
|
+
label: item.label,
|
|
409581
|
+
disabled: item.disabled,
|
|
409582
|
+
danger: item.danger,
|
|
409583
|
+
separator: item.separator,
|
|
409584
|
+
run: () => item.run(target, ctx)
|
|
409585
|
+
}));
|
|
409586
|
+
if (ctx.officialMenus.open("resource", ctx.sessionId, target.path, {
|
|
409587
|
+
x: menu.x,
|
|
409588
|
+
y: menu.y
|
|
409589
|
+
}, items, valid)) setMenu(null);
|
|
409590
|
+
}, [
|
|
409591
|
+
menu,
|
|
409592
|
+
menuValid,
|
|
409593
|
+
ctx?.officialMenus
|
|
409594
|
+
]);
|
|
409185
409595
|
const menuEntries = menuValid ? buildTreeMenu(ctx?.fileMenuItems, menu.target, ctx).map((item) => ({
|
|
409186
409596
|
id: item.id,
|
|
409187
409597
|
label: item.label,
|
|
@@ -412672,6 +413082,26 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
412672
413082
|
function createDefaultFileMenuItems() {
|
|
412673
413083
|
return [
|
|
412674
413084
|
...openGroupItems(),
|
|
413085
|
+
{
|
|
413086
|
+
id: "forge-open",
|
|
413087
|
+
label: "打开 Forge",
|
|
413088
|
+
order: 6,
|
|
413089
|
+
group: GROUP_OPEN,
|
|
413090
|
+
visible: (_target, ctx) => ctx.forge?.available() === true,
|
|
413091
|
+
run: (_target, ctx) => {
|
|
413092
|
+
if (ctx.sessionId) ctx.forge?.open(ctx.sessionId);
|
|
413093
|
+
}
|
|
413094
|
+
},
|
|
413095
|
+
{
|
|
413096
|
+
id: "forge-local",
|
|
413097
|
+
label: "查看本地变更(Forge)",
|
|
413098
|
+
order: 7,
|
|
413099
|
+
group: GROUP_OPEN,
|
|
413100
|
+
visible: (_target, ctx) => ctx.forge?.available() === true,
|
|
413101
|
+
run: (_target, ctx) => {
|
|
413102
|
+
if (ctx.sessionId) ctx.forge?.open(ctx.sessionId, true);
|
|
413103
|
+
}
|
|
413104
|
+
},
|
|
412675
413105
|
...revealGroupItems(),
|
|
412676
413106
|
...refGroupItems(),
|
|
412677
413107
|
...clipGroupItems(),
|
|
@@ -414513,7 +414943,9 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
414513
414943
|
officialSidebar: officialService !== void 0,
|
|
414514
414944
|
fileClaim: claimDisposer !== null,
|
|
414515
414945
|
claimWanted: shouldClaimFiles(selected),
|
|
414516
|
-
selected
|
|
414946
|
+
selected,
|
|
414947
|
+
officialMenus: Boolean(ctx.get("contextMenus")),
|
|
414948
|
+
forge: forge.available()
|
|
414517
414949
|
}, version);
|
|
414518
414950
|
ctx.provide("fileOpeners", registry);
|
|
414519
414951
|
ctx.effect(() => registry.register(vscodeOpener()), "vscode-mode: file opener");
|
|
@@ -414545,12 +414977,17 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
414545
414977
|
const sidebar = scanSidebar(ctx);
|
|
414546
414978
|
return sidebar ? registry.register(sidebar) : void 0;
|
|
414547
414979
|
}, "vscode-mode: sidebar file opener");
|
|
414980
|
+
const forge = forgeBridge(ctx, () => readSessionScope(ctx).sessionId ?? void 0);
|
|
414981
|
+
const menuBridge = lazyMenus(ctx);
|
|
414982
|
+
if (menuBridge) ctx.effect(() => () => menuBridge.dispose(), "vscode-mode: official menus");
|
|
414548
414983
|
const officialRenderTab = (props) => react$1.default.createElement(OfficialSideTab, Object.assign({}, props, {
|
|
414549
414984
|
schedule,
|
|
414550
414985
|
addToConversation,
|
|
414551
414986
|
sidebarPanels,
|
|
414552
414987
|
outlineSources,
|
|
414553
414988
|
fileMenuItems,
|
|
414989
|
+
officialMenus: menuBridge,
|
|
414990
|
+
forge,
|
|
414554
414991
|
fileOpeners: registry,
|
|
414555
414992
|
sessions,
|
|
414556
414993
|
readSessionScope: () => readSessionScope(ctx)
|
|
@@ -414735,6 +415172,8 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
414735
415172
|
sidebarPanels,
|
|
414736
415173
|
outlineSources,
|
|
414737
415174
|
fileMenuItems,
|
|
415175
|
+
officialMenus: menuBridge,
|
|
415176
|
+
forge,
|
|
414738
415177
|
fileOpeners: registry,
|
|
414739
415178
|
sessions
|
|
414740
415179
|
})));
|
|
@@ -414820,6 +415259,8 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
414820
415259
|
sidebarPanels,
|
|
414821
415260
|
outlineSources,
|
|
414822
415261
|
fileMenuItems,
|
|
415262
|
+
officialMenus: menuBridge,
|
|
415263
|
+
forge,
|
|
414823
415264
|
fileOpeners: registry,
|
|
414824
415265
|
sessions
|
|
414825
415266
|
})),
|
|
@@ -414929,6 +415370,17 @@ td.UniverTableCell, th.UniverTableCell{mso-padding-alt:0cm 5.4pt 0cm 5.4pt;}
|
|
|
414929
415370
|
compatSummary,
|
|
414930
415371
|
getShortcuts: () => detectShortcuts(ctx)
|
|
414931
415372
|
})));
|
|
415373
|
+
registerSlotSafely(ctx, {
|
|
415374
|
+
name: "settings.section.icon",
|
|
415375
|
+
id: "vscode-mode",
|
|
415376
|
+
order: 30
|
|
415377
|
+
}, (input) => {
|
|
415378
|
+
const props = input;
|
|
415379
|
+
return react$1.default.createElement(IconCodeOutline16, {
|
|
415380
|
+
size: props.size ?? 16,
|
|
415381
|
+
className: props.active ? "edrv-settings-active" : void 0
|
|
415382
|
+
});
|
|
415383
|
+
});
|
|
414932
415384
|
registerSlotSafely(ctx, {
|
|
414933
415385
|
name: "plugins.detail.section",
|
|
414934
415386
|
id: "edrv-plugin-status",
|