dsh-conversation-navigator 0.1.20 → 0.1.22
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 +4 -0
- package/lib/client.js +46 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,10 @@ Codex 风格的 **DeepSeek Harness(DSH)Web 端会话导航面板**:在对话页*
|
|
|
4
4
|
|
|
5
5
|
纯浏览器插件(无宿主行为)、纯 JavaScript、零构建、零 npm 依赖(按钮/Tooltip 复用 DSH 内核 seed 的官方 primitives)。
|
|
6
6
|
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
> 完整截图见 [assets/screenshots](./assets/screenshots)。其中「社区皮肤适配」两张为第三方皮肤下的效果(动漫女仆主题与君の名は主题),非插件自带。
|
|
10
|
+
|
|
7
11
|
## 功能
|
|
8
12
|
|
|
9
13
|
- **按轮折叠大纲**:默认只显示"第 N 轮 + 你的问题"列表,长对话一目了然
|
package/lib/client.js
CHANGED
|
@@ -92,6 +92,7 @@ window.__ModuleLoader__.load({
|
|
|
92
92
|
transition: opacity .18s ease, transform .18s ease;
|
|
93
93
|
}
|
|
94
94
|
.cnvnav-panel-hidden { opacity: 0; transform: translateY(-6px) scale(.985); pointer-events: none; }
|
|
95
|
+
.cnvnav-panel-unplaced { visibility: hidden; }
|
|
95
96
|
.cnvnav-head {
|
|
96
97
|
display: flex; align-items: center; gap: 8px;
|
|
97
98
|
padding: 10px 12px;
|
|
@@ -571,23 +572,59 @@ window.__ModuleLoader__.load({
|
|
|
571
572
|
|
|
572
573
|
React.useEffect(() => {
|
|
573
574
|
if (!snap.open) return;
|
|
575
|
+
let lastKey = null;
|
|
576
|
+
let stableTicks = 0;
|
|
577
|
+
let misses = 0;
|
|
574
578
|
function place() {
|
|
575
579
|
const panel = panelEl;
|
|
576
|
-
if (panel === null) return;
|
|
580
|
+
if (panel === null) return false;
|
|
577
581
|
const vw = document.documentElement.clientWidth || 1000;
|
|
578
582
|
const vh = document.documentElement.clientHeight || 800;
|
|
579
583
|
const sp = document.querySelector("[data-conversation-scroll]");
|
|
580
|
-
const rect = sp !== null ? sp.getBoundingClientRect() : { top: 60, height: vh - 90 };
|
|
581
584
|
const width = 288;
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
585
|
+
if (sp === null) {
|
|
586
|
+
/* 会话视图可能尚未挂载(刷新/重启/切会话时面板先就位);
|
|
587
|
+
非会话页(设置页等)则永远没有该容器。
|
|
588
|
+
连续 15 次(约 6s)仍未出现才回退到视口定位, 否则保持隐藏等待校准。 */
|
|
589
|
+
misses += 1;
|
|
590
|
+
if (misses >= 15) {
|
|
591
|
+
panel.style.left = Math.max(8, vw - width - 12) + "px";
|
|
592
|
+
panel.style.top = Math.max(8, 60) + "px";
|
|
593
|
+
panel.style.maxHeight = Math.round(vh - 90) + "px";
|
|
594
|
+
panel.classList.remove("cnvnav-panel-unplaced");
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
const r = sp.getBoundingClientRect();
|
|
600
|
+
const key = [Math.round(r.top), Math.round(r.height), Math.round(vw), Math.round(vh)].join("|");
|
|
601
|
+
if (key !== lastKey) {
|
|
602
|
+
lastKey = key;
|
|
603
|
+
panel.style.left = Math.max(8, vw - width - 12) + "px";
|
|
604
|
+
panel.style.top = Math.max(8, Math.round(r.top + 8)) + "px";
|
|
605
|
+
panel.style.maxHeight = Math.round(Math.min(r.height - 24, vh - 40)) + "px";
|
|
606
|
+
}
|
|
607
|
+
panel.classList.remove("cnvnav-panel-unplaced");
|
|
608
|
+
return true;
|
|
586
609
|
}
|
|
587
610
|
place();
|
|
611
|
+
/* 每 400ms 复查: 容器出现即校准; 布局连续 3 次无变化后停止 */
|
|
612
|
+
let id = setInterval(() => {
|
|
613
|
+
const before = lastKey;
|
|
614
|
+
if (!place()) return;
|
|
615
|
+
if (lastKey !== null && lastKey === before) {
|
|
616
|
+
stableTicks += 1;
|
|
617
|
+
if (stableTicks >= 3) clearInterval(id);
|
|
618
|
+
} else {
|
|
619
|
+
stableTicks = 0;
|
|
620
|
+
}
|
|
621
|
+
}, 400);
|
|
588
622
|
window.addEventListener("resize", place);
|
|
589
|
-
return () =>
|
|
590
|
-
|
|
623
|
+
return () => {
|
|
624
|
+
clearInterval(id);
|
|
625
|
+
window.removeEventListener("resize", place);
|
|
626
|
+
};
|
|
627
|
+
}, [snap.open, snap.sessionId]);
|
|
591
628
|
|
|
592
629
|
React.useEffect(() => {
|
|
593
630
|
if (!snap.open) return;
|
|
@@ -821,7 +858,7 @@ window.__ModuleLoader__.load({
|
|
|
821
858
|
|
|
822
859
|
return React.createElement("div", {
|
|
823
860
|
ref: (el) => { panelEl = el; },
|
|
824
|
-
className: "cnvnav-panel" + (snap.open ? "" : " cnvnav-panel-hidden"),
|
|
861
|
+
className: "cnvnav-panel cnvnav-panel-unplaced" + (snap.open ? "" : " cnvnav-panel-hidden"),
|
|
825
862
|
role: "complementary",
|
|
826
863
|
"aria-label": "会话导航",
|
|
827
864
|
"aria-hidden": !snap.open,
|