Mobile screen share bug fix
This commit is contained in:
+28
-11
@@ -20,7 +20,7 @@
|
||||
.sub{color:var(--muted);font-size:.97rem;line-height:1.5;margin-bottom:1.6rem;}
|
||||
.codewrap{background:#fffdf2;border:2px dashed var(--brand);border-radius:14px;padding:1.2rem;}
|
||||
.codelabel{font-size:.78rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-bottom:.3rem;}
|
||||
.code{font-size:3rem;letter-spacing:.5rem;font-weight:800;color:var(--ink);}
|
||||
.code{font-size:clamp(1.9rem,12vw,3rem);letter-spacing:clamp(.18rem,3vw,.5rem);font-weight:800;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:clip;}
|
||||
.status{margin-top:1.3rem;padding:.7rem 1rem;border-radius:10px;background:#f1f5f9;color:#475569;font-size:.92rem;}
|
||||
.status.on{background:#ecfdf3;color:#15803d;}
|
||||
.consent{margin-top:1.3rem;border:1px solid #c7d6f0;background:var(--blue-soft);border-left:5px solid var(--blue);border-radius:12px;padding:1.3rem;text-align:left;color:var(--blue-d);}
|
||||
@@ -117,23 +117,40 @@ function showConsent(m){
|
||||
const name=(m.technician&&m.technician.trim())?m.technician:'Your support agent';
|
||||
consentBox.innerHTML='<div class="consent">Your support agent <span class="who">'+esc(name)+'</span> would like to view your screen to help you.'+
|
||||
'<div class="btns"><button class="grant" id="g">Allow</button><button class="deny" id="d">Not now</button></div></div>';
|
||||
const allow=()=>{consentBox.innerHTML='';document.removeEventListener('keydown',onKey);ws.send(JSON.stringify({type:'consent',sessionId:m.sessionId,granted:true}));};
|
||||
const allow=async()=>{
|
||||
document.removeEventListener('keydown',onKey);
|
||||
setStatus('Opening the screen picker — choose your screen and tap Share / Start.','on');
|
||||
const ok=await beginCapture();
|
||||
if(!ok){ consentBox.innerHTML=''; try{ws.send(JSON.stringify({type:'consent',sessionId:m.sessionId,granted:false}));}catch(_){} setStatus('Screen share was cancelled. Refresh this page if you need a new code.'); return; }
|
||||
consentBox.innerHTML='';
|
||||
try{ws.send(JSON.stringify({type:'consent',sessionId:m.sessionId,granted:true}));}catch(_){}
|
||||
};
|
||||
const onKey=(e)=>{if(e.key==='Enter'){e.preventDefault();allow();}};
|
||||
document.addEventListener('keydown',onKey);
|
||||
document.getElementById('g').onclick=allow;
|
||||
document.getElementById('d').onclick=()=>{consentBox.innerHTML='';document.removeEventListener('keydown',onKey);ws.send(JSON.stringify({type:'consent',sessionId:m.sessionId,granted:false}));setStatus('Connection declined. Refresh this page if you need a new code.');};
|
||||
}
|
||||
// Capture the screen (+mic) DIRECTLY from the Allow tap. Mobile browsers reject
|
||||
// getDisplayMedia unless it is called from a user gesture, so this must not run
|
||||
// after a server round-trip. getDisplayMedia is called first to keep the gesture.
|
||||
async function beginCapture(){
|
||||
try{ localStream=await navigator.mediaDevices.getDisplayMedia({video:{displaySurface:'monitor',frameRate:{ideal:30}},audio:false,monitorTypeSurfaces:'include'}); }
|
||||
catch(err){ return false; }
|
||||
try{ const mic=await navigator.mediaDevices.getUserMedia({audio:true}); window.__mic=mic; mic.getAudioTracks().forEach(t=>localStream.addTrack(t)); }catch(e){}
|
||||
try{ ensureIce(); }catch(_){}
|
||||
return true;
|
||||
}
|
||||
async function startStreaming(){
|
||||
// Make sure TURN/ICE is loaded before building the connection (needed for mobile/cellular relay).
|
||||
// If the Allow tap already captured the screen (mobile path), reuse it.
|
||||
if(!localStream){
|
||||
await ensureIce();
|
||||
let mic=null; try{ mic=await navigator.mediaDevices.getUserMedia({audio:true}); }catch(e){ mic=null; }
|
||||
setStatus('In the popup: choose your screen, then tap Share / Start.','on');
|
||||
try{ localStream=await navigator.mediaDevices.getDisplayMedia({video:{displaySurface:'monitor',frameRate:{ideal:30}},audio:false,monitorTypeSurfaces:'include'}); }
|
||||
catch(err){ if(mic){try{mic.getTracks().forEach(t=>t.stop());}catch(_){}} try{ws.send(JSON.stringify({type:'end-session',sessionId,reason:'share-cancelled'}));}catch(e){} setStatus('Screen share was cancelled. Refresh the page to try again.'); return; }
|
||||
if(mic){ window.__mic=mic; try{mic.getAudioTracks().forEach(t=>localStream.addTrack(t));}catch(_){} }
|
||||
}
|
||||
await ensureIce();
|
||||
// Ask for the microphone FIRST. On Android the screen capture must be the LAST
|
||||
// capture started, otherwise the mic permission prompt interrupts it and the share ends.
|
||||
let mic=null;
|
||||
try{ mic=await navigator.mediaDevices.getUserMedia({audio:true}); }catch(e){ mic=null; }
|
||||
setStatus('In the popup: choose your screen, then tap Share / Start.','on');
|
||||
try{ localStream=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:{ideal:30}},audio:false}); }
|
||||
catch(err){ if(mic){try{mic.getTracks().forEach(t=>t.stop());}catch(_){}} try{ws.send(JSON.stringify({type:'end-session',sessionId,reason:'share-cancelled'}));}catch(e){} setStatus('Screen share was cancelled. Refresh the page to try again.'); return; }
|
||||
if(mic){ window.__mic=mic; try{mic.getAudioTracks().forEach(t=>localStream.addTrack(t));}catch(_){} }
|
||||
indicator.classList.add('show'); setStatus('You are now sharing your screen with your agent.','on');
|
||||
{ const hl=document.getElementById('homeLink'); if(hl) hl.style.display='none'; }
|
||||
window.onbeforeunload=function(){ if((localStream||document.getElementById('sessionBar'))&&!sessionOver){ return 'Leaving or refreshing this page will end your screen sharing session.'; } };
|
||||
|
||||
Reference in New Issue
Block a user