@nethesis/phone-island 1.0.9-dev.5 → 1.0.9-dev.7
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.
- package/dist/App.js +1 -1
- package/dist/App.js.map +1 -1
- package/dist/components/SideView/hooks/useSideViewLogic.js +1 -1
- package/dist/components/SideView/hooks/useSideViewLogic.js.map +1 -1
- package/dist/components/Socket.js +1 -1
- package/dist/components/Socket.js.map +1 -1
- package/dist/components/TranscriptionView/TranscriptionView.js.map +1 -1
- package/dist/components/VideoView/index.js +1 -1
- package/dist/components/VideoView/index.js.map +1 -1
- package/dist/lib/phone/call.js +1 -1
- package/dist/lib/phone/call.js.map +1 -1
- package/dist/package.json.js +1 -1
- package/dist/services/user.js +1 -1
- package/dist/services/user.js.map +1 -1
- package/dist/utils/genericFunctions/summaryEvents.js +2 -0
- package/dist/utils/genericFunctions/summaryEvents.js.map +1 -0
- package/package.json +1 -1
|
@@ -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, 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
|
+
{"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={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 {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","faVideoSlash","faVideo","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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"}
|
package/dist/lib/phone/call.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../node_modules/tslib/tslib.es6.js"),t=require("../webrtc/messages.js"),r=require("../../store/index.js"),n=require("../user/default_device.js"),s=require("../../services/astproxy.js"),o=require("../../static/dtmf/index.js");require("react");var i=require("../../utils/genericFunctions/eventDispatch.js"),a=require("../../services/user.js"),c=require("../../utils/genericFunctions/isEmpty.js"),u=require("../../utils/streaming/getStreamingSourceId.js");function l(){var e=r.store.getState().currentCall,o=e.outgoing,c=e.accepted,l=e.streamingSourceNumber,d=r.store.getState().island.isFromStreaming;if(o||c){if(n.isWebRTC()?t.hangup():s.hangupPhysical(),r.store.dispatch.player.stopAudioPlayer(),r.store.dispatch.currentCall.reset(),r.store.dispatch.listen.reset(),d&&l){var v=u.getStreamingSourceId(l);v&&(a.unsubscribe({id:v}).then((function(){return console.debug("Unsubscribed from streaming source: ".concat(v))})).catch((function(e){return console.error("Error unsubscribing from streaming source:",e)})),r.store.dispatch.streaming.clearSourceImages())}r.store.dispatch.island.setIsFromStreaming(!1)}r.store.dispatch.island.resetOperatorBusy(),i.eventDispatch("phone-island-call-ended",{})}function d(){n.isWebRTC()?t.unpauseWebRTC()&&(r.store.dispatch.currentCall.updateCurrentCall({paused:!1}),r.store.dispatch.player.playRemoteAudio()):s.pausePhysical(!1);i.eventDispatch("phone-island-call-unheld",{})}function v(t){return e.__awaiter(this,void 0,void 0,(function(){var n,o,i;return e.__generator(this,(function(e){switch(e.label){case 0:return n=r.store.getState().currentCall.conversationId,o=r.store.getState().currentUser.default_device,i=(null==o?void 0:o.id)||(null==o?void 0:o.exten),n&&i&&t?[4,s.attendedTransfer({convid:n,to:t,endpointId:i})]:[3,2];case 1:return[2,e.sent()];case 2:return[2]}}))}))}var p=function(e){return!e||!1!==e.recordingControlAvailable};function f(){var t;return e.__awaiter(this,void 0,void 0,(function(){var n,o,a,u,l,d,v,p,f,h,g,C,b,m;return e.__generator(this,(function(e){switch(e.label){case 0:if(n=null===(t=null===r.store||void 0===r.store?void 0:r.store.getState())||void 0===t?void 0:t.currentCall,o=n.accepted,a=n.chSource,u=n.chDest,l=n.incoming,d=n.outgoing,v=n.incomingSocket,p=n.outgoingSocket,f=n.conversationId,h=r.store.getState().currentUser.default_device,g=(null==h?void 0:h.id)||(null==h?void 0:h.exten),C="",o&&(l||v)&&!c.isEmpty(a)?C=null==a?void 0:a.callerNum:o&&(d||p)&&!c.isEmpty(u)&&(C=null==u?void 0:u.callerNum),""===g||""===f||""===C)return[3,4];if(!(b={convid:null==f?void 0:f.toString(),addEndpointId:null==C?void 0:C.toString(),ownerEndpointId:null==g?void 0:g.toString()}))return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,s.startConf(b)];case 2:return e.sent()?(r.store.dispatch.currentCall.updateCurrentCall({conferencing:!0,paused:!1}),i.eventDispatch("phone-island-call-conferenced",{}),[2,!0]):[2,!1];case 3:return m=e.sent(),console.error(m),[2,!1];case 4:return[2,!1]}}))}))}function h(){return e.__awaiter(this,void 0,void 0,(function(){var t,n,o;return e.__generator(this,(function(e){switch(e.label){case 0:if(""===(t=r.store.getState().conference.conferenceId))return[3,4];if(!(n={confId:null==t?void 0:t.toString()}))return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,s.endConf(n)];case 2:return e.sent()?(i.eventDispatch("phone-island-owner-conference-finished",{}),[2,!0]):[2,!1];case 3:return o=e.sent(),console.error(o),[2,!1];case 4:return[2,!1]}}))}))}var g=function(){return!!r.store.getState().island.isConferenceList},C=function(e,t){var n=r.store.getState(),s=n.currentUser.username,o=n.conference,a=o.isActive,c=o.isOwnerInside,u=o.conferenceId,d=n.users.extensions;!a&&s&&(t.conference.setConferenceActive(!0),t.conference.setConferenceStartedFrom(s));var v=d?Object.values(d).find((function(t){return t.exten===e})):null,p=(null==v?void 0:v.name)||e;t.conference.addPendingUser({id:"".concat(u,"-").concat(e),name:p,owner:!1,muted:!1,extenId:e,joinTime:Date.now()}),c&&(l(),t.conference.toggleIsOwnerInside(!1)),requestAnimationFrame((function(){setTimeout((function(){i.eventDispatch("phone-island-call-start",{number:e})}),1e3)}))};function b(t,r){return e.__awaiter(this,void 0,void 0,(function(){return e.__generator(this,(function(e){switch(e.label){case 0:return d(),[4,v(t)];case 1:return e.sent()&&(r.currentCall.updateCurrentCall({transferring:!0,paused:!1}),requestAnimationFrame((function(){r.player.playRemoteAudio(),i.eventDispatch("phone-island-call-transfered",{})}))),[2]}}))}))}exports.answerIncomingCall=function(){n.isWebRTC()?t.answerWebRTC():s.answerPhysical(),r.store.dispatch.island.resetOperatorBusyCompletely()},exports.attendedTransfer=v,exports.blindTransferFunction=function(t,n){return e.__awaiter(this,void 0,void 0,(function(){var o;return e.__generator(this,(function(e){switch(e.label){case 0:return(o=r.store.getState().currentCall.conversationId)&&n&&t?[4,s.blindTransfer({convid:o,to:t,endpointId:n})]:[3,2];case 1:return[2,e.sent()];case 2:return[2]}}))}))},exports.callNumber=function(e,o){var a="sip:".concat(e,"@").concat(o);r.store.dispatch.island.resetOperatorBusy(),r.store.dispatch.island.setOperatorBusyCalledNumber(e),n.isWebRTC()?t.callSipURI(a):s.callPhysical(e),i.eventDispatch("phone-island-call-started",{})},exports.clickTransferOrConference=function(t,n){return e.__awaiter(void 0,void 0,void 0,(function(){return e.__generator(this,(function(e){switch(e.label){case 0:return g()?r.store.getState().conference.isActive?[3,2]:[4,f()]:[3,3];case 1:if(!e.sent())return[2];e.label=2;case 2:return C(t,n),[3,4];case 3:b(t,n),e.label=4;case 4:return[2]}}))}))},exports.endConference=h,exports.forceHangupConversation=function(){var e=r.store.getState().currentUser.conversations,t=function(t){Object.keys(e[t]).forEach((function(e){s.forceHangup({convid:e,endpointId:t,endpointType:"extension"})}))};for(var n in e)t(n)},exports.handleAttendedTransfer=b,exports.hangupAllExtensions=function(){var e=r.store.getState().currentUser.conversations,t=function(t){Object.keys(e[t]).forEach((function(e){s.hangupConversation({convid:e,endpointId:t})}))};for(var n in e)t(n)},exports.hangupCurrentCall=l,exports.hangupCurrentPhysicalRecording=function(){s.hangupPhysicalRecordingCall(),r.store.dispatch.player.stopAudioPlayer(),r.store.dispatch.physicalRecorder.reset(),r.store.dispatch.physicalRecorder.setRecording(!1),r.store.dispatch.island.setIslandView(null),r.store.dispatch.listen.reset(),i.eventDispatch("phone-island-call-ended",{})},exports.isInsideConferenceList=g,exports.isRecordingControlAvailable=p,exports.joinConference=function(){return e.__awaiter(this,void 0,void 0,(function(){var t,n,o,a;return e.__generator(this,(function(e){switch(e.label){case 0:if(t=r.store.getState().currentUser.default_device,""===(n=(null==t?void 0:t.id)||(null==t?void 0:t.exten)))return[3,4];if(!(o={endpointId:null==n?void 0:n.toString()}))return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,s.joinMyConf(o)];case 2:return e.sent()?(i.eventDispatch("phone-island-owner-conference-enter",{}),[2,!0]):[2,!1];case 3:return a=e.sent(),console.error(a),[2,!1];case 4:return[2,!1]}}))}))},exports.muteAllUsersConference=function(t,n){var o;return e.__awaiter(this,void 0,void 0,(function(){var i,a,c,u,l,d,v,p;return e.__generator(this,(function(e){switch(e.label){case 0:if(""===t)return[2,!1];if(!(i=r.store.getState().conference.usersList)||0===Object.keys(i).length)return[2,!1];e.label=1;case 1:e.trys.push([1,6,,7]),a=Object.values(i),c=n?s.unmuteUserConf:s.muteUserConf,u=0,l=a,e.label=2;case 2:return u<l.length?(d=l[u],v={confId:null==t?void 0:t.toString(),userId:null===(o=d.id)||void 0===o?void 0:o.toString()},[4,c(v)]):[3,5];case 3:e.sent()&&r.store.dispatch.conference.toggleUserMuted({extenId:d.extenId,muted:!n}),e.label=4;case 4:return u++,[3,2];case 5:return[2,!0];case 6:return p=e.sent(),console.error(p),[2,!1];case 7:return[2]}}))}))},exports.muteCurrentCall=function(){n.isWebRTC()?t.muteWebRTC()&&r.store.dispatch.currentCall.updateCurrentCall({muted:!0}):s.mutePhysical(!0),i.eventDispatch("phone-island-call-muted",{})},exports.muteUserConference=function(t,r,n){return e.__awaiter(this,void 0,void 0,(function(){var o,i;return e.__generator(this,(function(e){switch(e.label){case 0:if(""===t||""===r)return[2,!1];o={confId:null==t?void 0:t.toString(),userId:null==r?void 0:r.toString()},e.label=1;case 1:return e.trys.push([1,3,,4]),[4,(n?s.unmuteUserConf:s.muteUserConf)(o)];case 2:return[2,!!e.sent()];case 3:return i=e.sent(),console.error(i),[2,!1];case 4:return[2]}}))}))},exports.parkCurrentCall=function(){var e,t,n,o,a=null===(t=null===(e=null===r.store||void 0===r.store?void 0:r.store.getState())||void 0===e?void 0:e.currentCall)||void 0===t?void 0:t.conversationId,c=null===(o=null===(n=null===r.store||void 0===r.store?void 0:r.store.getState())||void 0===n?void 0:n.currentUser)||void 0===o?void 0:o.conversations,u={};if(a){if(c)for(var l in c)if(c.hasOwnProperty(l)){var d=c[l];Object.keys(d).length>0&&(u={numberParkId:l,idConversation:a})}Object.keys(u).length>0&&(null==u?void 0:u.numberParkId)&&(s.parkConversation({applicantId:null==u?void 0:u.numberParkId,convid:a,endpointId:null==u?void 0:u.numberParkId}),r.store.dispatch.currentCall.setParked(!0),i.eventDispatch("phone-island-call-parked",{}))}},exports.pauseCurrentCall=function(){n.isWebRTC()?t.pauseWebRTC()&&(r.store.dispatch.currentCall.updateCurrentCall({paused:!0}),r.store.dispatch.player.pauseRemoteAudio()):s.pausePhysical(!0),i.eventDispatch("phone-island-call-held",{})},exports.playDtmfAudio=function(e){"*"===e&&(e="star"),"#"===e&&(e="pound"),r.store.dispatch.player.updateStartAudioPlayer({src:o.default["dtmf_".concat(e)]})},exports.recordCurrentCall=function(t){var n,o,i,a;return e.__awaiter(this,void 0,void 0,(function(){var c,u,l,d,v,f,h;return e.__generator(this,(function(e){switch(e.label){case 0:return c=null===(o=null===(n=null===r.store||void 0===r.store?void 0:r.store.getState())||void 0===n?void 0:n.currentUser)||void 0===o?void 0:o.conversations,(u=function(e){for(var t in e)if(0!==Object.keys(e[t]).length){var r=Object.values(e[t])[0];return{id:r.id,recording:r.recording,recordingControlAvailable:r.recordingControlAvailable}}return null}(c))?[3,1]:[2];case 1:if(!p(u))return[2];switch(l=null===(i=null==u?void 0:u.id)||void 0===i?void 0:i.match(/\/(\d+)-/),d=l[1],v={convid:null===(a=null==u?void 0:u.id)||void 0===a?void 0:a.toString(),endpointId:null==d?void 0:d.toString()},f="",null==u?void 0:u.recording){case"false":f="start_record";break;case"true":f="stop_record";break;default:f=""}if(!v||!f)return[3,5];e.label=2;case 2:return e.trys.push([2,4,,5]),[4,s.toggleRecord(f,v)];case 3:return e.sent(),r.store.dispatch.currentCall.updateRecordingStatus(!t),[3,5];case 4:return h=e.sent(),console.error(h),[2,[]];case 5:return[2]}}))}))},exports.removeUserConference=function(t,n){return e.__awaiter(this,void 0,void 0,(function(){var o,i,a=this;return e.__generator(this,(function(c){switch(c.label){case 0:if(""===t||""===n)return[3,4];if(!(o={confId:null==t?void 0:t.toString(),extenId:null==n?void 0:n.toString()}))return[3,4];c.label=1;case 1:return c.trys.push([1,3,,4]),[4,s.hangupUserConf(o)];case 2:return c.sent()?(setTimeout((function(){return e.__awaiter(a,void 0,void 0,(function(){var t,s;return e.__generator(this,(function(e){switch(e.label){case 0:return t=r.store.getState().conference.usersList,s=Object.values(t||{}).filter((function(e){return!e.owner&&e.extenId!==n})).length,0!==s?[3,2]:[4,h()];case 1:e.sent(),e.label=2;case 2:return[2]}}))}))}),500),[2,!0]):[2,!1];case 3:return i=c.sent(),console.error(i),[2,!1];case 4:return[2,!1]}}))}))},exports.startConference=f,exports.unmuteCurrentCall=function(){n.isWebRTC()?t.unmuteWebRTC()&&r.store.dispatch.currentCall.updateCurrentCall({muted:!1}):s.mutePhysical(!1),i.eventDispatch("phone-island-call-unmuted",{})},exports.unpauseCurrentCall=d,exports.waitingConferenceView=C;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../node_modules/tslib/tslib.es6.js"),t=require("../webrtc/messages.js"),r=require("../../store/index.js"),n=require("../user/default_device.js"),s=require("../../services/astproxy.js"),o=require("../../static/dtmf/index.js");require("react");var i=require("../../utils/genericFunctions/eventDispatch.js"),a=require("../../services/user.js"),c=require("../../utils/genericFunctions/isEmpty.js"),u=require("../../utils/streaming/getStreamingSourceId.js");function l(){var e=r.store.getState().currentCall,o=e.outgoing,c=e.accepted,l=e.streamingSourceNumber,d=r.store.getState().island.isFromStreaming;if(o||c){if(n.isWebRTC()?t.hangup():s.hangupPhysical(),r.store.dispatch.player.stopAudioPlayer(),r.store.dispatch.currentCall.reset(),r.store.dispatch.listen.reset(),d&&l){var p=u.getStreamingSourceId(l);p&&(a.unsubscribe({id:p}).then((function(){return console.debug("Unsubscribed from streaming source: ".concat(p))})).catch((function(e){return console.error("Error unsubscribing from streaming source:",e)})),r.store.dispatch.streaming.clearSourceImages())}r.store.dispatch.island.setIsFromStreaming(!1)}r.store.dispatch.island.resetOperatorBusy(),i.eventDispatch("phone-island-call-ended",{})}function d(){n.isWebRTC()?t.unpauseWebRTC()&&(r.store.dispatch.currentCall.updateCurrentCall({paused:!1}),r.store.dispatch.player.playRemoteAudio()):s.pausePhysical(!1);i.eventDispatch("phone-island-call-unheld",{})}function p(t){return e.__awaiter(this,void 0,void 0,(function(){var n,o,i;return e.__generator(this,(function(e){switch(e.label){case 0:return n=r.store.getState().currentCall.conversationId,o=r.store.getState().currentUser.default_device,i=(null==o?void 0:o.id)||(null==o?void 0:o.exten),n&&i&&t?[4,s.attendedTransfer({convid:n,to:t,endpointId:i})]:[3,2];case 1:return[2,e.sent()];case 2:return[2]}}))}))}function v(){var t;return e.__awaiter(this,void 0,void 0,(function(){var n,o,a,u,l,d,p,v,f,h,g,C,m,b;return e.__generator(this,(function(e){switch(e.label){case 0:if(n=null===(t=null===r.store||void 0===r.store?void 0:r.store.getState())||void 0===t?void 0:t.currentCall,o=n.accepted,a=n.chSource,u=n.chDest,l=n.incoming,d=n.outgoing,p=n.incomingSocket,v=n.outgoingSocket,f=n.conversationId,h=r.store.getState().currentUser.default_device,g=(null==h?void 0:h.id)||(null==h?void 0:h.exten),C="",o&&(l||p)&&!c.isEmpty(a)?C=null==a?void 0:a.callerNum:o&&(d||v)&&!c.isEmpty(u)&&(C=null==u?void 0:u.callerNum),""===g||""===f||""===C)return[3,4];if(!(m={convid:null==f?void 0:f.toString(),addEndpointId:null==C?void 0:C.toString(),ownerEndpointId:null==g?void 0:g.toString()}))return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,s.startConf(m)];case 2:return e.sent()?(r.store.dispatch.currentCall.updateCurrentCall({conferencing:!0,paused:!1}),i.eventDispatch("phone-island-call-conferenced",{}),[2,!0]):[2,!1];case 3:return b=e.sent(),console.error(b),[2,!1];case 4:return[2,!1]}}))}))}function f(){return e.__awaiter(this,void 0,void 0,(function(){var t,n,o;return e.__generator(this,(function(e){switch(e.label){case 0:if(""===(t=r.store.getState().conference.conferenceId))return[3,4];if(!(n={confId:null==t?void 0:t.toString()}))return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,s.endConf(n)];case 2:return e.sent()?(i.eventDispatch("phone-island-owner-conference-finished",{}),[2,!0]):[2,!1];case 3:return o=e.sent(),console.error(o),[2,!1];case 4:return[2,!1]}}))}))}var h=function(){return!!r.store.getState().island.isConferenceList},g=function(e,t){var n=r.store.getState(),s=n.currentUser.username,o=n.conference,a=o.isActive,c=o.isOwnerInside,u=o.conferenceId,d=n.users.extensions;!a&&s&&(t.conference.setConferenceActive(!0),t.conference.setConferenceStartedFrom(s));var p=d?Object.values(d).find((function(t){return t.exten===e})):null,v=(null==p?void 0:p.name)||e;t.conference.addPendingUser({id:"".concat(u,"-").concat(e),name:v,owner:!1,muted:!1,extenId:e,joinTime:Date.now()}),c&&(l(),t.conference.toggleIsOwnerInside(!1)),requestAnimationFrame((function(){setTimeout((function(){i.eventDispatch("phone-island-call-start",{number:e})}),1e3)}))};function C(t,r){return e.__awaiter(this,void 0,void 0,(function(){return e.__generator(this,(function(e){switch(e.label){case 0:return d(),[4,p(t)];case 1:return e.sent()&&(r.currentCall.updateCurrentCall({transferring:!0,paused:!1}),requestAnimationFrame((function(){r.player.playRemoteAudio(),i.eventDispatch("phone-island-call-transfered",{})}))),[2]}}))}))}exports.answerIncomingCall=function(){n.isWebRTC()?t.answerWebRTC():s.answerPhysical(),r.store.dispatch.island.resetOperatorBusyCompletely()},exports.attendedTransfer=p,exports.blindTransferFunction=function(t,n){return e.__awaiter(this,void 0,void 0,(function(){var o;return e.__generator(this,(function(e){switch(e.label){case 0:return(o=r.store.getState().currentCall.conversationId)&&n&&t?[4,s.blindTransfer({convid:o,to:t,endpointId:n})]:[3,2];case 1:return[2,e.sent()];case 2:return[2]}}))}))},exports.callNumber=function(e,o){var a="sip:".concat(e,"@").concat(o);r.store.dispatch.island.resetOperatorBusy(),r.store.dispatch.island.setOperatorBusyCalledNumber(e),n.isWebRTC()?t.callSipURI(a):s.callPhysical(e),i.eventDispatch("phone-island-call-started",{})},exports.clickTransferOrConference=function(t,n){return e.__awaiter(void 0,void 0,void 0,(function(){return e.__generator(this,(function(e){switch(e.label){case 0:return h()?r.store.getState().conference.isActive?[3,2]:[4,v()]:[3,3];case 1:if(!e.sent())return[2];e.label=2;case 2:return g(t,n),[3,4];case 3:C(t,n),e.label=4;case 4:return[2]}}))}))},exports.endConference=f,exports.forceHangupConversation=function(){var e=r.store.getState().currentUser.conversations,t=function(t){Object.keys(e[t]).forEach((function(e){s.forceHangup({convid:e,endpointId:t,endpointType:"extension"})}))};for(var n in e)t(n)},exports.handleAttendedTransfer=C,exports.hangupAllExtensions=function(){var e=r.store.getState().currentUser.conversations,t=function(t){Object.keys(e[t]).forEach((function(e){s.hangupConversation({convid:e,endpointId:t})}))};for(var n in e)t(n)},exports.hangupCurrentCall=l,exports.hangupCurrentPhysicalRecording=function(){s.hangupPhysicalRecordingCall(),r.store.dispatch.player.stopAudioPlayer(),r.store.dispatch.physicalRecorder.reset(),r.store.dispatch.physicalRecorder.setRecording(!1),r.store.dispatch.island.setIslandView(null),r.store.dispatch.listen.reset(),i.eventDispatch("phone-island-call-ended",{})},exports.isInsideConferenceList=h,exports.joinConference=function(){return e.__awaiter(this,void 0,void 0,(function(){var t,n,o,a;return e.__generator(this,(function(e){switch(e.label){case 0:if(t=r.store.getState().currentUser.default_device,""===(n=(null==t?void 0:t.id)||(null==t?void 0:t.exten)))return[3,4];if(!(o={endpointId:null==n?void 0:n.toString()}))return[3,4];e.label=1;case 1:return e.trys.push([1,3,,4]),[4,s.joinMyConf(o)];case 2:return e.sent()?(i.eventDispatch("phone-island-owner-conference-enter",{}),[2,!0]):[2,!1];case 3:return a=e.sent(),console.error(a),[2,!1];case 4:return[2,!1]}}))}))},exports.muteAllUsersConference=function(t,n){var o;return e.__awaiter(this,void 0,void 0,(function(){var i,a,c,u,l,d,p,v;return e.__generator(this,(function(e){switch(e.label){case 0:if(""===t)return[2,!1];if(!(i=r.store.getState().conference.usersList)||0===Object.keys(i).length)return[2,!1];e.label=1;case 1:e.trys.push([1,6,,7]),a=Object.values(i),c=n?s.unmuteUserConf:s.muteUserConf,u=0,l=a,e.label=2;case 2:return u<l.length?(d=l[u],p={confId:null==t?void 0:t.toString(),userId:null===(o=d.id)||void 0===o?void 0:o.toString()},[4,c(p)]):[3,5];case 3:e.sent()&&r.store.dispatch.conference.toggleUserMuted({extenId:d.extenId,muted:!n}),e.label=4;case 4:return u++,[3,2];case 5:return[2,!0];case 6:return v=e.sent(),console.error(v),[2,!1];case 7:return[2]}}))}))},exports.muteCurrentCall=function(){n.isWebRTC()?t.muteWebRTC()&&r.store.dispatch.currentCall.updateCurrentCall({muted:!0}):s.mutePhysical(!0),i.eventDispatch("phone-island-call-muted",{})},exports.muteUserConference=function(t,r,n){return e.__awaiter(this,void 0,void 0,(function(){var o,i;return e.__generator(this,(function(e){switch(e.label){case 0:if(""===t||""===r)return[2,!1];o={confId:null==t?void 0:t.toString(),userId:null==r?void 0:r.toString()},e.label=1;case 1:return e.trys.push([1,3,,4]),[4,(n?s.unmuteUserConf:s.muteUserConf)(o)];case 2:return[2,!!e.sent()];case 3:return i=e.sent(),console.error(i),[2,!1];case 4:return[2]}}))}))},exports.parkCurrentCall=function(){var e,t,n,o,a=null===(t=null===(e=null===r.store||void 0===r.store?void 0:r.store.getState())||void 0===e?void 0:e.currentCall)||void 0===t?void 0:t.conversationId,c=null===(o=null===(n=null===r.store||void 0===r.store?void 0:r.store.getState())||void 0===n?void 0:n.currentUser)||void 0===o?void 0:o.conversations,u={};if(a){if(c)for(var l in c)if(c.hasOwnProperty(l)){var d=c[l];Object.keys(d).length>0&&(u={numberParkId:l,idConversation:a})}Object.keys(u).length>0&&(null==u?void 0:u.numberParkId)&&(s.parkConversation({applicantId:null==u?void 0:u.numberParkId,convid:a,endpointId:null==u?void 0:u.numberParkId}),r.store.dispatch.currentCall.setParked(!0),i.eventDispatch("phone-island-call-parked",{}))}},exports.pauseCurrentCall=function(){n.isWebRTC()?t.pauseWebRTC()&&(r.store.dispatch.currentCall.updateCurrentCall({paused:!0}),r.store.dispatch.player.pauseRemoteAudio()):s.pausePhysical(!0),i.eventDispatch("phone-island-call-held",{})},exports.playDtmfAudio=function(e){"*"===e&&(e="star"),"#"===e&&(e="pound"),r.store.dispatch.player.updateStartAudioPlayer({src:o.default["dtmf_".concat(e)]})},exports.recordCurrentCall=function(t){var n,o,i,a;return e.__awaiter(this,void 0,void 0,(function(){var c,u,l,d,p,v,f;return e.__generator(this,(function(e){switch(e.label){case 0:return r.store.dispatch.currentCall.updateRecordingStatus(!t),c=null===(o=null===(n=null===r.store||void 0===r.store?void 0:r.store.getState())||void 0===n?void 0:n.currentUser)||void 0===o?void 0:o.conversations,(u=function(e){for(var t in e)if(0!==Object.keys(e[t]).length){var r=Object.values(e[t])[0];return{id:r.id,recording:r.recording}}return null}(c))?[3,1]:[2];case 1:switch(l=null===(i=null==u?void 0:u.id)||void 0===i?void 0:i.match(/\/(\d+)-/),d=l[1],p={convid:null===(a=null==u?void 0:u.id)||void 0===a?void 0:a.toString(),endpointId:null==d?void 0:d.toString()},v="",null==u?void 0:u.recording){case"false":v="start_record";break;case"true":v="mute_record";break;case"mute":v="unmute_record";break;default:v=""}if(!p)return[3,5];e.label=2;case 2:return e.trys.push([2,4,,5]),[4,s.toggleRecord(v,p)];case 3:return e.sent(),[3,5];case 4:return f=e.sent(),console.error(f),[2,[]];case 5:return[2]}}))}))},exports.removeUserConference=function(t,n){return e.__awaiter(this,void 0,void 0,(function(){var o,i,a=this;return e.__generator(this,(function(c){switch(c.label){case 0:if(""===t||""===n)return[3,4];if(!(o={confId:null==t?void 0:t.toString(),extenId:null==n?void 0:n.toString()}))return[3,4];c.label=1;case 1:return c.trys.push([1,3,,4]),[4,s.hangupUserConf(o)];case 2:return c.sent()?(setTimeout((function(){return e.__awaiter(a,void 0,void 0,(function(){var t,s;return e.__generator(this,(function(e){switch(e.label){case 0:return t=r.store.getState().conference.usersList,s=Object.values(t||{}).filter((function(e){return!e.owner&&e.extenId!==n})).length,0!==s?[3,2]:[4,f()];case 1:e.sent(),e.label=2;case 2:return[2]}}))}))}),500),[2,!0]):[2,!1];case 3:return i=c.sent(),console.error(i),[2,!1];case 4:return[2,!1]}}))}))},exports.startConference=v,exports.unmuteCurrentCall=function(){n.isWebRTC()?t.unmuteWebRTC()&&r.store.dispatch.currentCall.updateCurrentCall({muted:!1}):s.mutePhysical(!1),i.eventDispatch("phone-island-call-unmuted",{})},exports.unpauseCurrentCall=d,exports.waitingConferenceView=g;
|
|
2
2
|
//# sourceMappingURL=call.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call.js","sources":["../../../src/lib/phone/call.ts"],"sourcesContent":["// Copyright (C) 2024 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport {\n callSipURI,\n hangup,\n answerWebRTC,\n muteWebRTC,\n unmuteWebRTC,\n pauseWebRTC,\n unpauseWebRTC,\n} from '../webrtc/messages'\nimport { Dispatch, store } from '../../store'\nimport { isWebRTC } from '../user/default_device'\nimport {\n blindTransfer as blindTransferRequest,\n attendedTransfer as attendedTransferRequest,\n hangupPhysical,\n answerPhysical,\n mutePhysical,\n pausePhysical,\n callPhysical,\n toggleRecord,\n hangupPhysicalRecordingCall,\n startConf,\n joinMyConf,\n endConf,\n muteUserConf,\n unmuteUserConf,\n hangupUserConf,\n forceHangup,\n} from '../../services/astproxy'\nimport dtmfAudios from '../../static/dtmf'\nimport { hangupConversation, parkConversation } from '../../services/astproxy'\nimport { eventDispatch } from '../../utils'\nimport { isEmpty } from '../../utils/genericFunctions/isEmpty'\nimport { getStreamingSourceId } from '../../utils/streaming/getStreamingSourceId'\nimport { unsubscribe } from '../../services/user'\n\n/**\n * Starts a call to a number\n * @param number The number string\n */\nexport function callNumber(number: string, sipHost: string) {\n const sipURI = `sip:${number}@${sipHost}`\n\n // Reset any previous operator busy state when starting a new call\n store.dispatch.island.resetOperatorBusy()\n // Save the called number for potential operator busy scenarios\n store.dispatch.island.setOperatorBusyCalledNumber(number)\n\n if (isWebRTC()) {\n callSipURI(sipURI)\n } else {\n callPhysical(number)\n }\n\n eventDispatch('phone-island-call-started', {})\n}\n\n/**\n * Answer incoming call\n */\nexport function answerIncomingCall() {\n if (isWebRTC()) {\n answerWebRTC()\n } else {\n answerPhysical()\n }\n // Reset operator busy completely when call is answered successfully\n store.dispatch.island.resetOperatorBusyCompletely()\n}\n\n/**\n * Hangup all the conversations of all the extensions of the current user\n */\nexport function hangupAllExtensions() {\n // Get current user endpoints\n const { conversations } = store.getState().currentUser\n // Hangup all the conversations of all extensions of the current user\n for (const extension in conversations) {\n const conversationsIds = Object.keys(conversations[extension])\n conversationsIds.forEach((id) => {\n hangupConversation({\n convid: id,\n endpointId: extension,\n })\n })\n }\n}\n\nexport function forceHangupConversation() {\n // Get current user endpoints\n const { conversations } = store.getState().currentUser\n // Hangup all the conversations of all extensions of the current user\n for (const extension in conversations) {\n const conversationsIds = Object.keys(conversations[extension])\n conversationsIds.forEach((id) => {\n forceHangup({\n convid: id,\n endpointId: extension,\n endpointType: 'extension',\n })\n })\n }\n}\n\n/**\n * Hangup current call\n */\nexport function hangupCurrentCall() {\n const { outgoing, accepted, streamingSourceNumber } = store.getState().currentCall\n const { isFromStreaming } = store.getState().island\n\n if (outgoing || accepted) {\n if (isWebRTC()) {\n hangup()\n } else {\n hangupPhysical()\n }\n store.dispatch.player.stopAudioPlayer()\n store.dispatch.currentCall.reset()\n store.dispatch.listen.reset()\n\n // If call was from a streaming source, unsubscribe and clear images\n if (isFromStreaming && streamingSourceNumber) {\n const sourceId = getStreamingSourceId(streamingSourceNumber)\n if (sourceId) {\n // Unsubscribe from streaming updates\n unsubscribe({ id: sourceId })\n .then(() => console.debug(`Unsubscribed from streaming source: ${sourceId}`))\n .catch((error) => console.error('Error unsubscribing from streaming source:', error))\n\n // Clear source images to free up memory\n store.dispatch.streaming.clearSourceImages()\n }\n }\n\n // Reset isFromStreaming flag\n store.dispatch.island.setIsFromStreaming(false)\n }\n // Reset operator busy state when call ends\n store.dispatch.island.resetOperatorBusy()\n // Caller close the call before the call is accepted\n eventDispatch('phone-island-call-ended', {})\n}\n\n/**\n * Hangup current physical recording\n */\nexport function hangupCurrentPhysicalRecording() {\n hangupPhysicalRecordingCall()\n store.dispatch.player.stopAudioPlayer()\n store.dispatch.physicalRecorder.reset()\n store.dispatch.physicalRecorder.setRecording(false)\n store.dispatch.island.setIslandView(null)\n store.dispatch.listen.reset()\n // Caller close the call before the call is accepted\n eventDispatch('phone-island-call-ended', {})\n}\n\n/**\n * Mute the current call\n */\nexport function muteCurrentCall() {\n // Check the current user default device\n if (isWebRTC()) {\n const muted = muteWebRTC()\n if (muted) {\n store.dispatch.currentCall.updateCurrentCall({\n muted: true,\n })\n }\n } else {\n mutePhysical(true)\n }\n eventDispatch('phone-island-call-muted', {})\n}\n\n/**\n * Unmute the current call\n */\nexport function unmuteCurrentCall() {\n // Check the current user default device\n if (isWebRTC()) {\n const unmuted = unmuteWebRTC()\n if (unmuted) {\n store.dispatch.currentCall.updateCurrentCall({\n muted: false,\n })\n }\n } else {\n mutePhysical(false)\n }\n eventDispatch('phone-island-call-unmuted', {})\n}\n\n/**\n * Pause the current call\n */\nexport function pauseCurrentCall() {\n // Check the current user default device\n if (isWebRTC()) {\n const paused = pauseWebRTC()\n if (paused) {\n store.dispatch.currentCall.updateCurrentCall({\n paused: true,\n })\n // Pause remote audio\n store.dispatch.player.pauseRemoteAudio()\n }\n } else {\n pausePhysical(true)\n }\n eventDispatch('phone-island-call-held', {})\n}\n\n/**\n * Unpause the current call\n */\nexport function unpauseCurrentCall() {\n // Check the current user default device\n if (isWebRTC()) {\n const unpaused = unpauseWebRTC()\n if (unpaused) {\n store.dispatch.currentCall.updateCurrentCall({\n paused: false,\n })\n // Play remote audio\n store.dispatch.player.playRemoteAudio()\n }\n } else {\n pausePhysical(false)\n }\n eventDispatch('phone-island-call-unheld', {})\n}\n\n/**\n * Transfer the current call through a blind transfer (not in use)\n */\nexport async function blindTransferFunction(number: string, endpointIdInConversation: string) {\n // Retrieve current conversation info\n const { conversationId } = store.getState().currentCall\n // Transfer the call through blind transfer\n if (conversationId && endpointIdInConversation && number) {\n return await blindTransferRequest({\n convid: conversationId,\n to: number,\n endpointId: endpointIdInConversation,\n })\n }\n}\n\n/**\n * Transfer the current call through a attended transfer\n */\nexport async function attendedTransfer(number: string) {\n // Retrieve current conversation info\n const { conversationId } = store.getState().currentCall\n const { default_device } = store.getState().currentUser\n let default_device_details = default_device?.id || default_device?.exten\n // Transfer the call through attended transfer\n if (conversationId && default_device_details && number) {\n return await attendedTransferRequest({\n convid: conversationId,\n to: number,\n endpointId: default_device_details,\n })\n }\n}\n\n/**\n * Play the dtmf audio files\n */\nexport function playDtmfAudio(key: string) {\n if (key === '*') key = 'star'\n if (key === '#') key = 'pound'\n store.dispatch.player.updateStartAudioPlayer({ src: dtmfAudios[`dtmf_${key}`] })\n}\n\n/**\n * Park the current call\n */\nexport function parkCurrentCall() {\n const conversationId = store?.getState()?.currentCall?.conversationId\n const userConversationInformations = store?.getState()?.currentUser?.conversations\n\n let parkingInformation: any = {}\n\n if (conversationId) {\n if (userConversationInformations) {\n for (const key in userConversationInformations) {\n if (userConversationInformations.hasOwnProperty(key)) {\n const conversation = userConversationInformations[key]\n if (Object.keys(conversation).length > 0) {\n parkingInformation = {\n numberParkId: key,\n idConversation: conversationId,\n }\n }\n }\n }\n }\n\n if (Object.keys(parkingInformation).length > 0) {\n if (parkingInformation?.numberParkId) {\n // If park information are not empty park call\n parkConversation({\n applicantId: parkingInformation?.numberParkId,\n convid: conversationId,\n endpointId: parkingInformation?.numberParkId,\n })\n\n store.dispatch.currentCall.setParked(true)\n\n eventDispatch('phone-island-call-parked', {})\n }\n }\n }\n}\n\nconst findFirstExtesnionNotEmpty = (data) => {\n for (const key in data) {\n if (Object.keys(data[key]).length !== 0) {\n const firstEntry: any = Object.values(data[key])[0]\n return {\n id: firstEntry.id,\n recording: firstEntry.recording,\n recordingControlAvailable: firstEntry.recordingControlAvailable,\n }\n }\n }\n return null\n}\n\nexport const isRecordingControlAvailable = (conversation?: {\n recording?: string\n recordingControlAvailable?: boolean\n} | null) =>\n !conversation || conversation.recordingControlAvailable !== false\n\nexport async function recordCurrentCall(recordingValue: boolean) {\n const userConversationInformations = store?.getState()?.currentUser?.conversations\n\n const firstExtensionNotEmpty = findFirstExtesnionNotEmpty(userConversationInformations)\n\n if (!firstExtensionNotEmpty) {\n return\n } else {\n if (!isRecordingControlAvailable(firstExtensionNotEmpty)) {\n return\n }\n\n const numberToSendCall = firstExtensionNotEmpty?.id?.match(/\\/(\\d+)-/)\n const endpointId = numberToSendCall[1]\n\n const listenInformations = {\n convid: firstExtensionNotEmpty?.id?.toString(),\n endpointId: endpointId?.toString(),\n }\n\n let recordingValues = ''\n switch (firstExtensionNotEmpty?.recording) {\n case 'false':\n recordingValues = 'start_record'\n break\n case 'true':\n recordingValues = 'stop_record'\n break\n default:\n recordingValues = ''\n break\n }\n\n if (listenInformations && recordingValues) {\n try {\n await toggleRecord(recordingValues, listenInformations)\n store.dispatch.currentCall.updateRecordingStatus(!recordingValue)\n } catch (e) {\n console.error(e)\n return []\n }\n }\n }\n}\n\nexport async function startConference() {\n const {\n accepted,\n chSource,\n chDest,\n incoming,\n outgoing,\n incomingSocket,\n outgoingSocket,\n conversationId,\n }: any = store?.getState()?.currentCall\n const { default_device } = store.getState().currentUser\n const defaultDeviceId = default_device?.id || default_device?.exten\n let addedUserExtension = ''\n if (accepted && (incoming || incomingSocket) && !isEmpty(chSource)) {\n addedUserExtension = chSource?.callerNum\n } else if (accepted && (outgoing || outgoingSocket) && !isEmpty(chDest)) {\n addedUserExtension = chDest?.callerNum\n }\n\n if (defaultDeviceId !== '' && conversationId !== '' && addedUserExtension !== '') {\n const startConferenceInformations = {\n convid: conversationId?.toString(),\n addEndpointId: addedUserExtension?.toString(),\n ownerEndpointId: defaultDeviceId?.toString(),\n }\n\n if (startConferenceInformations) {\n try {\n const result = await startConf(startConferenceInformations)\n if (result) {\n // Set conferencing and disable pause\n store.dispatch.currentCall.updateCurrentCall({\n conferencing: true,\n paused: false,\n })\n\n eventDispatch('phone-island-call-conferenced', {})\n return true\n }\n return false\n } catch (e) {\n console.error(e)\n return false\n }\n }\n }\n return false\n}\n\nexport async function joinConference() {\n const { default_device } = store.getState().currentUser\n const defaultDeviceId = default_device?.id || default_device?.exten\n\n if (defaultDeviceId !== '') {\n const joinConferenceInformation = {\n endpointId: defaultDeviceId?.toString(),\n }\n\n if (joinConferenceInformation) {\n try {\n const result = await joinMyConf(joinConferenceInformation)\n if (result) {\n eventDispatch('phone-island-owner-conference-enter', {})\n return true\n }\n return false\n } catch (e) {\n console.error(e)\n return false\n }\n }\n }\n return false\n}\n\nexport async function endConference() {\n const { conferenceId } = store.getState().conference\n\n if (conferenceId !== '') {\n const endConferenceInformation = {\n confId: conferenceId?.toString(),\n }\n\n if (endConferenceInformation) {\n try {\n const result = await endConf(endConferenceInformation)\n if (result) {\n eventDispatch('phone-island-owner-conference-finished', {})\n return true\n }\n return false\n } catch (e) {\n console.error(e)\n return false\n }\n }\n }\n return false\n}\n\nexport async function muteUserConference(confId, userId, isAlreadyMuted) {\n if (confId === '' || userId === '') {\n return false\n }\n\n const muteUnmuteUserInformation = {\n confId: confId?.toString(),\n userId: userId?.toString(),\n }\n\n try {\n // Check if the user is already muted\n const actionFunction = isAlreadyMuted ? unmuteUserConf : muteUserConf\n const result = await actionFunction(muteUnmuteUserInformation)\n return !!result\n } catch (e) {\n console.error(e)\n return false\n }\n}\n\nexport async function muteAllUsersConference(confId, isAlreadyMuted) {\n if (confId === '') {\n return false\n }\n\n // Get the conference users from the store\n const { usersList } = store.getState().conference\n\n if (!usersList || Object.keys(usersList).length === 0) {\n return false\n }\n\n try {\n // Iterate through all users (except the owner) and mute/unmute them\n const nonOwnerUsers = Object.values(usersList)\n\n // Determine which function to use based on isAlreadyMuted\n const actionFunction = isAlreadyMuted ? unmuteUserConf : muteUserConf\n\n // For each user, call the appropriate function directly\n for (const user of nonOwnerUsers) {\n const muteUnmuteUserInformation = {\n confId: confId?.toString(),\n userId: user.id?.toString(),\n }\n\n const result = await actionFunction(muteUnmuteUserInformation)\n\n if (result) {\n store.dispatch.conference.toggleUserMuted({\n extenId: user.extenId,\n muted: !isAlreadyMuted,\n })\n }\n }\n\n return true\n } catch (e) {\n console.error(e)\n return false\n }\n}\n\nexport async function removeUserConference(conferenceId, extensionId) {\n if (conferenceId !== '' && extensionId !== '') {\n const removeUserInformation = {\n confId: conferenceId?.toString(),\n extenId: extensionId?.toString(),\n }\n\n if (removeUserInformation) {\n try {\n const result = await hangupUserConf(removeUserInformation)\n if (result) {\n // Check if this was the last participant (excluding owner)\n setTimeout(async () => {\n const { usersList } = store.getState().conference\n const remainingParticipants = Object.values(usersList || {}).filter(\n (user) => !user.owner && user.extenId !== extensionId,\n ).length\n\n // If no more participants left, end the conference\n if (remainingParticipants === 0) {\n await endConference()\n }\n }, 500)\n\n return true\n }\n\n return false\n } catch (e) {\n console.error(e)\n return false\n }\n }\n }\n return false\n}\n\nexport const clickTransferOrConference = async (number: string, dispatch: Dispatch) => {\n if (isInsideConferenceList()) {\n const { isActive } = store.getState().conference\n\n // Put current call user inside conference mode (only for first user to add not for the second one)\n // If conference is not active, start it first, otherwise proceed directly\n if (!isActive) {\n const conferenceStarted = await startConference()\n if (!conferenceStarted) {\n return // Early return if conference failed to start\n }\n }\n\n // Proceed to waiting conference view (common path for both cases)\n waitingConferenceView(number, dispatch)\n } else {\n handleAttendedTransfer(number, dispatch)\n }\n}\n\nexport const isInsideConferenceList = () => {\n const { isConferenceList } = store.getState().island\n if (isConferenceList) {\n return true\n }\n return false\n}\n\nexport const waitingConferenceView = (numberToCall, dispatch: Dispatch) => {\n // Get all required state in one call to minimize store access\n const state = store.getState()\n const { username } = state.currentUser\n const { isActive, isOwnerInside, conferenceId } = state.conference\n const { extensions } = state.users\n\n // Show current waiting user in back view (only on first)\n if (!isActive && username) {\n dispatch.conference.setConferenceActive(true)\n dispatch.conference.setConferenceStartedFrom(username)\n }\n\n // Add pending user to track the participant being added (before socket confirms)\n const extension = extensions\n ? Object.values(extensions).find((ext: any) => ext.exten === numberToCall)\n : null\n const extensionName = extension?.name || numberToCall\n\n dispatch.conference.addPendingUser({\n id: `${conferenceId}-${numberToCall}`,\n name: extensionName,\n owner: false,\n muted: false,\n extenId: numberToCall,\n joinTime: Date.now(),\n })\n\n // If owner has already started the conference, hangup before making a new call\n if (isOwnerInside) {\n hangupCurrentCall()\n dispatch.conference.toggleIsOwnerInside(false)\n }\n\n // Start new call with selected user from conference list\n // Use requestAnimationFrame to ensure state updates are complete before dispatching event\n requestAnimationFrame(() => {\n setTimeout(() => {\n eventDispatch('phone-island-call-start', { number: numberToCall })\n }, 1000)\n })\n}\n\nexport async function handleAttendedTransfer(number: string, dispatch: Dispatch) {\n // Send attended transfer message\n unpauseCurrentCall()\n const transferringMessageSent = await attendedTransfer(number)\n if (transferringMessageSent) {\n // Set transferring and disable pause\n dispatch.currentCall.updateCurrentCall({\n transferring: true,\n paused: false,\n })\n\n // Use requestAnimationFrame to ensure state update is complete before audio operations\n requestAnimationFrame(() => {\n dispatch.player.playRemoteAudio()\n eventDispatch('phone-island-call-transfered', {})\n })\n }\n}\n"],"names":["hangupCurrentCall","_a","store","getState","currentCall","outgoing","accepted","streamingSourceNumber","isFromStreaming","island","isWebRTC","hangup","hangupPhysical","dispatch","player","stopAudioPlayer","reset","listen","sourceId_1","getStreamingSourceId","unsubscribe","id","then","console","debug","concat","catch","error","streaming","clearSourceImages","setIsFromStreaming","resetOperatorBusy","eventDispatch","unpauseCurrentCall","unpauseWebRTC","updateCurrentCall","paused","playRemoteAudio","pausePhysical","attendedTransfer","number","conversationId","default_device","currentUser","default_device_details","exten","attendedTransferRequest","convid","to","endpointId","isRecordingControlAvailable","conversation","recordingControlAvailable","startConference","_b","chSource","chDest","incoming","incomingSocket","outgoingSocket","defaultDeviceId","addedUserExtension","isEmpty","callerNum","startConferenceInformations","toString","addEndpointId","ownerEndpointId","startConf","_c","sent","conferencing","e_2","endConference","conferenceId","conference","endConferenceInformation","confId","endConf","e_4","isInsideConferenceList","isConferenceList","waitingConferenceView","numberToCall","state","username","isActive","isOwnerInside","extensions","users","setConferenceActive","setConferenceStartedFrom","extension","Object","values","find","ext","extensionName","name","addPendingUser","owner","muted","extenId","joinTime","Date","now","toggleIsOwnerInside","requestAnimationFrame","setTimeout","handleAttendedTransfer","transferring","answerWebRTC","answerPhysical","resetOperatorBusyCompletely","endpointIdInConversation","blindTransferRequest","sipHost","sipURI","setOperatorBusyCalledNumber","callSipURI","callPhysical","__awaiter","conversations","keys","forEach","forceHangup","endpointType","hangupConversation","hangupPhysicalRecordingCall","physicalRecorder","setRecording","setIslandView","joinConferenceInformation","joinMyConf","e_3","isAlreadyMuted","usersList","length","nonOwnerUsers","actionFunction","unmuteUserConf","muteUserConf","_i","nonOwnerUsers_1","user","muteUnmuteUserInformation","userId","toggleUserMuted","e_6","muteWebRTC","mutePhysical","e_5","userConversationInformations","_d","parkingInformation","key","hasOwnProperty","numberParkId","idConversation","parkConversation","applicantId","setParked","pauseWebRTC","pauseRemoteAudio","updateStartAudioPlayer","src","dtmfAudios","recordingValue","firstExtensionNotEmpty","data","firstEntry","recording","findFirstExtesnionNotEmpty","numberToSendCall","match","listenInformations","recordingValues","toggleRecord","_e","updateRecordingStatus","e_1","extensionId","removeUserInformation","hangupUserConf","_this","remainingParticipants","filter","e_7","unmuteWebRTC"],"mappings":"oiBA8GgBA,IACR,IAAAC,EAAgDC,EAAKA,MAACC,WAAWC,YAA/DC,EAAQJ,EAAAI,SAAEC,EAAQL,EAAAK,SAAEC,0BACpBC,EAAoBN,EAAKA,MAACC,WAAWM,OAAMD,gBAEnD,GAAIH,GAAYC,EAAU,CAWxB,GAVII,EAAQA,WACVC,EAAAA,SAEAC,EAAAA,iBAEFV,EAAAA,MAAMW,SAASC,OAAOC,kBACtBb,EAAAA,MAAMW,SAAST,YAAYY,QAC3Bd,EAAAA,MAAMW,SAASI,OAAOD,QAGlBR,GAAmBD,EAAuB,CAC5C,IAAMW,EAAWC,uBAAqBZ,GAClCW,IAEFE,cAAY,CAAEC,GAAIH,IACfI,MAAK,WAAM,OAAAC,QAAQC,MAAM,uCAAAC,OAAuCP,OAChEQ,OAAM,SAACC,GAAU,OAAAJ,QAAQI,MAAM,6CAA8CA,EAA5D,IAGpBzB,EAAAA,MAAMW,SAASe,UAAUC,oBAE5B,CAGD3B,EAAAA,MAAMW,SAASJ,OAAOqB,oBAAmB,EAC1C,CAED5B,EAAAA,MAAMW,SAASJ,OAAOsB,oBAEtBC,gBAAc,0BAA2B,CAAA,EAC3C,UA2EgBC,IAEVvB,EAAQA,WACOwB,EAAAA,kBAEfhC,QAAMW,SAAST,YAAY+B,kBAAkB,CAC3CC,QAAQ,IAGVlC,EAAAA,MAAMW,SAASC,OAAOuB,mBAGxBC,EAAaA,eAAC,GAEhBN,gBAAc,2BAA4B,CAAA,EAC5C,CAqBM,SAAgBO,EAAiBC,6HAMjC,OAJIC,EAAmBvC,EAAAA,MAAMC,WAAWC,2BACpCsC,EAAmBxC,EAAAA,MAAMC,WAAWwC,2BACxCC,GAAyBF,aAAc,EAAdA,EAAgBrB,MAAMqB,aAAc,EAAdA,EAAgBG,OAE/DJ,GAAkBG,GAA0BJ,EACvC,CAAA,EAAMM,mBAAwB,CACnCC,OAAQN,EACRO,GAAIR,EACJS,WAAYL,KAJsC,CAAA,EAAA,GACpD,KAAA,EAAA,MAAA,CAAA,EAAO3C,iCAMV,CAoDD,IAcaiD,EAA8B,SAACC,GAI1C,OAACA,IAA2D,IAA3CA,EAAaC,yBAA9B,WA+CoBC,0JAoBhB,GAnBEC,UASGrD,EAAA,OAAAC,kBAAAA,EAAAA,aAAAA,EAAKA,MAAEC,iCAAYC,YAR1BE,EAAQgD,EAAAhD,SACRiD,EAAQD,EAAAC,SACRC,WACAC,EAAQH,EAAAG,SACRpD,EAAQiD,EAAAjD,SACRqD,EAAcJ,EAAAI,eACdC,EAAcL,EAAAK,eACdlB,mBAEMC,EAAmBxC,EAAAA,MAAMC,WAAWwC,2BACtCiB,GAAkBlB,aAAc,EAAdA,EAAgBrB,MAAMqB,aAAc,EAAdA,EAAgBG,OAC1DgB,EAAqB,GACrBvD,IAAamD,GAAYC,KAAoBI,EAAAA,QAAQP,GACvDM,EAAqBN,eAAAA,EAAUQ,UACtBzD,IAAaD,GAAYsD,KAAoBG,EAAAA,QAAQN,KAC9DK,EAAqBL,eAAAA,EAAQO,WAGP,KAApBH,GAA6C,KAAnBnB,GAAgD,KAAvBoB,EAAnD,MAA4E,CAAA,EAAA,GAO1E,KANEG,EAA8B,CAClCjB,OAAQN,eAAAA,EAAgBwB,WACxBC,cAAeL,eAAAA,EAAoBI,WACnCE,gBAAiBP,eAAAA,EAAiBK,aAGhC,MAA2B,CAAA,EAAA,oBAEZ,6BAAA,CAAA,EAAMG,YAAUJ,WAC/B,OADeK,EAA4CC,QAGzDpE,QAAMW,SAAST,YAAY+B,kBAAkB,CAC3CoC,cAAc,EACdnC,QAAQ,IAGVJ,gBAAc,gCAAiC,CAAA,GAC/C,CAAA,GAAO,IAET,CAAA,GAAO,UAGP,kBADAT,QAAQI,MAAM6C,GACd,CAAA,GAAO,GAIb,KAAA,EAAA,MAAA,CAAA,GAAO,SACR,UA4BqBC,8HAGhB,GAAiB,MAFbC,EAAiBxE,EAAAA,MAAMC,WAAWwE,yBAEtC,MAAmB,CAAA,EAAA,GAKjB,KAJEC,EAA2B,CAC/BC,OAAQH,eAAAA,EAAcT,aAGpB,MAAwB,CAAA,EAAA,oBAET,6BAAA,CAAA,EAAMa,UAAQF,WAC7B,OADe3E,EAAuCqE,QAEpDtC,gBAAc,yCAA0C,CAAA,GACxD,CAAA,GAAO,IAET,CAAA,GAAO,UAGP,kBADAT,QAAQI,MAAMoD,GACd,CAAA,GAAO,GAIb,KAAA,EAAA,MAAA,CAAA,GAAO,SACR,CAuGY,IAoBAC,EAAyB,WAEpC,QAD6B9E,EAAKA,MAACC,WAAWM,OAAMwE,gBAKtD,EAEaC,EAAwB,SAACC,EAActE,GAElD,IAAMuE,EAAQlF,QAAMC,WACZkF,EAAaD,EAAMzC,qBACrB1C,EAA4CmF,EAAMT,WAAhDW,EAAQrF,EAAAqF,SAAEC,EAAatF,EAAAsF,cAAEb,iBACzBc,EAAeJ,EAAMK,kBAGxBH,GAAYD,IACfxE,EAAS8D,WAAWe,qBAAoB,GACxC7E,EAAS8D,WAAWgB,yBAAyBN,IAI/C,IAAMO,EAAYJ,EACdK,OAAOC,OAAON,GAAYO,MAAK,SAACC,GAAa,OAAAA,EAAInD,QAAUsC,CAAd,IAC7C,KACEc,GAAgBL,aAAA,EAAAA,EAAWM,OAAQf,EAEzCtE,EAAS8D,WAAWwB,eAAe,CACjC9E,GAAI,GAAAI,OAAGiD,EAAY,KAAAjD,OAAI0D,GACvBe,KAAMD,EACNG,OAAO,EACPC,OAAO,EACPC,QAASnB,EACToB,SAAUC,KAAKC,QAIblB,IACFvF,IACAa,EAAS8D,WAAW+B,qBAAoB,IAK1CC,uBAAsB,WACpBC,YAAW,WACT5E,EAAAA,cAAc,0BAA2B,CAAEQ,OAAQ2C,GACpD,GAAE,IACL,GACF,EAEsB,SAAA0B,EAAuBrE,EAAgB3B,mHAG3B,OADhCoB,IACgC,CAAA,EAAMM,EAAiBC,kBAAvBvC,EAA8BqE,SAG5DzD,EAAST,YAAY+B,kBAAkB,CACrC2E,cAAc,EACd1E,QAAQ,IAIVuE,uBAAsB,WACpB9F,EAASC,OAAOuB,kBAChBL,gBAAc,+BAAgC,CAAA,EAChD,eAEH,uCApmBKtB,EAAQA,WACVqG,EAAAA,eAEAC,EAAAA,iBAGF9G,EAAAA,MAAMW,SAASJ,OAAOwG,6BACxB,2DAyKsB,SAAsBzE,EAAgB0E,yHAItD,OAFIzE,EAAmBvC,EAAAA,MAAMC,WAAWC,6BAEtB8G,GAA4B1E,EACzC,CAAA,EAAM2E,gBAAqB,CAChCpE,OAAQN,EACRO,GAAIR,EACJS,WAAYiE,KAJwC,CAAA,EAAA,GACtD,KAAA,EAAA,MAAA,CAAA,EAAOjH,iCAMV,qBAhNe,SAAWuC,EAAgB4E,GACzC,IAAMC,EAAS,OAAA5F,OAAOe,EAAU,KAAAf,OAAA2F,GAGhClH,EAAAA,MAAMW,SAASJ,OAAOsB,oBAEtB7B,EAAAA,MAAMW,SAASJ,OAAO6G,4BAA4B9E,GAE9C9B,EAAQA,WACV6G,EAAUA,WAACF,GAEXG,EAAYA,aAAChF,GAGfR,gBAAc,4BAA6B,CAAA,EAC7C,oCAkhByC,SAAOQ,EAAgB3B,GAAkB,OAAA4G,EAAAA,eAAA,OAAA,OAAA,GAAA,gFAC5EzC,IACmB9E,EAAAA,MAAMC,WAAWwE,oBAIzB,CAAA,EAAA,GACqB,CAAA,EAAAtB,KANR,CAAA,EAAA,UAOxB,IAD0BpD,EAAuBqE,OAE/C,MAAA,CAAA,2BAKJY,EAAsB1C,EAAQ3B,gBAE9BgG,EAAuBrE,EAAQ3B,oCAElC,qEAjgBS,IAAA6G,EAAkBxH,EAAKA,MAACC,WAAWwC,YAAW+E,yBAE3C9B,GACgBC,OAAO8B,KAAKD,EAAc9B,IAClCgC,SAAQ,SAACvG,GACxBwG,cAAY,CACV9E,OAAQ1B,EACR4B,WAAY2C,EACZkC,aAAc,aAElB,KARF,IAAK,IAAMlC,KAAa8B,IAAb9B,EAUb,0EA3BU,IAAA8B,EAAkBxH,EAAKA,MAACC,WAAWwC,YAAW+E,yBAE3C9B,GACgBC,OAAO8B,KAAKD,EAAc9B,IAClCgC,SAAQ,SAACvG,GACxB0G,qBAAmB,CACjBhF,OAAQ1B,EACR4B,WAAY2C,GAEhB,KAPF,IAAK,IAAMA,KAAa8B,IAAb9B,EASb,gFA8DEoC,EAAAA,8BACA9H,EAAAA,MAAMW,SAASC,OAAOC,kBACtBb,EAAAA,MAAMW,SAASoH,iBAAiBjH,QAChCd,EAAAA,MAAMW,SAASoH,iBAAiBC,cAAa,GAC7ChI,EAAAA,MAAMW,SAASJ,OAAO0H,cAAc,MACpCjI,EAAAA,MAAMW,SAASI,OAAOD,QAEtBgB,gBAAc,0BAA2B,CAAA,EAC3C,uOAyRM,GAHIU,EAAmBxC,EAAAA,MAAMC,WAAWwC,2BAGpB,MAFlBiB,GAAkBlB,aAAc,EAAdA,EAAgBrB,MAAMqB,aAAc,EAAdA,EAAgBG,QAE1D,MAAsB,CAAA,EAAA,GAKpB,KAJEuF,EAA4B,CAChCnF,WAAYW,eAAAA,EAAiBK,aAG3B,MAAyB,CAAA,EAAA,oBAEV,6BAAA,CAAA,EAAMoE,aAAWD,WAChC,OADenI,EAA2CqE,QAExDtC,gBAAc,sCAAuC,CAAA,GACrD,CAAA,GAAO,IAET,CAAA,GAAO,UAGP,kBADAT,QAAQI,MAAM2G,GACd,CAAA,GAAO,GAIb,KAAA,EAAA,MAAA,CAAA,GAAO,SACR,iCAgDqB,SAAuBzD,EAAQ0D,6IACnD,GAAe,KAAX1D,EACF,MAAA,CAAA,GAAO,GAMT,KAFQ2D,EAActI,EAAAA,MAAMC,WAAWwE,uBAEa,IAAlCkB,OAAO8B,KAAKa,GAAWC,OACvC,MAAA,CAAA,GAAO,0CAKDC,EAAgB7C,OAAOC,OAAO0C,GAG9BG,EAAiBJ,EAAiBK,EAAcA,eAAGC,eAGzBC,EAAA,EAAbC,EAAaL,mBAAb,OAAAI,YAARE,EAAID,EAAAD,GACPG,EAA4B,CAChCpE,OAAQA,eAAAA,EAAQZ,WAChBiF,OAAe,QAAPjJ,EAAA+I,EAAK3H,UAAE,IAAApB,OAAA,EAAAA,EAAEgE,YAGJ,CAAA,EAAM0E,EAAeM,KANN,CAAA,EAAA,UAMf3F,EAA+CgB,QAG5DpE,QAAMW,SAAS8D,WAAWwE,gBAAgB,CACxC7C,QAAS0C,EAAK1C,QACdD,OAAQkC,4BAXKO,UAgBnB,KAAA,EAAA,MAAA,CAAA,GAAO,UAGP,kBADAvH,QAAQI,MAAMyH,GACd,CAAA,GAAO,0BAEV,qCA/XK1I,EAAQA,WACI2I,EAAAA,cAEZnJ,QAAMW,SAAST,YAAY+B,kBAAkB,CAC3CkE,OAAO,IAIXiD,EAAYA,cAAC,GAEftH,gBAAc,0BAA2B,CAAA,EAC3C,sCAsTyC6C,EAAQqE,EAAQX,2HACvD,GAAe,KAAX1D,GAA4B,KAAXqE,EACnB,MAAA,CAAA,GAAO,GAGHD,EAA4B,CAChCpE,OAAQA,eAAAA,EAAQZ,WAChBiF,OAAQA,eAAAA,EAAQjF,6BAMD,6BAAA,CAAA,GADQsE,EAAiBK,EAAcA,eAAGC,gBACrBI,WACpC,MAAO,CAAA,IADQhJ,EAA+CqE,eAI9D,kBADA/C,QAAQI,MAAM4H,GACd,CAAA,GAAO,0BAEV,iDA9NO9G,EAA+C,QAA9Ba,EAAiB,QAAjBrD,SAAAC,EAAAA,YAAK,IAALA,EAAKA,WAAA,EAALA,EAAAA,MAAOC,kBAAU,IAAAF,OAAA,EAAAA,EAAEG,mBAAW,IAAAkD,OAAA,EAAAA,EAAEb,eACjD+G,EAA6D,QAA9BC,EAAiB,QAAjBpF,SAAAnE,EAAAA,YAAK,IAALA,EAAKA,WAAA,EAALA,EAAAA,MAAOC,kBAAU,IAAAkE,OAAA,EAAAA,EAAE1B,mBAAW,IAAA8G,OAAA,EAAAA,EAAE/B,cAEjEgC,EAA0B,CAAA,EAE9B,GAAIjH,EAAgB,CAClB,GAAI+G,EACF,IAAK,IAAMG,KAAOH,EAChB,GAAIA,EAA6BI,eAAeD,GAAM,CACpD,IAAMxG,EAAeqG,EAA6BG,GAC9C9D,OAAO8B,KAAKxE,GAAcsF,OAAS,IACrCiB,EAAqB,CACnBG,aAAcF,EACdG,eAAgBrH,GAGrB,CAIDoD,OAAO8B,KAAK+B,GAAoBjB,OAAS,IACvCiB,eAAAA,EAAoBG,gBAEtBE,mBAAiB,CACfC,YAAaN,aAAA,EAAAA,EAAoBG,aACjC9G,OAAQN,EACRQ,WAAYyG,aAAA,EAAAA,EAAoBG,eAGlC3J,EAAAA,MAAMW,SAAST,YAAY6J,WAAU,GAErCjI,gBAAc,2BAA4B,CAAA,GAG/C,CACH,sCArHMtB,EAAQA,WACKwJ,EAAAA,gBAEbhK,QAAMW,SAAST,YAAY+B,kBAAkB,CAC3CC,QAAQ,IAGVlC,EAAAA,MAAMW,SAASC,OAAOqJ,oBAGxB7H,EAAaA,eAAC,GAEhBN,gBAAc,yBAA0B,CAAA,EAC1C,wBA2DM,SAAwB2H,GAChB,MAARA,IAAaA,EAAM,QACX,MAARA,IAAaA,EAAM,SACvBzJ,EAAAA,MAAMW,SAASC,OAAOsJ,uBAAuB,CAAEC,IAAKC,UAAW,QAAQ7I,OAAAkI,KACzE,4BA+DM,SAAkCY,wJAChCf,EAA6D,QAA9BlG,EAAiB,QAAjBrD,SAAAC,EAAKA,YAAA,IAALA,aAAK,EAALA,EAAKA,MAAEC,kBAAU,IAAAF,OAAA,EAAAA,EAAE0C,mBAAW,IAAAW,OAAA,EAAAA,EAAEoE,eAE/D8C,EAvB2B,SAACC,GAClC,IAAK,IAAMd,KAAOc,EAChB,GAAsC,IAAlC5E,OAAO8B,KAAK8C,EAAKd,IAAMlB,OAAc,CACvC,IAAMiC,EAAkB7E,OAAOC,OAAO2E,EAAKd,IAAM,GACjD,MAAO,CACLtI,GAAIqJ,EAAWrJ,GACfsJ,UAAWD,EAAWC,UACtBvH,0BAA2BsH,EAAWtH,0BAEzC,CAEH,OAAO,IACT,CAWiCwH,CAA2BpB,IAE/B,CAAA,EAAA,GACnB,CAAA,UAEN,IAAKtG,EAA4BsH,GAC/B,MAAM,CAAA,GAYR,OATMK,EAA+C,QAA5BxG,EAAAmG,aAAA,EAAAA,EAAwBnJ,UAAI,IAAAgD,OAAA,EAAAA,EAAAyG,MAAM,YACrD7H,EAAa4H,EAAiB,GAE9BE,EAAqB,CACzBhI,OAAoC,QAA5B0G,EAAAe,aAAA,EAAAA,EAAwBnJ,UAAI,IAAAoI,OAAA,EAAAA,EAAAxF,WACpChB,WAAYA,eAAAA,EAAYgB,YAGtB+G,EAAkB,GACdR,eAAAA,EAAwBG,WAC9B,IAAK,QACHK,EAAkB,eAClB,MACF,IAAK,OACHA,EAAkB,cAClB,MACF,QACEA,EAAkB,GAIlB,IAAAD,IAAsBC,EAAtB,MAAqC,CAAA,EAAA,oBAErC,6BAAA,CAAA,EAAMC,EAAAA,aAAaD,EAAiBD,kBAApCG,EAAA5G,OACApE,EAAAA,MAAMW,SAAST,YAAY+K,uBAAuBZ,gBAGlD,kBADAhJ,QAAQI,MAAMyJ,GACd,CAAA,EAAO,2BAId,+BAuKqB,SAAqB1G,EAAc2G,qIAClC,KAAjB3G,GAAuC,KAAhB2G,EAAvB,MAAyC,CAAA,EAAA,GAMvC,KALEC,EAAwB,CAC5BzG,OAAQH,eAAAA,EAAcT,WACtBqC,QAAS+E,eAAAA,EAAapH,aAGpB,MAAqB,CAAA,EAAA,oBAEN,6BAAA,CAAA,EAAMsH,iBAAeD,WACpC,OADerL,EAA2CqE,QAGxDsC,YAAW,WAAA,OAAAa,EAAAA,UAAA+D,OAAA,OAAA,GAAA,iFAOL,OANIhD,EAActI,EAAAA,MAAMC,WAAWwE,qBACjC8G,EAAwB5F,OAAOC,OAAO0C,GAAa,CAAA,GAAIkD,QAC3D,SAAC1C,GAAS,OAACA,EAAK5C,OAAS4C,EAAK1C,UAAY+E,CAAhC,IACV5C,OAG4B,IAA1BgD,EAA2B,CAAA,EAAA,GACvB,CAAA,EAAAhH,YAANxE,EAAAqE,2CAED,KAEH,CAAA,GAAO,IAGT,CAAA,GAAO,UAGP,kBADA/C,QAAQI,MAAMgK,GACd,CAAA,GAAO,GAIb,KAAA,EAAA,MAAA,CAAA,GAAO,SACR,iEAlZKjL,EAAQA,WACMkL,EAAAA,gBAEd1L,QAAMW,SAAST,YAAY+B,kBAAkB,CAC3CkE,OAAO,IAIXiD,EAAYA,cAAC,GAEftH,gBAAc,4BAA6B,CAAA,EAC7C"}
|
|
1
|
+
{"version":3,"file":"call.js","sources":["../../../src/lib/phone/call.ts"],"sourcesContent":["// Copyright (C) 2024 Nethesis S.r.l.\n// SPDX-License-Identifier: AGPL-3.0-or-later\n\nimport {\n callSipURI,\n hangup,\n answerWebRTC,\n muteWebRTC,\n unmuteWebRTC,\n pauseWebRTC,\n unpauseWebRTC,\n} from '../webrtc/messages'\nimport { Dispatch, store } from '../../store'\nimport { isWebRTC } from '../user/default_device'\nimport {\n blindTransfer as blindTransferRequest,\n attendedTransfer as attendedTransferRequest,\n hangupPhysical,\n answerPhysical,\n mutePhysical,\n pausePhysical,\n callPhysical,\n toggleRecord,\n hangupPhysicalRecordingCall,\n startConf,\n joinMyConf,\n endConf,\n muteUserConf,\n unmuteUserConf,\n hangupUserConf,\n forceHangup,\n} from '../../services/astproxy'\nimport dtmfAudios from '../../static/dtmf'\nimport { hangupConversation, parkConversation } from '../../services/astproxy'\nimport { eventDispatch } from '../../utils'\nimport { isEmpty } from '../../utils/genericFunctions/isEmpty'\nimport { getStreamingSourceId } from '../../utils/streaming/getStreamingSourceId'\nimport { unsubscribe } from '../../services/user'\n\n/**\n * Starts a call to a number\n * @param number The number string\n */\nexport function callNumber(number: string, sipHost: string) {\n const sipURI = `sip:${number}@${sipHost}`\n\n // Reset any previous operator busy state when starting a new call\n store.dispatch.island.resetOperatorBusy()\n // Save the called number for potential operator busy scenarios\n store.dispatch.island.setOperatorBusyCalledNumber(number)\n\n if (isWebRTC()) {\n callSipURI(sipURI)\n } else {\n callPhysical(number)\n }\n\n eventDispatch('phone-island-call-started', {})\n}\n\n/**\n * Answer incoming call\n */\nexport function answerIncomingCall() {\n if (isWebRTC()) {\n answerWebRTC()\n } else {\n answerPhysical()\n }\n // Reset operator busy completely when call is answered successfully\n store.dispatch.island.resetOperatorBusyCompletely()\n}\n\n/**\n * Hangup all the conversations of all the extensions of the current user\n */\nexport function hangupAllExtensions() {\n // Get current user endpoints\n const { conversations } = store.getState().currentUser\n // Hangup all the conversations of all extensions of the current user\n for (const extension in conversations) {\n const conversationsIds = Object.keys(conversations[extension])\n conversationsIds.forEach((id) => {\n hangupConversation({\n convid: id,\n endpointId: extension,\n })\n })\n }\n}\n\nexport function forceHangupConversation() {\n // Get current user endpoints\n const { conversations } = store.getState().currentUser\n // Hangup all the conversations of all extensions of the current user\n for (const extension in conversations) {\n const conversationsIds = Object.keys(conversations[extension])\n conversationsIds.forEach((id) => {\n forceHangup({\n convid: id,\n endpointId: extension,\n endpointType: 'extension',\n })\n })\n }\n}\n\n/**\n * Hangup current call\n */\nexport function hangupCurrentCall() {\n const { outgoing, accepted, streamingSourceNumber } = store.getState().currentCall\n const { isFromStreaming } = store.getState().island\n\n if (outgoing || accepted) {\n if (isWebRTC()) {\n hangup()\n } else {\n hangupPhysical()\n }\n store.dispatch.player.stopAudioPlayer()\n store.dispatch.currentCall.reset()\n store.dispatch.listen.reset()\n\n // If call was from a streaming source, unsubscribe and clear images\n if (isFromStreaming && streamingSourceNumber) {\n const sourceId = getStreamingSourceId(streamingSourceNumber)\n if (sourceId) {\n // Unsubscribe from streaming updates\n unsubscribe({ id: sourceId })\n .then(() => console.debug(`Unsubscribed from streaming source: ${sourceId}`))\n .catch((error) => console.error('Error unsubscribing from streaming source:', error))\n\n // Clear source images to free up memory\n store.dispatch.streaming.clearSourceImages()\n }\n }\n\n // Reset isFromStreaming flag\n store.dispatch.island.setIsFromStreaming(false)\n }\n // Reset operator busy state when call ends\n store.dispatch.island.resetOperatorBusy()\n // Caller close the call before the call is accepted\n eventDispatch('phone-island-call-ended', {})\n}\n\n/**\n * Hangup current physical recording\n */\nexport function hangupCurrentPhysicalRecording() {\n hangupPhysicalRecordingCall()\n store.dispatch.player.stopAudioPlayer()\n store.dispatch.physicalRecorder.reset()\n store.dispatch.physicalRecorder.setRecording(false)\n store.dispatch.island.setIslandView(null)\n store.dispatch.listen.reset()\n // Caller close the call before the call is accepted\n eventDispatch('phone-island-call-ended', {})\n}\n\n/**\n * Mute the current call\n */\nexport function muteCurrentCall() {\n // Check the current user default device\n if (isWebRTC()) {\n const muted = muteWebRTC()\n if (muted) {\n store.dispatch.currentCall.updateCurrentCall({\n muted: true,\n })\n }\n } else {\n mutePhysical(true)\n }\n eventDispatch('phone-island-call-muted', {})\n}\n\n/**\n * Unmute the current call\n */\nexport function unmuteCurrentCall() {\n // Check the current user default device\n if (isWebRTC()) {\n const unmuted = unmuteWebRTC()\n if (unmuted) {\n store.dispatch.currentCall.updateCurrentCall({\n muted: false,\n })\n }\n } else {\n mutePhysical(false)\n }\n eventDispatch('phone-island-call-unmuted', {})\n}\n\n/**\n * Pause the current call\n */\nexport function pauseCurrentCall() {\n // Check the current user default device\n if (isWebRTC()) {\n const paused = pauseWebRTC()\n if (paused) {\n store.dispatch.currentCall.updateCurrentCall({\n paused: true,\n })\n // Pause remote audio\n store.dispatch.player.pauseRemoteAudio()\n }\n } else {\n pausePhysical(true)\n }\n eventDispatch('phone-island-call-held', {})\n}\n\n/**\n * Unpause the current call\n */\nexport function unpauseCurrentCall() {\n // Check the current user default device\n if (isWebRTC()) {\n const unpaused = unpauseWebRTC()\n if (unpaused) {\n store.dispatch.currentCall.updateCurrentCall({\n paused: false,\n })\n // Play remote audio\n store.dispatch.player.playRemoteAudio()\n }\n } else {\n pausePhysical(false)\n }\n eventDispatch('phone-island-call-unheld', {})\n}\n\n/**\n * Transfer the current call through a blind transfer (not in use)\n */\nexport async function blindTransferFunction(number: string, endpointIdInConversation: string) {\n // Retrieve current conversation info\n const { conversationId } = store.getState().currentCall\n // Transfer the call through blind transfer\n if (conversationId && endpointIdInConversation && number) {\n return await blindTransferRequest({\n convid: conversationId,\n to: number,\n endpointId: endpointIdInConversation,\n })\n }\n}\n\n/**\n * Transfer the current call through a attended transfer\n */\nexport async function attendedTransfer(number: string) {\n // Retrieve current conversation info\n const { conversationId } = store.getState().currentCall\n const { default_device } = store.getState().currentUser\n let default_device_details = default_device?.id || default_device?.exten\n // Transfer the call through attended transfer\n if (conversationId && default_device_details && number) {\n return await attendedTransferRequest({\n convid: conversationId,\n to: number,\n endpointId: default_device_details,\n })\n }\n}\n\n/**\n * Play the dtmf audio files\n */\nexport function playDtmfAudio(key: string) {\n if (key === '*') key = 'star'\n if (key === '#') key = 'pound'\n store.dispatch.player.updateStartAudioPlayer({ src: dtmfAudios[`dtmf_${key}`] })\n}\n\n/**\n * Park the current call\n */\nexport function parkCurrentCall() {\n const conversationId = store?.getState()?.currentCall?.conversationId\n const userConversationInformations = store?.getState()?.currentUser?.conversations\n\n let parkingInformation: any = {}\n\n if (conversationId) {\n if (userConversationInformations) {\n for (const key in userConversationInformations) {\n if (userConversationInformations.hasOwnProperty(key)) {\n const conversation = userConversationInformations[key]\n if (Object.keys(conversation).length > 0) {\n parkingInformation = {\n numberParkId: key,\n idConversation: conversationId,\n }\n }\n }\n }\n }\n\n if (Object.keys(parkingInformation).length > 0) {\n if (parkingInformation?.numberParkId) {\n // If park information are not empty park call\n parkConversation({\n applicantId: parkingInformation?.numberParkId,\n convid: conversationId,\n endpointId: parkingInformation?.numberParkId,\n })\n\n store.dispatch.currentCall.setParked(true)\n\n eventDispatch('phone-island-call-parked', {})\n }\n }\n }\n}\n\nconst findFirstExtesnionNotEmpty = (data) => {\n for (const key in data) {\n if (Object.keys(data[key]).length !== 0) {\n const firstEntry: any = Object.values(data[key])[0]\n return {\n id: firstEntry.id,\n recording: firstEntry.recording,\n }\n }\n }\n return null\n}\n\nexport async function recordCurrentCall(recordingValue: boolean) {\n store.dispatch.currentCall.updateRecordingStatus(!recordingValue)\n const userConversationInformations = store?.getState()?.currentUser?.conversations\n\n const firstExtensionNotEmpty = findFirstExtesnionNotEmpty(userConversationInformations)\n\n if (!firstExtensionNotEmpty) {\n return\n } else {\n const numberToSendCall = firstExtensionNotEmpty?.id?.match(/\\/(\\d+)-/)\n const endpointId = numberToSendCall[1]\n\n const listenInformations = {\n convid: firstExtensionNotEmpty?.id?.toString(),\n endpointId: endpointId?.toString(),\n }\n\n let recordingValues = ''\n switch (firstExtensionNotEmpty?.recording) {\n case 'false':\n recordingValues = 'start_record'\n break\n case 'true':\n recordingValues = 'mute_record'\n break\n case 'mute':\n recordingValues = 'unmute_record'\n break\n default:\n recordingValues = ''\n break\n }\n\n if (listenInformations) {\n try {\n await toggleRecord(recordingValues, listenInformations)\n } catch (e) {\n console.error(e)\n return []\n }\n }\n }\n}\n\nexport async function startConference() {\n const {\n accepted,\n chSource,\n chDest,\n incoming,\n outgoing,\n incomingSocket,\n outgoingSocket,\n conversationId,\n }: any = store?.getState()?.currentCall\n const { default_device } = store.getState().currentUser\n const defaultDeviceId = default_device?.id || default_device?.exten\n let addedUserExtension = ''\n if (accepted && (incoming || incomingSocket) && !isEmpty(chSource)) {\n addedUserExtension = chSource?.callerNum\n } else if (accepted && (outgoing || outgoingSocket) && !isEmpty(chDest)) {\n addedUserExtension = chDest?.callerNum\n }\n\n if (defaultDeviceId !== '' && conversationId !== '' && addedUserExtension !== '') {\n const startConferenceInformations = {\n convid: conversationId?.toString(),\n addEndpointId: addedUserExtension?.toString(),\n ownerEndpointId: defaultDeviceId?.toString(),\n }\n\n if (startConferenceInformations) {\n try {\n const result = await startConf(startConferenceInformations)\n if (result) {\n // Set conferencing and disable pause\n store.dispatch.currentCall.updateCurrentCall({\n conferencing: true,\n paused: false,\n })\n\n eventDispatch('phone-island-call-conferenced', {})\n return true\n }\n return false\n } catch (e) {\n console.error(e)\n return false\n }\n }\n }\n return false\n}\n\nexport async function joinConference() {\n const { default_device } = store.getState().currentUser\n const defaultDeviceId = default_device?.id || default_device?.exten\n\n if (defaultDeviceId !== '') {\n const joinConferenceInformation = {\n endpointId: defaultDeviceId?.toString(),\n }\n\n if (joinConferenceInformation) {\n try {\n const result = await joinMyConf(joinConferenceInformation)\n if (result) {\n eventDispatch('phone-island-owner-conference-enter', {})\n return true\n }\n return false\n } catch (e) {\n console.error(e)\n return false\n }\n }\n }\n return false\n}\n\nexport async function endConference() {\n const { conferenceId } = store.getState().conference\n\n if (conferenceId !== '') {\n const endConferenceInformation = {\n confId: conferenceId?.toString(),\n }\n\n if (endConferenceInformation) {\n try {\n const result = await endConf(endConferenceInformation)\n if (result) {\n eventDispatch('phone-island-owner-conference-finished', {})\n return true\n }\n return false\n } catch (e) {\n console.error(e)\n return false\n }\n }\n }\n return false\n}\n\nexport async function muteUserConference(confId, userId, isAlreadyMuted) {\n if (confId === '' || userId === '') {\n return false\n }\n\n const muteUnmuteUserInformation = {\n confId: confId?.toString(),\n userId: userId?.toString(),\n }\n\n try {\n // Check if the user is already muted\n const actionFunction = isAlreadyMuted ? unmuteUserConf : muteUserConf\n const result = await actionFunction(muteUnmuteUserInformation)\n return !!result\n } catch (e) {\n console.error(e)\n return false\n }\n}\n\nexport async function muteAllUsersConference(confId, isAlreadyMuted) {\n if (confId === '') {\n return false\n }\n\n // Get the conference users from the store\n const { usersList } = store.getState().conference\n\n if (!usersList || Object.keys(usersList).length === 0) {\n return false\n }\n\n try {\n // Iterate through all users (except the owner) and mute/unmute them\n const nonOwnerUsers = Object.values(usersList)\n\n // Determine which function to use based on isAlreadyMuted\n const actionFunction = isAlreadyMuted ? unmuteUserConf : muteUserConf\n\n // For each user, call the appropriate function directly\n for (const user of nonOwnerUsers) {\n const muteUnmuteUserInformation = {\n confId: confId?.toString(),\n userId: user.id?.toString(),\n }\n\n const result = await actionFunction(muteUnmuteUserInformation)\n\n if (result) {\n store.dispatch.conference.toggleUserMuted({\n extenId: user.extenId,\n muted: !isAlreadyMuted,\n })\n }\n }\n\n return true\n } catch (e) {\n console.error(e)\n return false\n }\n}\n\nexport async function removeUserConference(conferenceId, extensionId) {\n if (conferenceId !== '' && extensionId !== '') {\n const removeUserInformation = {\n confId: conferenceId?.toString(),\n extenId: extensionId?.toString(),\n }\n\n if (removeUserInformation) {\n try {\n const result = await hangupUserConf(removeUserInformation)\n if (result) {\n // Check if this was the last participant (excluding owner)\n setTimeout(async () => {\n const { usersList } = store.getState().conference\n const remainingParticipants = Object.values(usersList || {}).filter(\n (user) => !user.owner && user.extenId !== extensionId,\n ).length\n\n // If no more participants left, end the conference\n if (remainingParticipants === 0) {\n await endConference()\n }\n }, 500)\n\n return true\n }\n\n return false\n } catch (e) {\n console.error(e)\n return false\n }\n }\n }\n return false\n}\n\nexport const clickTransferOrConference = async (number: string, dispatch: Dispatch) => {\n if (isInsideConferenceList()) {\n const { isActive } = store.getState().conference\n\n // Put current call user inside conference mode (only for first user to add not for the second one)\n // If conference is not active, start it first, otherwise proceed directly\n if (!isActive) {\n const conferenceStarted = await startConference()\n if (!conferenceStarted) {\n return // Early return if conference failed to start\n }\n }\n\n // Proceed to waiting conference view (common path for both cases)\n waitingConferenceView(number, dispatch)\n } else {\n handleAttendedTransfer(number, dispatch)\n }\n}\n\nexport const isInsideConferenceList = () => {\n const { isConferenceList } = store.getState().island\n if (isConferenceList) {\n return true\n }\n return false\n}\n\nexport const waitingConferenceView = (numberToCall, dispatch: Dispatch) => {\n // Get all required state in one call to minimize store access\n const state = store.getState()\n const { username } = state.currentUser\n const { isActive, isOwnerInside, conferenceId } = state.conference\n const { extensions } = state.users\n\n // Show current waiting user in back view (only on first)\n if (!isActive && username) {\n dispatch.conference.setConferenceActive(true)\n dispatch.conference.setConferenceStartedFrom(username)\n }\n\n // Add pending user to track the participant being added (before socket confirms)\n const extension = extensions\n ? Object.values(extensions).find((ext: any) => ext.exten === numberToCall)\n : null\n const extensionName = extension?.name || numberToCall\n\n dispatch.conference.addPendingUser({\n id: `${conferenceId}-${numberToCall}`,\n name: extensionName,\n owner: false,\n muted: false,\n extenId: numberToCall,\n joinTime: Date.now(),\n })\n\n // If owner has already started the conference, hangup before making a new call\n if (isOwnerInside) {\n hangupCurrentCall()\n dispatch.conference.toggleIsOwnerInside(false)\n }\n\n // Start new call with selected user from conference list\n // Use requestAnimationFrame to ensure state updates are complete before dispatching event\n requestAnimationFrame(() => {\n setTimeout(() => {\n eventDispatch('phone-island-call-start', { number: numberToCall })\n }, 1000)\n })\n}\n\nexport async function handleAttendedTransfer(number: string, dispatch: Dispatch) {\n // Send attended transfer message\n unpauseCurrentCall()\n const transferringMessageSent = await attendedTransfer(number)\n if (transferringMessageSent) {\n // Set transferring and disable pause\n dispatch.currentCall.updateCurrentCall({\n transferring: true,\n paused: false,\n })\n\n // Use requestAnimationFrame to ensure state update is complete before audio operations\n requestAnimationFrame(() => {\n dispatch.player.playRemoteAudio()\n eventDispatch('phone-island-call-transfered', {})\n })\n }\n}\n"],"names":["hangupCurrentCall","_a","store","getState","currentCall","outgoing","accepted","streamingSourceNumber","isFromStreaming","island","isWebRTC","hangup","hangupPhysical","dispatch","player","stopAudioPlayer","reset","listen","sourceId_1","getStreamingSourceId","unsubscribe","id","then","console","debug","concat","catch","error","streaming","clearSourceImages","setIsFromStreaming","resetOperatorBusy","eventDispatch","unpauseCurrentCall","unpauseWebRTC","updateCurrentCall","paused","playRemoteAudio","pausePhysical","attendedTransfer","number","conversationId","default_device","currentUser","default_device_details","exten","attendedTransferRequest","convid","to","endpointId","startConference","_b","chSource","chDest","incoming","incomingSocket","outgoingSocket","defaultDeviceId","addedUserExtension","isEmpty","callerNum","startConferenceInformations","toString","addEndpointId","ownerEndpointId","startConf","_c","sent","conferencing","e_2","endConference","conferenceId","conference","endConferenceInformation","confId","endConf","e_4","isInsideConferenceList","isConferenceList","waitingConferenceView","numberToCall","state","username","isActive","isOwnerInside","extensions","users","setConferenceActive","setConferenceStartedFrom","extension","Object","values","find","ext","extensionName","name","addPendingUser","owner","muted","extenId","joinTime","Date","now","toggleIsOwnerInside","requestAnimationFrame","setTimeout","handleAttendedTransfer","transferring","answerWebRTC","answerPhysical","resetOperatorBusyCompletely","endpointIdInConversation","blindTransferRequest","sipHost","sipURI","setOperatorBusyCalledNumber","callSipURI","callPhysical","__awaiter","conversations","keys","forEach","forceHangup","endpointType","hangupConversation","hangupPhysicalRecordingCall","physicalRecorder","setRecording","setIslandView","joinConferenceInformation","joinMyConf","e_3","isAlreadyMuted","usersList","length","nonOwnerUsers","actionFunction","unmuteUserConf","muteUserConf","_i","nonOwnerUsers_1","user","muteUnmuteUserInformation","userId","toggleUserMuted","e_6","muteWebRTC","mutePhysical","e_5","userConversationInformations","_d","parkingInformation","key","hasOwnProperty","conversation","numberParkId","idConversation","parkConversation","applicantId","setParked","pauseWebRTC","pauseRemoteAudio","updateStartAudioPlayer","src","dtmfAudios","recordingValue","updateRecordingStatus","firstExtensionNotEmpty","data","firstEntry","recording","findFirstExtesnionNotEmpty","numberToSendCall","match","listenInformations","recordingValues","toggleRecord","_e","e_1","extensionId","removeUserInformation","hangupUserConf","_this","remainingParticipants","filter","e_7","unmuteWebRTC"],"mappings":"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"}
|