feat(app): give a device capture a column of its own - #370
Conversation
The PR is not yet safe to merge because metadata changes can leave a user-selected device column outside its newly calculated width bound. Findings
|
| // Own listener, not `window.onresize`: that is a single slot, so with five | ||
| // controllers on the page only the last one constructed ever ran — which is | ||
| // why nothing re-fitted on resize. | ||
| window.addEventListener('resize', this.#onWindowResize) |
There was a problem hiding this comment.
Resize listener lost on reconnect
The resize listener is registered only in the controller constructor but removed by hostDisconnected(). When a Lit host is detached and later reconnected without reconstructing the controller, the listener is never restored. Derived panes then stop following window resizes, and persisted pane sizes are no longer re-clamped.
| get #deviceLayout(): boolean { | ||
| return Boolean(this.metadata?.device) | ||
| } |
There was a problem hiding this comment.
Landscape devices use portrait layout
This gate checks only for metadata.device, although supported Android and iOS traces can have landscape viewports. A landscape capture therefore enters sizing logic designed for a portrait frame, potentially allocating up to 60% of the window to an unnecessarily wide device column and taking that space from the dock instead of retaining the stacked layout.
| #dragDevice = new DragController(this, { | ||
| localStorageKey: 'devicePaneWidth', | ||
| minPosition: DEVICE_PANE_MIN_WIDTH, | ||
| // Capped at the useful width, not at a share of the window: beyond | ||
| // "fills the height" the drag buys backdrop and costs the dock. | ||
| maxPosition: () => this.#deviceFillWidth(), | ||
| initialPosition: () => this.#deviceFillWidth(), |
There was a problem hiding this comment.
The device pane has a fixed 180px minimum, but its bounds use the whole window rather than the actual row width remaining after the actions sidebar. In a narrow window or after widening the sidebar, the row can become narrower than 180px. The non-shrinking device pane then overflows the clipped row, the dock collapses toward zero, and the divider can become inaccessible.
| maxPosition: () => this.#deviceFillWidth(), | ||
| initialPosition: () => this.#deviceFillWidth(), |
There was a problem hiding this comment.
Device width freezes before metadata
#dragDevice resolves its initial position while the element is being constructed, before the consumed metadata context can populate this.metadata, so a new workbench starts with the fallback 0.5 aspect ratio. Later metadata updates rerender the workbench but do not rederive the controller position. Captures with a different ratio therefore keep a stale column width until a window resize or user drag.
| protected updated(changed: PropertyValues<this>): void { | ||
| if ( | ||
| changed.has('metadata') && | ||
| this.#deviceLayout && | ||
| this.#dragDevice.refreshDerived() |
There was a problem hiding this comment.
Metadata leaves width oversized
When metadata changes after the user has dragged or restored the device-pane width, this path calls refreshDerived(), which skips user-chosen positions. Rendering then uses the stored width without checking the new bounds, so a rotated or newly loaded portrait capture can keep an obsolete oversized column and take space from the dock until the window is resized.
What & why
Type of change
Packages touched
shared(types and contracts)core(framework-agnostic capture/reporting)elements(published element/snapshot API —@wdio/elements)service(WebdriverIO adapter)nightwatch-devtools(Nightwatch adapter)selenium-devtools(Selenium adapter)selenium-devtools-py(Selenium Python adapter)backend(server)app(UI)script(page-injected runtime)trace(Trace mode)Notes for reviewers
Screenshots / recordings
Trace mode:
