fix(mobile): #432 landing fixes

Applies the review's landing list for the native-wrapper window bridge, with the verifier corrections.

detachSession now refuses before asking the host when there is no window channel (no BroadcastChannel). Without the channel there is no roll-call liveness, so a hosted tab could never re-dock and would stay detached, and excluded from tiles and split, until the session ended. The guard sits before the host call so a channel-less host never gets a native window and a window.open as well.

A single resolver, tabDetachButtonEnabled(), now lives in app.js next to hasHostWindows() and decides the host-aware pop-out default for the tab icon, App Settings and the tab action menu (which also serves the tile grid's menu). Before this the menu read the raw setting and hid "Open in a new window" under a host. The menu and both settings-ui.js sites call it optionally with a fallback, because test/session-sidebar-ux.browser.test.ts loads tab-rail-resize.js onto a bare CodemanApp without app.js, and a bare call would throw before the menu is appended.

The "Close window" button on the solo session-gone overlay goes through _closeSoloWindow(), as the re-dock button already did, so it works in a host window.

openWebviewExternal no longer falls through to window.open when the host refuses (in a WebView that can replace the dashboard page); it toasts instead, like the session and file-preview paths.

The hasHostWindows and openInHostWindow JSDoc now say what the code does: anything but false counts as opened, and a saved web tab passes its own origin.

docs/versioning-policy.md lists the window.CodemanHost bridge under experimental surfaces, so it does not read as a stable contract until the wrapper docs section lands.

test/host-window-detach.test.ts gives the harness a live window channel (Object.create leaves it undefined, which the new guard would refuse) and pins the no-channel refusal.

The per-PR changeset is removed; the release writes one consolidated changeset.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-10-09 05:57:49 +02:00
parent 48f54ec090
commit f79f530f93
7 changed files with 56 additions and 31 deletions
-18
View File
@@ -1,18 +0,0 @@
---
"aicodeman": minor
---
feat(mobile): pop a session or a file preview out beside the dashboard from a native wrapper
A WebView app has no browser pop-ups, so "Open in a new window" had nothing to open on a
phone, and mobile.css hid it there. An embedding app that can put a page in a window of its
own (an Android app on a foldable or in split screen) now says so with
`window.CodemanHost.openWindow(absoluteUrl)`, returning whether a window opened. When it is
present, the tab pop-out, the file viewer's detach button and a web tab's "open externally"
go through it, and the tab's pop-out icon defaults on and shows at tablet widths (phone tabs
keep their gear + close tap zones, so the host offers the pop-out from its own chrome through
`app.detachSession`). The dashboard
tracks such a window over the existing window channel, the path a reloaded dashboard already
uses, and a solo window closes and raises itself through the optional
`CodemanHost.closeWindow()` / `CodemanHost.focusWindow()`. Browsers define none of these, so
nothing changes there.