fix(run): re-attach a lane's live terminal after the Workspace page remounts
The lane-switch effect only synced `handle` from whatever activeRuns snapshot was already loaded, so navigating away and back to /run (a fresh mount with activeRuns still null) left a running lane's console stuck on the setup form until the user switched lanes and back.
This commit is contained in:
@@ -117,6 +117,7 @@ export function LaneConsolePane({
|
|||||||
// away when the new lane already has a live run: each lane sticks to its own
|
// away when the new lane already has a live run: each lane sticks to its own
|
||||||
// tmux session, and the switch should land on that session rather than on an
|
// tmux session, and the switch should land on that session rather than on an
|
||||||
// empty setup form the user then has to Start out of.
|
// empty setup form the user then has to Start out of.
|
||||||
|
const autoAttachedForLane = useRef<number | null>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { activeRuns: runs } = latest.current;
|
const { activeRuns: runs } = latest.current;
|
||||||
setPrompt("");
|
setPrompt("");
|
||||||
@@ -124,9 +125,27 @@ export function LaneConsolePane({
|
|||||||
setError(null);
|
setError(null);
|
||||||
setBusy(null);
|
setBusy(null);
|
||||||
setHandle(runs?.items.find((r) => r.laneId === laneId && r.status === "running") ?? null);
|
setHandle(runs?.items.find((r) => r.laneId === laneId && r.status === "running") ?? null);
|
||||||
|
autoAttachedForLane.current = null;
|
||||||
refreshList();
|
refreshList();
|
||||||
}, [laneId, refreshList]);
|
}, [laneId, refreshList]);
|
||||||
|
|
||||||
|
// The switch effect above only sees whatever `activeRuns` the page already
|
||||||
|
// had loaded at that instant. Remounting this page (navigating away and
|
||||||
|
// back) starts `activeRuns` at null again, so a lane with a live run would
|
||||||
|
// otherwise show the setup form until the user switched lanes and back —
|
||||||
|
// the only path that re-ran the effect after the poll caught up. Re-check
|
||||||
|
// once `activeRuns` actually arrives, but only once per lane so it never
|
||||||
|
// fights a user-initiated "New Run".
|
||||||
|
useEffect(() => {
|
||||||
|
if (handle || laneId === null) return;
|
||||||
|
if (autoAttachedForLane.current === laneId) return;
|
||||||
|
const running = activeRuns?.items.find((r) => r.laneId === laneId && r.status === "running");
|
||||||
|
if (running) {
|
||||||
|
autoAttachedForLane.current = laneId;
|
||||||
|
setHandle(running);
|
||||||
|
}
|
||||||
|
}, [activeRuns, laneId, handle]);
|
||||||
|
|
||||||
// The cwd tracks the lane's own folder separately, keyed on the resolved
|
// The cwd tracks the lane's own folder separately, keyed on the resolved
|
||||||
// path rather than on `laneId` alone: the pane can mount before the lane
|
// path rather than on `laneId` alone: the pane can mount before the lane
|
||||||
// list has loaded (split view restores its pane lanes from localStorage),
|
// list has loaded (split view restores its pane lanes from localStorage),
|
||||||
|
|||||||
Reference in New Issue
Block a user