UNPKG

@nethesis/phone-island

Version:
3 lines (2 loc) 28.2 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../node_modules/tslib/tslib.es6.js"),t=require("react");require("../node_modules/react-redux/es/index.js");var n=require("../node_modules/webrtc-adapter/src/js/adapter_core.js"),r=require("../lib/webrtc/janus.js"),o=require("../lib/webrtc/messages.js"),a=require("../store/index.js"),i=require("../lib/devices/devices.js"),c=require("../lib/phone/call.js"),l=require("../lib/webrtc/connection.js"),s=require("../static/outgoing_ringtone.js"),u=require("../utils/customHooks/useEventListener.js"),d=require("../utils/genericFunctions/eventDispatch.js"),g=require("../utils/genericFunctions/localStorage.js"),v=require("../lib/user/default_device.js"),p=require("../node_modules/react-redux/es/hooks/useDispatch.js");function f(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var m=f(t);exports.WebRTC=function(f){var S,w,b=f.hostName,h=f.sipExten,D=f.sipSecret,I=f.children,C=f.sipHost,A=f.sipPort,T=f.reload,R=f.uaType,y=f.reloadedCallback,k=p.useDispatch(),E=t.useRef(null),U=t.useRef(!1),j=t.useRef(Date.now()),G=t.useRef(!1),O=t.useRef(0),N=t.useRef(!1),J=t.useRef(null),P=t.useRef(!1),_=t.useRef(!1),L=t.useRef(null),W=t.useRef(null),M=t.useRef(r.default),V={},q=t.useCallback((function(e,t){var n,r,c,l;if(e)if("answer"!==e.type){if("offer"!==e.type)return console.warn("[SIP UPDATE] Unsupported JSEP type",{sourceEvent:t,type:e.type}),void o.handleRemote(e);var s=a.store.getState().webrtc.sipcall,u=a.store.getState().currentCall.isLocalVideoEnabled;if(s){var d=null!==(l=null===(c=null===(r=null===(n=null==s?void 0:s.webrtcStuff)||void 0===n?void 0:n.pc)||void 0===r?void 0:r.getTransceivers)||void 0===c?void 0:c.call(r))&&void 0!==l?l:[],g=d.some((function(e){var t,n;return"audio"===(null===(n=null===(t=e.sender)||void 0===t?void 0:t.track)||void 0===n?void 0:n.kind)}));d.some((function(e){var t,n;return"video"===(null===(n=null===(t=e.sender)||void 0===t?void 0:t.track)||void 0===n?void 0:n.kind)}));var v=[],p="string"==typeof e.sdp&&e.sdp.includes("m=audio "),f="string"==typeof e.sdp&&e.sdp.includes("m=video ");if(p&&!g){var m=i.getCurrentAudioInputDeviceId();v.push(m?{type:"audio",capture:{deviceId:{exact:m}},recv:!0}:{type:"audio",capture:!0,recv:!0})}if(f)if(u){var S=i.getCurrentVideoInputDeviceId();v.push(S?{type:"video",capture:{deviceId:{exact:S}},recv:!0}:{type:"video",capture:!0,recv:!0})}else v.push({type:"video",recv:!0});s.createAnswer({jsep:e,tracks:v,success:function(e){s.send({message:{request:"update"},jsep:e})},error:function(e){console.error("[SIP UPDATE] WebRTC error...",{sourceEvent:t,error:e})}})}}else o.handleRemote(e)}),[]),H=t.useCallback((function(){var t,r,i,l,u,p;if(_.current)console.log("[JANUS-GUARD] initWebRTC already in progress, skipping",{timestamp:(new Date).toISOString()});else{_.current=!0,L.current&&clearTimeout(L.current),L.current=setTimeout((function(){_.current&&(console.warn("[JANUS-GUARD] Initialization timeout (30s) - resetting isInitializing flag",{timestamp:(new Date).toISOString()}),_.current=!1,N.current=!0,k.alerts.setAlert("webrtc_down"),d.eventDispatch("phone-island-alert-set",{type:"webrtc_down"})),L.current=null}),3e4);var f=a.store.getState().webrtc,m=f.janusInstance,S=f.registered,w=f.isDetached,I=!0;if(m){var T=null===(t=m.getSessionId)||void 0===t?void 0:t.call(m),y=null===(r=m.isConnected)||void 0===r?void 0:r.call(m),E=O.current,j=Math.round(E/6e4),G=E>18e5,P=a.store.getState().webrtc,H=P.sipcall,x=!!P.jsepGlobal,z="connected"===(null===(l=null===(i=null==H?void 0:H.webrtcStuff)||void 0===i?void 0:i.pc)||void 0===l?void 0:l.iceConnectionState)||"completed"===(null===(p=null===(u=null==H?void 0:H.webrtcStuff)||void 0===u?void 0:u.pc)||void 0===p?void 0:p.iceConnectionState);if(!y||!S||w||G&&!(x||z)){var F=y?w?"phone island detached":S?G?"long inactivity (".concat(j," min) without active call"):"unknown":"not registered":"not connected";console.warn("[JANUS-GUARD] Session exists but is invalid, cleaning up and reinitializing",{reason:F,sessionId:T,isConnected:y,registered:S,isDetached:w,inactivityMinutes:j,hasIncomingCall:x,hasActiveCall:z,timestamp:(new Date).toISOString()});try{m.destroy({unload:!0,notifyDestroyed:!1,cleanupHandles:!0})}catch(e){console.error("[JANUS-GUARD] Error destroying session",e)}a.store.dispatch.webrtc.updateWebRTC({janusInstance:null,sipcall:null,registered:!1,isDetached:!1,jsepGlobal:null})}else console.log("[JANUS-GUARD] Valid session already exists, skipping init",{sessionId:T,isConnected:y,registered:S,isDetached:w,inactivityMinutes:j,hasIncomingCall:x,hasActiveCall:z,timestamp:(new Date).toISOString()}),I=!1}if(!I)return _.current=!1,void(L.current&&(clearTimeout(L.current),L.current=null));console.log("[JANUS-GUARD] Creating new session",{timestamp:(new Date).toISOString()}),M.current.init({debug:"all",dependencies:M.current.useDefaultDependencies({adapter:n.default}),callback:function(){var t,n=new M.current({server:"https://".concat(b,"/janus"),success:function(){n.attach&&n.attach({plugin:"janus.plugin.sip",opaqueId:"sebastian_"+(new Date).getTime(),success:function(e){e&&(k.webrtc.updateWebRTC({sipcall:e}),o.register({sipExten:h,sipSecret:D,sipHost:C,sipPort:A}),e&&M.current.log&&M.current.log("SIP plugin attached! ("+e.getPlugin()+", id = )"))},error:function(e){M.current.error&&(M.current.error(" -- Error attaching plugin..."),M.current.error(e)),_.current=!1,L.current&&(clearTimeout(L.current),L.current=null)},consentDialog:function(e){M.current.log&&M.current.log("janus consentDialog (on: ".concat(e,")"))},webrtcState:function(e){if(M.current.log&&M.current.log("Janus says our WebRTC PeerConnection is "+(e?"up":"down")+" now"),e){var t=a.store.getState().island.view,n=a.store.getState().currentCall,r=n.accepted,o=n.outgoing,i=n.incoming;(r||o||i)&&!t&&(console.warn('[WEBRTC] WebRTC up but view is null with active call - forcing view to "call"'),a.store.dispatch.island.setIslandView("call"))}},iceState:function(e){if(a.store.getState().webrtc.sipcall&&M.current.log&&M.current.log('ICE state of PeerConnection of handle has changed to "'.concat(e,'"')),"connected"===e||"completed"===e){var t=a.store.getState().island.view,n=a.store.getState().currentCall,r=n.accepted,o=n.outgoing,i=n.incoming;(r||o||i)&&!t&&(console.warn('[WEBRTC] ICE connected but view is null with active call - forcing view to "call"'),a.store.dispatch.island.setIslandView("call"))}},mediaState:function(e,t){M.current.log&&M.current.log("Janus "+(t?"started":"stopped")+" receiving our "+e)},slowLink:function(e,t){e?M.current.warn&&M.current.warn("SLOW link: several missing packets from janus (".concat(t,")")):M.current.warn&&M.current.warn("SLOW link: janus is not receiving all your packets (".concat(t,")"))},onmessage:function(e,t){var n=a.store.getState().webrtc.sipcall;M.current.debug&&(M.current.debug(" ::: Got a message :::"),M.current.debug(JSON.stringify(e)));var r=e.error;if(null==r||null==r){var i=e.result;if(null!=i&&void 0!==i.event&&null!==i.event){var l=i.event,u=a.store.getState().recorder.recording,g=a.store.getState().island.view;switch(l){case"registration_failed":M.current.error&&M.current.error("Registration failed: "+i.code+" "+i.reason);break;case"unregistered":M.current.log&&M.current.log("Successfully un-registered as "+i.username+"!"),a.store.dispatch.webrtc.updateWebRTC({registered:!1}),d.eventDispatch("phone-island-webrtc-unregistered",{});break;case"registered":M.current.log&&M.current.log("Successfully registered as "+i.username+"!"),console.log("[REGISTER] Registration successful",{username:i.username,wasAlreadyRegistered:a.store.getState().webrtc.registered,timestamp:(new Date).toISOString()}),d.eventDispatch("phone-island-webrtc-registered",{}),a.store.getState().webrtc.registered||a.store.dispatch.webrtc.updateWebRTC({registered:!0,isDetached:!1}),k.alerts.removeAlert("webrtc_down"),d.eventDispatch("phone-island-alert-removed",{type:"webrtc_down"}),N.current=!1,_.current=!1,L.current&&(clearTimeout(L.current),L.current=null),W.current&&(clearTimeout(W.current),W.current=null,console.info("[JANUS-GUARD] Cleared network error grace timeout - connection restored")),k.webrtc.updateLastActivity((new Date).getTime());break;case"registering":M.current.log&&M.current.log("janus registering");break;case"calling":k.currentCall.checkOutgoingUpdate({outgoingWebRTC:!0}),k.webrtc.updateLastActivity((new Date).getTime());break;case"ringing":a.store.getState().player.audioPlayerPlaying||k.player.updateStartAudioPlayer({src:s.default,loop:!0}),k.webrtc.updateLastActivity((new Date).getTime()),"call"!==g&&k.island.setIslandView("call");break;case"progress":M.current.log&&M.current.log("There's early media from "+i.username+", wairing for the call!"),t&&o.handleRemote(t),k.webrtc.updateLastActivity((new Date).getTime());break;case"incomingcall":var p=a.store.getState().currentUser.default_device,f=a.store.getState().currentUser,m=f.endpoints,S=f.username,w=a.store.getState().users.extensions,b=function(){if(!w||!S)return!1;var e=Object.values(w).filter((function(e){return(null==e?void 0:e.username)===S}));return null==e?void 0:e.some((function(e){var t=null==m?void 0:m.extension.find((function(t){return t.id===(null==e?void 0:e.exten)}));return"nethlink"===(null==t?void 0:t.type)&&"offline"!==(null==e?void 0:e.status)}))};t&&(console.log("[JSEP] Saving jsepGlobal for incoming call",{from:i.username,timestamp:(new Date).toISOString()}),k.webrtc.updateWebRTC({jsepGlobal:t}),J.current=Date.now()),("mobile"===R&&b()||"desktop"===R&&("webrtc"===(null==p?void 0:p.type)||void 0===(null==p?void 0:p.type)&&!b()||!b()&&"physical"===(null==p?void 0:p.type)))&&(u?k.recorder.setIncoming(!0):(k.currentCall.checkIncomingUpdatePlay({incoming:!0,incomingWebRTC:!0}),M.current.log&&(k.currentCall.updateIncoming(!0),M.current.log("Incoming call from "+i.username+"!"))),k.webrtc.updateLastActivity((new Date).getTime()));break;case"accepted":var h=Math.floor(Date.now()/1e3);if(M.current.log){var D=i.username||i.displayname||a.store.getState().currentCall.number||"Remote party";M.current.log(D+" accepted the call!")}t&&o.handleRemote(t),console.log("[JSEP] Clearing jsepGlobal after call accepted",{timestamp:(new Date).toISOString()}),k.webrtc.updateWebRTC({jsepGlobal:null}),J.current=null,k.currentCall.checkAcceptedUpdate({acceptedWebRTC:!0}),k.currentCall.updateCurrentCall({incoming:!1,incomingWebRTC:!1,startTime:null==h?void 0:h.toString()}),a.store.dispatch.player.stopAudioPlayer(),k.webrtc.updateLastActivity((new Date).getTime());break;case"updatingcall":M.current.log&&M.current.log("Got SIP re-INVITE, preparing update answer"),t&&q(t,"updatingcall"),k.webrtc.updateLastActivity((new Date).getTime());break;case"hangup":console.log("[JSEP] Clearing jsepGlobal on hangup",{timestamp:(new Date).toISOString()}),k.webrtc.updateWebRTC({jsepGlobal:null}),J.current=null,u&&k.recorder.setRecording(!1),v.isPhysical()||"mobile"===R||(c.hangupCurrentCall(),n.hangup(),a.store.dispatch.player.stopAudioPlayer(),a.store.dispatch.currentCall.reset(),M.current.log&&M.current.log("Call hung up ("+i.code+" "+i.reason+")!"),k.webrtc.updateLastActivity((new Date).getTime())),a.store.dispatch.player.stopAudioPlayer();var I=a.store.getState().screenShare,C=I.active,A=I.plugin,T=I.localScreenStream,y=I.remoteScreenStream;C&&(M.current.stopAllTracks(T),M.current.stopAllTracks(y),k.screenShare.update({active:!1}),A.detach()),N.current&&(console.info("[JANUS-GUARD] Call ended with stale connection - forcing reload to reset Janus session",{timestamp:(new Date).toISOString()}),setTimeout((function(){k.island.setForceReload(!0)}),500));break;case"gateway_down":console.warn("THE GATEWAY IS DOWN");break;case"info":"application/media_control+xml"===i.type&&i.content.includes("<picture_fast_update")&&n.send({message:{request:"keyframe",user:!0,peer:!0}});break;default:M.current.debug&&M.current.debug("Event not handled:",l)}}}else a.store.getState().webrtc.registered?(n&&n.hangup(),a.store.dispatch.player.stopAudioPlayer()):M.current.log&&M.current.log("User is not registered")},onlocaltrack:function(e,t){M.current.debug&&M.current.debug("Local track "+(t?"added":"removed")+":",e);var n=e.id.replace(/[{}]/g,"");if(!t){var r=V[n];if(r)try{var o=r.getTracks();for(var i in o){var c=o[i];c&&c.stop()}}catch(e){M.current.error&&M.current.error("Error removing track:",e)}return e.kind,void delete V[n]}var l=V[n];if(!l)if("audio"===e.kind)l=new MediaStream([e]),a.store.dispatch.webrtc.updateLocalAudioStream(l);else{l=new MediaStream([e]),a.store.dispatch.webrtc.updateLocalVideoStream(l),V[n]=l,M.current.debug&&M.current.debug("Created local stream:",l);var s=a.store.getState().player.localVideo;M.current.attachMediaStream&&s&&s.current&&M.current.attachMediaStream(s.current,l)}},onremotetrack:function(t,n,r){var o=this;if(M.current.debug&&M.current.debug("Remote track (mid="+n+") "+(r?"added":"removed")+":",t),a.store.dispatch.player.stopAudioPlayer(),!r)return t.kind,void k.currentCall.updateCurrentCall({showRemoteVideoPlaceHolder:!0});if("audio"===t.kind){var i=new MediaStream([t]);M.current.debug&&M.current.debug("Created remote audio stream: "+i);var c=a.store.getState().player.remoteAudio;if(c&&c.current&&M.current.attachMediaStream){M.current.attachMediaStream(c.current,i);var l=g.getJSONItem("phone-island-audio-output-device");if(null==l?void 0:l.deviceId){e.__awaiter(o,void 0,void 0,(function(){var t,n,r,o,a;return e.__generator(this,(function(e){switch(e.label){case 0:if(!(t=l.deviceId)||"default"===t)return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,navigator.mediaDevices.enumerateDevices()];case 2:return n=e.sent(),n.filter((function(e){return"audiooutput"===e.kind})).some((function(e){return e.deviceId===t}))||(console.warn("Saved audio device ".concat(t," no longer available, using default device")),t="default",g.setJSONItem("phone-island-audio-output-device",{deviceId:"default"})),[3,4];case 3:return r=e.sent(),console.warn("Error checking device availability, using default:",r),t="default",[3,4];case 4:if(!c.current)return console.warn("Remote audio element no longer available"),[2];e.label=5;case 5:return e.trys.push([5,7,,12]),[4,c.current.setSinkId(t)];case 6:return e.sent(),console.info("Audio output device applied successfully to new stream:",t),[3,12];case 7:if(o=e.sent(),console.warn("Failed to apply audio output device to new stream:",o),"default"===t||!c.current)return[3,11];e.label=8;case 8:return e.trys.push([8,10,,11]),[4,c.current.setSinkId("default")];case 9:return e.sent(),g.setJSONItem("phone-island-audio-output-device",{deviceId:"default"}),console.info("Fallback to default device successful"),[3,11];case 10:return a=e.sent(),console.error("Even default device failed:",a),[3,11];case 11:return[3,12];case 12:return[2]}}))}))}}a.store.dispatch.webrtc.updateRemoteAudioStream(i)}else{i=new MediaStream([t]);a.store.dispatch.webrtc.updateRemoteVideoStream(i),M.current.debug&&M.current.debug("Created remote video stream:"+i);var s=a.store.getState().player.largeRemoteVideo,u=a.store.getState().player.smallRemoteVideo;M.current.attachMediaStream&&s&&s.current&&M.current.attachMediaStream(s.current,i),M.current.attachMediaStream&&u&&u.current&&(M.current.attachMediaStream(u.current,i),k.currentCall.updateCurrentCall({showRemoteVideoPlaceHolder:!1}))}},oncleanup:function(){M.current.log&&M.current.log(" ::: janus Got a cleanup notification :::")}})},error:function(e){var t,n;M.current.log&&M.current.log("error",e),console.warn("[JANUS-GUARD] Network error detected, marking connection as stale",{error:e,timestamp:(new Date).toISOString()}),N.current=!0,_.current=!1,L.current&&(clearTimeout(L.current),L.current=null);var r=a.store.getState().webrtc.sipcall,o=a.store.getState().currentCall,i=o.accepted,c=o.outgoing,l=null===(n=null===(t=null==r?void 0:r.webrtcStuff)||void 0===t?void 0:t.pc)||void 0===n?void 0:n.iceConnectionState;i||c||"connected"===l||"completed"===l?(console.info("[JANUS-GUARD] Network error during active call - giving ICE grace period to recover",{iceState:l,accepted:i,outgoing:c,timestamp:(new Date).toISOString()}),W.current&&clearTimeout(W.current),W.current=setTimeout((function(){var e,t,n=a.store.getState().webrtc.sipcall,r=null===(t=null===(e=null==n?void 0:n.webrtcStuff)||void 0===e?void 0:e.pc)||void 0===t?void 0:t.iceConnectionState,o=a.store.getState().currentCall,i=o.accepted,c=o.outgoing,l=i||c;l&&("disconnected"===r||"failed"===r||!r)?(console.warn("[JANUS-GUARD] ICE failed to recover after grace period - resetting call state and activating alert",{checkIceState:r||"undefined/null",timestamp:(new Date).toISOString()}),a.store.dispatch.currentCall.reset(),k.alerts.setAlert("webrtc_down")):l?console.info("[JANUS-GUARD] ICE recovered during grace period - call preserved, Janus HTTP still stale",{checkIceState:r,connectionStale:N.current,timestamp:(new Date).toISOString()}):(console.info("[JANUS-GUARD] Call ended during grace period - activating alert for reconnection",{timestamp:(new Date).toISOString()}),k.alerts.setAlert("webrtc_down")),W.current=null}),15e3)):k.alerts.setAlert("webrtc_down")},destroyed:function(){console.log("[JANUS-GUARD] Session destroyed, clearing janusInstance",{timestamp:(new Date).toISOString()}),_.current=!1,L.current&&(clearTimeout(L.current),L.current=null),k.webrtc.updateWebRTC({destroyed:!0,janusInstance:null}),U.current?console.log("[JANUS-GUARD] Skipping alert activation (voluntary reload in progress)"):(console.log("[JANUS-GUARD] Activating webrtc_down alert (not a voluntary reload)"),k.alerts.setAlert("webrtc_down"))}});console.log("[JANUS-GUARD] Saving janusInstance to Redux",{sessionId:null===(t=n.getSessionId)||void 0===t?void 0:t.call(n),timestamp:(new Date).toISOString()}),k.webrtc.updateWebRTC({janusInstance:n})}})}}),[M.current]);t.useEffect((function(){void 0!==a.store.getState().currentUser.default_device&&i.checkMediaPermissions()}),[null===(w=null===(S=null===a.store||void 0===a.store?void 0:a.store.getState())||void 0===S?void 0:S.currentUser)||void 0===w?void 0:w.default_device]);var x=t.useState(navigator.onLine),z=x[0],F=x[1],B=t.useState(!1),Y=B[0],K=B[1],Q=t.useRef(!1);return t.useEffect((function(){var e=function(){return F(!0)},t=function(){return F(!1)};return window.addEventListener("online",e),window.addEventListener("offline",t),function(){window.removeEventListener("online",e),window.removeEventListener("offline",t)}}),[]),t.useEffect((function(){z?Q.current&&(console.log("Internet connection restored."),K(!0),Q.current=!1):(console.log("Internet connection lost."),Q.current=!0,K(!1))}),[z]),t.useEffect((function(){var e;return H(),e=a.store.getState().webrtc.CHECK_INTERVAL_TIME,E.current||(E.current=setInterval((function(){return l.webrtcCheck((function(){o.register({sipExten:h,sipSecret:D,sipHost:C,sipPort:A})}))}),e)),function(){o.unregister(),clearInterval(E.current),L.current&&(clearTimeout(L.current),L.current=null),W.current&&(clearTimeout(W.current),W.current=null)}}),[]),t.useEffect((function(){var e,t,n,r,i;if(T||Y){var c=a.store.getState().alerts.data,l=a.store.getState().island.forceReload,s=a.store.getState().webrtc,u=s.sipcall,d=s.janusInstance,g=a.store.getState().currentCall,v=g.accepted,p=g.outgoing,f=null===(t=null===(e=null==u?void 0:u.webrtcStuff)||void 0===e?void 0:e.pc)||void 0===t?void 0:t.iceConnectionState,m=v||p||"connected"===f||"completed"===f,S=(null===(n=c.webrtc_down)||void 0===n?void 0:n.active)||!1;if(Y&&m&&!l){var w=null===(r=null==d?void 0:d.isConnected)||void 0===r?void 0:r.call(d);return!w&&(null==d?void 0:d.reconnect)?(console.info("[JANUS-GUARD] Connection returned with active call but Janus HTTP is dead - attempting Janus reconnect",{iceState:f,sessionId:null===(i=null==d?void 0:d.getSessionId)||void 0===i?void 0:i.call(d),timestamp:(new Date).toISOString()}),d.reconnect({success:function(){var e;console.info("[JANUS-GUARD] Janus HTTP reconnected successfully during active call (connectionReturned)",{sessionId:null===(e=null==d?void 0:d.getSessionId)||void 0===e?void 0:e.call(d),timestamp:(new Date).toISOString()}),N.current=!1,W.current&&(clearTimeout(W.current),W.current=null)},error:function(e){console.error("[JANUS-GUARD] Janus reconnect failed during active call (connectionReturned)",{error:e,timestamp:(new Date).toISOString()}),N.current=!0}})):console.info("[JANUS-GUARD] Connection returned but active call in progress - Janus still connected, no action needed",{iceState:f,janusConnected:w,timestamp:(new Date).toISOString()}),void K(!1)}if(S||l||Y){if(U.current||_.current)return void console.log("[JANUS-GUARD] Reload or init already in progress, skipping",{isReloading:U.current,isInitializing:_.current});U.current=!0,L.current&&(clearTimeout(L.current),L.current=null),console.info(l?"Force reload requested, performing full WebRTC reconnection":Y?"Internet connection restored, performing full WebRTC reconnection":"WebRTC down detected (alert active), performing full reload"),l&&a.store.dispatch.island.setForceReload(!1),console.log("[JANUS-GUARD] Manual reload, clearing janusInstance and registered state",{timestamp:(new Date).toISOString()}),k.webrtc.updateWebRTC({janusInstance:null,sipcall:null,registered:!1,isDetached:!1,jsepGlobal:null}),J.current=null,o.unregister(),u&&u.detach(),d&&d.destroy&&d.destroy({unload:!0,notifyDestroyed:!1,cleanupHandles:!0}),setTimeout((function(){H(),Y&&K(!1),y&&y(),setTimeout((function(){U.current=!1,N.current=!1,P.current=!1,O.current=0}),1e3)}),100)}else console.info("WebRTC already connected (no alert active), skipping heavy reload"),y&&y()}}),[T,Y]),t.useEffect((function(){var e,t=function(){var e;navigator&&(null===navigator||void 0===navigator?void 0:navigator.mediaDevices)&&(null===(e=null===navigator||void 0===navigator?void 0:navigator.mediaDevices)||void 0===e?void 0:e.enumerateDevices)?null===navigator||void 0===navigator||navigator.mediaDevices.enumerateDevices().then((function(e){k.mediaDevices.updateMediaDevices(e)})).catch((function(e){console.error("Error fetching devices:",e)})):(console.warn("MediaDevices API not supported in this browser or context"),k.mediaDevices.updateMediaDevices([]))};if(t(),navigator&&(null===navigator||void 0===navigator?void 0:navigator.mediaDevices))return null===(e=null===navigator||void 0===navigator?void 0:navigator.mediaDevices)||void 0===e||e.addEventListener("devicechange",t),function(){var e;null===(e=null===navigator||void 0===navigator?void 0:navigator.mediaDevices)||void 0===e||e.removeEventListener("devicechange",t)}}),[]),t.useEffect((function(){var e=function(){console.warn("[STANDBY-GUARD] Page frozen (standby or browser froze tab)",{timestamp:(new Date).toISOString()}),P.current=!0},t=function(){console.log("[STANDBY-GUARD] Page resumed from freeze",{timestamp:(new Date).toISOString()})};return document.addEventListener("freeze",e),document.addEventListener("resume",t),function(){document.removeEventListener("freeze",e),document.removeEventListener("resume",t)}}),[]),t.useEffect((function(){var e=function(){var e,t,n,r,i=Date.now();if(document.hidden)G.current=!0,j.current=i,console.log("[STANDBY-GUARD] Tab going to background",{timestamp:(new Date).toISOString()});else if(G.current){var c=i-j.current;O.current=c,console.log("[STANDBY-GUARD] Tab returning to foreground",{timeHiddenMs:c,timeHiddenMinutes:Math.round(c/6e4),wasFrozen:P.current,timestamp:(new Date).toISOString()});var l=a.store.getState().webrtc,s=l.registered,u=l.jsepGlobal,d=l.sipcall,g=a.store.getState().currentCall.outgoing,v=!!u,p="connected"===(null===(t=null===(e=null==d?void 0:d.webrtcStuff)||void 0===e?void 0:e.pc)||void 0===t?void 0:t.iceConnectionState)||"completed"===(null===(r=null===(n=null==d?void 0:d.webrtcStuff)||void 0===n?void 0:n.pc)||void 0===r?void 0:r.iceConnectionState),f=v||p||g,m=c>18e4&&!f,S=c>18e5&&!f,w=P.current||N.current||m||S;if(w){var b=P.current?"frozen":N.current?"stale connection":S?"throttled >30min (session too old)":"throttled >3min";if(f){var h=p?"active call":g?"outgoing call":"incoming call";console.warn("[STANDBY-GUARD] Reload needed (".concat(b,") but ").concat(h," in progress. ")+"Skipping reload to preserve call.",{wasFrozen:P.current,connectionStale:N.current,wasThrottledShort:m,wasThrottledVeryLong:S,hasIncomingCall:v,hasOutgoingCall:g,hasActiveCall:p,timestamp:(new Date).toISOString()})}else console.warn("[STANDBY-GUARD] Reload needed (".concat(b,"), forcing reload"),{wasFrozen:P.current,connectionStale:N.current,wasThrottledShort:m,wasThrottledVeryLong:S,timestamp:(new Date).toISOString()})}else if(f){h=p?"active call":g?"outgoing call":"incoming call";console.log("[STANDBY-GUARD] Tab change without issues, ".concat(h," preserved"),{timeHiddenMinutes:Math.round(c/6e4),hasIncomingCall:v,hasOutgoingCall:g,hasActiveCall:p,timestamp:(new Date).toISOString()})}var D=s&&!U.current&&!_.current&&w&&!v&&!g;if(D){console.warn("[STANDBY-GUARD] ⚠️ Reloading WebRTC",{timestamp:(new Date).toISOString()}),U.current=!0,L.current&&(clearTimeout(L.current),L.current=null);var I=a.store.getState().webrtc,C=I.janusInstance,A=I.sipcall;o.unregister(),A&&A.detach(),C&&C.destroy&&C.destroy({unload:!0,notifyDestroyed:!1,cleanupHandles:!0}),k.webrtc.updateWebRTC({janusInstance:null,sipcall:null,registered:!1,isDetached:!1,jsepGlobal:null}),J.current=null,setTimeout((function(){H(),setTimeout((function(){U.current=!1,N.current=!1,P.current=!1,O.current=0}),1e3)}),100)}G.current=!1,D||(P.current=!1,O.current=0)}};return document.addEventListener("visibilitychange",e),function(){document.removeEventListener("visibilitychange",e)}}),[H,k]),u.useEventListener("phone-island-attach",(function(e){console.log("[EVENT] phone-island-attach received, calling initWebRTC",{timestamp:(new Date).toISOString()}),H(),d.eventDispatch("phone-island-attached",{})})),u.useEventListener("phone-island-socket-reconnected",(function(){var e,t,n,r,o=a.store.getState().webrtc,i=o.sipcall,c=o.janusInstance,l=a.store.getState().currentCall,s=l.accepted,u=l.outgoing,d=null===(t=null===(e=null==i?void 0:i.webrtcStuff)||void 0===e?void 0:e.pc)||void 0===t?void 0:t.iceConnectionState,g=s||u||"connected"===d||"completed"===d,v=null===(n=null==c?void 0:c.isConnected)||void 0===n?void 0:n.call(c);return console.log("[EVENT] phone-island-socket-reconnected received",{hasActiveCall:g,iceState:d,accepted:s,outgoing:u,janusConnected:v,timestamp:(new Date).toISOString()}),g&&!v&&(null==c?void 0:c.reconnect)?(console.info("[EVENT] Socket reconnected with active call but Janus HTTP is dead - attempting Janus reconnect",{iceState:d,sessionId:null===(r=null==c?void 0:c.getSessionId)||void 0===r?void 0:r.call(c),timestamp:(new Date).toISOString()}),void c.reconnect({success:function(){var e;console.info("[JANUS-GUARD] Janus HTTP reconnected successfully during active call",{sessionId:null===(e=null==c?void 0:c.getSessionId)||void 0===e?void 0:e.call(c),timestamp:(new Date).toISOString()}),N.current=!1,W.current&&(clearTimeout(W.current),W.current=null)},error:function(e){console.error("[JANUS-GUARD] Janus reconnect failed during active call",{error:e,timestamp:(new Date).toISOString()}),N.current=!0}})):g&&v?(console.info("[EVENT] Socket reconnected with active call, Janus HTTP still connected - no action needed",{iceState:d,timestamp:(new Date).toISOString()}),void(W.current&&(clearTimeout(W.current),W.current=null))):(a.store.getState().webrtc.jsepGlobal&&(console.log("[EVENT] Clearing stale jsepGlobal after socket reconnect",{timestamp:(new Date).toISOString()}),k.webrtc.updateWebRTC({jsepGlobal:null}),J.current=null),void K(!0))})),u.useEventListener("phone-island-call-transfer",(function(t){var n=null==t?void 0:t.to;k.island.toggleIsOpen(!0),function(t){e.__awaiter(this,void 0,void 0,(function(){return e.__generator(this,(function(e){switch(e.label){case 0:return[4,c.attendedTransfer(t)];case 1:return e.sent()&&(k.currentCall.updateCurrentCall({transferring:!0,paused:!1}),k.player.playRemoteAudio()),[2]}}))}))}(n),d.eventDispatch("phone-island-call-transfer-opened",{})})),m.default.createElement(m.default.Fragment,null,I)}; //# sourceMappingURL=WebRTC.js.map