aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-10-22 10:06:20 -0700
committerAdam Soltys <[email protected]>2026-10-22 10:06:20 -0700
commit2c1acf85ac24f78207e0c667a7fae8dfdfa54ac0 (patch)
tree3a14c6cff68d28c542bda1b0142f23c9aac10f18
parent9e48c1513bccdd1bd9cb59736d9efe7676353f6b (diff)
downloadcoinosv3-2c1acf85ac24f78207e0c667a7fae8dfdfa54ac0.tar.gz
coinosv3-2c1acf85ac24f78207e0c667a7fae8dfdfa54ac0.zip
Videos grid: "All shapes" lays the clips out three across in squares (tall tiles stay for a phone held upright showing tall clips only)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--src/features/messages.js10
-rw-r--r--src/style.css2
-rw-r--r--tools/media-grid-dups-test.js2
3 files changed, 9 insertions, 5 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index 0f8c78a..350ad7e 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -14205,10 +14205,12 @@ export function messagesFeature(ctx) {
if (missing.length) warmTileThumbs(missing).then(() => queueTileThumbs(missing.filter((u) => !tileThumbs.has(u))));
}
if (mediaMode === 'videos') for (const it of items.slice(0, 24)) preconnect(playSrc(it.url));
- // wide clips only (a wide screen, not "All shapes"): one to a row, wide
- // posters, not slivers of them cut to portrait tiles (Adam, 2026-10-22)
- const wideRows = mediaMode === 'videos' && !clipsAll() && !screenTall();
- return h('div', { class: 'media-grid' + (wideRows ? ' wide' : ''), 'data-key': 'media-grid:' + mediaMode },
+ // The tiles take the clips' shape (Adam, 2026-10-22): wide clips only (a
+ // wide screen) go one to a row, their posters whole, not slivers cut to
+ // portrait tiles; every shape ("All shapes") goes three across in
+ // squares; tall ones only (a phone held upright) keep the tall tiles.
+ const shape = mediaMode !== 'videos' ? '' : clipsAll() ? ' square' : screenTall() ? '' : ' wide';
+ return h('div', { class: 'media-grid' + shape, 'data-key': 'media-grid:' + mediaMode },
...items.map((it) => {
const k = mediaKey(it);
// a video tile shows a still at once: kept, given, or the server's
diff --git a/src/style.css b/src/style.css
index 25f3bed..0403a88 100644
--- a/src/style.css
+++ b/src/style.css
@@ -1541,6 +1541,8 @@ body::after {
/* only wide clips in it: one to a row, the poster whole */
.media-grid.wide { grid-template-columns: 1fr; gap: 6px; }
.media-grid.wide .media-tile.video { aspect-ratio: 16 / 9; }
+/* every shape in it: squares, none of them favoured */
+.media-grid.square .media-tile.video { aspect-ratio: 1; }
.media-tile img, .media-tile video { width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none; }
.media-tile.broken { display: none; }
.media-tile-play {
diff --git a/tools/media-grid-dups-test.js b/tools/media-grid-dups-test.js
index 2181f69..0c3783d 100644
--- a/tools/media-grid-dups-test.js
+++ b/tools/media-grid-dups-test.js
@@ -104,7 +104,7 @@ try {
check('…and "All shapes" brings it in', await waitFor(() => { const s = [...document.querySelectorAll('.mp-slide')].find((x) => x.getAttribute('data-k').endsWith('/tall.webm')); return !!s && !s.closest('.mp-group').classList.contains('mp-off'); }, null, 3000));
await page.keyboard.press('Escape');
check('the grid has it too', await waitFor(() => [...document.querySelectorAll('.media-grid .media-tile')].some((t) => t.getAttribute('data-key').endsWith('/tall.webm')), null, 5000));
- check('…in the 3-across grid of tall tiles again', await page.evaluate(() => !document.querySelector('.media-grid').classList.contains('wide')));
+ check('…in a 3-across grid of squares', await page.evaluate(() => { const g = document.querySelector('.media-grid'), t = g.querySelector('.media-tile').getBoundingClientRect(); return g.classList.contains('square') && Math.abs(t.width - t.height) < 2 && t.width < g.getBoundingClientRect().width / 2.5; }));
check('no page errors', errs.length === 0, errs.slice(0, 2).join(' | '));
} finally {
await browser.close();