Screen sharing #16

Merged
kibi merged 2 commits from screen-sharing into main 2026-10-01 22:39:03 +00:00
2 changed files with 15 additions and 2 deletions
Showing only changes of commit fdf6c12afa - Show all commits
+3 -2
View File
@@ -411,8 +411,9 @@
.tile:hover { background: var(--bg-hover); }
.tile.talking { border-color: var(--speaking); box-shadow: 0 0 0 1px var(--speaking), 0 0 18px -4px var(--speaking); }
.tile.focused { border-color: var(--accent); }
/* A camera fills its tile; your own is mirrored, the way a mirror shows you */
.tile video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: #000; }
/* A camera keeps its own shape inside the tile, whatever size the tile is: nothing is cut
off, a phone held upright gets bars at the sides. Your own is mirrored, like a mirror. */
.tile video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; background: #000; }
.tile video.mirror { transform: scaleX(-1); }
.icon-btn.live, .icon-btn.live:hover { color: var(--speaking); }
.camgrid { position: relative; display: flex; flex-direction: column; flex: none; }
+12
View File
@@ -294,6 +294,18 @@ try {
await camsShown(bob.page, 2);
await camsShown(alice.page, 2);
assert.equal(await bob.page.locator('.stage .tile.self video.mirror').count(), 1, 'own camera is mirrored');
// The picture keeps its shape in the tile at any tile size: whole, not cropped
const shape = () => bob.page.evaluate(() => [...document.querySelectorAll('.stage .tile video')].map(v => {
const el = v as HTMLVideoElement, r = el.getBoundingClientRect();
const scale = Math.min(r.width / el.videoWidth, r.height / el.videoHeight);
return { fit: getComputedStyle(el).objectFit, inside: el.videoWidth * scale <= r.width + 1 && el.videoHeight * scale <= r.height + 1, box: r.width > 50 && r.height > 50 };
}));
for (const size of [{ width: 1280, height: 800 }, { width: 760, height: 620 }]) {
await bob.page.setViewportSize(size);
await camsShown(bob.page, 2);
assert.ok((await shape()).every(s => s.fit === 'contain' && s.inside && s.box), `cameras whole at ${size.width} wide`);
}
await bob.page.setViewportSize({ width: 1280, height: 800 });
assert.equal(await bob.page.locator('.stage .tile:not(.self) video.mirror').count(), 0);
await alice.page.locator('.stage .status', { hasText: '1 watching' }).waitFor();
await bob.page.locator('.stage .status', { hasText: '1 watching' }).waitFor();