-
- browser needs your tap to recapture the screen — security requirement.
-
@@ -663,22 +659,11 @@ const THEME_KEY = 'zebra-theme-v1';
* hard refresh auto-rejoins. Different tabs can sit in different
* spaces because sessionStorage doesn't bleed across tabs. */
const ACTIVE_CALL_KEY = 'zebra-spaces-active-call-v1';
-/* what publishes were live before the refresh. Camera can attempt
- * silent resume (browser usually remembers getUserMedia permission
- * per-origin); screen CANNOT silently restart — getDisplayMedia
- * requires a fresh user gesture every time (security boundary, by
- * design). We surface a 'resume screen' button instead. */
-const ACTIVE_CAM_KEY = 'zebra-spaces-active-cam-v1';
-const ACTIVE_SCREEN_KEY = 'zebra-spaces-active-screen-v1';
-
-function showResumeScreenPrompt(){
- const r = document.getElementById('row-resume-screen');
- if (r) r.classList.remove('hidden');
-}
-function hideResumeScreenPrompt(){
- const r = document.getElementById('row-resume-screen');
- if (r) r.classList.add('hidden');
-}
+/* camera resume only — screen-share recovery isn't possible silently
+ * (getDisplayMedia needs a fresh gesture) and offering a separate
+ * 'resume screen' button is the same friction as clicking 'share
+ * screen' again, so we just don't track screen state across reload. */
+const ACTIVE_CAM_KEY = 'zebra-spaces-active-cam-v1';
/* theme toggle. The class is already applied pre-paint by the head
* script, so this just wires the click + keeps the button label in
@@ -1146,8 +1131,6 @@ async function sfuPublishScreen(){
renderScreenTile(myKeys.pubHex, stream, { local: true });
$('btn-screen-share').classList.add('hidden');
$('btn-screen-stop').classList.remove('hidden');
- try { sessionStorage.setItem(ACTIVE_SCREEN_KEY, '1'); } catch(_){}
- hideResumeScreenPrompt();
}
async function sfuUnpublishScreen(){
if (!sfuScreenPC && !sfuScreenStream) return;
@@ -1161,8 +1144,6 @@ async function sfuUnpublishScreen(){
$('btn-screen-share').classList.remove('hidden');
$('btn-screen-stop').classList.add('hidden');
logLine('', 'screen share stopped');
- try { sessionStorage.removeItem(ACTIVE_SCREEN_KEY); } catch(_){}
- hideResumeScreenPrompt();
}
/* ----- camera publish (kind=camera) ----- */
@@ -1624,13 +1605,11 @@ async function handleSignal(raw){
* role is listener (was speaker before but room demoted us on
* rejoin), drop the flags so we don't endlessly prompt. */
if (canSpeak(myRole)){
- /* camera: silent attempt — getUserMedia normally remembers
+ /* camera silent attempt — getUserMedia normally remembers
* per-origin permission, so the browser won't prompt. If it
- * does prompt + the user denies, the flag self-clears via
- * sfuPublishCamera's error path the next time it tries. */
- let wantCam = false, wantScreen = false;
+ * does prompt + the user denies, the flag self-clears. */
+ let wantCam = false;
try { wantCam = sessionStorage.getItem(ACTIVE_CAM_KEY) === '1'; } catch(_){}
- try { wantScreen = sessionStorage.getItem(ACTIVE_SCREEN_KEY) === '1'; } catch(_){}
if (wantCam){
setTimeout(() => {
sfuPublishCamera().catch(e => {
@@ -1639,14 +1618,8 @@ async function handleSignal(raw){
});
}, 250);
}
- if (wantScreen){
- /* screen needs a user gesture per browser security — surface the
- * resume button instead of trying to call getDisplayMedia silently */
- showResumeScreenPrompt();
- }
} else {
try { sessionStorage.removeItem(ACTIVE_CAM_KEY); } catch(_){}
- try { sessionStorage.removeItem(ACTIVE_SCREEN_KEY); } catch(_){}
}
renderShareUrl();
onRoleEntered();
@@ -2070,12 +2043,6 @@ function renderRoom(){
$('btn-raise').addEventListener('click', () => { send({ type:'raise-hand' }); });
$('btn-lower').addEventListener('click', () => { send({ type:'lower-hand' }); });
$('btn-screen-share').addEventListener('click', () => { sfuPublishScreen().catch(e => logLine('err','screen share: '+e.message)); });
-$('btn-resume-screen').addEventListener('click', () => {
- /* user gesture — getDisplayMedia can fire now. On cancel we leave the
- * prompt visible so they can try again; on success the publish path
- * hides it via hideResumeScreenPrompt(). */
- sfuPublishScreen().catch(e => logLine('err','screen resume: '+e.message));
-});
$('btn-screen-stop').addEventListener('click', () => { sfuUnpublishScreen(); });
$('btn-camera-share').addEventListener('click', () => { sfuPublishCamera().catch(e => logLine('err','camera share: '+e.message)); });
$('btn-camera-stop').addEventListener('click', () => { sfuUnpublishCamera(); });
@@ -2279,8 +2246,6 @@ function handleBlocked(source){
/* booted = clear auto-rejoin so a refresh doesn't immediately retry */
try { sessionStorage.removeItem(ACTIVE_CALL_KEY); } catch(_){}
try { sessionStorage.removeItem(ACTIVE_CAM_KEY); } catch(_){}
- try { sessionStorage.removeItem(ACTIVE_SCREEN_KEY); } catch(_){}
- hideResumeScreenPrompt();
showNotice('You are blocked from this space.', 'warn');
logLine('err','blocked ('+source+') — stopping reconnects');
setStatus('blocked from this space','err');
@@ -2410,8 +2375,6 @@ $('btn-leave').addEventListener('click', async () => {
/* explicit leave wipes the auto-rejoin state — user said 'out' */
try { sessionStorage.removeItem(ACTIVE_CALL_KEY); } catch(_){}
try { sessionStorage.removeItem(ACTIVE_CAM_KEY); } catch(_){}
- try { sessionStorage.removeItem(ACTIVE_SCREEN_KEY); } catch(_){}
- hideResumeScreenPrompt();
if (sigReconnect){ clearTimeout(sigReconnect); sigReconnect = null; }
for (const u of [...peers.keys()]) tearPeer(u);
if (ws){ try { ws.close(); } catch(_){} ws = null; }
@@ -2443,8 +2406,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');