@@ -11825,6 +11825,103 @@ class ClaudeOrchestrator {
1182511825 return uniqueSessionIds;
1182611826 }
1182711827
11828+ getReviewConsoleTerminalScrollContainer(containerEl) {
11829+ const container = containerEl || null;
11830+ if (!container) return null;
11831+ return container.closest?.('[data-rc-panel="terminals"]')
11832+ || container.closest?.('.worktree-inspector-panel')
11833+ || container;
11834+ }
11835+
11836+ scrollReviewConsoleTerminalIntoView(containerEl, sessionId, { block = 'center' } = {}) {
11837+ const container = this.getReviewConsoleTerminalScrollContainer(containerEl);
11838+ const sid = String(sessionId || '').trim();
11839+ if (!container || !sid) return;
11840+
11841+ const wrapper = document.getElementById(this.getSessionDomId('wrapper', sid));
11842+ if (!wrapper || !wrapper.isConnected) return;
11843+
11844+ const wrapperRect = wrapper.getBoundingClientRect();
11845+ const containerRect = container.getBoundingClientRect();
11846+ if (!wrapperRect.height || !containerRect.height) return;
11847+
11848+ const deltaTop = wrapperRect.top - containerRect.top;
11849+ const deltaBottom = wrapperRect.bottom - containerRect.bottom;
11850+ let nextScrollTop = container.scrollTop;
11851+
11852+ if (block === 'nearest') {
11853+ if (deltaTop < 0) nextScrollTop += deltaTop;
11854+ else if (deltaBottom > 0) nextScrollTop += deltaBottom;
11855+ } else {
11856+ nextScrollTop += deltaTop - Math.max(0, (containerRect.height - wrapperRect.height) / 2);
11857+ }
11858+
11859+ container.scrollTop = Math.max(0, nextScrollTop);
11860+ }
11861+
11862+ queueReviewConsoleTerminalLayout(containerEl, sessionIds, { preferredSessionId = '', scrollToBottom = false } = {}) {
11863+ const container = containerEl || null;
11864+ const uniqueSessionIds = Array.from(new Set(
11865+ (Array.isArray(sessionIds) ? sessionIds : [])
11866+ .map((sid) => String(sid || '').trim())
11867+ .filter(Boolean)
11868+ ));
11869+ if (!container || uniqueSessionIds.length === 0) return;
11870+
11871+ const runLayoutPass = ({ anchor = false, pushBottom = false } = {}) => {
11872+ const visibleSessionIds = [];
11873+ uniqueSessionIds.forEach((sid) => {
11874+ const wrapper = document.getElementById(this.getSessionDomId('wrapper', sid));
11875+ if (!wrapper || !wrapper.isConnected || wrapper.style.display === 'none' || wrapper.classList.contains('hidden')) {
11876+ return;
11877+ }
11878+
11879+ visibleSessionIds.push(sid);
11880+ try {
11881+ this.terminalManager?.fitTerminal?.(sid);
11882+ } catch {
11883+ // ignore
11884+ }
11885+
11886+ const term = this.terminalManager?.terminals?.get?.(sid);
11887+ if (!term) return;
11888+
11889+ try {
11890+ term.refresh(0, Math.max(0, term.rows - 1));
11891+ } catch {
11892+ // ignore
11893+ }
11894+
11895+ if (!pushBottom) return;
11896+
11897+ try {
11898+ this.terminalManager?.userScrolling?.set?.(sid, false);
11899+ } catch {
11900+ // ignore
11901+ }
11902+ try {
11903+ term.scrollToBottom?.();
11904+ } catch {
11905+ // ignore
11906+ }
11907+ });
11908+
11909+ if (!anchor || visibleSessionIds.length === 0) return;
11910+ const preferred = String(preferredSessionId || visibleSessionIds[0] || '').trim();
11911+ if (preferred) {
11912+ this.scrollReviewConsoleTerminalIntoView(container, preferred, { block: 'center' });
11913+ }
11914+ };
11915+
11916+ requestAnimationFrame(() => {
11917+ requestAnimationFrame(() => {
11918+ runLayoutPass({ anchor: true, pushBottom: !!scrollToBottom });
11919+ setTimeout(() => runLayoutPass({ anchor: false, pushBottom: false }), 140);
11920+ setTimeout(() => runLayoutPass({ anchor: false, pushBottom: false }), 420);
11921+ });
11922+ });
11923+ }
11924+
1182811925 restoreReviewConsoleDockedTerminals() {
1182911926 try {
1183011927 if (!this.reviewConsoleDockedTerminals || this.reviewConsoleDockedTerminals.size === 0) {
@@ -11961,17 +12058,13 @@ class ClaudeOrchestrator {
1196112058 wrapper.style.display = '';
1196212059 wrapper.classList.add('review-console-terminal');
1196312060 container.appendChild(wrapper);
11964-
11965- // Let layout settle, then fit.
11966- setTimeout(() => {
11967- try {
11968- this.terminalManager?.fitTerminal?.(sid);
11969- } catch {
11970- // ignore
11971- }
11972- }, 60);
1197312061 }
1197412062
12063+ this.queueReviewConsoleTerminalLayout(container, sessionIds, {
12064+ preferredSessionId: sessionIdHint || sessionIds[0] || '',
12065+ scrollToBottom: true
12066+ });
12067+
1197512068 return sessionIds.length;
1197612069 }
1197712070
@@ -13472,14 +13565,6 @@ class ClaudeOrchestrator {
1347213565
1347313566 const label = inferredWorktreeId || String(t.id || '').trim() || worktreePath;
1347413567 await this.openWorktreeInspectorForPath(worktreePath, { label, task: t, reviewConsole: true, sessionIdHint: sessionId, prUrlHint });
13475-
13476- if (rcShowTerminals) {
13477- const preferredSessionId = sessionId || (inferredWorktreeId ? `${inferredWorktreeId}-claude` : '');
13478- if (preferredSessionId) {
13479- const wrapper = document.getElementById(this.getSessionDomId('wrapper', preferredSessionId));
13480- wrapper?.scrollIntoView?.({ behavior: 'smooth', block: 'center' });
13481- }
13482- }
1348313568 }
1348413569
1348513570 async fetchPullRequestDetails(prUrl, { maxFiles = 300, maxCommits = 200, maxComments = 50, maxReviews = 50 } = {}) {
@@ -13814,6 +13899,14 @@ class ClaudeOrchestrator {
1381413899 return String(a).localeCompare(String(b));
1381513900 });
1381613901
13902+ const preferredMatchingSessionId = (() => {
13903+ const taskSessionId = String(t?.sessionId || '').trim();
13904+ if (taskSessionId && matchingSessionIds.includes(taskSessionId)) return taskSessionId;
13905+ const currentSessionId = this.getCurrentInteractionSessionId?.();
13906+ if (currentSessionId && matchingSessionIds.includes(currentSessionId)) return currentSessionId;
13907+ return matchingSessionIds.find((sid) => !isServer(sid)) || matchingSessionIds[0] || '';
13908+ })();
13909+
1381713910 this.setReviewConsoleVisibilityBypass(matchingSessionIds);
1381813911
1381913912 const statusLabel = (s) => {
@@ -14259,13 +14352,11 @@ class ClaudeOrchestrator {
1425914352 });
1426014353 terminalsContainer.classList.toggle('paired-layout', hasVisibleAgent && hasVisibleServer);
1426114354
14262- if (visibleSessionIds.length) {
14263- setTimeout(() => {
14264- visibleSessionIds.forEach((sid) => {
14265- try { this.terminalManager?.fitTerminal?.(sid); } catch {}
14266- });
14267- }, 60);
14268- }
14355+ if (visibleSessionIds.length) {
14356+ this.queueReviewConsoleTerminalLayout(terminalsContainer, visibleSessionIds, {
14357+ preferredSessionId: preferredMatchingSessionId
14358+ });
14359+ }
1426914360 };
1427014361
1427114362 const updateGrid = () => {
@@ -14996,15 +15087,11 @@ class ClaudeOrchestrator {
1499615087 wrapper.style.display = '';
1499715088 wrapper.classList.add('review-console-terminal');
1499815089 terminalsContainer.appendChild(wrapper);
14999-
15000- setTimeout(() => {
15001- try {
15002- this.terminalManager?.fitTerminal?.(sid);
15003- } catch {
15004- // ignore
15005- }
15006- }, 60);
1500715090 }
15091+ this.queueReviewConsoleTerminalLayout(terminalsContainer, matchingSessionIds, {
15092+ preferredSessionId: preferredMatchingSessionId,
15093+ scrollToBottom: true
15094+ });
1500815095 try { updateTerminalKindVisibility(); } catch {}
1500915096 }
1501015097
0 commit comments