dsh-vscode-mode 0.14.11 → 0.14.13
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 +133 -75
- package/lib/client.js.map +1 -1
- package/lib/index.js +129 -37
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/sidebar/panels/FileExplorer.ts +24 -76
- package/src/client/sidebar/panels/SearchPanel.ts +12 -4
- package/src/client/sidebar/panels/useExplorerReveal.ts +109 -0
- package/src/search/fallback.ts +12 -9
- package/src/search/orchestrator.ts +1 -1
- package/src/search/query.ts +30 -6
- package/src/search/ranker.ts +52 -13
- package/src/search/ripgrep.ts +29 -12
package/README.md
CHANGED
|
@@ -464,13 +464,13 @@ profile 请替换为实际目标,不要把示例目录当成当前运行 profi
|
|
|
464
464
|
|
|
465
465
|
```bash
|
|
466
466
|
# ① Git 安装(clone + prepare 构建;推荐打固定 tag)
|
|
467
|
-
dsh plugin --profile web add github:Lenonss/DSH_VsCodeMode#v0.14.
|
|
467
|
+
dsh plugin --profile web add github:Lenonss/DSH_VsCodeMode#v0.14.13
|
|
468
468
|
|
|
469
469
|
# ② npm 注册表(发布到 npm 后)
|
|
470
|
-
dsh plugin --profile web add dsh-vscode-mode@0.14.
|
|
470
|
+
dsh plugin --profile web add dsh-vscode-mode@0.14.13
|
|
471
471
|
|
|
472
472
|
# ③ GitHub Release tgz 直装(Release asset 可用后)
|
|
473
|
-
dsh plugin --profile web add https://github.com/Lenonss/DSH_VsCodeMode/releases/download/v0.14.
|
|
473
|
+
dsh plugin --profile web add https://github.com/Lenonss/DSH_VsCodeMode/releases/download/v0.14.13/dsh-vscode-mode-0.14.13.tgz
|
|
474
474
|
```
|
|
475
475
|
|
|
476
476
|
> **DSH 版本政策(0.14.10 起)**:六项 DSH peer 统一声明为 `*`,不再维护逐版
|
|
@@ -808,6 +808,10 @@ Keep All / Undo All 却是亮的。修复:单文件 Keep / Undo 覆盖冲突
|
|
|
808
808
|
完整变更见 [GitHub Releases](https://github.com/Lenonss/DSH_VsCodeMode/releases)。
|
|
809
809
|
近期关键版本:
|
|
810
810
|
|
|
811
|
+
- **v0.14.13**:**资源管理器跟随活动文件**——打开或切换编辑文件时自动展开祖先并滚动定位;资源管理器隐藏期间保留最新活动文件,切回后定位。慢目录加载不再受短重试窗口限制,仅滚动资源树、不抢输入焦点,保留手动定位。用户已确认本地功能验收通过,详见 [0.14.13 发布说明](docs/release-0.14.13.md)。
|
|
812
|
+
|
|
813
|
+
- **v0.14.12**:**搜索框全选与模糊文件搜索**——工作区搜索打开/再次聚焦时在输入更新后全选旧词或编辑器选区种子,便于直接改写;Ctrl+P 支持大小写不敏感的文件名有序非连续匹配(如 `bn` → `BaseNavigationManager.cs`、`ISTSD` → `ISTaskSystemData.lua`),保留带目录的连续路径查询与 DAP 文件定位规则。更新后需重启 DSH Host;真实 GUI 行为、主题/滚动和 Console 尚未验收,发布不代表现场验收完成。
|
|
814
|
+
|
|
811
815
|
- **v0.14.11**:**编辑快捷键文案与动作验证**——注释菜单不再写死默认键位,避免自定义绑定后显示误导;明确编辑器本地 Ctrl+D 向下复制、不使用剪贴板;加强原生动作转发与幂等清理断言。默认键位与编辑算法不变,详见 [0.14.11 发布说明](docs/release-0.14.11.md)。
|
|
812
816
|
- **v0.14.10**:**简化 DSH 版本政策**——六项 DSH peer 统一为 `*`,取消逐版白名单、上界和仅因版本较新的告警,保留实际能力与冲突诊断;开发依赖固定原版本,避免自动解析漂移。npm 默认预发布语义和验收边界见 [0.14.10 发布说明](docs/release-0.14.10.md)。
|
|
813
817
|
- **v0.14.9**:**编辑快捷键与桌面安全刷新**——`Ctrl+/` 保留官方快捷键入口,行注释改为 `Ctrl+Alt+/`(Web Linux 默认不绑定);编辑器本地 `Ctrl+D` 调用 Monaco 原生向下复制行,块注释不变。桌面 `Ctrl+Shift+R` 刷新当前界面、不重启 Host;未保存代码/PDF、待保存、保存中或外部冲突时拒绝刷新,界面状态镜像失败/超时也不刷新。真实 GUI 按键和状态恢复尚未验收,详见 [0.14.9 发布说明](docs/release-0.14.9.md)。
|
package/lib/client.js
CHANGED
|
@@ -30357,6 +30357,102 @@ window.__ModuleLoader__.load({
|
|
|
30357
30357
|
};
|
|
30358
30358
|
}
|
|
30359
30359
|
//#endregion
|
|
30360
|
+
//#region src/client/sidebar/panels/useExplorerReveal.ts
|
|
30361
|
+
/** @private @author ddj 2026年10月14号 @param path Editor path. @returns Safe normalized tree path, or null. */
|
|
30362
|
+
function treeRevealPath(path) {
|
|
30363
|
+
if (!path || !isTreeRevealable(path)) return null;
|
|
30364
|
+
return path.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
30365
|
+
}
|
|
30366
|
+
/** @private @author ddj 2026年10月14号 @param host Tree scroll container. @param path Exact row path. @returns Whether a visible row was located. Only scrolls the tree. */
|
|
30367
|
+
function revealTreeRow(host, path) {
|
|
30368
|
+
if (!host || host.clientHeight <= 0) return false;
|
|
30369
|
+
const escaped = path.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
30370
|
+
const row = host.querySelector("[data-edrv-path=\"" + escaped + "\"]");
|
|
30371
|
+
if (!row) return false;
|
|
30372
|
+
const viewport = host.getBoundingClientRect();
|
|
30373
|
+
const bounds = row.getBoundingClientRect();
|
|
30374
|
+
const top = viewport.top + host.clientTop;
|
|
30375
|
+
if (bounds.top < top || bounds.bottom > top + host.clientHeight) host.scrollTop += bounds.top - top - (host.clientHeight - bounds.height) / 2;
|
|
30376
|
+
return true;
|
|
30377
|
+
}
|
|
30378
|
+
/** @private @author ddj 2026年10月14号 @param options Current workspace, active editor and tree preparation. @returns Highlight and manual request callback. Waits for committed rows without polling; unmount cancels highlight cleanup. */
|
|
30379
|
+
function useExplorerReveal(options) {
|
|
30380
|
+
const { scope, activePath, treeRef } = options;
|
|
30381
|
+
const [target, setTarget] = react.default.useState(null);
|
|
30382
|
+
const [revealPath, setRevealPath] = react.default.useState(null);
|
|
30383
|
+
const pending = react.default.useRef(null);
|
|
30384
|
+
const timer = react.default.useRef(null);
|
|
30385
|
+
const latest = react.default.useRef(options);
|
|
30386
|
+
latest.current = options;
|
|
30387
|
+
/** @private @author ddj 2026年10月14号 Clears only this hook's highlight timer. */
|
|
30388
|
+
function clearHighlight() {
|
|
30389
|
+
if (timer.current !== null) clearTimeout(timer.current);
|
|
30390
|
+
timer.current = null;
|
|
30391
|
+
}
|
|
30392
|
+
/** @private @author ddj 2026年10月14号 @param path Requested tree path. Expands ancestors and replaces any previous pending target. */
|
|
30393
|
+
function requestReveal(path) {
|
|
30394
|
+
clearHighlight();
|
|
30395
|
+
setRevealPath(null);
|
|
30396
|
+
const normalized = treeRevealPath(path);
|
|
30397
|
+
const current = latest.current;
|
|
30398
|
+
const next = normalized ? {
|
|
30399
|
+
scope: current.scope,
|
|
30400
|
+
path: normalized,
|
|
30401
|
+
active: current.activePath
|
|
30402
|
+
} : null;
|
|
30403
|
+
pending.current = next;
|
|
30404
|
+
setTarget(next);
|
|
30405
|
+
if (next) current.prepare(next.path);
|
|
30406
|
+
}
|
|
30407
|
+
/** @private @author ddj 2026年10月14号 Attempts the latest target after row commit or container resize. Consumes only a successful, current request. */
|
|
30408
|
+
function tryReveal() {
|
|
30409
|
+
const next = pending.current;
|
|
30410
|
+
const current = latest.current;
|
|
30411
|
+
if (!next || next.scope !== current.scope || next.active !== current.activePath) return;
|
|
30412
|
+
if (!revealTreeRow(current.treeRef.current, next.path)) return;
|
|
30413
|
+
pending.current = null;
|
|
30414
|
+
setRevealPath(next.path);
|
|
30415
|
+
clearHighlight();
|
|
30416
|
+
timer.current = setTimeout(endHighlight, 2e3);
|
|
30417
|
+
}
|
|
30418
|
+
/** @private @author ddj 2026年10月14号 Ends transient reveal styling without changing the active editor row. */
|
|
30419
|
+
function endHighlight() {
|
|
30420
|
+
timer.current = null;
|
|
30421
|
+
setRevealPath(null);
|
|
30422
|
+
}
|
|
30423
|
+
/** @private @author ddj 2026年10月14号 Establishes the latest editor target after workspace tree restoration. */
|
|
30424
|
+
function followActive() {
|
|
30425
|
+
requestReveal(activePath);
|
|
30426
|
+
}
|
|
30427
|
+
react.default.useEffect(followActive, [scope, activePath]);
|
|
30428
|
+
react.default.useLayoutEffect(tryReveal);
|
|
30429
|
+
/** @private @author ddj 2026年10月14号 @returns Cleanup for manual events, resize observation and highlight timer. */
|
|
30430
|
+
function listenReveal() {
|
|
30431
|
+
/** @private @author ddj 2026年10月14号 @param event Existing explicit reveal request. */
|
|
30432
|
+
function onReveal(event) {
|
|
30433
|
+
const detail = event.detail;
|
|
30434
|
+
if (detail?.scope && detail.scope !== latest.current.scope) return;
|
|
30435
|
+
if (typeof detail?.path === "string") requestReveal(detail.path);
|
|
30436
|
+
}
|
|
30437
|
+
const observer = typeof ResizeObserver === "function" ? new ResizeObserver(tryReveal) : null;
|
|
30438
|
+
if (treeRef.current) observer?.observe(treeRef.current);
|
|
30439
|
+
window.addEventListener("edrv:reveal-path", onReveal);
|
|
30440
|
+
/** @private @author ddj 2026年10月14号 Cancels callbacks owned by this mounted tree. */
|
|
30441
|
+
function cleanup() {
|
|
30442
|
+
observer?.disconnect();
|
|
30443
|
+
window.removeEventListener("edrv:reveal-path", onReveal);
|
|
30444
|
+
pending.current = null;
|
|
30445
|
+
clearHighlight();
|
|
30446
|
+
}
|
|
30447
|
+
return cleanup;
|
|
30448
|
+
}
|
|
30449
|
+
react.default.useEffect(listenReveal, [treeRef]);
|
|
30450
|
+
return {
|
|
30451
|
+
revealPath,
|
|
30452
|
+
requestReveal
|
|
30453
|
+
};
|
|
30454
|
+
}
|
|
30455
|
+
//#endregion
|
|
30360
30456
|
//#region src/client/sidebar/panels/FileExplorer.ts
|
|
30361
30457
|
/**
|
|
30362
30458
|
* dsh-vscode-mode client — 侧边栏「文件管理」面板(懒加载目录树 + SWR 缓存)。
|
|
@@ -30381,10 +30477,6 @@ window.__ModuleLoader__.load({
|
|
|
30381
30477
|
".pnpm",
|
|
30382
30478
|
".pnpm-store"
|
|
30383
30479
|
]);
|
|
30384
|
-
/** 「在资源管理器视图中显示」高亮时长与定位重试上限(目录懒加载需等待行渲染)。 */
|
|
30385
|
-
const REVEAL_HIGHLIGHT_MS = 2e3;
|
|
30386
|
-
const REVEAL_RETRY_MAX = 6;
|
|
30387
|
-
const REVEAL_RETRY_MS = 120;
|
|
30388
30480
|
/** 外部文件变化重列去抖:一轮外部批量写入(如 agent 连写多文件)合并为一次重列。 */
|
|
30389
30481
|
const FILE_CHANGE_DEBOUNCE_MS = 400;
|
|
30390
30482
|
/**
|
|
@@ -30443,15 +30535,6 @@ window.__ModuleLoader__.load({
|
|
|
30443
30535
|
}
|
|
30444
30536
|
const ExplorerRow = react.default.memo(rowView);
|
|
30445
30537
|
/**
|
|
30446
|
-
* 转义 CSS 属性选择器的值(路径含引号/反斜杠时避免选择器语法错误)。
|
|
30447
|
-
* @author ddj 2026年09月11号
|
|
30448
|
-
* @param value 原始值
|
|
30449
|
-
* @returns 可安全嵌入 `[attr="…"]` 的字符串
|
|
30450
|
-
*/
|
|
30451
|
-
function cssEscape(value) {
|
|
30452
|
-
return String(value ?? "").replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
30453
|
-
}
|
|
30454
|
-
/**
|
|
30455
30538
|
* 目录树面板主体(SWR:有缓存先渲染,无缓存才显示加载态;加载总在后台)。
|
|
30456
30539
|
* @param props.ctx 面板共享上下文(sessionId/openFile/activePath/pendingByPath/fileMenuItems/notify)
|
|
30457
30540
|
*/
|
|
@@ -30470,7 +30553,6 @@ window.__ModuleLoader__.load({
|
|
|
30470
30553
|
const [loading, setLoading] = react.default.useState({});
|
|
30471
30554
|
const [errors, setErrors] = react.default.useState({});
|
|
30472
30555
|
const [menu, setMenu] = react.default.useState(null);
|
|
30473
|
-
const [revealPath, setRevealPath] = react.default.useState(null);
|
|
30474
30556
|
const tokensRef = react.default.useRef({});
|
|
30475
30557
|
const expandedRef = react.default.useRef({});
|
|
30476
30558
|
expandedRef.current = expanded;
|
|
@@ -30481,9 +30563,6 @@ window.__ModuleLoader__.load({
|
|
|
30481
30563
|
const saveTimerRef = react.default.useRef(null);
|
|
30482
30564
|
const loadDirRef = react.default.useRef(null);
|
|
30483
30565
|
const refreshRef = react.default.useRef(null);
|
|
30484
|
-
const revealTimerRef = react.default.useRef(null);
|
|
30485
|
-
const revealTryRef = react.default.useRef(0);
|
|
30486
|
-
const revealInTreeRef = react.default.useRef(null);
|
|
30487
30566
|
const treeRef = react.default.useRef(null);
|
|
30488
30567
|
const reloadDirRef = react.default.useRef(null);
|
|
30489
30568
|
const changedTimerRef = react.default.useRef(null);
|
|
@@ -30511,8 +30590,10 @@ window.__ModuleLoader__.load({
|
|
|
30511
30590
|
const force = opts?.force === true;
|
|
30512
30591
|
const doPrefetch = opts?.prefetch === true;
|
|
30513
30592
|
if (!force && loadingRef.current[rel]) return;
|
|
30514
|
-
const
|
|
30515
|
-
|
|
30593
|
+
const tokens = tokensRef.current;
|
|
30594
|
+
const token = (tokens[rel] || 0) + 1;
|
|
30595
|
+
tokens[rel] = token;
|
|
30596
|
+
loadingRef.current = Object.assign({}, loadingRef.current, { [rel]: true });
|
|
30516
30597
|
setLoading((prev) => Object.assign({}, prev, { [rel]: true }));
|
|
30517
30598
|
setErrors((prev) => {
|
|
30518
30599
|
const next = Object.assign({}, prev);
|
|
@@ -30525,7 +30606,7 @@ window.__ModuleLoader__.load({
|
|
|
30525
30606
|
};
|
|
30526
30607
|
if (force) args.force = true;
|
|
30527
30608
|
rpc("edrv.listDir", args).then((res) => {
|
|
30528
|
-
if (tokensRef.current[rel] !== token) return;
|
|
30609
|
+
if (scopeRef.current !== scope || tokensRef.current !== tokens || tokens[rel] !== token) return;
|
|
30529
30610
|
if (res && res.ok && Array.isArray(res.entries)) {
|
|
30530
30611
|
setDirs((prev) => Object.assign({}, prev, { [rel]: res.entries }));
|
|
30531
30612
|
if (res.root) setRoot((prev) => prev || res.root);
|
|
@@ -30533,10 +30614,10 @@ window.__ModuleLoader__.load({
|
|
|
30533
30614
|
if (doPrefetch) prefetchDirs(rel, res.entries);
|
|
30534
30615
|
} else if (!entriesOf(rel)) setErrors((prev) => Object.assign({}, prev, { [rel]: res?.error ? String(res.error) : "读取目录失败" }));
|
|
30535
30616
|
}).catch((e) => {
|
|
30536
|
-
if (tokensRef.current[rel] !== token) return;
|
|
30617
|
+
if (scopeRef.current !== scope || tokensRef.current !== tokens || tokens[rel] !== token) return;
|
|
30537
30618
|
if (!entriesOf(rel)) setErrors((prev) => Object.assign({}, prev, { [rel]: "读取目录异常:" + String(e) }));
|
|
30538
30619
|
}).finally(() => {
|
|
30539
|
-
if (tokensRef.current[rel] !== token) return;
|
|
30620
|
+
if (scopeRef.current !== scope || tokensRef.current !== tokens || tokens[rel] !== token) return;
|
|
30540
30621
|
setLoading((prev) => {
|
|
30541
30622
|
const next = Object.assign({}, prev);
|
|
30542
30623
|
delete next[rel];
|
|
@@ -30553,45 +30634,21 @@ window.__ModuleLoader__.load({
|
|
|
30553
30634
|
setExpanded((prev) => Object.assign({}, prev, { [rel]: true }));
|
|
30554
30635
|
loadDir(rel, { prefetch: true });
|
|
30555
30636
|
};
|
|
30556
|
-
/**
|
|
30557
|
-
|
|
30558
|
-
* @author ddj 2026年09月11号
|
|
30559
|
-
* @param path 目标相对路径
|
|
30560
|
-
*/
|
|
30561
|
-
const tryReveal = (path) => {
|
|
30562
|
-
const row = treeRef.current?.querySelector?.("[data-edrv-path=\"" + cssEscape(path) + "\"]");
|
|
30563
|
-
if (!row) {
|
|
30564
|
-
revealTryRef.current += 1;
|
|
30565
|
-
if (revealTryRef.current < REVEAL_RETRY_MAX) window.setTimeout(() => tryReveal(path), REVEAL_RETRY_MS);
|
|
30566
|
-
return;
|
|
30567
|
-
}
|
|
30568
|
-
row.scrollIntoView?.({ block: "center" });
|
|
30569
|
-
setRevealPath(path);
|
|
30570
|
-
if (revealTimerRef.current) clearTimeout(revealTimerRef.current);
|
|
30571
|
-
revealTimerRef.current = window.setTimeout(() => {
|
|
30572
|
-
revealTimerRef.current = null;
|
|
30573
|
-
setRevealPath(null);
|
|
30574
|
-
}, REVEAL_HIGHLIGHT_MS);
|
|
30575
|
-
};
|
|
30576
|
-
/**
|
|
30577
|
-
* 在资源管理器视图中显示:展开全部祖先目录并定位高亮目标文件。
|
|
30578
|
-
* 目录条目懒加载,故先展开祖先并触发加载,再由 tryReveal 轮询等行渲染。
|
|
30579
|
-
* @author ddj 2026年09月11号
|
|
30580
|
-
* @param path 目标相对路径
|
|
30581
|
-
*/
|
|
30582
|
-
const revealInTree = (path) => {
|
|
30583
|
-
if (!path) return;
|
|
30637
|
+
/** @private @author ddj 2026年10月14号 @param path Safe relative file path. Expands only the ancestor chain and reuses available directory entries. */
|
|
30638
|
+
function prepareReveal(path) {
|
|
30584
30639
|
const ancestors = ancestorDirsOf(path);
|
|
30585
|
-
|
|
30586
|
-
|
|
30640
|
+
setExpanded(expandParents);
|
|
30641
|
+
for (const dir of ["", ...ancestors]) {
|
|
30642
|
+
if (entriesOf(dir)) continue;
|
|
30643
|
+
loadDir(dir, { prefetch: false });
|
|
30644
|
+
}
|
|
30645
|
+
/** @private @author ddj 2026年10月14号 @param prev Current expansion map. @returns Expanded ancestor map. */
|
|
30646
|
+
function expandParents(prev) {
|
|
30587
30647
|
const next = Object.assign({}, prev);
|
|
30588
30648
|
for (const dir of ancestors) next[dir] = true;
|
|
30589
30649
|
return next;
|
|
30590
|
-
}
|
|
30591
|
-
|
|
30592
|
-
tryReveal(path);
|
|
30593
|
-
};
|
|
30594
|
-
revealInTreeRef.current = revealInTree;
|
|
30650
|
+
}
|
|
30651
|
+
}
|
|
30595
30652
|
const refresh = (event) => {
|
|
30596
30653
|
if (event?.detail?.scope && event.detail.scope !== scope) return;
|
|
30597
30654
|
if (event?.detail?.paths?.length) {
|
|
@@ -30600,6 +30657,7 @@ window.__ModuleLoader__.load({
|
|
|
30600
30657
|
}
|
|
30601
30658
|
const keep = Object.keys(expandedRef.current).filter((k) => expandedRef.current[k] === true);
|
|
30602
30659
|
tokensRef.current = {};
|
|
30660
|
+
loadingRef.current = {};
|
|
30603
30661
|
setMenu(null);
|
|
30604
30662
|
setErrors({});
|
|
30605
30663
|
setLoading({});
|
|
@@ -30664,13 +30722,13 @@ window.__ModuleLoader__.load({
|
|
|
30664
30722
|
}, []);
|
|
30665
30723
|
react.default.useEffect(() => {
|
|
30666
30724
|
tokensRef.current = {};
|
|
30725
|
+
loadingRef.current = {};
|
|
30667
30726
|
setDirs({});
|
|
30668
30727
|
setExpanded({});
|
|
30669
30728
|
setLoading({});
|
|
30670
30729
|
setErrors({});
|
|
30671
30730
|
setMenu(null);
|
|
30672
30731
|
setRoot(null);
|
|
30673
|
-
setRevealPath(null);
|
|
30674
30732
|
const cached = scope ? explorerLoad(scope) : null;
|
|
30675
30733
|
const restored = cached?.expanded ?? [];
|
|
30676
30734
|
if (cached?.root) setRoot(cached.root);
|
|
@@ -30712,20 +30770,13 @@ window.__ModuleLoader__.load({
|
|
|
30712
30770
|
window.addEventListener("edrv:refresh", onRefresh);
|
|
30713
30771
|
return () => window.removeEventListener("edrv:refresh", onRefresh);
|
|
30714
30772
|
}, []);
|
|
30715
|
-
|
|
30716
|
-
|
|
30717
|
-
|
|
30718
|
-
|
|
30719
|
-
|
|
30720
|
-
|
|
30721
|
-
|
|
30722
|
-
window.removeEventListener("edrv:reveal-path", onReveal);
|
|
30723
|
-
if (revealTimerRef.current) {
|
|
30724
|
-
clearTimeout(revealTimerRef.current);
|
|
30725
|
-
revealTimerRef.current = null;
|
|
30726
|
-
}
|
|
30727
|
-
};
|
|
30728
|
-
}, []);
|
|
30773
|
+
const { revealPath } = useExplorerReveal({
|
|
30774
|
+
scope,
|
|
30775
|
+
activePath,
|
|
30776
|
+
treeRef,
|
|
30777
|
+
prepare: prepareReveal
|
|
30778
|
+
});
|
|
30779
|
+
const activeTreePath = treeRevealPath(activePath);
|
|
30729
30780
|
react.default.useEffect(() => {
|
|
30730
30781
|
if (!scope) return;
|
|
30731
30782
|
const timer = setInterval(() => {
|
|
@@ -30824,7 +30875,7 @@ window.__ModuleLoader__.load({
|
|
|
30824
30875
|
isDir,
|
|
30825
30876
|
isOpen,
|
|
30826
30877
|
pending: isDir ? 0 : pendingByPath[e.path] ?? 0,
|
|
30827
|
-
active: !isDir && e.path ===
|
|
30878
|
+
active: !isDir && e.path === activeTreePath,
|
|
30828
30879
|
context: Boolean(menu && menuEntries.length && menu.target.path === e.path),
|
|
30829
30880
|
reveal: revealPath === e.path,
|
|
30830
30881
|
mark: svn.local?.get(e.path),
|
|
@@ -30987,6 +31038,7 @@ window.__ModuleLoader__.load({
|
|
|
30987
31038
|
const seqRef = react.default.useRef(0);
|
|
30988
31039
|
const timerRef = react.default.useRef(null);
|
|
30989
31040
|
const inputRef = react.default.useRef(null);
|
|
31041
|
+
const [focusTick, setFocusTick] = react.default.useState(0);
|
|
30990
31042
|
const queryRef = react.default.useRef("");
|
|
30991
31043
|
queryRef.current = query;
|
|
30992
31044
|
const activePathRef = react.default.useRef(activePath);
|
|
@@ -31175,7 +31227,6 @@ window.__ModuleLoader__.load({
|
|
|
31175
31227
|
queryRef.current = seed;
|
|
31176
31228
|
setQuery(seed);
|
|
31177
31229
|
runSearch(seed);
|
|
31178
|
-
inputRef.current?.select?.();
|
|
31179
31230
|
return true;
|
|
31180
31231
|
};
|
|
31181
31232
|
/**
|
|
@@ -31200,16 +31251,23 @@ window.__ModuleLoader__.load({
|
|
|
31200
31251
|
react.default.useEffect(() => {
|
|
31201
31252
|
applyScopeSeed();
|
|
31202
31253
|
applySeed();
|
|
31254
|
+
setFocusTick((tick) => tick + 1);
|
|
31203
31255
|
}, []);
|
|
31204
31256
|
react.default.useEffect(() => {
|
|
31257
|
+
/** @private @author ddj 2026年10月14号 @description 消费种子并请求提交后聚焦全选;不额外发起搜索。 */
|
|
31205
31258
|
const onFocus = () => {
|
|
31206
31259
|
applyScopeSeed();
|
|
31207
31260
|
applySeed();
|
|
31208
|
-
|
|
31261
|
+
setFocusTick((tick) => tick + 1);
|
|
31209
31262
|
};
|
|
31210
31263
|
window.addEventListener("edrv:search-focus", onFocus);
|
|
31211
31264
|
return () => window.removeEventListener("edrv:search-focus", onFocus);
|
|
31212
31265
|
}, []);
|
|
31266
|
+
react.default.useLayoutEffect(() => {
|
|
31267
|
+
if (!focusTick) return;
|
|
31268
|
+
inputRef.current?.focus?.();
|
|
31269
|
+
inputRef.current?.select?.();
|
|
31270
|
+
}, [focusTick]);
|
|
31213
31271
|
const groups = react.default.useMemo(() => {
|
|
31214
31272
|
if (!Array.isArray(matches)) return [];
|
|
31215
31273
|
const map = /* @__PURE__ */ new Map();
|