From 7b29cf7d10be95fe305f47541122785fa952bfe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mats=20T=C3=B6rnberg?= Date: Tue, 22 Sep 2026 09:52:05 +0200 Subject: [PATCH] fix(screenshare): enable button feedback, audio capture fallback and bump version --- public/app.js | 43 +++++++++++++++++++++++++++++++++++++------ public/index.html | 4 ++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/public/app.js b/public/app.js index 88833be..ee2aaed 100644 --- a/public/app.js +++ b/public/app.js @@ -119,7 +119,7 @@ function leaveVoice(reason) { if (S.ws) { try { S.ws.close(); } catch {} S.ws = null; } if (S.micStream) { S.micStream.getTracks().forEach((t) => t.stop()); S.micStream = null; } els.mic.disabled = false; - $('#btn-share').disabled = true; + // Keep btn-share enabled so clicking it prompts the user to join a channel updateMicButton(); document.querySelectorAll('.channel.voice').forEach((c) => c.classList.remove('active')); S.room = null; @@ -388,21 +388,52 @@ function orientListener() { // screen share (local) // --------------------------------------------------------------------------- async function startScreenShare() { - if (S.sharing || !S.room) return; + if (S.sharing) { + stopScreenShare(); + return; + } + if (!S.room) { + toast('Join a voice channel first to share your screen', 'warn'); + return; + } + if (!navigator.mediaDevices || !navigator.mediaDevices.getDisplayMedia) { + toast('Screen sharing is not supported in this browser or context', 'error'); + return; + } let stream; try { + // Try requesting display media with audio first stream = await navigator.mediaDevices.getDisplayMedia({ video: { frameRate: 30 }, audio: true, }); - } catch { - return; // user cancelled + } catch (err) { + // If user cancelled / denied, don't toast as error unless it's not NotAllowedError/AbortError + if (err.name === 'NotAllowedError' || err.name === 'AbortError') { + return; + } + // Try fallback without audio constraint if audio failed + try { + stream = await navigator.mediaDevices.getDisplayMedia({ + video: { frameRate: 30 }, + }); + } catch (fallbackErr) { + if (fallbackErr.name === 'NotAllowedError' || fallbackErr.name === 'AbortError') { + return; + } + console.error('Failed to get display media:', fallbackErr); + toast(`Could not share screen: ${fallbackErr.message || fallbackErr}`, 'error'); + return; + } } S.screenStream = stream; S.sharing = true; send({ type: 'state', state: { muted: S.muted, deafened: S.deafened, sharing: true } }); for (const peer of S.peers.values()) addScreenToPeer(peer); - stream.getVideoTracks()[0].addEventListener('ended', () => stopScreenShare()); + const videoTrack = stream.getVideoTracks()[0]; + if (videoTrack) { + videoTrack.addEventListener('ended', () => stopScreenShare()); + } renderScreens(); renderTiles(); $('#btn-share').classList.add('active'); @@ -823,7 +854,7 @@ window.addEventListener('keydown', (ev) => { if (ev.target.tagName === 'INPUT' || ev.target.tagName === 'TEXTAREA') return; if (ev.key === 'm') toggleMic(); if (ev.key === 'd') toggleDeafen(); - if (ev.key === 's' && S.room) $('#btn-share').click(); + if (ev.key === 's') $('#btn-share').click(); }); window.addEventListener('beforeunload', () => { try { leaveVoice(); } catch {} }); diff --git a/public/index.html b/public/index.html index 8c58774..08c24b9 100644 --- a/public/index.html +++ b/public/index.html @@ -46,7 +46,7 @@
- +
@@ -97,6 +97,6 @@
- +