feat(ui): full-screen video stage with PiP local preview
Some checks failed
Mirror to GitHub / mirror (push) Failing after 28s
Build Release Binaries / build-amd64 (push) Failing after 3m5s

Move video out of the voice drawer into a fixed-position stage that
covers the lobby above the drawer. Remote canvas fills the stage with
object-fit: contain; local preview is a 200x112 PiP in the bottom-right.
Placeholder shows "Waiting for remote video" with a frame counter until
the first frame arrives. Counter logs first remote frame to console for
debugging.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-05-25 17:53:10 +04:00
parent 1329abbeba
commit cbc3a8d37e
3 changed files with 61 additions and 16 deletions

View File

@@ -465,6 +465,9 @@ function leaveVoice() {
if (statusInterval) { clearInterval(statusInterval); statusInterval = null; }
stopCamera();
remoteVideoActive = false;
remoteFrameCount = 0;
vdRemoteCounter.textContent = "0 frames received";
vdRemotePlaceholder.classList.remove("hidden");
vdVideoStrip.classList.add("hidden");
remoteCtx.clearRect(0, 0, vdRemoteVideo.width, vdRemoteVideo.height);
}
@@ -535,6 +538,9 @@ vdCamBtn.addEventListener("click", () => {
// ── Remote video display (Blocker 5) ─────────────────────────────
const remoteCtx = vdRemoteVideo.getContext("2d")!;
const vdRemotePlaceholder = document.getElementById("vd-remote-placeholder")!;
const vdRemoteCounter = document.getElementById("vd-remote-counter")!;
let remoteFrameCount = 0;
listen("video:frame", (event: any) => {
const { width, height, jpeg_b64 } = event.payload;
@@ -542,8 +548,11 @@ listen("video:frame", (event: any) => {
remoteVideoActive = true;
vdVideoStrip.classList.remove("hidden");
vdRemotePlaceholder.classList.add("hidden");
vdRemoteVideo.width = width ?? vdRemoteVideo.width;
vdRemoteVideo.height = height ?? vdRemoteVideo.height;
remoteFrameCount++;
if (remoteFrameCount === 1) console.log("first remote video frame:", width, "x", height);
const img = new Image();
img.onload = () => {