PR-C1: adaptive video grid sizing (foundation) #2

Closed
hudson wants to merge 18 commits from flotilla-sph-adaptive-grid into dev

18 commits

Author SHA1 Message Date
mplorentz
63b00e0214 refactor: clean up grid algorithm
- Unify buildUniformRow + buildMixedCandidate into single buildCandidate
- Remove dead overflows field from AdaptiveTileGrid
- Add rowWidth to TileRow to eliminate magic 8 in template
- Simplify scoring: all rows uniform, no need for Math.min/reduce
- Fix stale comments referencing old mixed-size behavior
2026-08-12 13:26:04 -04:00
mplorentz
13f9a5c13d fix: grid algorithm — 4:3 breakpoint, 16:9 cap, uniform tile sizes
- Lower landscape breakpoint from width>height to width/height>=4:3
- fitTile helper caps tiles at 16:9 and shrinks to fit both dimensions,
  preventing overflow on ultrawide containers
- Mixed candidate uses uniform tile sizes for all rows; partial rows
  are centered with the same tile dimensions as full rows
2026-08-12 13:09:12 -04:00
mplorentz
f099e97981 fix: use 1:1 min aspect on landscape, scrollbar-gutter to prevent flicker
- minAspect=1:1 (square) on landscape containers, 3:4 on portrait
- scrollbar-gutter:stable on grid prevents scrollbar feedback loop
2026-08-12 13:06:12 -04:00
mplorentz
1df2b8f7b8 fix: video grid wrapping and mobile height constraints
- flex-nowrap on grid rows prevents subpixel rounding from wrapping the
  second tile onto a new row (caused 'half off screen' on desktop)
- flex flex-col on mobile wrapper gives the grid container a constrained
  height so it renders at narrow viewport widths
2026-08-12 12:49:03 -04:00
mplorentz
972425a4b7 Merge branch 'flotilla-sph-adaptive-grid' of ssh://forgejo.lorentz.is:4201/matt/flotilla into flotilla-sph-adaptive-grid 2026-08-12 10:04:58 -04:00
Agent
0d9e511f41 fix: mixed-row rendering bug and Jitsi-style algorithm refinements 2026-08-12 09:49:24 -04:00
Agent
90b9bda329 feat: Jitsi-style adaptive grid with mixed row sizes
Complete rewrite of the tile grid sizing algorithm addressing all
review feedback from @matt across both reviews.

Review #1 (Jitsi-style approach):
- Tiles flex between 3:4 (portrait) and arbitrarily wide (no upper
  clamp on aspect ratio) to avoid overflow.
- Mixed row sizes: when the last row is partial, those tiles are
  wider (16:9 'match heights') while full rows use square-ish
  tiles, creating a cohesive Jitsi-style look.
- Example: 3 participants = 2 square-ish tiles on top + 1 centered
  16:9 tile on bottom.

Review #2 (n=2 half-off-screen bug + minimum size policy):
- FIX: No upper-bound clamping on aspect ratio - tiles can be wider
  than 16:9 when the container is very wide. At n=2 on a wide desktop,
  tiles are 16:9 (889x500) with side whitespace instead of overflowing.
- MIN_TILE_HEIGHT=120: only allows overflow (scroll) when all tiles
  fall below this threshold. At n=2 tiles are always fully visible.
- For n=6-12 on a portrait phone, tiles shrink to fit within aspect
  bounds with no scroll.

Inline code review feedback:
- Full words everywhere: containerWidth, columnCount, tileWidth,
  tileHeight, aspectRatio, etc.
- No 'key' naming: replaced with LayoutScore struct with named fields
- Type renamed from UniformTileGrid to AdaptiveTileGrid + TileRow
- No 'compareKeys' - replaced with compareScores on named fields

Scoring: overflow penalty -> min-height penalty -> tile area ->
whitespace -> aspect deviation.
2026-08-12 09:43:17 -04:00
mplorentz
d552b6f245 Merge branch 'flotilla-sph-adaptive-grid' of ssh://forgejo.lorentz.is:4201/matt/flotilla into flotilla-sph-adaptive-grid 2026-08-12 09:21:14 -04:00
Agent
521e611d6b fix: three bugs in computeUniformGrid sizing and scoring
1. Array-comparison bug (CRITICAL): 'key < bestKey' coerces arrays to
   comma-joined strings, so [1668,...] < [23,...] is TRUE ('1'<'2').
   Replaced with explicit numeric lexicographic compare (compareKeys).
   Root cause of @matt's report: n=2 @1920x500 picked 1x2 stacked with
   1668px overflow instead of 2x1 side-by-side fitting nearly exactly.

2. <MIN branch bug (CRITICAL): fillAspect < 3/4 computed tileW = rowH *
   TILE_ASPECT_MIN which ALWAYS exceeds widthLimit (the column width),
   producing tiles wider than the container. Fix: tileW = widthLimit;
   tileH = widthLimit / TILE_ASPECT_MIN (letterbox vertically, fits).

3. Missing horizontal overflow scoring: added hOverflow to the key
   (after vOverflow) as belt-and-braces guard.
2026-08-11 16:51:30 -04:00
mplorentz
957ab58956 Merge branch 'flotilla-sph-adaptive-grid' of ssh://forgejo.lorentz.is:4201/matt/flotilla into flotilla-sph-adaptive-grid 2026-08-11 16:40:31 -04:00
Agent
2aca6c5393 fix: add mx-auto to flex container for grid block centering 2026-08-11 16:35:17 -04:00
Agent
8bcc3ac918 fix: orphan centering — switch inner grid to flex-wrap + justify-center
CSS grid + mx-auto centers the whole block but not orphan tiles within
their row (e.g. 5 tiles @1685x1342, the 2-tile row was left-aligned).
Switched to display:flex; flex-wrap:wrap; justify-content:center with
explicit width/height on each tile wrapper. This naturally centers every
row, including orphan rows with fewer tiles.

The computeUniformGrid algorithm is unchanged — still uniform px tile
sizes with aspect flexing in [3:4..16:9].
2026-08-11 16:30:51 -04:00
Agent
4b1e209262 feat: uniform-size tile grid with flex-fill aspect (PR-C1 plan v2)
Replaces the Jitsi-style mixed-row layout (~190 lines: partitions,
mixed-size rows, per-row aspect, penalty scoring) with a simple uniform
grid (~25 lines): all tiles identical px size, aspect flexes within
[3:4 .. 16:9], column count chosen to maximize area via key ordering
(overflow < waste < aspect closeness < -area).

Key changes:
- computeUniformGrid / UniformTileGrid replaces computeTileLayout/TileLayout
- TILE_ASPECT_MIN widened from 9/16 to 3/4 per @matt
- CSS grid with explicit px column/row tracks replaces flex rows
- mx-auto centers the grid block; orphan rows have same-size tiles
  (never full-width giants)
- Outer measuring container always mounted (bind:clientWidth/Height);
  inner grid gated on tileGrid
- Each tile wrapper: overflow-hidden rounded-2xl (grid cell sizes it)
- 'default' tile variant keeps min-h-0 h-full w-full (fills grid cell)

Per @matt's approved plan v2: flex-fill single rule everywhere, no
portrait special-casing, no mixed-size rows, uniform tiles, centered
block.
2026-08-11 16:25:55 -04:00
mplorentz
b9a1f9c7ba Merge branch 'flotilla-sph-adaptive-grid' of ssh://forgejo.lorentz.is:4201/matt/flotilla into flotilla-sph-adaptive-grid 2026-08-11 15:44:03 -04:00
Agent
1b1e0169ff fix: two critical rendering bugs in mixed-size grid layout
Bug 1 — chicken-and-egg gating: '{:else if useMultiGrid && tileLayout}'
prevented the measuring container from ever mounting, because tileLayout
is undefined while gridWidth/gridHeight are 0, and the bind:clientWidth/
clientHeight are on the same div. Fix: always mount the measuring
container when useMultiGrid, gate only the rows with {#if tileLayout}.

Bug 2 — collapsed tile height: 'default' tile class lost aspect-video but
gained no replacement for intrinsic height. All children are absolutely
positioned (VideoCallTile 'absolute inset-0', profile fallback, badges,
label, pin button), so the div collapses to 0 height. Fix: add 'h-full'
to the default tile class so it fills the aspect-ratio wrapper.
2026-08-11 10:21:34 -04:00
Agent
d8dea9c4dd feat: Jitsi-style mixed-size tile grid sizing (PR-C1 rework)
Replaces the uniform grid-sizing helper (computeGridSize -> rows/cols)
with a Jitsi-inspired mixed-size layout algorithm (computeTileLayout).

Key changes:
- Tiles flex between 9:16 and 16:9 aspect ratio per row, matched to
  container dimensions
- Rows can have different tile counts (e.g. [2,1] for 3 participants,
  [3,2] for 5, [4,3] for 7)
- Last row with fewer tiles gets a wider (more landscape) aspect ratio
  while earlier rows stay more square-ish
- CSS grid replaced with flex rows; each tile's aspect-ratio set via
  inline style (no more hardcoded aspect-video)
- Container dimensions bound via bind:clientWidth/clientHeight
- Dead {:else} branch (always-true useMultiGrid) removed
- Overflow penalty, whitespace penalty, and balance penalty ensure
  reasonable layouts at all tile counts

Per @matt's PR review feedback: read jitsi-meet source
(react/features/video-layout/functions.web.ts,
react/features/filmstrip/functions.web.ts) for the tile sizing
approach.
2026-08-11 10:13:05 -04:00
mplorentz
1e2e4923c3 Merge remote-tracking branch 'origin/dev' into flotilla-sph-adaptive-grid 2026-08-11 09:44:19 -04:00
Agent
664a57d4eb feat: adaptive video grid sizing (PR-C1)
Add computeGridSize helper in call.ts that computes optimal row/column
counts for a video tile grid given tile count and container dimensions,
maximizing tile size while maintaining ~16:9 cells.

Apply via computed grid-template-columns/rows on the multi-grid path
(no-spotlight) in VideoCallContent.svelte, replacing the fixed
grid-cols-1 / grid-cols-1 sm:grid-cols-2 heuristic. The multi-grid now
handles all tile counts from 1 to 12+ smoothly.

- computeGridSize(tileCount, containerWidth, containerHeight) -> GridSize
- Container dimensions bound via clientWidth/clientHeight
- useMultiGrid: dropped the > 2 check, now !useSpotlightLayout
- gridStyle: computed grid-template-columns/rows string from gridSize
- Scope: multi-grid only, no spotlight/strip/breakpoint changes
2026-08-05 14:39:01 -04:00