fix(maestro): keep the keyboard in the list while previewing
Two mounts were taking focus out of the sidebar mid-walk: the render that put the multi-view on screen before the preview applied, and the render that restores the previous pane when a preview ends. Both now mount without focusing, so j/k keeps walking. Also marks the preview with a badge on the canvas and drops the close button from its tab.
This commit is contained in:
+20
-5
@@ -110,6 +110,20 @@ export function createMultiView(opts: MultiViewOptions): MultiView {
|
||||
tempTabId: string | null;
|
||||
}
|
||||
let preview: Preview | null = null;
|
||||
/// Set while a preview-driven render runs: ending a preview re-mounts the
|
||||
/// pane that was there, and that mount must not pull the keyboard out of the
|
||||
/// sidebar the operator is still walking.
|
||||
let quietRender = false;
|
||||
|
||||
/** Render without any mount taking the keyboard. */
|
||||
function renderQuietly(): void {
|
||||
quietRender = true;
|
||||
try {
|
||||
render();
|
||||
} finally {
|
||||
quietRender = false;
|
||||
}
|
||||
}
|
||||
|
||||
const isTempTab = (tabId: string) => preview?.tempTabId === tabId;
|
||||
|
||||
@@ -152,7 +166,7 @@ export function createMultiView(opts: MultiViewOptions): MultiView {
|
||||
function previewSession(sessionId: string | null): void {
|
||||
if (preview?.sessionId === sessionId) return;
|
||||
if (sessionId === null) {
|
||||
if (restorePreview()) render();
|
||||
if (restorePreview()) renderQuietly();
|
||||
return;
|
||||
}
|
||||
restorePreview();
|
||||
@@ -176,7 +190,7 @@ export function createMultiView(opts: MultiViewOptions): MultiView {
|
||||
layout.activeTabId = tab.id;
|
||||
preview = { sessionId, prevActiveTabId, prevFocus: null, tempTabId: tab.id };
|
||||
}
|
||||
render();
|
||||
renderQuietly();
|
||||
}
|
||||
|
||||
/** Any user action that changes the layout for real ends the preview first,
|
||||
@@ -385,7 +399,8 @@ export function createMultiView(opts: MultiViewOptions): MultiView {
|
||||
}
|
||||
render();
|
||||
});
|
||||
if (layout.tabs.length > 1) {
|
||||
// A preview tab is not the operator's to close: it goes on its own.
|
||||
if (layout.tabs.length > 1 && !isTempTab(t.id)) {
|
||||
const close = document.createElement("span");
|
||||
close.className = "mv-tab-close";
|
||||
close.textContent = "✕";
|
||||
@@ -555,7 +570,7 @@ export function createMultiView(opts: MultiViewOptions): MultiView {
|
||||
// terminal, or j/k would stop walking the list after the first step.
|
||||
pool.setVisible(
|
||||
hosts.map((h) => ({ id: h.id, pane: h.host, info: h.info })),
|
||||
{ focus: !preview },
|
||||
{ focus: !preview && !quietRender },
|
||||
);
|
||||
syncFocus();
|
||||
persist();
|
||||
@@ -579,7 +594,7 @@ export function createMultiView(opts: MultiViewOptions): MultiView {
|
||||
// Only the focused leaf's session is live on mobile; the rest park.
|
||||
pool.setVisible(
|
||||
focused.sessionId ? [{ id: focused.sessionId, pane: pane.host, info: infoFor(focused.sessionId) }] : [],
|
||||
{ focus: !preview },
|
||||
{ focus: !preview && !quietRender },
|
||||
);
|
||||
if (!preview) pool.setFocus(focused.sessionId ?? null);
|
||||
sidebar.setHighlights({ open: realOpenSessions(), focused: focused.sessionId ?? null });
|
||||
|
||||
Reference in New Issue
Block a user