|
|
@@ -79,7 +79,7 @@ let ICE={iceServers:[{urls:'stun:stun.l.google.com:19302'}]};
|
|
79
|
79
|
let SHARER_NAME='Customer';
|
|
80
|
80
|
try{fetch('/api/me').then(r=>r.ok?r.json():null).then(m=>{if(m&&(m.name||m.email))SHARER_NAME=m.name||m.email;}).catch(()=>{});}catch(_){}
|
|
81
|
81
|
const IS_MOBILE=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile/i.test(navigator.userAgent||'');
|
|
82
|
|
-let __icePromise=Promise.resolve();try{__icePromise=fetch('/api/ice').then(r=>r.ok?r.json():null).then(c=>{if(c&&c.iceServers&&IS_MOBILE)ICE=c;}).catch(()=>{});}catch(_){}
|
|
|
82
|
+let __icePromise=Promise.resolve();try{__icePromise=fetch('/api/ice').then(r=>r.ok?r.json():null).then(c=>{if(c&&c.iceServers)ICE=c;}).catch(()=>{});}catch(_){}
|
|
83
|
83
|
async function ensureIce(){try{await __icePromise;}catch(_){}return ICE;}
|
|
84
|
84
|
function pEsc(s){return String(s==null?'':s).replace(/[&<>"]/g,c=>({'&':'&','<':'<','>':'>','"':'"'}[c]));}
|
|
85
|
85
|
// When embedded in the home shell, tell the parent when a session is live so the
|
|
|
@@ -168,11 +168,15 @@ async function startStreaming(){
|
|
168
|
168
|
pc.ondatachannel=(ev)=>{ev.channel.onmessage=()=>{};};
|
|
169
|
169
|
pc.ontrack=(ev)=>{ if(ev.track.kind==='audio'){ let a=document.getElementById('remoteAudio'); if(!a){a=document.createElement('audio');a.id='remoteAudio';a.autoplay=true;document.body.appendChild(a);} a.srcObject=ev.streams[0]; } };
|
|
170
|
170
|
pc.onicecandidate=(ev)=>{if(ev.candidate)ws.send(JSON.stringify({type:'ice-candidate',sessionId,candidate:ev.candidate}));};
|
|
171
|
|
- pc.onconnectionstatechange=()=>{ if(pc&&pc.connectionState==='failed'){ try{ws.send(JSON.stringify({type:'end-session',sessionId,reason:'customer-ended'}));}catch(_){} endShareSession('The connection was lost. Tap below for a new code if you still need help.'); } };
|
|
|
171
|
+ pc.onconnectionstatechange=()=>{ if(!pc) return; if(pc.connectionState==='connected'){ clearTimeout(window.__connWatch); } if(pc.connectionState==='failed'){ clearTimeout(window.__connWatch); try{ws.send(JSON.stringify({type:'end-session',sessionId,reason:'customer-ended'}));}catch(_){} endShareSession("Couldn't connect on this network — it may be blocking screen sharing. Try a different network (e.g. mobile data / hotspot), then tap below for a new code."); } };
|
|
172
|
172
|
chatChannel=pc.createDataChannel('chat',{ordered:true});
|
|
173
|
173
|
chatChannel.onmessage=(e)=>{try{addChat(JSON.parse(e.data));}catch(_){}};
|
|
174
|
174
|
const offer=await pc.createOffer(); await pc.setLocalDescription(offer);
|
|
175
|
175
|
ws.send(JSON.stringify({type:'offer',sessionId,sdp:pc.localDescription}));
|
|
|
176
|
+ // Watchdog: if we can't establish the peer connection in time, show a clear reason
|
|
|
177
|
+ // instead of a blank screen (covers networks with no usable path even via TURN).
|
|
|
178
|
+ clearTimeout(window.__connWatch);
|
|
|
179
|
+ window.__connWatch=setTimeout(()=>{ if(pc && pc.connectionState!=='connected' && !sessionOver){ try{ws.send(JSON.stringify({type:'end-session',sessionId,reason:'customer-ended'}));}catch(_){} endShareSession("Couldn't connect on this network — it may be blocking screen sharing. Try a different network (e.g. mobile data / hotspot), then tap below for a new code."); } }, 20000);
|
|
176
|
180
|
localStream.getVideoTracks()[0].onended=()=>{ws.send(JSON.stringify({type:'end-session',sessionId,reason:'customer-ended'}));teardown();};
|
|
177
|
181
|
}
|
|
178
|
182
|
const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
|