Skip to content

feat(app): give a device capture a column of its own - #370

Open
vishnuv688 wants to merge 3 commits into
mainfrom
fix/349-adapt-pane-to-the-window
Open

feat(app): give a device capture a column of its own#370
vishnuv688 wants to merge 3 commits into
mainfrom
fix/349-adapt-pane-to-the-window

Conversation

@vishnuv688

@vishnuv688 vishnuv688 commented Sep 8, 2026

Copy link
Copy Markdown
Member

What & why

Type of change

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Polish (an improvement to an existing feature)
  • Breaking change (existing behavior changes for users)
  • Documentation
  • Internal (build, CI, dependencies, tooling)

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:
image

@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

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

  1. P1 Metadata leaves width oversized

Summary

  • Adds separate stacked and device-column layouts based on capture metadata and orientation.
  • Makes drag-controller defaults and bounds responsive to window changes and reconnects.
  • Re-fits browser snapshots using their own observed box.
  • Adds UI and unit coverage for device layout, resizing, metadata updates, and controller lifecycle.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  M[Capture metadata changes] --> O{Device with portrait or unknown viewport?}
  O -->|No| S[Render stacked browser and dock]
  O -->|Yes| R[Render dock beside device column]
  R --> D[Resolve device pane width]
  D --> U{User-selected width?}
  U -->|No| F[Re-derive width from viewport and window]
  U -->|Yes| K[Keep stored width without re-clamping]
  K --> X[Width may exceed the new useful maximum]
Loading

// 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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Comment on lines +201 to +203
get #deviceLayout(): boolean {
return Boolean(this.metadata?.device)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Comment on lines +256 to +262
#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(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Device pane can overflow

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.

Comment on lines +261 to +262
maxPosition: () => this.#deviceFillWidth(),
initialPosition: () => this.#deviceFillWidth(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Comment on lines +576 to +580
protected updated(changed: PropertyValues<this>): void {
if (
changed.has('metadata') &&
this.#deviceLayout &&
this.#dragDevice.refreshDerived()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant