fix(coding-agent): prioritize active branch in sorting and fix gutters spacing

This commit is contained in:
Mario Zechner 2025-12-29 15:46:09 +01:00
parent 97e5e8c918
commit 975e90ea8c

View file

@ -108,16 +108,34 @@ class TreeList implements Component {
// - At indent 1: children always go to indent 2 (visual grouping of subtree) // - At indent 1: children always go to indent 2 (visual grouping of subtree)
// - At indent 2+: stay flat for single-child chains, +1 only if parent branches // - At indent 2+: stay flat for single-child chains, +1 only if parent branches
// Stack items: [node, indent, justBranched, showConnector, isLast, gutters] // Stack items: [node, indent, justBranched, showConnector, isLast, gutters, isVirtualRootChild]
type StackItem = [SessionTreeNode, number, boolean, boolean, boolean, boolean[], boolean]; type StackItem = [SessionTreeNode, number, boolean, boolean, boolean, boolean[], boolean];
const stack: StackItem[] = []; const stack: StackItem[] = [];
// Add roots in reverse order // Determine which subtrees contain the active leaf (to sort current branch first)
const containsActive = new Map<SessionTreeNode, boolean>();
const leafId = this.currentLeafId;
const markContains = (node: SessionTreeNode): boolean => {
let has = leafId !== null && node.entry.id === leafId;
for (const child of node.children) {
if (markContains(child)) {
has = true;
}
}
containsActive.set(node, has);
return has;
};
for (const root of roots) {
markContains(root);
}
// Add roots in reverse order, prioritizing the one containing the active leaf
// If multiple roots, treat them as children of a virtual root that branches // If multiple roots, treat them as children of a virtual root that branches
const multipleRoots = roots.length > 1; const multipleRoots = roots.length > 1;
for (let i = roots.length - 1; i >= 0; i--) { const orderedRoots = [...roots].sort((a, b) => Number(containsActive.get(b)) - Number(containsActive.get(a)));
const isLast = i === roots.length - 1; for (let i = orderedRoots.length - 1; i >= 0; i--) {
stack.push([roots[i], multipleRoots ? 1 : 0, multipleRoots, multipleRoots, isLast, [], multipleRoots]); const isLast = i === orderedRoots.length - 1;
stack.push([orderedRoots[i], multipleRoots ? 1 : 0, multipleRoots, multipleRoots, isLast, [], multipleRoots]);
} }
while (stack.length > 0) { while (stack.length > 0) {
@ -142,6 +160,20 @@ class TreeList implements Component {
const children = node.children; const children = node.children;
const multipleChildren = children.length > 1; const multipleChildren = children.length > 1;
// Order children so the branch containing the active leaf comes first
const orderedChildren = (() => {
const prioritized: SessionTreeNode[] = [];
const rest: SessionTreeNode[] = [];
for (const child of children) {
if (containsActive.get(child)) {
prioritized.push(child);
} else {
rest.push(child);
}
}
return [...prioritized, ...rest];
})();
// Calculate child indent // Calculate child indent
let childIndent: number; let childIndent: number;
if (multipleChildren) { if (multipleChildren) {
@ -160,10 +192,10 @@ class TreeList implements Component {
const childGutters = showConnector ? [...gutters, !isLast] : gutters; const childGutters = showConnector ? [...gutters, !isLast] : gutters;
// Add children in reverse order // Add children in reverse order
for (let i = children.length - 1; i >= 0; i--) { for (let i = orderedChildren.length - 1; i >= 0; i--) {
const childIsLast = i === children.length - 1; const childIsLast = i === orderedChildren.length - 1;
stack.push([ stack.push([
children[i], orderedChildren[i],
childIndent, childIndent,
multipleChildren, multipleChildren,
multipleChildren, multipleChildren,
@ -355,9 +387,9 @@ class TreeList implements Component {
const displayIndent = this.multipleRoots ? Math.max(0, flatNode.indent - 1) : flatNode.indent; const displayIndent = this.multipleRoots ? Math.max(0, flatNode.indent - 1) : flatNode.indent;
// Build prefix: gutters + connector + extra spaces // Build prefix: gutters + connector + extra spaces
const gutterStr = flatNode.gutters.map((g) => (g ? "│ " : " ")).join(""); const gutterStr = flatNode.gutters.map((g) => (g ? "│ " : " ")).join("");
const connector = const connector =
flatNode.showConnector && !flatNode.isVirtualRootChild ? (flatNode.isLast ? "└─" : "├─") : ""; flatNode.showConnector && !flatNode.isVirtualRootChild ? (flatNode.isLast ? "└─ " : "├─ ") : "";
// Extra indent for visual grouping beyond gutters/connector // Extra indent for visual grouping beyond gutters/connector
const prefixLevels = flatNode.gutters.length + (connector ? 1 : 0); const prefixLevels = flatNode.gutters.length + (connector ? 1 : 0);
const extraIndent = " ".repeat(Math.max(0, displayIndent - prefixLevels)); const extraIndent = " ".repeat(Math.max(0, displayIndent - prefixLevels));