fix: hand a proposal only to the page the reader is looking at

Re-pointing a tab reloads it and rebuilds its url. On a tab that is not on
screen that silently drops whatever had been typed into its form and leaves the
call on a page the reader cannot see, while the card folds because the call is
carried — so the run is confirmable on neither surface in view. Declining
instead leaves it on the card, which can run it.

The automatic path therefore requires the matching tab to be the active one in
an open panel, alongside the existing version-pin check, and the three ways of
being busy read as one condition. An explicit Preview press still re-points,
reveals and unpins, which is what pressing it asks for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guilhem Lemouel
2026-10-13 07:42:21 -07:00
co-authored by Claude Opus 5
parent 6c2ad4bbf6
commit 93ac4f495e
@@ -666,22 +666,26 @@ function createRuntime(session: Session): SessionRuntime {
return slot.kind === 'viewer' && slot.viewerKind === kind && slot.path === path return slot.kind === 'viewer' && slot.viewerKind === kind && slot.path === path
}) })
if (open) { if (open) {
// A tab pinned to a version is one the reader put somewhere deliberately, and // An unasked-for hand-off goes only to the page the reader already has in front of
// `navigate` below rebuilds its url without the pin. Worth it when the reader asked // them. `navigate` below re-points the tab, which reloads it and rebuilds its url:
// for this page; not worth silently moving them off a version they chose, so an // on a tab they cannot see that silently drops whatever they had typed into its
// unasked-for hand-off declines and leaves the call on the card. // form and leaves the call on an off-screen page, and on a pinned one it moves them
if (onlyIfAlreadyOpen && new URL(open.url, 'http://x').searchParams.get('version')) { // off the version they chose. Declining leaves the call on the card, which can run
// it. A reader who presses Preview is asking for all of that.
if (
onlyIfAlreadyOpen &&
(previewTabs.activeId !== open.id ||
previewTabs.collapsed ||
new URL(open.url, 'http://x').searchParams.get('version'))
) {
return false return false
} }
previewTabs.navigate(viewTarget, open.id) previewTabs.navigate(viewTarget, open.id)
// `navigate` re-points a tab in place and nothing more, while the call is about to // `navigate` re-points a tab in place and nothing more, while the call is about to
// tell the reader the page is open. `open` would have brought it forward and shown // tell the reader the page is open. `open` would have brought it forward and shown
// the panel; this path has to do both itself — except when nobody asked, where // the panel; this path has to do both itself.
// taking the panel off the tab the reader is on is the thing to avoid. previewTabs.select(open.id)
if (!onlyIfAlreadyOpen || previewTabs.activeId === open.id) { previewTabs.setCollapsed(false)
previewTabs.select(open.id)
previewTabs.setCollapsed(false)
}
} else { } else {
// Only the item's own page carries a form for this call, so a caller routing a call // Only the item's own page carries a form for this call, so a caller routing a call
// that was not asked to open anything gets a no rather than a new tab. // that was not asked to open anything gets a no rather than a new tab.