@duke-dsh-plugins/dsh-archive-manager 1.3.4 → 1.3.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/client.js +47 -18
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Rendered by the DSH web shell via `window.__ModuleLoader__.load`. Registers:
|
|
5
5
|
* - a sidebar footer action button (archived-session entry),
|
|
6
|
-
* - a frame-wide archive manager panel (search / group / restore / delete)
|
|
6
|
+
* - a frame-wide archive manager panel (search / group / restore / delete),
|
|
7
|
+
* rendered together with the button from the sidebar.footer.action slot —
|
|
8
|
+
* mirroring how ui-settings renders its modal from sidebar.settings (see
|
|
9
|
+
* the registration comment for the stacking-context rationale).
|
|
7
10
|
*
|
|
8
11
|
* The panel mirrors the DSH 工作区 (workspace) browsing region: a dialog
|
|
9
12
|
* surface using the same design tokens as the workspace browser — folder
|
|
@@ -26,8 +29,15 @@ window.__ModuleLoader__.load({
|
|
|
26
29
|
const CSS = `
|
|
27
30
|
[class*="footerActions"]{flex-direction:column;align-items:center;}
|
|
28
31
|
|
|
29
|
-
/* Overlay — same mask surface as DSH Modal
|
|
30
|
-
|
|
32
|
+
/* Overlay — same mask surface as DSH Modal, same z-index tier as the DSH
|
|
33
|
+
settings overlay (1000). This layer MUST be rendered from a slot that sits
|
|
34
|
+
outside any stacking context (the sidebar foot, like Settings does), never
|
|
35
|
+
from the shell.overlay slot: AppFrame renders that slot inside its
|
|
36
|
+
.overlayLayer (position:absolute;z-index:20, a stacking context), which
|
|
37
|
+
traps any child z-index below it — dsh-better-sidebar appends a
|
|
38
|
+
position:fixed;z-index:25 layer to document.body and would cover the
|
|
39
|
+
modal. */
|
|
40
|
+
.am-overlay{position:fixed;inset:0;z-index:1000;background:var(--dsw-alias-bg-mask-1,rgba(0,0,0,.4));backdrop-filter:var(--dsw-mask-blur,blur(2px));display:flex;align-items:center;justify-content:center;padding:24px;}
|
|
31
41
|
|
|
32
42
|
/* Panel — same surface & size as the DSH Settings dialog (width 800px) */
|
|
33
43
|
.am-panel{position:relative;display:flex;flex-direction:column;width:800px;max-width:calc(100vw - 48px);height:min(800px,100vh - 48px);overflow:hidden;border:1px solid var(--dsw-alias-border-inverted,rgba(128,128,128,.3));border-radius:24px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,inherit);box-shadow:var(--dsw-shadow-lv3,0 12px 40px rgba(0,0,0,.25));}
|
|
@@ -465,7 +475,18 @@ window.__ModuleLoader__.load({
|
|
|
465
475
|
);
|
|
466
476
|
}
|
|
467
477
|
|
|
468
|
-
// Sidebar footer action entry (Cordis Plugin 下方、设置上方;纵向排列由注入
|
|
478
|
+
// Sidebar footer action entry (Cordis Plugin 下方、设置上方;纵向排列由注入
|
|
479
|
+
// CSS 保证) + frame-wide archive manager panel.
|
|
480
|
+
//
|
|
481
|
+
// 弹窗为什么从这里渲染而不是 `shell.overlay`:AppFrame 把 `shell.overlay`
|
|
482
|
+
// 渲染在 `.overlayLayer`(position:absolute; z-index:20)内,该层形成独立
|
|
483
|
+
// stacking context,把子元素 z-index 锁死在其下;而 dsh-better-sidebar 把
|
|
484
|
+
// 整层 append 到 document.body(position:fixed; z-index:25),归档弹窗因此
|
|
485
|
+
// 会被它盖住。设置弹窗(ui-settings)的做法是把全屏 fixed 遮罩
|
|
486
|
+
// (z-index:1000)从 sidebar.settings 槽渲染——侧栏列不构成 stacking
|
|
487
|
+
// context,fixed 层直接参与根 stacking context,压过 better-sidebar 的 25。
|
|
488
|
+
// 这里照搬同一做法:弹窗与按钮同从 sidebar.footer.action 槽渲染,两者共享
|
|
489
|
+
// useOpen 状态,UI 行为不变。
|
|
469
490
|
ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register(
|
|
470
491
|
{ name: "sidebar.footer.action", id: "archive-manager", order: 500, label: () => "归档" },
|
|
471
492
|
(props) => {
|
|
@@ -477,11 +498,25 @@ window.__ModuleLoader__.load({
|
|
|
477
498
|
const count = rawCount - (ghostIds.length > rawCount ? rawCount : ghostIds.length);
|
|
478
499
|
const safeCount = count > 0 ? count : 0;
|
|
479
500
|
const isOpen = useOpen();
|
|
501
|
+
// Esc 关闭弹窗:打开期间在 document 捕获阶段监听 keydown,命中
|
|
502
|
+
// Escape 即关闭并 stopPropagation——弹窗位于 z-index:1000 顶层,
|
|
503
|
+
// 此时 Esc 应只作用于它,不穿透到 shell 的全局快捷键或底层输入框。
|
|
504
|
+
React.useEffect(() => {
|
|
505
|
+
if (!isOpen) return undefined;
|
|
506
|
+
const onKeyDown = (e) => {
|
|
507
|
+
if (e.key === "Escape") {
|
|
508
|
+
e.stopPropagation();
|
|
509
|
+
setOpen(false);
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
513
|
+
return () => document.removeEventListener("keydown", onKeyDown, true);
|
|
514
|
+
}, [isOpen]);
|
|
480
515
|
const children = [];
|
|
481
516
|
children.push(React.createElement("span", { key: "icon", className: "am-foot-icon", "aria-hidden": true }, React.createElement(ArchiveIcon)));
|
|
482
517
|
if (wide) children.push(React.createElement("span", { key: "label", className: "am-foot-label" }, "归档"));
|
|
483
518
|
if (wide && safeCount > 0) children.push(React.createElement("span", { key: "cnt", className: "am-badge" }, String(safeCount)));
|
|
484
|
-
|
|
519
|
+
const button = React.createElement(
|
|
485
520
|
"div", { className: "am-foot-layer" + (wide ? "" : " am-foot-rail") },
|
|
486
521
|
React.createElement("button", {
|
|
487
522
|
type: "button",
|
|
@@ -491,19 +526,13 @@ window.__ModuleLoader__.load({
|
|
|
491
526
|
className: "am-foot" + (isOpen ? " am-active" : ""),
|
|
492
527
|
}, children)
|
|
493
528
|
);
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const isOpen = useOpen();
|
|
502
|
-
if (!isOpen) return null;
|
|
503
|
-
return React.createElement(
|
|
504
|
-
"div", { className: "am-overlay", onClick: () => setOpen(false) },
|
|
505
|
-
React.createElement(ArchiveManager, { slotProps: props, onClose: () => setOpen(false) })
|
|
506
|
-
);
|
|
529
|
+
const overlay = isOpen
|
|
530
|
+
? React.createElement(
|
|
531
|
+
"div", { className: "am-overlay", onClick: () => setOpen(false) },
|
|
532
|
+
React.createElement(ArchiveManager, { slotProps: props, onClose: () => setOpen(false) })
|
|
533
|
+
)
|
|
534
|
+
: null;
|
|
535
|
+
return [button, overlay];
|
|
507
536
|
}
|
|
508
537
|
));
|
|
509
538
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duke-dsh-plugins/dsh-archive-manager",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"description": "Archive manager for DeepSeek Harness: group archived sessions by project, newest-first, with search, restore and delete.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|