dsh-neotui 0.0.13 → 0.0.14
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/package.json +1 -1
- package/src/views.js +25 -16
package/package.json
CHANGED
package/src/views.js
CHANGED
|
@@ -849,22 +849,31 @@ export class ChatView extends Widget {
|
|
|
849
849
|
}
|
|
850
850
|
const node = this.nodes[info.nodeIdx];
|
|
851
851
|
// Expand/collapse changes the line count ABOVE the viewport, which would
|
|
852
|
-
// leave scrollY pointing at unrelated content
|
|
853
|
-
//
|
|
854
|
-
//
|
|
855
|
-
//
|
|
856
|
-
//
|
|
857
|
-
const
|
|
858
|
-
|
|
852
|
+
// leave scrollY pointing at unrelated content. Anchor: remember the
|
|
853
|
+
// viewport-top line's identity AND its offset within that block, then
|
|
854
|
+
// restore the same position after the rebuild — the view does not move
|
|
855
|
+
// at all when the top line survives (e.g. clicking a block header), and
|
|
856
|
+
// lands on the fold's last line when the top line itself was collapsed.
|
|
857
|
+
const lineKey = (m) => (m ? `${m.nodeIdx}:${m.blockIdx ?? "n"}` : null);
|
|
858
|
+
const topKey = lineKey(this.lineMap[this.view.scrollY]);
|
|
859
|
+
let topFirst = -1;
|
|
860
|
+
if (topKey !== null) {
|
|
859
861
|
for (let i = 0; i < this.lineMap.length; i++) {
|
|
860
|
-
if (
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
862
|
+
if (lineKey(this.lineMap[i]) === topKey) { topFirst = i; break; }
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
const topOffset = topFirst >= 0 ? this.view.scrollY - topFirst : 0;
|
|
866
|
+
const reanchor = () => {
|
|
867
|
+
if (topKey === null || topFirst < 0) return;
|
|
868
|
+
let first = -1, last = -1;
|
|
869
|
+
for (let i = 0; i < this.lineMap.length; i++) {
|
|
870
|
+
if (lineKey(this.lineMap[i]) !== topKey) continue;
|
|
871
|
+
if (first < 0) first = i;
|
|
872
|
+
last = i;
|
|
866
873
|
}
|
|
867
|
-
if (
|
|
874
|
+
if (first < 0) return;
|
|
875
|
+
const target = Math.min(first + topOffset, last);
|
|
876
|
+
this.view.scrollY = Math.max(0, Math.min(target, this.view.maxScroll()));
|
|
868
877
|
};
|
|
869
878
|
if (node?.kind === "assistant" && info.blockIdx !== null) {
|
|
870
879
|
const b = node.blocks[info.blockIdx];
|
|
@@ -880,7 +889,7 @@ export class ChatView extends Widget {
|
|
|
880
889
|
else this.collapsedBlocks.add(key);
|
|
881
890
|
}
|
|
882
891
|
this.#rebuild();
|
|
883
|
-
reanchor(
|
|
892
|
+
reanchor();
|
|
884
893
|
return true;
|
|
885
894
|
}
|
|
886
895
|
}
|
|
@@ -888,7 +897,7 @@ export class ChatView extends Widget {
|
|
|
888
897
|
if (this.expanded.has(info.nodeIdx)) this.expanded.delete(info.nodeIdx);
|
|
889
898
|
else this.expanded.add(info.nodeIdx);
|
|
890
899
|
this.#rebuild();
|
|
891
|
-
reanchor(
|
|
900
|
+
reanchor();
|
|
892
901
|
return true;
|
|
893
902
|
}
|
|
894
903
|
}
|