@nethesis/phone-island 1.0.8-dev.9 → 1.0.9-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/_virtual/index6.js +1 -1
  2. package/dist/_virtual/index8.js +1 -1
  3. package/dist/components/SideView/hooks/useSideViewLogic.js +1 -1
  4. package/dist/components/SideView/hooks/useSideViewLogic.js.map +1 -1
  5. package/dist/components/VideoView/index.js +1 -1
  6. package/dist/components/VideoView/index.js.map +1 -1
  7. package/dist/components/WebRTC.js +1 -1
  8. package/dist/components/WebRTC.js.map +1 -1
  9. package/dist/lib/devices/devices.js +1 -1
  10. package/dist/lib/phone/call.js +1 -1
  11. package/dist/lib/phone/call.js.map +1 -1
  12. package/dist/node_modules/@fortawesome/fontawesome-svg-core/index.mjs.js +7 -1
  13. package/dist/node_modules/@fortawesome/fontawesome-svg-core/index.mjs.js.map +1 -1
  14. package/dist/node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js +1 -1
  15. package/dist/node_modules/@fortawesome/free-solid-svg-icons/index.mjs.js.map +1 -1
  16. package/dist/node_modules/@fortawesome/react-fontawesome/index.es.js +1 -1
  17. package/dist/node_modules/@fortawesome/react-fontawesome/index.es.js.map +1 -1
  18. package/dist/node_modules/mic-check/lib/index.js +1 -1
  19. package/dist/node_modules/prop-types/index.js +1 -1
  20. package/dist/node_modules/prop-types/node_modules/react-is/index.js +1 -1
  21. package/dist/node_modules/webrtc-adapter/src/js/adapter_factory.js +1 -1
  22. package/dist/node_modules/webrtc-adapter/src/js/adapter_factory.js.map +1 -1
  23. package/dist/node_modules/webrtc-adapter/src/js/chrome/chrome_shim.js +1 -1
  24. package/dist/node_modules/webrtc-adapter/src/js/chrome/chrome_shim.js.map +1 -1
  25. package/dist/node_modules/webrtc-adapter/src/js/common_shim.js +1 -1
  26. package/dist/node_modules/webrtc-adapter/src/js/common_shim.js.map +1 -1
  27. package/dist/node_modules/webrtc-adapter/src/js/firefox/firefox_shim.js +1 -1
  28. package/dist/node_modules/webrtc-adapter/src/js/firefox/firefox_shim.js.map +1 -1
  29. package/dist/node_modules/webrtc-adapter/src/js/utils.js +1 -1
  30. package/dist/node_modules/webrtc-adapter/src/js/utils.js.map +1 -1
  31. package/dist/package.json.js +1 -1
  32. package/package.json +5 -6
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/components/VideoView/index.tsx"],"sourcesContent":["// Copyright (C) 2025 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { type FC, useEffect, useRef, useState } from 'react'\nimport { Button } from '../Button'\nimport { useDispatch, useSelector } from 'react-redux'\nimport { Dispatch, RootState, store } from '../../store'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport {\n faCompress,\n faDisplay,\n faExpand,\n faMicrophone,\n faMicrophoneSlash,\n faPause,\n faPlay,\n faStop,\n faVideo,\n faVideoSlash,\n} from '@fortawesome/free-solid-svg-icons'\nimport { t } from 'i18next'\nimport { eventDispatch, useEventListener, useIsomorphicLayoutEffect } from '../../utils'\nimport Hangup from '../Hangup'\nimport {\n muteCurrentCall,\n pauseCurrentCall,\n recordCurrentCall,\n unmuteCurrentCall,\n unpauseCurrentCall,\n} from '../../lib/phone/call'\nimport { JanusTrack, JanusTypes } from '../../types/webrtc'\nimport JanusLib from '../../lib/webrtc/janus.js'\nimport Avatar from '../CallView/Avatar'\nimport Timer from '../CallView/Timer'\nimport { isPhysical } from '../../lib/user/default_device'\nimport { AudioBars } from '../AudioBars'\nimport { CustomThemedTooltip } from '../CustomThemedTooltip'\nimport { faDisplaySlash, faRecord } from '@nethesis/nethesis-solid-svg-icons'\nimport { getCurrentVideoInputDeviceId } from '../../lib/devices/devices'\nimport { getInitials } from '../../lib/avatars/avatars'\nimport { checkWebCamPermission } from '../../lib/devices/devices'\nimport { dispatchVideoCallStarted } from '../../events/SocketEvents'\n\nexport interface VideoViewProps {}\n\nexport type ScreenSharingMessage = {\n message: 'screenSharingStart' | 'screenSharingStop'\n roomId: string\n destUser: string\n callUser: string\n}\n\nexport type VideoCallMessage = {\n message: 'videoCallStart'\n destUser: string\n callUser: string\n}\n\nexport const VideoView: FC<VideoViewProps> = () => {\n const dispatch = useDispatch<Dispatch>()\n const {\n muted,\n startTime,\n isRecording,\n paused,\n isLocalVideoEnabled,\n showRemoteVideoPlaceHolder,\n hasVideoTrackAdded,\n displayName,\n isStartingVideoCall,\n } = useSelector((state: RootState) => state.currentCall)\n const {\n localTracks,\n localVideos,\n role: screenShareRole,\n active: screenShareActive,\n isStartingScreenShare,\n isJoiningScreenShare,\n isLeavingScreenShare,\n } = useSelector((state: RootState) => state.screenShare)\n const intrudeListenStatus = useSelector((state: RootState) => state.listen)\n const { isOpen } = useSelector((state: RootState) => state.island)\n const { janusInstance, remoteAudioStream } = useSelector((state: RootState) => state.webrtc)\n const userInfo = store.getState().currentUser\n const [isFullscreen, setIsFullscreen] = useState(false)\n const [isUiShown, setUiShown] = useState(false)\n const uiTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const debounceTimerRef = useRef<NodeJS.Timeout | null>(null)\n const videoRenegotiationInFlightRef = useRef(false)\n const screenSharePublisherJoinRequestedRef = useRef(false)\n const screenShareViewRef = useRef(null)\n const localScreen = useRef<HTMLVideoElement>(null)\n const remoteScreen = useRef<HTMLVideoElement>(null)\n const localVideo = useRef<HTMLVideoElement>(null)\n const largeRemoteVideo = useRef<HTMLVideoElement>(null)\n const smallRemoteVideo = useRef<HTMLVideoElement>(null)\n const janus = useRef<JanusTypes>(JanusLib)\n const videoInputDevices = store.select.mediaDevices.videoInputDevices(store.getState())\n\n const notifyPeerVideoStart = () => {\n const { socket } = store.getState().websocket\n const { username: destUser } = store.getState().currentCall\n const { username: callUser } = store.getState().currentUser\n\n if (!socket || !destUser || !callUser) {\n return\n }\n\n socket.emit('message', {\n message: 'videoCallStart',\n destUser,\n callUser,\n } as VideoCallMessage)\n }\n\n useIsomorphicLayoutEffect(() => {\n dispatch.player.updatePlayer({\n localScreen: localScreen,\n remoteScreen: remoteScreen,\n localVideo: localVideo,\n largeRemoteVideo: largeRemoteVideo,\n smallRemoteVideo: smallRemoteVideo,\n })\n }, [])\n\n // component did mount\n useEffect(() => {\n updateScreenStreams()\n updateVideoStreams()\n\n // register for full screen change\n addEventListener('fullscreenchange', handleFullscreenChange)\n\n return () => {\n removeEventListener('fullscreenchange', handleFullscreenChange)\n\n // clear timeout\n if (uiTimeoutRef.current) {\n clearTimeout(uiTimeoutRef.current)\n }\n }\n }, [])\n\n // starting videocall\n useEffect(() => {\n if (isStartingVideoCall) {\n enableVideo()\n dispatch.currentCall.updateCurrentCall({\n isStartingVideoCall: false,\n })\n }\n }, [isStartingVideoCall])\n\n // starting screen sharing\n useEffect(() => {\n if (isStartingScreenShare) {\n initAndStartScreenShare()\n store.dispatch.screenShare.update({\n isStartingScreenShare: false,\n })\n }\n }, [isStartingScreenShare])\n\n // joining screen sharing\n useEffect(() => {\n if (isJoiningScreenShare) {\n initAndJoinScreenShare()\n store.dispatch.screenShare.update({\n isJoiningScreenShare: false,\n })\n }\n }, [isJoiningScreenShare])\n\n // leaving screen sharing\n useEffect(() => {\n if (isLeavingScreenShare) {\n leaveScreenShare()\n store.dispatch.screenShare.update({\n isLeavingScreenShare: false,\n })\n }\n }, [isLeavingScreenShare])\n\n // isOpen changed\n useEffect(() => {\n updateScreenStreams()\n updateVideoStreams()\n }, [isOpen])\n\n const updateVideoStreams = () => {\n const localVideoElement = store.getState().player.localVideo\n const largeRemoteVideoElement = store.getState().player.largeRemoteVideo\n const smallRemoteVideoElement = store.getState().player.smallRemoteVideo\n const { localVideoStream, remoteVideoStream } = store.getState().webrtc\n\n // local video stream\n\n if (localVideoElement?.current) {\n if (janus.current.attachMediaStream) {\n janus.current.attachMediaStream(localVideoElement.current, localVideoStream as MediaStream)\n }\n }\n\n // large remote video stream\n\n if (largeRemoteVideoElement?.current && janus.current.attachMediaStream) {\n janus.current.attachMediaStream(\n largeRemoteVideoElement.current,\n remoteVideoStream as MediaStream,\n )\n }\n\n // small remote video stream\n\n if (smallRemoteVideoElement?.current && janus.current.attachMediaStream) {\n janus.current.attachMediaStream(\n smallRemoteVideoElement.current,\n remoteVideoStream as MediaStream,\n )\n }\n\n if (remoteVideoStream instanceof MediaStream && remoteVideoStream.getVideoTracks().length > 0) {\n dispatch.currentCall.updateCurrentCall({\n showRemoteVideoPlaceHolder: false,\n })\n }\n }\n\n const handleFullscreenChange = () => {\n setIsFullscreen(!!document.fullscreenElement)\n }\n\n const toggleFullScreen = () => {\n if (document.fullscreenElement) {\n document.exitFullscreen()\n eventDispatch('phone-island-fullscreen-exited', {})\n } else {\n if (screenShareViewRef.current) {\n ;(screenShareViewRef.current as HTMLElement).requestFullscreen()\n eventDispatch('phone-island-fullscreen-entered', {})\n }\n }\n }\n useEventListener('phone-island-fullscreen-enter', () => {\n toggleFullScreen()\n })\n useEventListener('phone-island-fullscreen-exit', () => {\n toggleFullScreen()\n })\n\n const newRemoteFeed = (id, display) => {\n // A new feed has been published, create a new plugin handle and attach to it as a listener\n\n dispatch.screenShare.update({\n source: id,\n })\n\n let remoteFeed: any = null\n janusInstance?.attach({\n plugin: 'janus.plugin.videoroom',\n opaqueId: janus.current.randomString(32),\n success: function (pluginHandle) {\n remoteFeed = pluginHandle\n\n dispatch.screenShare.update({\n remoteFeed: pluginHandle,\n })\n remoteFeed.remoteTracks = {}\n remoteFeed.remoteVideos = 0\n janus.current.log?.(\n 'Plugin attached! (' + remoteFeed.getPlugin() + ', id=' + remoteFeed.getId() + ')',\n )\n janus.current.log?.(' -- This is a subscriber')\n // We wait for the plugin to send us an offer\n const { room } = store.getState().screenShare\n\n let listen = {\n request: 'join',\n room: room,\n ptype: 'subscriber',\n feed: id,\n }\n remoteFeed.send({ message: listen })\n },\n error: function (error) {\n janus.current.error?.('Error attaching videoroom plugin', error)\n },\n iceState: function (state) {\n janus.current.log?.('ICE state (feed #' + remoteFeed.rfindex + ') changed to ' + state)\n },\n webrtcState: function (on) {\n janus.current.log?.(\n 'Janus says this WebRTC PeerConnection (feed #' +\n remoteFeed.rfindex +\n ') is ' +\n (on ? 'up' : 'down') +\n ' now',\n )\n },\n slowLink: function (uplink, lost, mid) {\n janus.current.warn?.(\n 'Janus reports problems ' +\n (uplink ? 'sending' : 'receiving') +\n ' packets on mid ' +\n mid +\n ' (' +\n lost +\n ' lost packets)',\n )\n },\n onmessage: function (msg, jsep) {\n janus.current.debug?.(' ::: Got a message (listener) :::', msg)\n let event = msg['videoroom']\n janus.current.debug?.('Event: ' + event)\n if (event) {\n if (event === 'attached') {\n // Subscriber created and attached\n janus.current.log?.(\n 'Successfully attached to feed ' + id + ' (' + display + ') in room ' + msg['room'],\n )\n } else {\n janus.current.warn?.('Unhandled event: ' + event)\n }\n }\n if (jsep) {\n janus.current.debug?.('Handling SDP as well...', jsep)\n // Answer and attach\n remoteFeed.createAnswer({\n jsep: jsep,\n // We only specify data channels here, as this way in\n // case they were offered we'll enable them. Since we\n // don't mention audio or video tracks, we autoaccept them\n // as recvonly (since we won't capture anything ourselves)\n tracks: [{ type: 'data' }],\n success: function (jsep) {\n janus.current.debug?.('Got SDP!', jsep)\n\n const { room } = store.getState().screenShare\n\n let body = { request: 'start', room: room }\n remoteFeed.send({ message: body, jsep: jsep })\n },\n error: function (error) {\n janus.current.error?.('WebRTC error:', error)\n },\n })\n }\n },\n // eslint-disable-next-line no-unused-vars\n onlocaltrack: function (track, on) {\n // The subscriber stream is recvonly, we don't expect anything here\n },\n onremotetrack: function (track, mid, on, metadata) {\n janus.current.debug?.(\n 'Remote track (mid=' +\n mid +\n ') ' +\n (on ? 'added' : 'removed') +\n (metadata ? ' (' + metadata.reason + ') ' : '') +\n ':',\n track,\n )\n // Screen sharing tracks are sometimes muted/unmuted by browser\n // when data is not flowing fast enough; this can make streams blink.\n // We can ignore these.\n if (\n track.kind === 'video' &&\n metadata &&\n (metadata.reason === 'mute' || metadata.reason === 'unmute')\n ) {\n janus.current.log?.('Ignoring mute/unmute on screen-sharing track.')\n return\n }\n if (!on) {\n const { remoteScreenStream } = store.getState().screenShare\n janus.current.stopAllTracks(remoteScreenStream)\n dispatch.screenShare.update({ active: false })\n return\n }\n // If we're here, a new track was added\n if (track.kind === 'video') {\n // New video track: create a stream out of it\n let stream = new MediaStream([track])\n\n // Save the new video stream to the store\n store.dispatch.screenShare.update({ remoteScreenStream: stream })\n\n remoteFeed.remoteTracks[mid] = stream\n janus.current.log?.('Created remote video stream: ' + stream)\n const remoteScreenElement = store.getState().player.remoteScreen\n\n if (remoteScreenElement?.current) {\n janus.current.attachMediaStream?.(remoteScreenElement.current, stream)\n }\n }\n },\n oncleanup: function () {\n janus.current.log?.(' ::: Got a cleanup notification (remote feed ' + id + ') :::')\n remoteFeed.remoteTracks = {}\n remoteFeed.remoteVideos = 0\n },\n })\n }\n\n const enableVideo = () => {\n if (videoRenegotiationInFlightRef.current) {\n return\n }\n\n const { sipcall }: { sipcall: any } = store.getState().webrtc\n videoRenegotiationInFlightRef.current = true\n store.dispatch.currentCall.updateCurrentCall({\n isLocalVideoEnabled: true,\n })\n const tracks: JanusTrack[] = []\n const currentVideoInputDeviceId = getCurrentVideoInputDeviceId()\n\n const track: Partial<JanusTrack> = {\n type: 'video',\n recv: true,\n }\n\n if (currentVideoInputDeviceId) {\n track.capture = { deviceId: { exact: currentVideoInputDeviceId } }\n } else {\n track.capture = true\n }\n\n const { hasVideoTrackAdded } = store.getState().currentCall\n const { remoteVideoStream } = store.getState().webrtc\n const videoTransceiver = sipcall?.webrtcStuff?.pc\n ?.getTransceivers?.()\n ?.find(\n (transceiver: RTCRtpTransceiver) =>\n transceiver.receiver?.track?.kind === 'video' ||\n transceiver.sender?.track?.kind === 'video',\n )\n const shouldReplaceExistingVideoTransceiver =\n hasVideoTrackAdded ||\n Boolean(videoTransceiver) ||\n (remoteVideoStream instanceof MediaStream && remoteVideoStream.getVideoTracks().length > 0)\n\n if (!shouldReplaceExistingVideoTransceiver) {\n track.add = true\n dispatch.currentCall.setVideoTrackAdded(true)\n } else {\n // Reuse the existing video transceiver when available instead of assuming a\n // fixed mid, otherwise fall back to adding a new local video track.\n if (videoTransceiver) {\n track.replace = true\n if (videoTransceiver.mid) {\n track.mid = videoTransceiver.mid\n }\n if (!hasVideoTrackAdded) {\n dispatch.currentCall.setVideoTrackAdded(true)\n }\n } else {\n track.add = true\n dispatch.currentCall.setVideoTrackAdded(true)\n }\n }\n tracks.push(track as JanusTrack)\n\n sipcall.createOffer({\n tracks: tracks,\n success: function (jsep) {\n videoRenegotiationInFlightRef.current = false\n sipcall.send({ message: { request: 'update' }, jsep: jsep })\n notifyPeerVideoStart()\n dispatchVideoCallStarted({\n initiator: 'local',\n callUser: store.getState().currentUser.username,\n destUser: store.getState().currentCall.username,\n })\n eventDispatch('phone-island-video-enabled', {})\n },\n error: function (error) {\n videoRenegotiationInFlightRef.current = false\n console.error('WebRTC error... ' + JSON.stringify(error))\n },\n })\n }\n useEventListener('phone-island-video-enable', () => {\n enableVideo()\n })\n\n const disableVideo = () => {\n if (videoRenegotiationInFlightRef.current) {\n return\n }\n\n const { sipcall, localVideoStream }: { sipcall: any; localVideoStream: MediaStream | null } =\n store.getState().webrtc\n videoRenegotiationInFlightRef.current = true\n const videoTransceiver = sipcall?.webrtcStuff?.pc\n ?.getTransceivers?.()\n ?.find(\n (transceiver: RTCRtpTransceiver) =>\n transceiver.receiver?.track?.kind === 'video' ||\n transceiver.sender?.track?.kind === 'video',\n )\n\n janus.current.stopAllTracks(localVideoStream)\n store.dispatch.webrtc.updateLocalVideoStream(null)\n store.dispatch.currentCall.setLocalVideoEnabled(false)\n const tracks: JanusTrack[] = []\n tracks.push({\n type: 'video',\n ...(videoTransceiver?.mid ? { mid: videoTransceiver.mid } : {}),\n remove: true,\n })\n\n sipcall.createOffer({\n tracks: tracks,\n success: function (jsep) {\n videoRenegotiationInFlightRef.current = false\n sipcall.send({ message: { request: 'update' }, jsep: jsep })\n eventDispatch('phone-island-video-disabled', {})\n },\n error: function (error) {\n videoRenegotiationInFlightRef.current = false\n console.error('WebRTC error... ' + JSON.stringify(error))\n },\n })\n }\n useEventListener('phone-island-video-disable', () => {\n disableVideo()\n })\n\n const toggleVideo = async () => {\n let cameraPermission = await checkCameraPermission()\n if (cameraPermission) {\n if (isLocalVideoEnabled) {\n disableVideo()\n } else {\n enableVideo()\n }\n }\n }\n\n const shareScreen = () => {\n if (!janus.current.isExtensionEnabled()) {\n janus.current.error?.(\n \"This browser doesn't support screensharing (getDisplayMedia unavailable)\",\n )\n return\n }\n\n // Create a new room\n const roomName = janus.current.randomString(32)\n\n let create = {\n request: 'create',\n description: roomName,\n bitrate: 500000,\n publishers: 1,\n }\n\n const { plugin } = store.getState().screenShare\n\n plugin.send({\n message: create,\n success: function (result) {\n if (result['error']) {\n janus.current.error?.(\"Couldn't create room: \" + result['error'])\n return\n }\n let event = result['videoroom']\n janus.current.debug?.('Event: ' + event)\n if (event) {\n // Our own screen sharing session has been created, join it\n\n const room = result['room']\n // Set room to the store\n dispatch.screenShare.update({\n room: room,\n })\n\n janus.current.log?.('Screen sharing session created: ' + room)\n\n const { username } = store.getState().currentUser\n\n if (screenSharePublisherJoinRequestedRef.current) {\n janus.current.log?.(\n 'Screen share publisher join already requested on this handle, skipping duplicate join',\n )\n return\n }\n\n screenSharePublisherJoinRequestedRef.current = true\n\n let register = {\n request: 'join',\n room: room,\n ptype: 'publisher',\n display: username,\n }\n plugin.send({ message: register })\n }\n },\n })\n }\n\n const initScreenShare = () => {\n janusInstance?.attach({\n plugin: 'janus.plugin.videoroom',\n opaqueId: janus.current.randomString(32),\n success: function (pluginHandle) {\n // Set plugin to the store\n dispatch.screenShare.update({\n plugin: pluginHandle,\n })\n const { role } = store.getState().screenShare\n\n if (role === 'publisher') {\n // trigger event to nethlink\n eventDispatch('phone-island-screen-share-initialized', {})\n\n setTimeout(function () {\n shareScreen()\n }, 500)\n } else if (role === 'listener') {\n joinScreenShare()\n }\n eventDispatch('phone-island-screen-share-started', {})\n },\n error: function (error) {\n janus.current.error?.('Error attaching videoroom plugin', error)\n },\n consentDialog: function (on) {},\n iceState: function (state) {\n janus.current.log?.('ICE state changed to ' + state)\n },\n mediaState: function (medium, on) {\n janus.current.log?.('Janus ' + (on ? 'started' : 'stopped') + ' receiving our ' + medium)\n },\n webrtcState: function (on) {\n janus.current.log?.(\n 'Janus says our WebRTC PeerConnection is ' + (on ? 'up' : 'down') + ' now',\n )\n },\n slowLink: function (uplink, lost, mid) {\n janus.current.warn?.(\n 'Janus reports problems ' +\n (uplink ? 'sending' : 'receiving') +\n ' packets on mid ' +\n mid +\n ' (' +\n lost +\n ' lost packets)',\n )\n },\n onmessage: function (msg, jsep) {\n janus.current.debug?.(' ::: Got a message (publisher) :::', msg)\n const { plugin, role } = store.getState().screenShare\n const event = msg['videoroom']\n janus.current.debug?.('Event: ' + event)\n\n if (event) {\n if (event === 'joined') {\n if (role === 'publisher') {\n // This is our session, publish our stream\n janus.current.debug?.('Negotiating WebRTC stream for our screen')\n\n plugin.createOffer({\n // We want sendonly audio and screensharing\n tracks: [\n { type: 'audio', capture: true, recv: false },\n { type: 'screen', capture: true, recv: false },\n ],\n success: function (jsep) {\n janus.current.debug?.('Got publisher SDP!', jsep)\n let publish = { request: 'configure', audio: true, video: true }\n plugin.send({ message: publish, jsep: jsep })\n },\n error: function (error) {\n screenSharePublisherJoinRequestedRef.current = false\n janus.current.error?.('WebRTC error:', error)\n dispatch.screenShare.update({ active: false, role: '' })\n },\n })\n } else {\n // We're just watching a session, any feed to attach to?\n if (msg['publishers']) {\n let list = msg['publishers']\n janus.current.debug?.('Got a list of available publishers/feeds:', list)\n for (let f in list) {\n if (list[f]['dummy']) continue\n let id = list[f]['id']\n let display = list[f]['display']\n janus.current.debug?.(' >> [' + id + '] ' + display)\n newRemoteFeed(id, display)\n }\n }\n }\n } else if (event === 'event') {\n // Any feed to attach to?\n if (role === 'listener' && msg['publishers']) {\n let list = msg['publishers']\n janus.current.debug?.('Got a list of available publishers/feeds:', list)\n for (let f in list) {\n if (list[f]['dummy']) continue\n let id = list[f]['id']\n let display = list[f]['display']\n janus.current.debug?.(' >> [' + id + '] ' + display)\n newRemoteFeed(id, display)\n }\n } else if (msg['leaving']) {\n // One of the publishers has gone away?\n let leaving = msg['leaving']\n janus.current.log?.('Publisher left: ' + leaving)\n } else if (msg['error']) {\n janus.current.error?.('Error event: ' + msg['error'])\n }\n }\n }\n if (jsep) {\n janus.current.debug?.('Handling SDP as well...', jsep)\n plugin.handleRemoteJsep({ jsep: jsep })\n }\n },\n onlocaltrack: function (track, on) {\n janus.current.debug?.('Local track ' + (on ? 'added' : 'removed') + ':', track)\n // We use the track ID as name of the element, but it may contain invalid characters\n let trackId = track.id.replace(/[{}]/g, '')\n if (!on) {\n // Track removed, get rid of the stream and the rendering\n let stream = localTracks?.[trackId]\n if (stream) {\n try {\n let tracks = stream.getTracks()\n for (let i in tracks) {\n let mst = tracks[i]\n if (mst) mst.stop()\n }\n // eslint-disable-next-line no-unused-vars\n } catch (e) {}\n }\n if (track.kind === 'video') {\n dispatch.screenShare.update({\n localVideos: localVideos - 1,\n })\n }\n\n // remove track\n const filteredTracks = localTracks?.filter((track) => track !== localTracks[trackId])\n dispatch.screenShare.update({\n localTracks: filteredTracks,\n })\n return\n }\n // If we're here, a new track was added\n let stream = localTracks?.[trackId]\n if (stream) {\n // We've been here already\n return\n }\n\n if (track.kind === 'video') {\n // New video track: create a stream out of it\n dispatch.screenShare.update({\n localVideos: localVideos + 1,\n })\n let stream = new MediaStream([track])\n\n // Save the new video stream to the store\n store.dispatch.screenShare.update({\n localScreenStream: stream,\n })\n\n janus.current.log?.('Created local stream: ' + stream)\n const localScreenElement = store.getState().player.localScreen\n\n if (localScreenElement?.current) {\n janus.current.attachMediaStream?.(localScreenElement.current, stream)\n inviteOtherUser()\n\n // Listen for the 'ended' event on the screen-sharing track\n track.addEventListener('ended', () => {\n stopScreenShare()\n })\n }\n }\n const { plugin } = store.getState().screenShare\n\n if (\n plugin.webrtcStuff.pc.iceConnectionState !== 'completed' &&\n plugin.webrtcStuff.pc.iceConnectionState !== 'connected'\n ) {\n }\n },\n // eslint-disable-next-line no-unused-vars\n onremotetrack: function (track, mid, on) {\n // The publisher stream is sendonly, we don't expect anything here\n },\n oncleanup: function () {\n janus.current.log?.(' ::: Got a cleanup notification :::')\n screenSharePublisherJoinRequestedRef.current = false\n\n dispatch.screenShare.update({\n localTracks: {},\n localVideos: 0,\n })\n },\n })\n }\n\n const updateScreenStreams = () => {\n const localScreenElement = store.getState().player.localScreen\n const remoteScreenElement = store.getState().player.remoteScreen\n const { localScreenStream, remoteScreenStream } = store.getState().screenShare\n\n // local screen stream\n\n if (localScreenElement?.current) {\n if (janus.current.attachMediaStream) {\n janus.current.attachMediaStream(\n localScreenElement.current,\n localScreenStream as MediaStream,\n )\n }\n }\n\n // remote screen stream\n\n if (remoteScreenElement?.current) {\n if (janus.current.attachMediaStream) {\n janus.current.attachMediaStream(\n remoteScreenElement.current,\n remoteScreenStream as MediaStream,\n )\n }\n }\n }\n\n const inviteOtherUser = () => {\n // send message to websocket to invite the other user\n const { socket } = store.getState().websocket\n const { username: destUsername } = store.getState().currentCall\n const { room } = store.getState().screenShare\n const { username } = store.getState().currentUser\n\n socket.emit('message', {\n message: 'screenSharingStart',\n roomId: room,\n destUser: destUsername,\n callUser: username,\n } as ScreenSharingMessage)\n }\n\n const initAndStartScreenShare = () => {\n screenSharePublisherJoinRequestedRef.current = false\n dispatch.screenShare.update({ active: true, role: 'publisher' })\n initScreenShare()\n }\n useEventListener('phone-island-screen-share-start', () => {\n initAndStartScreenShare()\n })\n\n const initAndJoinScreenShare = () => {\n dispatch.screenShare.update({ active: true, role: 'listener' })\n initScreenShare()\n eventDispatch('phone-island-screen-share-joined', {})\n }\n\n const joinScreenShare = () => {\n const { room } = store.getState().screenShare\n const { username } = store.getState().currentUser\n\n const joinMessage = {\n request: 'join',\n room: room,\n ptype: 'publisher',\n display: username,\n }\n\n const { plugin } = store.getState().screenShare\n plugin.send({ message: joinMessage })\n }\n\n const leaveScreenShare = () => {\n const { remoteScreenStream } = store.getState().screenShare\n janus.current.stopAllTracks(remoteScreenStream)\n dispatch.screenShare.update({ active: false })\n eventDispatch('phone-island-screen-share-left', {})\n }\n\n const handleMouseMove = () => {\n setUiShown(true)\n\n if (uiTimeoutRef.current) {\n clearTimeout(uiTimeoutRef.current)\n uiTimeoutRef.current = null\n }\n }\n\n const startHideTimer = () => {\n // start a timer when mouse stops moving to hide video UI\n uiTimeoutRef.current = setTimeout(() => {\n setUiShown(false)\n }, 3000)\n }\n\n const handleMouseMoveWithDebounce = () => {\n handleMouseMove()\n\n // clear the previous debounce timer\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n\n // set a new debounce timer - when this isn't cleared, it means the mouse has stopped\n debounceTimerRef.current = setTimeout(() => {\n startHideTimer()\n }, 100) // small delay to detect \"stopped moving\"\n }\n\n const stopScreenShare = () => {\n const { plugin, localScreenStream } = store.getState().screenShare\n\n screenSharePublisherJoinRequestedRef.current = false\n janus.current.stopAllTracks(localScreenStream)\n dispatch.screenShare.update({ active: false })\n plugin.detach()\n\n // send message to websocket to tell the other user the screen share has stopped\n const { socket } = store.getState().websocket\n const { username: destUsername } = store.getState().currentCall\n const { room } = store.getState().screenShare\n const { username } = store.getState().currentUser\n\n socket.emit('message', {\n message: 'screenSharingStop',\n roomId: room,\n destUser: destUsername,\n callUser: username,\n } as ScreenSharingMessage)\n\n eventDispatch('phone-island-screen-share-stopped', {})\n }\n useEventListener('phone-island-screen-share-stop', () => {\n stopScreenShare()\n })\n\n const pauseCall = () => {\n pauseCurrentCall()\n stopScreenShare()\n }\n\n const [isVideoCallButtonVisible, setIsVideoCallButtonVisible] = useState(true)\n\n const checkCameraPermission = async () => {\n if (videoInputDevices?.length > 0) {\n const isWebCamAccepted = await checkWebCamPermission()\n if (isWebCamAccepted) {\n setIsVideoCallButtonVisible(true)\n return true\n } else {\n setIsVideoCallButtonVisible(false)\n return false\n }\n } else {\n setIsVideoCallButtonVisible(false)\n return false\n }\n }\n\n return (\n <>\n {isOpen ? (\n <div\n ref={screenShareViewRef}\n onMouseMove={() => handleMouseMoveWithDebounce()}\n className={isFullscreen ? 'pi-h-screen' : 'pi-h-[480px] pi-w-[600px]'}\n >\n <div className={`pi-flex pi-relative pi-justify-center pi-w-full pi-h-full`}>\n {/* large remote screen */}\n <video\n autoPlay\n muted={true}\n ref={remoteScreen}\n className={`pi-rounded-2xl pi-w-full pi-h-full ${\n !screenShareActive || screenShareRole !== 'listener' ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* large local screen */}\n <video\n autoPlay\n muted={true}\n ref={localScreen}\n className={`pi-rounded-2xl pi-w-full pi-h-full ${\n !screenShareActive || screenShareRole !== 'publisher' ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* large remote video */}\n <video\n autoPlay\n muted={true}\n ref={largeRemoteVideo}\n className={`pi-rounded-2xl ${\n screenShareActive || showRemoteVideoPlaceHolder ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* remote video placeholder */}\n <div\n className={`pi-w-full pi-bg-gray-200 dark:pi-bg-gray-800 pi-flex pi-items-center pi-justify-center ${\n screenShareActive || !showRemoteVideoPlaceHolder ? 'pi-hidden' : ''\n }`}\n >\n <div className='pi-rounded-full pi-bg-gray-700 dark:pi-bg-gray-200 pi-w-32 pi-h-32 pi-flex pi-items-center pi-justify-center'>\n <span className='pi-text-4xl pi-text-gray-50 dark:pi-text-gray-900'>\n {getInitials(displayName)}\n </span>\n </div>\n </div>\n {/* small local video */}\n <video\n muted={true}\n autoPlay\n ref={localVideo}\n className={`pi-max-w-32 pi-max-h-32 pi-absolute pi-top-5 pi-right-5 pi-rounded-lg ${\n !isLocalVideoEnabled ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* small local video placeholder */}\n <div\n className={`pi-w-32 pi-h-24 pi-absolute pi-top-5 pi-right-5 pi-rounded-lg pi-bg-gray-200 dark:pi-bg-gray-900 pi-flex pi-items-center pi-justify-center ${\n isLocalVideoEnabled || !hasVideoTrackAdded ? 'pi-hidden' : ''\n }`}\n >\n <div className='pi-rounded-full pi-bg-gray-700 dark:pi-bg-gray-200 pi-w-12 pi-h-12 pi-flex pi-items-center pi-justify-center'>\n <span className='pi-text-base pi-text-gray-50 dark:pi-text-gray-900'>\n {getInitials(userInfo.name || '-')}\n </span>\n </div>\n </div>\n {/* small remote video */}\n <video\n muted={true}\n autoPlay\n ref={smallRemoteVideo}\n className={`pi-max-w-32 pi-max-h-32 pi-absolute pi-top-32 pi-right-5 pi-rounded-lg ${\n !screenShareActive || showRemoteVideoPlaceHolder ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* small remote video placeholder */}\n <div\n className={`pi-w-32 pi-h-24 pi-absolute pi-top-32 pi-right-5 pi-rounded-lg pi-bg-gray-200 dark:pi-bg-gray-900 pi-flex pi-items-center pi-justify-center ${\n !screenShareActive || !showRemoteVideoPlaceHolder || !hasVideoTrackAdded\n ? 'pi-hidden'\n : ''\n }`}\n >\n <div className='pi-rounded-full pi-bg-gray-700 dark:pi-bg-gray-200 pi-w-12 pi-h-12 pi-flex pi-items-center pi-justify-center'>\n <span className='pi-text-base pi-text-gray-50 dark:pi-text-gray-900'>\n {getInitials(displayName)}\n </span>\n </div>\n </div>\n </div>\n\n <div\n className={`${\n !isUiShown && 'pi-opacity-0 pi-pointer-events-none'\n } pi-absolute pi-bottom-0 pi-bg-gray-950/65 pi-w-full pi-p-6 pi-rounded-bl-[20px] pi-rounded-br-[20px] pi-transition-all`}\n >\n <div className='pi-flex pi-items-center pi-justify-center pi-gap-6 pi-mb-5'>\n {/* mute button */}\n {!intrudeListenStatus?.isListen && (\n <Button\n variant='default'\n active={muted ? true : false}\n onClick={() => (muted ? unmuteCurrentCall() : muteCurrentCall())}\n data-tooltip-id='tooltip-mute'\n data-tooltip-content={muted ? `${t('Tooltip.Unmute')}` : `${t('Tooltip.Mute')}`}\n >\n {muted ? (\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={faMicrophoneSlash} />\n ) : (\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={faMicrophone} />\n )}\n </Button>\n )}\n\n {/* video button */}\n {videoInputDevices?.length > 0 && (\n <Button\n variant='default'\n onClick={() => toggleVideo()}\n data-tooltip-id='tooltip-toggle-video'\n data-tooltip-content={`${\n !isVideoCallButtonVisible\n ? t('Tooltip.Enable camera permission') || ''\n : isLocalVideoEnabled\n ? t('Tooltip.Disable camera')\n : t('Tooltip.Enable camera')\n }`}\n disabled={!isVideoCallButtonVisible}\n className={`${!isVideoCallButtonVisible ? 'pi-cursor-auto' : ''}`}\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={isVideoCallButtonVisible || isLocalVideoEnabled ? faVideo : faVideoSlash}\n />\n </Button>\n )}\n\n {/* Share screen button */}\n {janus.current.webRTCAdapter.browserDetails.browser !== 'safari' &&\n userInfo?.profile?.macro_permissions?.nethvoice_cti?.permissions?.screen_sharing\n ?.value &&\n !screenShareActive && (\n <Button\n variant='default'\n onClick={() => initAndStartScreenShare()}\n data-tooltip-id='tooltip-start-screen-share'\n data-tooltip-content={t('Tooltip.Share screen') || ''}\n >\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={faDisplay} />\n </Button>\n )}\n\n {/* stop screen share */}\n {screenShareActive && screenShareRole === 'publisher' && (\n <Button\n variant='default'\n onClick={() => stopScreenShare()}\n data-tooltip-id='tooltip-stop-screen-share'\n data-tooltip-content={t('Tooltip.Stop sharing')}\n >\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={faDisplaySlash} />\n </Button>\n )}\n\n {/* fullscreen */}\n {screenShareActive && screenShareRole === 'listener' && (\n <Button\n variant='default'\n onClick={() => toggleFullScreen()}\n data-tooltip-id='tooltip-toggle-fullscreen'\n data-tooltip-content={\n isFullscreen ? t('Tooltip.Exit fullscreen') : t('Tooltip.Enter fullscreen')\n }\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={isFullscreen ? faCompress : faExpand}\n />\n </Button>\n )}\n\n {/* record */}\n {userInfo?.profile?.macro_permissions?.settings?.permissions?.recording?.value && (\n <Button\n variant='default'\n onClick={() => recordCurrentCall(isRecording)}\n data-tooltip-id='tooltip-record-video-view'\n data-tooltip-content={\n isRecording ? t('Tooltip.Stop recording') : t('Tooltip.Record')\n }\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={isRecording ? faStop : faRecord}\n />\n </Button>\n )}\n\n {/* hold */}\n {!(intrudeListenStatus?.isIntrude || intrudeListenStatus?.isListen) && (\n <Button\n variant='default'\n onClick={() => (paused ? unpauseCurrentCall() : pauseCall())}\n data-tooltip-id='tooltip-pause-video-view'\n data-tooltip-content={paused ? t('Tooltip.Play') : t('Tooltip.Pause')}\n >\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={paused ? faPlay : faPause} />\n </Button>\n )}\n </div>\n <Hangup buttonsVariant='default' />\n </div>\n {/* Buttons tooltips */}\n <CustomThemedTooltip className='pi-z-20' id='tooltip-mute-video-view' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-toggle-video' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-toggle-fullscreen' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-start-screen-share' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-stop-screen-share' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-record-video-view' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-pause-video-view' place='bottom' />\n </div>\n ) : (\n // collapsed view\n <>\n <div className='pi-flex pi-justify-between pi-items-center'>\n <Avatar />\n <Timer startTime={startTime} isNotAlwaysWhite />\n {!isOpen && remoteAudioStream && !isPhysical() && (\n <AudioBars\n audioStream={remoteAudioStream}\n paused={paused}\n size={isOpen ? 'large' : 'small'}\n />\n )}\n </div>\n </>\n )}\n </>\n )\n}\n\nexport default VideoView\n"],"names":["VideoView","dispatch","useDispatch","_l","useSelector","state","currentCall","muted","startTime","isRecording","paused","isLocalVideoEnabled","showRemoteVideoPlaceHolder","hasVideoTrackAdded","displayName","isStartingVideoCall","_m","screenShare","localTracks","localVideos","screenShareRole","role","screenShareActive","active","isStartingScreenShare","isJoiningScreenShare","isLeavingScreenShare","intrudeListenStatus","listen","isOpen","island","_o","webrtc","janusInstance","remoteAudioStream","userInfo","store","getState","currentUser","_p","useState","isFullscreen","setIsFullscreen","_q","isUiShown","setUiShown","uiTimeoutRef","useRef","debounceTimerRef","videoRenegotiationInFlightRef","screenSharePublisherJoinRequestedRef","screenShareViewRef","localScreen","remoteScreen","localVideo","largeRemoteVideo","smallRemoteVideo","janus","JanusLib","videoInputDevices","select","mediaDevices","useIsomorphicLayoutEffect","player","updatePlayer","useEffect","updateScreenStreams","updateVideoStreams","addEventListener","handleFullscreenChange","removeEventListener","current","clearTimeout","enableVideo","updateCurrentCall","initAndStartScreenShare","update","initAndJoinScreenShare","leaveScreenShare","localVideoElement","largeRemoteVideoElement","smallRemoteVideoElement","_a","localVideoStream","remoteVideoStream","attachMediaStream","MediaStream","getVideoTracks","length","document","fullscreenElement","toggleFullScreen","exitFullscreen","eventDispatch","requestFullscreen","useEventListener","newRemoteFeed","id","display","source","remoteFeed","attach","plugin","opaqueId","randomString","success","pluginHandle","remoteTracks","remoteVideos","_b","log","call","getPlugin","getId","_d","_c","request","room","ptype","feed","send","message","error","iceState","rfindex","webrtcState","on","slowLink","uplink","lost","mid","warn","onmessage","msg","jsep","debug","event","_f","_e","_h","_g","_k","_j","createAnswer","tracks","type","body","onlocaltrack","track","onremotetrack","metadata","reason","kind","remoteScreenStream","stopAllTracks","stream","remoteScreenElement","oncleanup","sipcall","currentVideoInputDeviceId","getCurrentVideoInputDeviceId","recv","capture","deviceId","exact","videoTransceiver","webrtcStuff","pc","getTransceivers","find","transceiver","receiver","sender","Boolean","replace","setVideoTrackAdded","add","push","createOffer","socket","destUser","callUser","websocket","username","emit","dispatchVideoCallStarted","initiator","console","JSON","stringify","disableVideo","updateLocalVideoStream","setLocalVideoEnabled","__assign","remove","initScreenShare","setTimeout","isExtensionEnabled","create","description","bitrate","publishers","result","register","shareScreen","joinScreenShare","consentDialog","mediaState","medium","_w","audio","video","list","f","leaving","_r","_t","_s","_v","_u","handleRemoteJsep","trackId","stream_2","localScreenStream","localScreenElement","inviteOtherUser","stopScreenShare","iceConnectionState","stream_1","getTracks","i","mst","stop","e","filteredTracks","filter","destUsername","roomId","joinMessage","handleMouseMoveWithDebounce","detach","isVideoCallButtonVisible","setIsVideoCallButtonVisible","checkCameraPermission","__awaiter","checkWebCamPermission","sent","React","createElement","Fragment","ref","onMouseMove","className","autoPlay","concat","getInitials","name","isListen","Button","variant","onClick","unmuteCurrentCall","muteCurrentCall","t","FontAwesomeIcon","icon","faMicrophoneSlash","faMicrophone","disabled","faVideo","faVideoSlash","webRTCAdapter","browserDetails","browser","profile","macro_permissions","nethvoice_cti","permissions","screen_sharing","value","faDisplay","faDisplaySlash","faCompress","faExpand","settings","recording","recordCurrentCall","faStop","faRecord","isIntrude","unpauseCurrentCall","pauseCurrentCall","faPlay","faPause","Hangup","buttonsVariant","CustomThemedTooltip","place","Avatar","Timer","isNotAlwaysWhite","isPhysical","AudioBars","audioStream","size"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/components/VideoView/index.tsx"],"sourcesContent":["// Copyright (C) 2025 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport React, { type FC, useEffect, useMemo, useRef, useState } from 'react'\nimport { Button } from '../Button'\nimport { useDispatch, useSelector } from 'react-redux'\nimport { Dispatch, RootState, store } from '../../store'\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\nimport {\n faCompress,\n faDisplay,\n faExpand,\n faMicrophone,\n faMicrophoneSlash,\n faPause,\n faPlay,\n faStop,\n faVideo,\n faVideoSlash,\n} from '@fortawesome/free-solid-svg-icons'\nimport { t } from 'i18next'\nimport { eventDispatch, useEventListener, useIsomorphicLayoutEffect } from '../../utils'\nimport Hangup from '../Hangup'\nimport {\n muteCurrentCall,\n pauseCurrentCall,\n recordCurrentCall,\n isRecordingControlAvailable,\n unmuteCurrentCall,\n unpauseCurrentCall,\n} from '../../lib/phone/call'\nimport { JanusTrack, JanusTypes } from '../../types/webrtc'\nimport JanusLib from '../../lib/webrtc/janus.js'\nimport Avatar from '../CallView/Avatar'\nimport Timer from '../CallView/Timer'\nimport { isPhysical } from '../../lib/user/default_device'\nimport { AudioBars } from '../AudioBars'\nimport { CustomThemedTooltip } from '../CustomThemedTooltip'\nimport { faDisplaySlash, faRecord } from '@nethesis/nethesis-solid-svg-icons'\nimport { getCurrentVideoInputDeviceId } from '../../lib/devices/devices'\nimport { getInitials } from '../../lib/avatars/avatars'\nimport { checkWebCamPermission } from '../../lib/devices/devices'\nimport { dispatchVideoCallStarted } from '../../events/SocketEvents'\n\nexport interface VideoViewProps {}\n\nexport type ScreenSharingMessage = {\n message: 'screenSharingStart' | 'screenSharingStop'\n roomId: string\n destUser: string\n callUser: string\n}\n\nexport type VideoCallMessage = {\n message: 'videoCallStart'\n destUser: string\n callUser: string\n}\n\nexport const VideoView: FC<VideoViewProps> = () => {\n const dispatch = useDispatch<Dispatch>()\n const {\n muted,\n startTime,\n isRecording,\n paused,\n isLocalVideoEnabled,\n showRemoteVideoPlaceHolder,\n hasVideoTrackAdded,\n displayName,\n isStartingVideoCall,\n } = useSelector((state: RootState) => state.currentCall)\n const {\n localTracks,\n localVideos,\n role: screenShareRole,\n active: screenShareActive,\n isStartingScreenShare,\n isJoiningScreenShare,\n isLeavingScreenShare,\n } = useSelector((state: RootState) => state.screenShare)\n const intrudeListenStatus = useSelector((state: RootState) => state.listen)\n const { isOpen } = useSelector((state: RootState) => state.island)\n const { janusInstance, remoteAudioStream } = useSelector((state: RootState) => state.webrtc)\n const userInfo = useSelector((state: RootState) => state.currentUser)\n const [isFullscreen, setIsFullscreen] = useState(false)\n const [isUiShown, setUiShown] = useState(false)\n const uiTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const debounceTimerRef = useRef<NodeJS.Timeout | null>(null)\n const videoRenegotiationInFlightRef = useRef(false)\n const screenSharePublisherJoinRequestedRef = useRef(false)\n const screenShareViewRef = useRef(null)\n const localScreen = useRef<HTMLVideoElement>(null)\n const remoteScreen = useRef<HTMLVideoElement>(null)\n const localVideo = useRef<HTMLVideoElement>(null)\n const largeRemoteVideo = useRef<HTMLVideoElement>(null)\n const smallRemoteVideo = useRef<HTMLVideoElement>(null)\n const janus = useRef<JanusTypes>(JanusLib)\n const videoInputDevices = store.select.mediaDevices.videoInputDevices(store.getState())\n const activeConversation = useMemo(() => {\n const conversations = userInfo?.conversations || {}\n const activeConversation = Object.values(conversations).find((conv) => Object.keys(conv).length > 0)\n return activeConversation ? (Object.values(activeConversation)[0] as any) : null\n }, [userInfo?.conversations])\n const recordingPermission =\n userInfo?.profile?.macro_permissions?.settings?.permissions?.recording?.value || false\n const recordingControlAvailable = isRecordingControlAvailable(activeConversation)\n const canRecordCurrentCall = recordingPermission && recordingControlAvailable\n\n const notifyPeerVideoStart = () => {\n const { socket } = store.getState().websocket\n const { username: destUser } = store.getState().currentCall\n const { username: callUser } = store.getState().currentUser\n\n if (!socket || !destUser || !callUser) {\n return\n }\n\n socket.emit('message', {\n message: 'videoCallStart',\n destUser,\n callUser,\n } as VideoCallMessage)\n }\n\n useIsomorphicLayoutEffect(() => {\n dispatch.player.updatePlayer({\n localScreen: localScreen,\n remoteScreen: remoteScreen,\n localVideo: localVideo,\n largeRemoteVideo: largeRemoteVideo,\n smallRemoteVideo: smallRemoteVideo,\n })\n }, [])\n\n // component did mount\n useEffect(() => {\n updateScreenStreams()\n updateVideoStreams()\n\n // register for full screen change\n addEventListener('fullscreenchange', handleFullscreenChange)\n\n return () => {\n removeEventListener('fullscreenchange', handleFullscreenChange)\n\n // clear timeout\n if (uiTimeoutRef.current) {\n clearTimeout(uiTimeoutRef.current)\n }\n }\n }, [])\n\n // starting videocall\n useEffect(() => {\n if (isStartingVideoCall) {\n enableVideo()\n dispatch.currentCall.updateCurrentCall({\n isStartingVideoCall: false,\n })\n }\n }, [isStartingVideoCall])\n\n // starting screen sharing\n useEffect(() => {\n if (isStartingScreenShare) {\n initAndStartScreenShare()\n store.dispatch.screenShare.update({\n isStartingScreenShare: false,\n })\n }\n }, [isStartingScreenShare])\n\n // joining screen sharing\n useEffect(() => {\n if (isJoiningScreenShare) {\n initAndJoinScreenShare()\n store.dispatch.screenShare.update({\n isJoiningScreenShare: false,\n })\n }\n }, [isJoiningScreenShare])\n\n // leaving screen sharing\n useEffect(() => {\n if (isLeavingScreenShare) {\n leaveScreenShare()\n store.dispatch.screenShare.update({\n isLeavingScreenShare: false,\n })\n }\n }, [isLeavingScreenShare])\n\n // isOpen changed\n useEffect(() => {\n updateScreenStreams()\n updateVideoStreams()\n }, [isOpen])\n\n const updateVideoStreams = () => {\n const localVideoElement = store.getState().player.localVideo\n const largeRemoteVideoElement = store.getState().player.largeRemoteVideo\n const smallRemoteVideoElement = store.getState().player.smallRemoteVideo\n const { localVideoStream, remoteVideoStream } = store.getState().webrtc\n\n // local video stream\n\n if (localVideoElement?.current) {\n if (janus.current.attachMediaStream) {\n janus.current.attachMediaStream(localVideoElement.current, localVideoStream as MediaStream)\n }\n }\n\n // large remote video stream\n\n if (largeRemoteVideoElement?.current && janus.current.attachMediaStream) {\n janus.current.attachMediaStream(\n largeRemoteVideoElement.current,\n remoteVideoStream as MediaStream,\n )\n }\n\n // small remote video stream\n\n if (smallRemoteVideoElement?.current && janus.current.attachMediaStream) {\n janus.current.attachMediaStream(\n smallRemoteVideoElement.current,\n remoteVideoStream as MediaStream,\n )\n }\n\n if (remoteVideoStream instanceof MediaStream && remoteVideoStream.getVideoTracks().length > 0) {\n dispatch.currentCall.updateCurrentCall({\n showRemoteVideoPlaceHolder: false,\n })\n }\n }\n\n const handleFullscreenChange = () => {\n setIsFullscreen(!!document.fullscreenElement)\n }\n\n const toggleFullScreen = () => {\n if (document.fullscreenElement) {\n document.exitFullscreen()\n eventDispatch('phone-island-fullscreen-exited', {})\n } else {\n if (screenShareViewRef.current) {\n ;(screenShareViewRef.current as HTMLElement).requestFullscreen()\n eventDispatch('phone-island-fullscreen-entered', {})\n }\n }\n }\n useEventListener('phone-island-fullscreen-enter', () => {\n toggleFullScreen()\n })\n useEventListener('phone-island-fullscreen-exit', () => {\n toggleFullScreen()\n })\n\n const newRemoteFeed = (id, display) => {\n // A new feed has been published, create a new plugin handle and attach to it as a listener\n\n dispatch.screenShare.update({\n source: id,\n })\n\n let remoteFeed: any = null\n janusInstance?.attach({\n plugin: 'janus.plugin.videoroom',\n opaqueId: janus.current.randomString(32),\n success: function (pluginHandle) {\n remoteFeed = pluginHandle\n\n dispatch.screenShare.update({\n remoteFeed: pluginHandle,\n })\n remoteFeed.remoteTracks = {}\n remoteFeed.remoteVideos = 0\n janus.current.log?.(\n 'Plugin attached! (' + remoteFeed.getPlugin() + ', id=' + remoteFeed.getId() + ')',\n )\n janus.current.log?.(' -- This is a subscriber')\n // We wait for the plugin to send us an offer\n const { room } = store.getState().screenShare\n\n let listen = {\n request: 'join',\n room: room,\n ptype: 'subscriber',\n feed: id,\n }\n remoteFeed.send({ message: listen })\n },\n error: function (error) {\n janus.current.error?.('Error attaching videoroom plugin', error)\n },\n iceState: function (state) {\n janus.current.log?.('ICE state (feed #' + remoteFeed.rfindex + ') changed to ' + state)\n },\n webrtcState: function (on) {\n janus.current.log?.(\n 'Janus says this WebRTC PeerConnection (feed #' +\n remoteFeed.rfindex +\n ') is ' +\n (on ? 'up' : 'down') +\n ' now',\n )\n },\n slowLink: function (uplink, lost, mid) {\n janus.current.warn?.(\n 'Janus reports problems ' +\n (uplink ? 'sending' : 'receiving') +\n ' packets on mid ' +\n mid +\n ' (' +\n lost +\n ' lost packets)',\n )\n },\n onmessage: function (msg, jsep) {\n janus.current.debug?.(' ::: Got a message (listener) :::', msg)\n let event = msg['videoroom']\n janus.current.debug?.('Event: ' + event)\n if (event) {\n if (event === 'attached') {\n // Subscriber created and attached\n janus.current.log?.(\n 'Successfully attached to feed ' + id + ' (' + display + ') in room ' + msg['room'],\n )\n } else {\n janus.current.warn?.('Unhandled event: ' + event)\n }\n }\n if (jsep) {\n janus.current.debug?.('Handling SDP as well...', jsep)\n // Answer and attach\n remoteFeed.createAnswer({\n jsep: jsep,\n // We only specify data channels here, as this way in\n // case they were offered we'll enable them. Since we\n // don't mention audio or video tracks, we autoaccept them\n // as recvonly (since we won't capture anything ourselves)\n tracks: [{ type: 'data' }],\n success: function (jsep) {\n janus.current.debug?.('Got SDP!', jsep)\n\n const { room } = store.getState().screenShare\n\n let body = { request: 'start', room: room }\n remoteFeed.send({ message: body, jsep: jsep })\n },\n error: function (error) {\n janus.current.error?.('WebRTC error:', error)\n },\n })\n }\n },\n // eslint-disable-next-line no-unused-vars\n onlocaltrack: function (track, on) {\n // The subscriber stream is recvonly, we don't expect anything here\n },\n onremotetrack: function (track, mid, on, metadata) {\n janus.current.debug?.(\n 'Remote track (mid=' +\n mid +\n ') ' +\n (on ? 'added' : 'removed') +\n (metadata ? ' (' + metadata.reason + ') ' : '') +\n ':',\n track,\n )\n // Screen sharing tracks are sometimes muted/unmuted by browser\n // when data is not flowing fast enough; this can make streams blink.\n // We can ignore these.\n if (\n track.kind === 'video' &&\n metadata &&\n (metadata.reason === 'mute' || metadata.reason === 'unmute')\n ) {\n janus.current.log?.('Ignoring mute/unmute on screen-sharing track.')\n return\n }\n if (!on) {\n const { remoteScreenStream } = store.getState().screenShare\n janus.current.stopAllTracks(remoteScreenStream)\n dispatch.screenShare.update({ active: false })\n return\n }\n // If we're here, a new track was added\n if (track.kind === 'video') {\n // New video track: create a stream out of it\n let stream = new MediaStream([track])\n\n // Save the new video stream to the store\n store.dispatch.screenShare.update({ remoteScreenStream: stream })\n\n remoteFeed.remoteTracks[mid] = stream\n janus.current.log?.('Created remote video stream: ' + stream)\n const remoteScreenElement = store.getState().player.remoteScreen\n\n if (remoteScreenElement?.current) {\n janus.current.attachMediaStream?.(remoteScreenElement.current, stream)\n }\n }\n },\n oncleanup: function () {\n janus.current.log?.(' ::: Got a cleanup notification (remote feed ' + id + ') :::')\n remoteFeed.remoteTracks = {}\n remoteFeed.remoteVideos = 0\n },\n })\n }\n\n const enableVideo = () => {\n if (videoRenegotiationInFlightRef.current) {\n return\n }\n\n const { sipcall }: { sipcall: any } = store.getState().webrtc\n videoRenegotiationInFlightRef.current = true\n store.dispatch.currentCall.updateCurrentCall({\n isLocalVideoEnabled: true,\n })\n const tracks: JanusTrack[] = []\n const currentVideoInputDeviceId = getCurrentVideoInputDeviceId()\n\n const track: Partial<JanusTrack> = {\n type: 'video',\n recv: true,\n }\n\n if (currentVideoInputDeviceId) {\n track.capture = { deviceId: { exact: currentVideoInputDeviceId } }\n } else {\n track.capture = true\n }\n\n const { hasVideoTrackAdded } = store.getState().currentCall\n const { remoteVideoStream } = store.getState().webrtc\n const videoTransceiver = sipcall?.webrtcStuff?.pc\n ?.getTransceivers?.()\n ?.find(\n (transceiver: RTCRtpTransceiver) =>\n transceiver.receiver?.track?.kind === 'video' ||\n transceiver.sender?.track?.kind === 'video',\n )\n const shouldReplaceExistingVideoTransceiver =\n hasVideoTrackAdded ||\n Boolean(videoTransceiver) ||\n (remoteVideoStream instanceof MediaStream && remoteVideoStream.getVideoTracks().length > 0)\n\n if (!shouldReplaceExistingVideoTransceiver) {\n track.add = true\n dispatch.currentCall.setVideoTrackAdded(true)\n } else {\n // Reuse the existing video transceiver when available instead of assuming a\n // fixed mid, otherwise fall back to adding a new local video track.\n if (videoTransceiver) {\n track.replace = true\n if (videoTransceiver.mid) {\n track.mid = videoTransceiver.mid\n }\n if (!hasVideoTrackAdded) {\n dispatch.currentCall.setVideoTrackAdded(true)\n }\n } else {\n track.add = true\n dispatch.currentCall.setVideoTrackAdded(true)\n }\n }\n tracks.push(track as JanusTrack)\n\n sipcall.createOffer({\n tracks: tracks,\n success: function (jsep) {\n videoRenegotiationInFlightRef.current = false\n sipcall.send({ message: { request: 'update' }, jsep: jsep })\n notifyPeerVideoStart()\n dispatchVideoCallStarted({\n initiator: 'local',\n callUser: store.getState().currentUser.username,\n destUser: store.getState().currentCall.username,\n })\n eventDispatch('phone-island-video-enabled', {})\n },\n error: function (error) {\n videoRenegotiationInFlightRef.current = false\n console.error('WebRTC error... ' + JSON.stringify(error))\n },\n })\n }\n useEventListener('phone-island-video-enable', () => {\n enableVideo()\n })\n\n const disableVideo = () => {\n if (videoRenegotiationInFlightRef.current) {\n return\n }\n\n const { sipcall, localVideoStream }: { sipcall: any; localVideoStream: MediaStream | null } =\n store.getState().webrtc\n videoRenegotiationInFlightRef.current = true\n const videoTransceiver = sipcall?.webrtcStuff?.pc\n ?.getTransceivers?.()\n ?.find(\n (transceiver: RTCRtpTransceiver) =>\n transceiver.receiver?.track?.kind === 'video' ||\n transceiver.sender?.track?.kind === 'video',\n )\n\n janus.current.stopAllTracks(localVideoStream)\n store.dispatch.webrtc.updateLocalVideoStream(null)\n store.dispatch.currentCall.setLocalVideoEnabled(false)\n const tracks: JanusTrack[] = []\n tracks.push({\n type: 'video',\n ...(videoTransceiver?.mid ? { mid: videoTransceiver.mid } : {}),\n remove: true,\n })\n\n sipcall.createOffer({\n tracks: tracks,\n success: function (jsep) {\n videoRenegotiationInFlightRef.current = false\n sipcall.send({ message: { request: 'update' }, jsep: jsep })\n eventDispatch('phone-island-video-disabled', {})\n },\n error: function (error) {\n videoRenegotiationInFlightRef.current = false\n console.error('WebRTC error... ' + JSON.stringify(error))\n },\n })\n }\n useEventListener('phone-island-video-disable', () => {\n disableVideo()\n })\n\n const toggleVideo = async () => {\n let cameraPermission = await checkCameraPermission()\n if (cameraPermission) {\n if (isLocalVideoEnabled) {\n disableVideo()\n } else {\n enableVideo()\n }\n }\n }\n\n const shareScreen = () => {\n if (!janus.current.isExtensionEnabled()) {\n janus.current.error?.(\n \"This browser doesn't support screensharing (getDisplayMedia unavailable)\",\n )\n return\n }\n\n // Create a new room\n const roomName = janus.current.randomString(32)\n\n let create = {\n request: 'create',\n description: roomName,\n bitrate: 500000,\n publishers: 1,\n }\n\n const { plugin } = store.getState().screenShare\n\n plugin.send({\n message: create,\n success: function (result) {\n if (result['error']) {\n janus.current.error?.(\"Couldn't create room: \" + result['error'])\n return\n }\n let event = result['videoroom']\n janus.current.debug?.('Event: ' + event)\n if (event) {\n // Our own screen sharing session has been created, join it\n\n const room = result['room']\n // Set room to the store\n dispatch.screenShare.update({\n room: room,\n })\n\n janus.current.log?.('Screen sharing session created: ' + room)\n\n const { username } = store.getState().currentUser\n\n if (screenSharePublisherJoinRequestedRef.current) {\n janus.current.log?.(\n 'Screen share publisher join already requested on this handle, skipping duplicate join',\n )\n return\n }\n\n screenSharePublisherJoinRequestedRef.current = true\n\n let register = {\n request: 'join',\n room: room,\n ptype: 'publisher',\n display: username,\n }\n plugin.send({ message: register })\n }\n },\n })\n }\n\n const initScreenShare = () => {\n janusInstance?.attach({\n plugin: 'janus.plugin.videoroom',\n opaqueId: janus.current.randomString(32),\n success: function (pluginHandle) {\n // Set plugin to the store\n dispatch.screenShare.update({\n plugin: pluginHandle,\n })\n const { role } = store.getState().screenShare\n\n if (role === 'publisher') {\n // trigger event to nethlink\n eventDispatch('phone-island-screen-share-initialized', {})\n\n setTimeout(function () {\n shareScreen()\n }, 500)\n } else if (role === 'listener') {\n joinScreenShare()\n }\n eventDispatch('phone-island-screen-share-started', {})\n },\n error: function (error) {\n janus.current.error?.('Error attaching videoroom plugin', error)\n },\n consentDialog: function (on) {},\n iceState: function (state) {\n janus.current.log?.('ICE state changed to ' + state)\n },\n mediaState: function (medium, on) {\n janus.current.log?.('Janus ' + (on ? 'started' : 'stopped') + ' receiving our ' + medium)\n },\n webrtcState: function (on) {\n janus.current.log?.(\n 'Janus says our WebRTC PeerConnection is ' + (on ? 'up' : 'down') + ' now',\n )\n },\n slowLink: function (uplink, lost, mid) {\n janus.current.warn?.(\n 'Janus reports problems ' +\n (uplink ? 'sending' : 'receiving') +\n ' packets on mid ' +\n mid +\n ' (' +\n lost +\n ' lost packets)',\n )\n },\n onmessage: function (msg, jsep) {\n janus.current.debug?.(' ::: Got a message (publisher) :::', msg)\n const { plugin, role } = store.getState().screenShare\n const event = msg['videoroom']\n janus.current.debug?.('Event: ' + event)\n\n if (event) {\n if (event === 'joined') {\n if (role === 'publisher') {\n // This is our session, publish our stream\n janus.current.debug?.('Negotiating WebRTC stream for our screen')\n\n plugin.createOffer({\n // We want sendonly audio and screensharing\n tracks: [\n { type: 'audio', capture: true, recv: false },\n { type: 'screen', capture: true, recv: false },\n ],\n success: function (jsep) {\n janus.current.debug?.('Got publisher SDP!', jsep)\n let publish = { request: 'configure', audio: true, video: true }\n plugin.send({ message: publish, jsep: jsep })\n },\n error: function (error) {\n screenSharePublisherJoinRequestedRef.current = false\n janus.current.error?.('WebRTC error:', error)\n dispatch.screenShare.update({ active: false, role: '' })\n },\n })\n } else {\n // We're just watching a session, any feed to attach to?\n if (msg['publishers']) {\n let list = msg['publishers']\n janus.current.debug?.('Got a list of available publishers/feeds:', list)\n for (let f in list) {\n if (list[f]['dummy']) continue\n let id = list[f]['id']\n let display = list[f]['display']\n janus.current.debug?.(' >> [' + id + '] ' + display)\n newRemoteFeed(id, display)\n }\n }\n }\n } else if (event === 'event') {\n // Any feed to attach to?\n if (role === 'listener' && msg['publishers']) {\n let list = msg['publishers']\n janus.current.debug?.('Got a list of available publishers/feeds:', list)\n for (let f in list) {\n if (list[f]['dummy']) continue\n let id = list[f]['id']\n let display = list[f]['display']\n janus.current.debug?.(' >> [' + id + '] ' + display)\n newRemoteFeed(id, display)\n }\n } else if (msg['leaving']) {\n // One of the publishers has gone away?\n let leaving = msg['leaving']\n janus.current.log?.('Publisher left: ' + leaving)\n } else if (msg['error']) {\n janus.current.error?.('Error event: ' + msg['error'])\n }\n }\n }\n if (jsep) {\n janus.current.debug?.('Handling SDP as well...', jsep)\n plugin.handleRemoteJsep({ jsep: jsep })\n }\n },\n onlocaltrack: function (track, on) {\n janus.current.debug?.('Local track ' + (on ? 'added' : 'removed') + ':', track)\n // We use the track ID as name of the element, but it may contain invalid characters\n let trackId = track.id.replace(/[{}]/g, '')\n if (!on) {\n // Track removed, get rid of the stream and the rendering\n let stream = localTracks?.[trackId]\n if (stream) {\n try {\n let tracks = stream.getTracks()\n for (let i in tracks) {\n let mst = tracks[i]\n if (mst) mst.stop()\n }\n // eslint-disable-next-line no-unused-vars\n } catch (e) {}\n }\n if (track.kind === 'video') {\n dispatch.screenShare.update({\n localVideos: localVideos - 1,\n })\n }\n\n // remove track\n const filteredTracks = localTracks?.filter((track) => track !== localTracks[trackId])\n dispatch.screenShare.update({\n localTracks: filteredTracks,\n })\n return\n }\n // If we're here, a new track was added\n let stream = localTracks?.[trackId]\n if (stream) {\n // We've been here already\n return\n }\n\n if (track.kind === 'video') {\n // New video track: create a stream out of it\n dispatch.screenShare.update({\n localVideos: localVideos + 1,\n })\n let stream = new MediaStream([track])\n\n // Save the new video stream to the store\n store.dispatch.screenShare.update({\n localScreenStream: stream,\n })\n\n janus.current.log?.('Created local stream: ' + stream)\n const localScreenElement = store.getState().player.localScreen\n\n if (localScreenElement?.current) {\n janus.current.attachMediaStream?.(localScreenElement.current, stream)\n inviteOtherUser()\n\n // Listen for the 'ended' event on the screen-sharing track\n track.addEventListener('ended', () => {\n stopScreenShare()\n })\n }\n }\n const { plugin } = store.getState().screenShare\n\n if (\n plugin.webrtcStuff.pc.iceConnectionState !== 'completed' &&\n plugin.webrtcStuff.pc.iceConnectionState !== 'connected'\n ) {\n }\n },\n // eslint-disable-next-line no-unused-vars\n onremotetrack: function (track, mid, on) {\n // The publisher stream is sendonly, we don't expect anything here\n },\n oncleanup: function () {\n janus.current.log?.(' ::: Got a cleanup notification :::')\n screenSharePublisherJoinRequestedRef.current = false\n\n dispatch.screenShare.update({\n localTracks: {},\n localVideos: 0,\n })\n },\n })\n }\n\n const updateScreenStreams = () => {\n const localScreenElement = store.getState().player.localScreen\n const remoteScreenElement = store.getState().player.remoteScreen\n const { localScreenStream, remoteScreenStream } = store.getState().screenShare\n\n // local screen stream\n\n if (localScreenElement?.current) {\n if (janus.current.attachMediaStream) {\n janus.current.attachMediaStream(\n localScreenElement.current,\n localScreenStream as MediaStream,\n )\n }\n }\n\n // remote screen stream\n\n if (remoteScreenElement?.current) {\n if (janus.current.attachMediaStream) {\n janus.current.attachMediaStream(\n remoteScreenElement.current,\n remoteScreenStream as MediaStream,\n )\n }\n }\n }\n\n const inviteOtherUser = () => {\n // send message to websocket to invite the other user\n const { socket } = store.getState().websocket\n const { username: destUsername } = store.getState().currentCall\n const { room } = store.getState().screenShare\n const { username } = store.getState().currentUser\n\n socket.emit('message', {\n message: 'screenSharingStart',\n roomId: room,\n destUser: destUsername,\n callUser: username,\n } as ScreenSharingMessage)\n }\n\n const initAndStartScreenShare = () => {\n screenSharePublisherJoinRequestedRef.current = false\n dispatch.screenShare.update({ active: true, role: 'publisher' })\n initScreenShare()\n }\n useEventListener('phone-island-screen-share-start', () => {\n initAndStartScreenShare()\n })\n\n const initAndJoinScreenShare = () => {\n dispatch.screenShare.update({ active: true, role: 'listener' })\n initScreenShare()\n eventDispatch('phone-island-screen-share-joined', {})\n }\n\n const joinScreenShare = () => {\n const { room } = store.getState().screenShare\n const { username } = store.getState().currentUser\n\n const joinMessage = {\n request: 'join',\n room: room,\n ptype: 'publisher',\n display: username,\n }\n\n const { plugin } = store.getState().screenShare\n plugin.send({ message: joinMessage })\n }\n\n const leaveScreenShare = () => {\n const { remoteScreenStream } = store.getState().screenShare\n janus.current.stopAllTracks(remoteScreenStream)\n dispatch.screenShare.update({ active: false })\n eventDispatch('phone-island-screen-share-left', {})\n }\n\n const handleMouseMove = () => {\n setUiShown(true)\n\n if (uiTimeoutRef.current) {\n clearTimeout(uiTimeoutRef.current)\n uiTimeoutRef.current = null\n }\n }\n\n const startHideTimer = () => {\n // start a timer when mouse stops moving to hide video UI\n uiTimeoutRef.current = setTimeout(() => {\n setUiShown(false)\n }, 3000)\n }\n\n const handleMouseMoveWithDebounce = () => {\n handleMouseMove()\n\n // clear the previous debounce timer\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n\n // set a new debounce timer - when this isn't cleared, it means the mouse has stopped\n debounceTimerRef.current = setTimeout(() => {\n startHideTimer()\n }, 100) // small delay to detect \"stopped moving\"\n }\n\n const stopScreenShare = () => {\n const { plugin, localScreenStream } = store.getState().screenShare\n\n screenSharePublisherJoinRequestedRef.current = false\n janus.current.stopAllTracks(localScreenStream)\n dispatch.screenShare.update({ active: false })\n plugin.detach()\n\n // send message to websocket to tell the other user the screen share has stopped\n const { socket } = store.getState().websocket\n const { username: destUsername } = store.getState().currentCall\n const { room } = store.getState().screenShare\n const { username } = store.getState().currentUser\n\n socket.emit('message', {\n message: 'screenSharingStop',\n roomId: room,\n destUser: destUsername,\n callUser: username,\n } as ScreenSharingMessage)\n\n eventDispatch('phone-island-screen-share-stopped', {})\n }\n useEventListener('phone-island-screen-share-stop', () => {\n stopScreenShare()\n })\n\n const pauseCall = () => {\n pauseCurrentCall()\n stopScreenShare()\n }\n\n const [isVideoCallButtonVisible, setIsVideoCallButtonVisible] = useState(true)\n\n const checkCameraPermission = async () => {\n if (videoInputDevices?.length > 0) {\n const isWebCamAccepted = await checkWebCamPermission()\n if (isWebCamAccepted) {\n setIsVideoCallButtonVisible(true)\n return true\n } else {\n setIsVideoCallButtonVisible(false)\n return false\n }\n } else {\n setIsVideoCallButtonVisible(false)\n return false\n }\n }\n\n return (\n <>\n {isOpen ? (\n <div\n ref={screenShareViewRef}\n onMouseMove={() => handleMouseMoveWithDebounce()}\n className={isFullscreen ? 'pi-h-screen' : 'pi-h-[480px] pi-w-[600px]'}\n >\n <div className={`pi-flex pi-relative pi-justify-center pi-w-full pi-h-full`}>\n {/* large remote screen */}\n <video\n autoPlay\n muted={true}\n ref={remoteScreen}\n className={`pi-rounded-2xl pi-w-full pi-h-full ${\n !screenShareActive || screenShareRole !== 'listener' ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* large local screen */}\n <video\n autoPlay\n muted={true}\n ref={localScreen}\n className={`pi-rounded-2xl pi-w-full pi-h-full ${\n !screenShareActive || screenShareRole !== 'publisher' ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* large remote video */}\n <video\n autoPlay\n muted={true}\n ref={largeRemoteVideo}\n className={`pi-rounded-2xl ${\n screenShareActive || showRemoteVideoPlaceHolder ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* remote video placeholder */}\n <div\n className={`pi-w-full pi-bg-gray-200 dark:pi-bg-gray-800 pi-flex pi-items-center pi-justify-center ${\n screenShareActive || !showRemoteVideoPlaceHolder ? 'pi-hidden' : ''\n }`}\n >\n <div className='pi-rounded-full pi-bg-gray-700 dark:pi-bg-gray-200 pi-w-32 pi-h-32 pi-flex pi-items-center pi-justify-center'>\n <span className='pi-text-4xl pi-text-gray-50 dark:pi-text-gray-900'>\n {getInitials(displayName)}\n </span>\n </div>\n </div>\n {/* small local video */}\n <video\n muted={true}\n autoPlay\n ref={localVideo}\n className={`pi-max-w-32 pi-max-h-32 pi-absolute pi-top-5 pi-right-5 pi-rounded-lg ${\n !isLocalVideoEnabled ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* small local video placeholder */}\n <div\n className={`pi-w-32 pi-h-24 pi-absolute pi-top-5 pi-right-5 pi-rounded-lg pi-bg-gray-200 dark:pi-bg-gray-900 pi-flex pi-items-center pi-justify-center ${\n isLocalVideoEnabled || !hasVideoTrackAdded ? 'pi-hidden' : ''\n }`}\n >\n <div className='pi-rounded-full pi-bg-gray-700 dark:pi-bg-gray-200 pi-w-12 pi-h-12 pi-flex pi-items-center pi-justify-center'>\n <span className='pi-text-base pi-text-gray-50 dark:pi-text-gray-900'>\n {getInitials(userInfo.name || '-')}\n </span>\n </div>\n </div>\n {/* small remote video */}\n <video\n muted={true}\n autoPlay\n ref={smallRemoteVideo}\n className={`pi-max-w-32 pi-max-h-32 pi-absolute pi-top-32 pi-right-5 pi-rounded-lg ${\n !screenShareActive || showRemoteVideoPlaceHolder ? 'pi-hidden' : ''\n }`}\n ></video>\n {/* small remote video placeholder */}\n <div\n className={`pi-w-32 pi-h-24 pi-absolute pi-top-32 pi-right-5 pi-rounded-lg pi-bg-gray-200 dark:pi-bg-gray-900 pi-flex pi-items-center pi-justify-center ${\n !screenShareActive || !showRemoteVideoPlaceHolder || !hasVideoTrackAdded\n ? 'pi-hidden'\n : ''\n }`}\n >\n <div className='pi-rounded-full pi-bg-gray-700 dark:pi-bg-gray-200 pi-w-12 pi-h-12 pi-flex pi-items-center pi-justify-center'>\n <span className='pi-text-base pi-text-gray-50 dark:pi-text-gray-900'>\n {getInitials(displayName)}\n </span>\n </div>\n </div>\n </div>\n\n <div\n className={`${\n !isUiShown && 'pi-opacity-0 pi-pointer-events-none'\n } pi-absolute pi-bottom-0 pi-bg-gray-950/65 pi-w-full pi-p-6 pi-rounded-bl-[20px] pi-rounded-br-[20px] pi-transition-all`}\n >\n <div className='pi-flex pi-items-center pi-justify-center pi-gap-6 pi-mb-5'>\n {/* mute button */}\n {!intrudeListenStatus?.isListen && (\n <Button\n variant='default'\n active={muted ? true : false}\n onClick={() => (muted ? unmuteCurrentCall() : muteCurrentCall())}\n data-tooltip-id='tooltip-mute'\n data-tooltip-content={muted ? `${t('Tooltip.Unmute')}` : `${t('Tooltip.Mute')}`}\n >\n {muted ? (\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={faMicrophoneSlash} />\n ) : (\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={faMicrophone} />\n )}\n </Button>\n )}\n\n {/* video button */}\n {videoInputDevices?.length > 0 && (\n <Button\n variant='default'\n onClick={() => toggleVideo()}\n data-tooltip-id='tooltip-toggle-video'\n data-tooltip-content={`${\n !isVideoCallButtonVisible\n ? t('Tooltip.Enable camera permission') || ''\n : isLocalVideoEnabled\n ? t('Tooltip.Disable camera')\n : t('Tooltip.Enable camera')\n }`}\n disabled={!isVideoCallButtonVisible}\n className={`${!isVideoCallButtonVisible ? 'pi-cursor-auto' : ''}`}\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={isLocalVideoEnabled ? faVideoSlash : faVideo}\n />\n </Button>\n )}\n\n {/* Share screen button */}\n {janus.current.webRTCAdapter.browserDetails.browser !== 'safari' &&\n userInfo?.profile?.macro_permissions?.nethvoice_cti?.permissions?.screen_sharing\n ?.value &&\n !screenShareActive && (\n <Button\n variant='default'\n onClick={() => initAndStartScreenShare()}\n data-tooltip-id='tooltip-start-screen-share'\n data-tooltip-content={t('Tooltip.Share screen') || ''}\n >\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={faDisplay} />\n </Button>\n )}\n\n {/* stop screen share */}\n {screenShareActive && screenShareRole === 'publisher' && (\n <Button\n variant='default'\n onClick={() => stopScreenShare()}\n data-tooltip-id='tooltip-stop-screen-share'\n data-tooltip-content={t('Tooltip.Stop sharing')}\n >\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={faDisplaySlash} />\n </Button>\n )}\n\n {/* fullscreen */}\n {screenShareActive && screenShareRole === 'listener' && (\n <Button\n variant='default'\n onClick={() => toggleFullScreen()}\n data-tooltip-id='tooltip-toggle-fullscreen'\n data-tooltip-content={\n isFullscreen ? t('Tooltip.Exit fullscreen') : t('Tooltip.Enter fullscreen')\n }\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={isFullscreen ? faCompress : faExpand}\n />\n </Button>\n )}\n\n {/* record */}\n {canRecordCurrentCall && (\n <Button\n variant='default'\n onClick={() => recordCurrentCall(isRecording)}\n data-tooltip-id='tooltip-record-video-view'\n data-tooltip-content={\n isRecording ? t('Tooltip.Stop recording') : t('Tooltip.Record')\n }\n >\n <FontAwesomeIcon\n className='pi-h-6 pi-w-6'\n icon={isRecording ? faStop : faRecord}\n />\n </Button>\n )}\n\n {/* hold */}\n {!(intrudeListenStatus?.isIntrude || intrudeListenStatus?.isListen) && (\n <Button\n variant='default'\n onClick={() => (paused ? unpauseCurrentCall() : pauseCall())}\n data-tooltip-id='tooltip-pause-video-view'\n data-tooltip-content={paused ? t('Tooltip.Play') : t('Tooltip.Pause')}\n >\n <FontAwesomeIcon className='pi-h-6 pi-w-6' icon={paused ? faPlay : faPause} />\n </Button>\n )}\n </div>\n <Hangup buttonsVariant='default' />\n </div>\n {/* Buttons tooltips */}\n <CustomThemedTooltip className='pi-z-20' id='tooltip-mute-video-view' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-toggle-video' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-toggle-fullscreen' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-start-screen-share' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-stop-screen-share' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-record-video-view' place='bottom' />\n <CustomThemedTooltip className='pi-z-20' id='tooltip-pause-video-view' place='bottom' />\n </div>\n ) : (\n // collapsed view\n <>\n <div className='pi-flex pi-justify-between pi-items-center'>\n <Avatar />\n <Timer startTime={startTime} isNotAlwaysWhite />\n {!isOpen && remoteAudioStream && !isPhysical() && (\n <AudioBars\n audioStream={remoteAudioStream}\n paused={paused}\n size={isOpen ? 'large' : 'small'}\n />\n )}\n </div>\n </>\n )}\n </>\n )\n}\n\nexport default VideoView\n"],"names":["VideoView","dispatch","useDispatch","_l","useSelector","state","currentCall","muted","startTime","isRecording","paused","isLocalVideoEnabled","showRemoteVideoPlaceHolder","hasVideoTrackAdded","displayName","isStartingVideoCall","_m","screenShare","localTracks","localVideos","screenShareRole","role","screenShareActive","active","isStartingScreenShare","isJoiningScreenShare","isLeavingScreenShare","intrudeListenStatus","listen","isOpen","island","_o","webrtc","janusInstance","remoteAudioStream","userInfo","currentUser","_p","useState","isFullscreen","setIsFullscreen","_q","isUiShown","setUiShown","uiTimeoutRef","useRef","debounceTimerRef","videoRenegotiationInFlightRef","screenSharePublisherJoinRequestedRef","screenShareViewRef","localScreen","remoteScreen","localVideo","largeRemoteVideo","smallRemoteVideo","janus","JanusLib","videoInputDevices","store","select","mediaDevices","getState","activeConversation","useMemo","conversations","Object","values","find","conv","keys","length","recordingPermission","_e","_d","_c","_b","_a","profile","macro_permissions","settings","permissions","recording","value","recordingControlAvailable","isRecordingControlAvailable","canRecordCurrentCall","useIsomorphicLayoutEffect","player","updatePlayer","useEffect","updateScreenStreams","updateVideoStreams","addEventListener","handleFullscreenChange","removeEventListener","current","clearTimeout","enableVideo","updateCurrentCall","initAndStartScreenShare","update","initAndJoinScreenShare","leaveScreenShare","localVideoElement","largeRemoteVideoElement","smallRemoteVideoElement","localVideoStream","remoteVideoStream","attachMediaStream","MediaStream","getVideoTracks","document","fullscreenElement","toggleFullScreen","exitFullscreen","eventDispatch","requestFullscreen","useEventListener","newRemoteFeed","id","display","source","remoteFeed","attach","plugin","opaqueId","randomString","success","pluginHandle","remoteTracks","remoteVideos","log","call","getPlugin","getId","request","room","ptype","feed","send","message","error","iceState","rfindex","webrtcState","on","slowLink","uplink","lost","mid","warn","onmessage","msg","jsep","debug","event","_f","_h","_g","_k","_j","createAnswer","tracks","type","body","onlocaltrack","track","onremotetrack","metadata","reason","kind","remoteScreenStream","stopAllTracks","stream","remoteScreenElement","oncleanup","sipcall","currentVideoInputDeviceId","getCurrentVideoInputDeviceId","recv","capture","deviceId","exact","videoTransceiver","webrtcStuff","pc","getTransceivers","transceiver","receiver","sender","Boolean","replace","setVideoTrackAdded","add","push","createOffer","socket","destUser","callUser","websocket","username","emit","dispatchVideoCallStarted","initiator","console","JSON","stringify","disableVideo","updateLocalVideoStream","setLocalVideoEnabled","__assign","remove","initScreenShare","setTimeout","isExtensionEnabled","create","description","bitrate","publishers","result","register","shareScreen","joinScreenShare","consentDialog","mediaState","medium","_w","audio","video","list","f","leaving","_r","_t","_s","_v","_u","handleRemoteJsep","trackId","stream_2","localScreenStream","localScreenElement","inviteOtherUser","stopScreenShare","iceConnectionState","stream_1","getTracks","i","mst","stop","e","filteredTracks","filter","destUsername","roomId","joinMessage","handleMouseMoveWithDebounce","detach","isVideoCallButtonVisible","setIsVideoCallButtonVisible","checkCameraPermission","__awaiter","checkWebCamPermission","sent","React","createElement","Fragment","ref","onMouseMove","className","autoPlay","concat","getInitials","name","isListen","Button","variant","onClick","unmuteCurrentCall","muteCurrentCall","t","FontAwesomeIcon","icon","faMicrophoneSlash","faMicrophone","disabled","faVideoSlash","faVideo","webRTCAdapter","browserDetails","browser","nethvoice_cti","screen_sharing","faDisplay","faDisplaySlash","faCompress","faExpand","recordCurrentCall","faStop","faRecord","isIntrude","unpauseCurrentCall","pauseCurrentCall","faPlay","faPause","Hangup","buttonsVariant","CustomThemedTooltip","place","Avatar","Timer","isNotAlwaysWhite","isPhysical","AudioBars","audioStream","size"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "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,y=f.uaType,R=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),R=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(!R||!S||w||G&&!(x||z)){var F=R?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:R,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:R,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 o=e.result;if(null!=o&&void 0!==o.event&&null!==o.event){var i=o.event,l=a.store.getState().recorder.recording,u=a.store.getState().island.view;switch(i){case"registration_failed":M.current.error&&M.current.error("Registration failed: "+o.code+" "+o.reason);break;case"unregistered":M.current.log&&M.current.log("Successfully un-registered as "+o.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 "+o.username+"!"),console.log("[REGISTER] Registration successful",{username:o.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"!==u&&k.island.setIslandView("call");break;case"progress":M.current.log&&M.current.log("There's early media from "+o.username+", wairing for the call!"),t&&q(t,"progress"),k.webrtc.updateLastActivity((new Date).getTime());break;case"incomingcall":var g=a.store.getState().currentUser.default_device,p=a.store.getState().currentUser,f=p.endpoints,m=p.username,S=a.store.getState().users.extensions,w=function(){if(!S||!m)return!1;var e=Object.values(S).filter((function(e){return(null==e?void 0:e.username)===m}));return null==e?void 0:e.some((function(e){var t=null==f?void 0:f.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:o.username,timestamp:(new Date).toISOString()}),k.webrtc.updateWebRTC({jsepGlobal:t}),J.current=Date.now()),("mobile"===y&&w()||"desktop"===y&&("webrtc"===(null==g?void 0:g.type)||void 0===(null==g?void 0:g.type)&&!w()||!w()&&"physical"===(null==g?void 0:g.type)))&&(l?k.recorder.setIncoming(!0):(k.currentCall.checkIncomingUpdatePlay({incoming:!0,incomingWebRTC:!0}),M.current.log&&(k.currentCall.updateIncoming(!0),M.current.log("Incoming call from "+o.username+"!"))),k.webrtc.updateLastActivity((new Date).getTime()));break;case"accepted":var b=Math.floor(Date.now()/1e3);if(M.current.log){var h=o.username||o.displayname||a.store.getState().currentCall.number||"Remote party";M.current.log(h+" accepted the call!")}t&&q(t,"accepted"),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==b?void 0:b.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,l&&k.recorder.setRecording(!1),v.isPhysical()||"mobile"===y||(c.hangupCurrentCall(),n.hangup(),a.store.dispatch.player.stopAudioPlayer(),a.store.dispatch.currentCall.reset(),M.current.log&&M.current.log("Call hung up ("+o.code+" "+o.reason+")!"),k.webrtc.updateLastActivity((new Date).getTime())),a.store.dispatch.player.stopAudioPlayer();var D=a.store.getState().screenShare,I=D.active,C=D.plugin,A=D.localScreenStream,T=D.remoteScreenStream;I&&(M.current.stopAllTracks(A),M.current.stopAllTracks(T),k.screenShare.update({active:!1}),C.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"===o.type&&o.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:",i)}}}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),R&&R(),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"),R&&R()}}),[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)};
1
+ "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)};
2
2
  //# sourceMappingURL=WebRTC.js.map