mediasfu-shared 1.0.6 → 1.2.0
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/HEADLESS_GUIDE.md +156 -0
- package/README.md +130 -62
- package/dist/ProducerClient/producerClientEmits/createDeviceClient.d.ts +23 -0
- package/dist/ProducerClient/producerClientEmits/createDeviceClient.d.ts.map +1 -0
- package/dist/ProducerClient/producerClientEmits/joinRoomClient.d.ts +22 -0
- package/dist/ProducerClient/producerClientEmits/joinRoomClient.d.ts.map +1 -0
- package/dist/ProducerClient/producerClientEmits/updateRoomParametersClient.d.ts +85 -0
- package/dist/ProducerClient/producerClientEmits/updateRoomParametersClient.d.ts.map +1 -0
- package/dist/consumers/addVideosGrid.d.ts +10 -0
- package/dist/consumers/addVideosGrid.d.ts.map +1 -0
- package/dist/consumers/autoAdjust.d.ts +41 -0
- package/dist/consumers/autoAdjust.d.ts.map +1 -0
- package/dist/consumers/calculateRowsAndColumns.d.ts +24 -0
- package/dist/consumers/calculateRowsAndColumns.d.ts.map +1 -0
- package/dist/consumers/changeVids.d.ts +252 -0
- package/dist/consumers/changeVids.d.ts.map +1 -0
- package/dist/consumers/checkGrid.d.ts +42 -0
- package/dist/consumers/checkGrid.d.ts.map +1 -0
- package/dist/consumers/checkPermission.d.ts +42 -0
- package/dist/consumers/checkPermission.d.ts.map +1 -0
- package/dist/consumers/checkScreenShare.d.ts +59 -0
- package/dist/consumers/checkScreenShare.d.ts.map +1 -0
- package/dist/consumers/closeAndResize.d.ts +157 -0
- package/dist/consumers/closeAndResize.d.ts.map +1 -0
- package/dist/consumers/compareActiveNames.d.ts +50 -0
- package/dist/consumers/compareActiveNames.d.ts.map +1 -0
- package/dist/consumers/compareScreenStates.d.ts +55 -0
- package/dist/consumers/compareScreenStates.d.ts.map +1 -0
- package/dist/consumers/connectIps.d.ts +66 -0
- package/dist/consumers/connectIps.d.ts.map +1 -0
- package/dist/consumers/connectLocalIps.d.ts +52 -0
- package/dist/consumers/connectLocalIps.d.ts.map +1 -0
- package/dist/consumers/connectRecvTransport.d.ts +64 -0
- package/dist/consumers/connectRecvTransport.d.ts.map +1 -0
- package/dist/consumers/connectSendTransport.d.ts +75 -0
- package/dist/consumers/connectSendTransport.d.ts.map +1 -0
- package/dist/consumers/connectSendTransportAudio.d.ts +62 -0
- package/dist/consumers/connectSendTransportAudio.d.ts.map +1 -0
- package/dist/consumers/connectSendTransportScreen.d.ts +72 -0
- package/dist/consumers/connectSendTransportScreen.d.ts.map +1 -0
- package/dist/consumers/connectSendTransportVideo.d.ts +75 -0
- package/dist/consumers/connectSendTransportVideo.d.ts.map +1 -0
- package/dist/consumers/consumerResume.d.ts +16 -0
- package/dist/consumers/consumerResume.d.ts.map +1 -0
- package/dist/consumers/controlMedia.d.ts +61 -0
- package/dist/consumers/controlMedia.d.ts.map +1 -0
- package/dist/consumers/createSendTransport.d.ts +80 -0
- package/dist/consumers/createSendTransport.d.ts.map +1 -0
- package/dist/consumers/disconnectSendTransportAudio.d.ts +79 -0
- package/dist/consumers/disconnectSendTransportAudio.d.ts.map +1 -0
- package/dist/consumers/disconnectSendTransportScreen.d.ts +61 -0
- package/dist/consumers/disconnectSendTransportScreen.d.ts.map +1 -0
- package/dist/consumers/disconnectSendTransportVideo.d.ts +72 -0
- package/dist/consumers/disconnectSendTransportVideo.d.ts.map +1 -0
- package/dist/consumers/dispStreams.d.ts +189 -0
- package/dist/consumers/dispStreams.d.ts.map +1 -0
- package/dist/consumers/frameworkConsumerContract.d.ts +2 -0
- package/dist/consumers/frameworkConsumerContract.d.ts.map +1 -0
- package/dist/consumers/generatePageContent.d.ts +68 -0
- package/dist/consumers/generatePageContent.d.ts.map +1 -0
- package/dist/consumers/getEstimate.d.ts +62 -0
- package/dist/consumers/getEstimate.d.ts.map +1 -0
- package/dist/consumers/getPipedProducersAlt.d.ts +62 -0
- package/dist/consumers/getPipedProducersAlt.d.ts.map +1 -0
- package/dist/consumers/getProducersPiped.d.ts +49 -0
- package/dist/consumers/getProducersPiped.d.ts.map +1 -0
- package/dist/consumers/getVideos.d.ts +49 -0
- package/dist/consumers/getVideos.d.ts.map +1 -0
- package/dist/consumers/gridLayout/addVideosGrid.engine.d.ts +19 -0
- package/dist/consumers/gridLayout/addVideosGrid.engine.d.ts.map +1 -0
- package/dist/consumers/gridLayout/prepopulateUserMedia.engine.d.ts +138 -0
- package/dist/consumers/gridLayout/prepopulateUserMedia.engine.d.ts.map +1 -0
- package/dist/consumers/index.cjs +80 -0
- package/dist/consumers/index.cjs.map +1 -0
- package/dist/consumers/index.d.ts +62 -0
- package/dist/consumers/index.d.ts.map +1 -0
- package/dist/consumers/index.js +80 -0
- package/dist/consumers/index.js.map +1 -0
- package/dist/consumers/mixStreams.d.ts +37 -0
- package/dist/consumers/mixStreams.d.ts.map +1 -0
- package/dist/consumers/onScreenChanges.d.ts +62 -0
- package/dist/consumers/onScreenChanges.d.ts.map +1 -0
- package/dist/consumers/prepopulateUserMedia.d.ts +10 -0
- package/dist/consumers/prepopulateUserMedia.d.ts.map +1 -0
- package/dist/consumers/processConsumerTransports.d.ts +73 -0
- package/dist/consumers/processConsumerTransports.d.ts.map +1 -0
- package/dist/consumers/processConsumerTransportsAudio.d.ts +57 -0
- package/dist/consumers/processConsumerTransportsAudio.d.ts.map +1 -0
- package/dist/consumers/rePort.d.ts +63 -0
- package/dist/consumers/rePort.d.ts.map +1 -0
- package/dist/consumers/reUpdateInter.d.ts +142 -0
- package/dist/consumers/reUpdateInter.d.ts.map +1 -0
- package/dist/consumers/readjust.d.ts +68 -0
- package/dist/consumers/readjust.d.ts.map +1 -0
- package/dist/consumers/receiveAllPipedTransports.d.ts +44 -0
- package/dist/consumers/receiveAllPipedTransports.d.ts.map +1 -0
- package/dist/consumers/receiveRoomMessages.d.ts +31 -0
- package/dist/consumers/receiveRoomMessages.d.ts.map +1 -0
- package/dist/consumers/reorderStreams.d.ts +98 -0
- package/dist/consumers/reorderStreams.d.ts.map +1 -0
- package/dist/consumers/requestScreenShare.d.ts +47 -0
- package/dist/consumers/requestScreenShare.d.ts.map +1 -0
- package/dist/consumers/resumePauseAudioStreams.d.ts +85 -0
- package/dist/consumers/resumePauseAudioStreams.d.ts.map +1 -0
- package/dist/consumers/resumePauseStreams.d.ts +68 -0
- package/dist/consumers/resumePauseStreams.d.ts.map +1 -0
- package/dist/consumers/resumeSendTransportAudio.d.ts +65 -0
- package/dist/consumers/resumeSendTransportAudio.d.ts.map +1 -0
- package/dist/consumers/signalNewConsumerTransport.d.ts +59 -0
- package/dist/consumers/signalNewConsumerTransport.d.ts.map +1 -0
- package/dist/consumers/socketReceiveMethods/joinConsumeRoom.d.ts +76 -0
- package/dist/consumers/socketReceiveMethods/joinConsumeRoom.d.ts.map +1 -0
- package/dist/consumers/socketReceiveMethods/newPipeProducer.d.ts +119 -0
- package/dist/consumers/socketReceiveMethods/newPipeProducer.d.ts.map +1 -0
- package/dist/consumers/socketReceiveMethods/producerClosed.d.ts +53 -0
- package/dist/consumers/socketReceiveMethods/producerClosed.d.ts.map +1 -0
- package/dist/consumers/startShareScreen.d.ts +58 -0
- package/dist/consumers/startShareScreen.d.ts.map +1 -0
- package/dist/consumers/stopShareScreen.d.ts +127 -0
- package/dist/consumers/stopShareScreen.d.ts.map +1 -0
- package/dist/consumers/streamSuccessAudio.d.ts +149 -0
- package/dist/consumers/streamSuccessAudio.d.ts.map +1 -0
- package/dist/consumers/streamSuccessAudioSwitch.d.ts +131 -0
- package/dist/consumers/streamSuccessAudioSwitch.d.ts.map +1 -0
- package/dist/consumers/streamSuccessScreen.d.ts +109 -0
- package/dist/consumers/streamSuccessScreen.d.ts.map +1 -0
- package/dist/consumers/streamSuccessVideo.d.ts +160 -0
- package/dist/consumers/streamSuccessVideo.d.ts.map +1 -0
- package/dist/consumers/switchUserAudio.d.ts +56 -0
- package/dist/consumers/switchUserAudio.d.ts.map +1 -0
- package/dist/consumers/switchUserVideo.d.ts +77 -0
- package/dist/consumers/switchUserVideo.d.ts.map +1 -0
- package/dist/consumers/switchUserVideoAlt.d.ts +69 -0
- package/dist/consumers/switchUserVideoAlt.d.ts.map +1 -0
- package/dist/consumers/translationConsumerSwitch.d.ts +67 -0
- package/dist/consumers/translationConsumerSwitch.d.ts.map +1 -0
- package/dist/consumers/trigger.d.ts +71 -0
- package/dist/consumers/trigger.d.ts.map +1 -0
- package/dist/consumers/updateMiniCardsGrid.d.ts +65 -0
- package/dist/consumers/updateMiniCardsGrid.d.ts.map +1 -0
- package/dist/consumers/updateParticipantAudioDecibels.d.ts +31 -0
- package/dist/consumers/updateParticipantAudioDecibels.d.ts.map +1 -0
- package/dist/getParticipantMedia-B0JS6d2b.js +3555 -0
- package/dist/getParticipantMedia-B0JS6d2b.js.map +1 -0
- package/dist/getParticipantMedia-CdcYqcbD.cjs +3554 -0
- package/dist/getParticipantMedia-CdcYqcbD.cjs.map +1 -0
- package/dist/index.cjs +2727 -13252
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +192 -11233
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2636 -13143
- package/dist/index.js.map +1 -1
- package/dist/index.native.cjs +352 -0
- package/dist/index.native.cjs.map +1 -0
- package/dist/index.native.d.ts +204 -0
- package/dist/index.native.d.ts.map +1 -0
- package/dist/index.native.js +352 -0
- package/dist/index.native.js.map +1 -0
- package/dist/joinLocalRoom-BdM1msQt.cjs +673 -0
- package/dist/joinLocalRoom-BdM1msQt.cjs.map +1 -0
- package/dist/joinLocalRoom-CvteNe4R.js +657 -0
- package/dist/joinLocalRoom-CvteNe4R.js.map +1 -0
- package/dist/joinRoomOnMediaSFU-CC8RVJgr.cjs +1222 -0
- package/dist/joinRoomOnMediaSFU-CC8RVJgr.cjs.map +1 -0
- package/dist/joinRoomOnMediaSFU-y6vJ1OBo.js +1223 -0
- package/dist/joinRoomOnMediaSFU-y6vJ1OBo.js.map +1 -0
- package/dist/methods/background/launchBackground.d.ts +10 -0
- package/dist/methods/background/launchBackground.d.ts.map +1 -0
- package/dist/methods/breakoutRooms/breakoutRoomUpdated.d.ts +67 -0
- package/dist/methods/breakoutRooms/breakoutRoomUpdated.d.ts.map +1 -0
- package/dist/methods/breakoutRooms/handleStartBreakout.d.ts +42 -0
- package/dist/methods/breakoutRooms/handleStartBreakout.d.ts.map +1 -0
- package/dist/methods/breakoutRooms/handleStopBreakout.d.ts +33 -0
- package/dist/methods/breakoutRooms/handleStopBreakout.d.ts.map +1 -0
- package/dist/methods/breakoutRooms/index.d.ts +5 -0
- package/dist/methods/breakoutRooms/index.d.ts.map +1 -0
- package/dist/methods/breakoutRooms/launchBreakoutRooms.d.ts +25 -0
- package/dist/methods/breakoutRooms/launchBreakoutRooms.d.ts.map +1 -0
- package/dist/methods/coHost/launchCoHost.d.ts +25 -0
- package/dist/methods/coHost/launchCoHost.d.ts.map +1 -0
- package/dist/methods/coHostMethods/index.d.ts +3 -0
- package/dist/methods/coHostMethods/index.d.ts.map +1 -0
- package/dist/methods/coHostMethods/modifyCoHostSettings.d.ts +49 -0
- package/dist/methods/coHostMethods/modifyCoHostSettings.d.ts.map +1 -0
- package/dist/methods/displaySettings/index.d.ts +2 -0
- package/dist/methods/displaySettings/index.d.ts.map +1 -0
- package/dist/methods/displaySettings/launchDisplaySettings.d.ts +25 -0
- package/dist/methods/displaySettings/launchDisplaySettings.d.ts.map +1 -0
- package/dist/methods/displaySettings/modifyDisplaySettings.d.ts +106 -0
- package/dist/methods/displaySettings/modifyDisplaySettings.d.ts.map +1 -0
- package/dist/methods/exit/confirmExit.d.ts +38 -0
- package/dist/methods/exit/confirmExit.d.ts.map +1 -0
- package/dist/methods/exit/index.d.ts +3 -0
- package/dist/methods/exit/index.d.ts.map +1 -0
- package/dist/methods/exit/launchConfirmExit.d.ts +23 -0
- package/dist/methods/exit/launchConfirmExit.d.ts.map +1 -0
- package/dist/methods/index.cjs +3975 -0
- package/dist/methods/index.cjs.map +1 -0
- package/dist/methods/index.d.ts +66 -0
- package/dist/methods/index.d.ts.map +1 -0
- package/dist/methods/index.js +3976 -0
- package/dist/methods/index.js.map +1 -0
- package/dist/methods/mediaSettings/launchMediaSettings.d.ts +38 -0
- package/dist/methods/mediaSettings/launchMediaSettings.d.ts.map +1 -0
- package/dist/methods/menu/launchMenuModal.d.ts +22 -0
- package/dist/methods/menu/launchMenuModal.d.ts.map +1 -0
- package/dist/methods/message/index.d.ts +2 -0
- package/dist/methods/message/index.d.ts.map +1 -0
- package/dist/methods/message/launchMessages.d.ts +24 -0
- package/dist/methods/message/launchMessages.d.ts.map +1 -0
- package/dist/methods/message/sendMessage.d.ts +63 -0
- package/dist/methods/message/sendMessage.d.ts.map +1 -0
- package/dist/methods/panelists/focusPanelists.d.ts +24 -0
- package/dist/methods/panelists/focusPanelists.d.ts.map +1 -0
- package/dist/methods/panelists/index.d.ts +4 -0
- package/dist/methods/panelists/index.d.ts.map +1 -0
- package/dist/methods/panelists/launchPanelists.d.ts +7 -0
- package/dist/methods/panelists/launchPanelists.d.ts.map +1 -0
- package/dist/methods/panelists/updatePanelists.d.ts +35 -0
- package/dist/methods/panelists/updatePanelists.d.ts.map +1 -0
- package/dist/methods/participants/index.d.ts +4 -0
- package/dist/methods/participants/index.d.ts.map +1 -0
- package/dist/methods/participants/launchParticipants.d.ts +22 -0
- package/dist/methods/participants/launchParticipants.d.ts.map +1 -0
- package/dist/methods/participants/messageParticipants.d.ts +43 -0
- package/dist/methods/participants/messageParticipants.d.ts.map +1 -0
- package/dist/methods/participants/muteParticipants.d.ts +41 -0
- package/dist/methods/participants/muteParticipants.d.ts.map +1 -0
- package/dist/methods/participants/removeParticipants.d.ts +47 -0
- package/dist/methods/participants/removeParticipants.d.ts.map +1 -0
- package/dist/methods/permissions/index.d.ts +4 -0
- package/dist/methods/permissions/index.d.ts.map +1 -0
- package/dist/methods/permissions/launchPermissions.d.ts +7 -0
- package/dist/methods/permissions/launchPermissions.d.ts.map +1 -0
- package/dist/methods/permissions/updateParticipantPermission.d.ts +25 -0
- package/dist/methods/permissions/updateParticipantPermission.d.ts.map +1 -0
- package/dist/methods/permissions/updatePermissionConfig.d.ts +22 -0
- package/dist/methods/permissions/updatePermissionConfig.d.ts.map +1 -0
- package/dist/methods/polls/handleCreatePoll.d.ts +39 -0
- package/dist/methods/polls/handleCreatePoll.d.ts.map +1 -0
- package/dist/methods/polls/handleEndPoll.d.ts +34 -0
- package/dist/methods/polls/handleEndPoll.d.ts.map +1 -0
- package/dist/methods/polls/handleVotePoll.d.ts +39 -0
- package/dist/methods/polls/handleVotePoll.d.ts.map +1 -0
- package/dist/methods/polls/index.d.ts +4 -0
- package/dist/methods/polls/index.d.ts.map +1 -0
- package/dist/methods/polls/launchPoll.d.ts +22 -0
- package/dist/methods/polls/launchPoll.d.ts.map +1 -0
- package/dist/methods/polls/pollUpdated.d.ts +38 -0
- package/dist/methods/polls/pollUpdated.d.ts.map +1 -0
- package/dist/methods/prejoin/handleCreateRoom.d.ts +77 -0
- package/dist/methods/prejoin/handleCreateRoom.d.ts.map +1 -0
- package/dist/methods/prejoin/handleJoinRoom.d.ts +56 -0
- package/dist/methods/prejoin/handleJoinRoom.d.ts.map +1 -0
- package/dist/methods/prejoin/index.d.ts +5 -0
- package/dist/methods/prejoin/index.d.ts.map +1 -0
- package/dist/methods/recording/checkPauseState.d.ts +34 -0
- package/dist/methods/recording/checkPauseState.d.ts.map +1 -0
- package/dist/methods/recording/checkResumeState.d.ts +30 -0
- package/dist/methods/recording/checkResumeState.d.ts.map +1 -0
- package/dist/methods/recording/confirmRecording.d.ts +46 -0
- package/dist/methods/recording/confirmRecording.d.ts.map +1 -0
- package/dist/methods/recording/launchRecording.d.ts +56 -0
- package/dist/methods/recording/launchRecording.d.ts.map +1 -0
- package/dist/methods/recording/recordPauseTimer.d.ts +31 -0
- package/dist/methods/recording/recordPauseTimer.d.ts.map +1 -0
- package/dist/methods/recording/recordResumeTimer.d.ts +29 -0
- package/dist/methods/recording/recordResumeTimer.d.ts.map +1 -0
- package/dist/methods/recording/recordStartTimer.d.ts +45 -0
- package/dist/methods/recording/recordStartTimer.d.ts.map +1 -0
- package/dist/methods/recording/recordUpdateTimer.d.ts +29 -0
- package/dist/methods/recording/recordUpdateTimer.d.ts.map +1 -0
- package/dist/methods/recording/startRecording.d.ts +122 -0
- package/dist/methods/recording/startRecording.d.ts.map +1 -0
- package/dist/methods/recording/stopRecording.d.ts +36 -0
- package/dist/methods/recording/stopRecording.d.ts.map +1 -0
- package/dist/methods/recording/timeLeftRecording.d.ts +13 -0
- package/dist/methods/recording/timeLeftRecording.d.ts.map +1 -0
- package/dist/methods/recording/updateRecording.d.ts +49 -0
- package/dist/methods/recording/updateRecording.d.ts.map +1 -0
- package/dist/methods/requests/hostRequestResponse.d.ts +33 -0
- package/dist/methods/requests/hostRequestResponse.d.ts.map +1 -0
- package/dist/methods/requests/index.d.ts +2 -0
- package/dist/methods/requests/index.d.ts.map +1 -0
- package/dist/methods/requests/launchRequests.d.ts +22 -0
- package/dist/methods/requests/launchRequests.d.ts.map +1 -0
- package/dist/methods/requests/respondToRequests.d.ts +38 -0
- package/dist/methods/requests/respondToRequests.d.ts.map +1 -0
- package/dist/methods/settings/index.d.ts +3 -0
- package/dist/methods/settings/index.d.ts.map +1 -0
- package/dist/methods/settings/launchSettings.d.ts +22 -0
- package/dist/methods/settings/launchSettings.d.ts.map +1 -0
- package/dist/methods/settings/modifySettings.d.ts +45 -0
- package/dist/methods/settings/modifySettings.d.ts.map +1 -0
- package/dist/methods/socketReceive/allMembers.d.ts +117 -0
- package/dist/methods/socketReceive/allMembers.d.ts.map +1 -0
- package/dist/methods/socketReceive/allMembersRest.d.ts +122 -0
- package/dist/methods/socketReceive/allMembersRest.d.ts.map +1 -0
- package/dist/methods/socketReceive/allWaitingRoomMembers.d.ts +24 -0
- package/dist/methods/socketReceive/allWaitingRoomMembers.d.ts.map +1 -0
- package/dist/methods/socketReceive/banParticipant.d.ts +44 -0
- package/dist/methods/socketReceive/banParticipant.d.ts.map +1 -0
- package/dist/methods/socketReceive/controlMediaHost.d.ts +62 -0
- package/dist/methods/socketReceive/controlMediaHost.d.ts.map +1 -0
- package/dist/methods/socketReceive/disconnect.d.ts +24 -0
- package/dist/methods/socketReceive/disconnect.d.ts.map +1 -0
- package/dist/methods/socketReceive/disconnectUserSelf.d.ts +29 -0
- package/dist/methods/socketReceive/disconnectUserSelf.d.ts.map +1 -0
- package/dist/methods/socketReceive/getDomains.d.ts +48 -0
- package/dist/methods/socketReceive/getDomains.d.ts.map +1 -0
- package/dist/methods/socketReceive/meetingEnded.d.ts +27 -0
- package/dist/methods/socketReceive/meetingEnded.d.ts.map +1 -0
- package/dist/methods/socketReceive/meetingStillThere.d.ts +19 -0
- package/dist/methods/socketReceive/meetingStillThere.d.ts.map +1 -0
- package/dist/methods/socketReceive/panelistReceiveMethods.d.ts +66 -0
- package/dist/methods/socketReceive/panelistReceiveMethods.d.ts.map +1 -0
- package/dist/methods/socketReceive/participantRequested.d.ts +28 -0
- package/dist/methods/socketReceive/participantRequested.d.ts.map +1 -0
- package/dist/methods/socketReceive/permissionReceiveMethods.d.ts +23 -0
- package/dist/methods/socketReceive/permissionReceiveMethods.d.ts.map +1 -0
- package/dist/methods/socketReceive/personJoined.d.ts +24 -0
- package/dist/methods/socketReceive/personJoined.d.ts.map +1 -0
- package/dist/methods/socketReceive/producerMediaClosed.d.ts +66 -0
- package/dist/methods/socketReceive/producerMediaClosed.d.ts.map +1 -0
- package/dist/methods/socketReceive/producerMediaPaused.d.ts +70 -0
- package/dist/methods/socketReceive/producerMediaPaused.d.ts.map +1 -0
- package/dist/methods/socketReceive/producerMediaResumed.d.ts +53 -0
- package/dist/methods/socketReceive/producerMediaResumed.d.ts.map +1 -0
- package/dist/methods/socketReceive/reInitiateRecording.d.ts +33 -0
- package/dist/methods/socketReceive/reInitiateRecording.d.ts.map +1 -0
- package/dist/methods/socketReceive/receiveMessage.d.ts +36 -0
- package/dist/methods/socketReceive/receiveMessage.d.ts.map +1 -0
- package/dist/methods/socketReceive/recordingNotice.d.ts +98 -0
- package/dist/methods/socketReceive/recordingNotice.d.ts.map +1 -0
- package/dist/methods/socketReceive/roomRecordParams.d.ts +60 -0
- package/dist/methods/socketReceive/roomRecordParams.d.ts.map +1 -0
- package/dist/methods/socketReceive/screenProducerId.d.ts +36 -0
- package/dist/methods/socketReceive/screenProducerId.d.ts.map +1 -0
- package/dist/methods/socketReceive/startRecords.d.ts +31 -0
- package/dist/methods/socketReceive/startRecords.d.ts.map +1 -0
- package/dist/methods/socketReceive/stoppedRecording.d.ts +24 -0
- package/dist/methods/socketReceive/stoppedRecording.d.ts.map +1 -0
- package/dist/methods/socketReceive/translationReceiveMethods.d.ts +227 -0
- package/dist/methods/socketReceive/translationReceiveMethods.d.ts.map +1 -0
- package/dist/methods/socketReceive/updateConsumingDomains.d.ts +60 -0
- package/dist/methods/socketReceive/updateConsumingDomains.d.ts.map +1 -0
- package/dist/methods/socketReceive/updateMediaSettings.d.ts +28 -0
- package/dist/methods/socketReceive/updateMediaSettings.d.ts.map +1 -0
- package/dist/methods/socketReceive/updatedCoHost.d.ts +38 -0
- package/dist/methods/socketReceive/updatedCoHost.d.ts.map +1 -0
- package/dist/methods/socketReceive/userWaiting.d.ts +30 -0
- package/dist/methods/socketReceive/userWaiting.d.ts.map +1 -0
- package/dist/methods/stream/clickAudio.d.ts +71 -0
- package/dist/methods/stream/clickAudio.d.ts.map +1 -0
- package/dist/methods/stream/clickChat.d.ts +11 -0
- package/dist/methods/stream/clickChat.d.ts.map +1 -0
- package/dist/methods/stream/clickScreenShare.d.ts +45 -0
- package/dist/methods/stream/clickScreenShare.d.ts.map +1 -0
- package/dist/methods/stream/clickVideo.d.ts +101 -0
- package/dist/methods/stream/clickVideo.d.ts.map +1 -0
- package/dist/methods/stream/index.d.ts +5 -0
- package/dist/methods/stream/index.d.ts.map +1 -0
- package/dist/methods/stream/switchAudio.d.ts +40 -0
- package/dist/methods/stream/switchAudio.d.ts.map +1 -0
- package/dist/methods/stream/switchVideo.d.ts +56 -0
- package/dist/methods/stream/switchVideo.d.ts.map +1 -0
- package/dist/methods/stream/switchVideoAlt.d.ts +55 -0
- package/dist/methods/stream/switchVideoAlt.d.ts.map +1 -0
- package/dist/methods/utils/SoundPlayer.d.ts +19 -0
- package/dist/methods/utils/SoundPlayer.d.ts.map +1 -0
- package/dist/methods/utils/checkLimitsAndMakeRequest.d.ts +30 -0
- package/dist/methods/utils/checkLimitsAndMakeRequest.d.ts.map +1 -0
- package/dist/methods/utils/createResponseJoinRoom.d.ts +24 -0
- package/dist/methods/utils/createResponseJoinRoom.d.ts.map +1 -0
- package/dist/methods/utils/createRoomOnMediaSFU.d.ts +28 -0
- package/dist/methods/utils/createRoomOnMediaSFU.d.ts.map +1 -0
- package/dist/methods/utils/formatNumber.d.ts +21 -0
- package/dist/methods/utils/formatNumber.d.ts.map +1 -0
- package/dist/methods/utils/generateRandomMessages.d.ts +11 -0
- package/dist/methods/utils/generateRandomMessages.d.ts.map +1 -0
- package/dist/methods/utils/generateRandomParticipants.d.ts +10 -0
- package/dist/methods/utils/generateRandomParticipants.d.ts.map +1 -0
- package/dist/methods/utils/generateRandomPolls.d.ts +7 -0
- package/dist/methods/utils/generateRandomPolls.d.ts.map +1 -0
- package/dist/methods/utils/generateRandomRequestList.d.ts +10 -0
- package/dist/methods/utils/generateRandomRequestList.d.ts.map +1 -0
- package/dist/methods/utils/generateRandomWaitingRoomList.d.ts +4 -0
- package/dist/methods/utils/generateRandomWaitingRoomList.d.ts.map +1 -0
- package/dist/methods/utils/getModalPosition.d.ts +7 -0
- package/dist/methods/utils/getModalPosition.d.ts.map +1 -0
- package/dist/methods/utils/getOverlayPosition.d.ts +22 -0
- package/dist/methods/utils/getOverlayPosition.d.ts.map +1 -0
- package/dist/methods/utils/getParticipantMedia.d.ts +55 -0
- package/dist/methods/utils/getParticipantMedia.d.ts.map +1 -0
- package/dist/methods/utils/headless/getCurrentParams.d.ts +27 -0
- package/dist/methods/utils/headless/getCurrentParams.d.ts.map +1 -0
- package/dist/methods/utils/headless/getMediaStreams.d.ts +96 -0
- package/dist/methods/utils/headless/getMediaStreams.d.ts.map +1 -0
- package/dist/methods/utils/headless/getRoomReadiness.d.ts +25 -0
- package/dist/methods/utils/headless/getRoomReadiness.d.ts.map +1 -0
- package/dist/methods/utils/headless/headlessTypes.d.ts +89 -0
- package/dist/methods/utils/headless/headlessTypes.d.ts.map +1 -0
- package/dist/methods/utils/headless/index.d.ts +29 -0
- package/dist/methods/utils/headless/index.d.ts.map +1 -0
- package/dist/methods/utils/headless/mediaPermissions.d.ts +53 -0
- package/dist/methods/utils/headless/mediaPermissions.d.ts.map +1 -0
- package/dist/methods/utils/headless/mediaProduction.d.ts +177 -0
- package/dist/methods/utils/headless/mediaProduction.d.ts.map +1 -0
- package/dist/methods/utils/headless/moderation.d.ts +157 -0
- package/dist/methods/utils/headless/moderation.d.ts.map +1 -0
- package/dist/methods/utils/headless/participantState.d.ts +128 -0
- package/dist/methods/utils/headless/participantState.d.ts.map +1 -0
- package/dist/methods/utils/headless/playback.d.ts +106 -0
- package/dist/methods/utils/headless/playback.d.ts.map +1 -0
- package/dist/methods/utils/headless/roomActions.d.ts +88 -0
- package/dist/methods/utils/headless/roomActions.d.ts.map +1 -0
- package/dist/methods/utils/headless/sessionControls.d.ts +159 -0
- package/dist/methods/utils/headless/sessionControls.d.ts.map +1 -0
- package/dist/methods/utils/headless/sessionExtras.d.ts +291 -0
- package/dist/methods/utils/headless/sessionExtras.d.ts.map +1 -0
- package/dist/methods/utils/headless/sessionFeatures.d.ts +159 -0
- package/dist/methods/utils/headless/sessionFeatures.d.ts.map +1 -0
- package/dist/methods/utils/headless/viewerSession.d.ts +125 -0
- package/dist/methods/utils/headless/viewerSession.d.ts.map +1 -0
- package/dist/methods/utils/headless/virtualBackground.d.ts +72 -0
- package/dist/methods/utils/headless/virtualBackground.d.ts.map +1 -0
- package/dist/methods/utils/initialValuesState.d.ts +388 -0
- package/dist/methods/utils/initialValuesState.d.ts.map +1 -0
- package/dist/methods/utils/joinRoomOnMediaSFU.d.ts +56 -0
- package/dist/methods/utils/joinRoomOnMediaSFU.d.ts.map +1 -0
- package/dist/methods/utils/liveSubtitle.d.ts +36 -0
- package/dist/methods/utils/liveSubtitle.d.ts.map +1 -0
- package/dist/methods/utils/meetingTimeRemaining.d.ts +15 -0
- package/dist/methods/utils/meetingTimeRemaining.d.ts.map +1 -0
- package/dist/methods/utils/meetingTimer/startMeetingProgressTimer.d.ts +35 -0
- package/dist/methods/utils/meetingTimer/startMeetingProgressTimer.d.ts.map +1 -0
- package/dist/methods/utils/producer/aParams.d.ts +3 -0
- package/dist/methods/utils/producer/aParams.d.ts.map +1 -0
- package/dist/methods/utils/producer/hParams.d.ts +3 -0
- package/dist/methods/utils/producer/hParams.d.ts.map +1 -0
- package/dist/methods/utils/producer/screenParams.d.ts +3 -0
- package/dist/methods/utils/producer/screenParams.d.ts.map +1 -0
- package/dist/methods/utils/producer/vParams.d.ts +3 -0
- package/dist/methods/utils/producer/vParams.d.ts.map +1 -0
- package/dist/methods/utils/producer/videoCaptureConstraints.d.ts +145 -0
- package/dist/methods/utils/producer/videoCaptureConstraints.d.ts.map +1 -0
- package/dist/methods/utils/resolveMediaSFURoomApi.d.ts +4 -0
- package/dist/methods/utils/resolveMediaSFURoomApi.d.ts.map +1 -0
- package/dist/methods/utils/sleep.d.ts +21 -0
- package/dist/methods/utils/sleep.d.ts.map +1 -0
- package/dist/methods/utils/translationLanguages.d.ts +100 -0
- package/dist/methods/utils/translationLanguages.d.ts.map +1 -0
- package/dist/methods/utils/validateAlphanumeric.d.ts +21 -0
- package/dist/methods/utils/validateAlphanumeric.d.ts.map +1 -0
- package/dist/methods/utils/virtualBackgroundCompositor.d.ts +21 -0
- package/dist/methods/utils/virtualBackgroundCompositor.d.ts.map +1 -0
- package/dist/methods/utils/webrtc.d.ts +18 -0
- package/dist/methods/utils/webrtc.d.ts.map +1 -0
- package/dist/methods/waiting/index.d.ts +2 -0
- package/dist/methods/waiting/index.d.ts.map +1 -0
- package/dist/methods/waiting/launchWaiting.d.ts +23 -0
- package/dist/methods/waiting/launchWaiting.d.ts.map +1 -0
- package/dist/methods/waiting/respondToWaiting.d.ts +40 -0
- package/dist/methods/waiting/respondToWaiting.d.ts.map +1 -0
- package/dist/methods/welcome/handleWelcomeRequest.d.ts +47 -0
- package/dist/methods/welcome/handleWelcomeRequest.d.ts.map +1 -0
- package/dist/methods/welcome/index.d.ts +3 -0
- package/dist/methods/welcome/index.d.ts.map +1 -0
- package/dist/methods/whiteboard/captureCanvasStream.d.ts +38 -0
- package/dist/methods/whiteboard/captureCanvasStream.d.ts.map +1 -0
- package/dist/methods/whiteboard/handleStartWhiteboard.d.ts +31 -0
- package/dist/methods/whiteboard/handleStartWhiteboard.d.ts.map +1 -0
- package/dist/methods/whiteboard/handleStopWhiteboard.d.ts +25 -0
- package/dist/methods/whiteboard/handleStopWhiteboard.d.ts.map +1 -0
- package/dist/methods/whiteboard/index.d.ts +5 -0
- package/dist/methods/whiteboard/index.d.ts.map +1 -0
- package/dist/methods/whiteboard/launchConfigureWhiteboard.d.ts +23 -0
- package/dist/methods/whiteboard/launchConfigureWhiteboard.d.ts.map +1 -0
- package/dist/producers/producerEmits/joinConRoom.d.ts +54 -0
- package/dist/producers/producerEmits/joinConRoom.d.ts.map +1 -0
- package/dist/producers/producerEmits/joinLocalRoom.d.ts +30 -0
- package/dist/producers/producerEmits/joinLocalRoom.d.ts.map +1 -0
- package/dist/producers/producerEmits/joinRoom.d.ts +35 -0
- package/dist/producers/producerEmits/joinRoom.d.ts.map +1 -0
- package/dist/readme/mediasfu-platform-capabilities.webp +0 -0
- package/dist/sockets/SocketManager.d.ts +102 -0
- package/dist/sockets/SocketManager.d.ts.map +1 -0
- package/dist/translationConsumerSwitch-C20MfNNq.cjs +509 -0
- package/dist/translationConsumerSwitch-C20MfNNq.cjs.map +1 -0
- package/dist/translationConsumerSwitch-zKuS5wgH.js +510 -0
- package/dist/translationConsumerSwitch-zKuS5wgH.js.map +1 -0
- package/dist/types/index.cjs +85 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +85 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/shared-base-types.d.ts +656 -0
- package/dist/types/shared-base-types.d.ts.map +1 -0
- package/dist/types/types.d.ts +124 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/updateParticipantAudioDecibels-DLd8Y-Fh.js +5392 -0
- package/dist/updateParticipantAudioDecibels-DLd8Y-Fh.js.map +1 -0
- package/dist/updateParticipantAudioDecibels-DPmHiy3K.cjs +5391 -0
- package/dist/updateParticipantAudioDecibels-DPmHiy3K.cjs.map +1 -0
- package/dist/validateAlphanumeric-DKn5BsUP.cjs +15 -0
- package/dist/validateAlphanumeric-DKn5BsUP.cjs.map +1 -0
- package/dist/validateAlphanumeric-Dk1JB80W.js +16 -0
- package/dist/validateAlphanumeric-Dk1JB80W.js.map +1 -0
- package/package.json +106 -99
- package/src/ProducerClient/producerClientEmits/createDeviceClient.ts +1 -2
- package/src/ProducerClient/producerClientEmits/updateRoomParametersClient.ts +1 -1
- package/src/consumers/connectIps.ts +1 -1
- package/src/consumers/connectRecvTransport.ts +1 -1
- package/src/consumers/connectSendTransport.ts +1 -1
- package/src/consumers/connectSendTransportAudio.ts +1 -1
- package/src/consumers/connectSendTransportScreen.ts +5 -2
- package/src/consumers/connectSendTransportVideo.ts +1 -1
- package/src/consumers/createSendTransport.ts +34 -29
- package/src/consumers/disconnectSendTransportAudio.ts +1 -1
- package/src/consumers/disconnectSendTransportScreen.ts +1 -1
- package/src/consumers/disconnectSendTransportVideo.ts +1 -1
- package/src/consumers/index.ts +61 -0
- package/src/consumers/resumeSendTransportAudio.ts +1 -1
- package/src/consumers/signalNewConsumerTransport.ts +1 -2
- package/src/consumers/socketReceiveMethods/joinConsumeRoom.ts +1 -1
- package/src/consumers/socketReceiveMethods/newPipeProducer.ts +1 -1
- package/src/consumers/streamSuccessAudio.ts +1 -2
- package/src/consumers/streamSuccessAudioSwitch.ts +1 -2
- package/src/consumers/streamSuccessVideo.ts +35 -6
- package/src/index.native.ts +24 -1
- package/src/index.ts +7 -0
- package/src/methods/exit/confirmExit.ts +11 -4
- package/src/methods/socketReceive/getDomains.ts +1 -1
- package/src/methods/utils/getParticipantMedia.ts +112 -0
- package/src/methods/utils/headless/getCurrentParams.ts +44 -0
- package/src/methods/utils/headless/getMediaStreams.ts +256 -0
- package/src/methods/utils/headless/getRoomReadiness.ts +49 -0
- package/src/methods/utils/headless/headlessTypes.ts +102 -0
- package/src/methods/utils/headless/index.ts +28 -0
- package/src/methods/utils/headless/mediaPermissions.ts +124 -0
- package/src/methods/utils/headless/mediaProduction.ts +505 -0
- package/src/methods/utils/headless/moderation.ts +455 -0
- package/src/methods/utils/headless/participantState.ts +254 -0
- package/src/methods/utils/headless/playback.ts +336 -0
- package/src/methods/utils/headless/roomActions.ts +230 -0
- package/src/methods/utils/headless/sessionControls.ts +335 -0
- package/src/methods/utils/headless/sessionExtras.ts +593 -0
- package/src/methods/utils/headless/sessionFeatures.ts +480 -0
- package/src/methods/utils/headless/viewerSession.ts +246 -0
- package/src/methods/utils/headless/virtualBackground.ts +280 -0
- package/src/methods/utils/resolveMediaSFURoomApi.ts +2 -2
- package/src/methods/utils/virtualBackgroundCompositor.ts +53 -0
- package/src/methods/whiteboard/captureCanvasStream.ts +2 -2
- package/src/producers/producerEmits/joinConRoom.ts +1 -1
- package/src/producers/producerEmits/joinRoom.ts +1 -1
- package/src/types/index.ts +1 -0
- package/src/types/shared-base-types.ts +2 -3
|
@@ -0,0 +1,3555 @@
|
|
|
1
|
+
import { m as modifySettings } from "./joinLocalRoom-CvteNe4R.js";
|
|
2
|
+
import { K as streamSuccessAudio, M as streamSuccessScreen, O as streamSuccessVideo, o as disconnectSendTransportAudio, p as disconnectSendTransportScreen, q as disconnectSendTransportVideo } from "./updateParticipantAudioDecibels-DLd8Y-Fh.js";
|
|
3
|
+
const launchBackground = ({
|
|
4
|
+
updateIsBackgroundModalVisible,
|
|
5
|
+
isBackgroundModalVisible
|
|
6
|
+
}) => {
|
|
7
|
+
updateIsBackgroundModalVisible(!isBackgroundModalVisible);
|
|
8
|
+
};
|
|
9
|
+
const handleStartBreakout = ({
|
|
10
|
+
socket,
|
|
11
|
+
localSocket,
|
|
12
|
+
breakoutRooms,
|
|
13
|
+
newParticipantAction,
|
|
14
|
+
roomName,
|
|
15
|
+
breakOutRoomStarted,
|
|
16
|
+
breakOutRoomEnded,
|
|
17
|
+
showAlert,
|
|
18
|
+
updateBreakOutRoomStarted,
|
|
19
|
+
updateBreakOutRoomEnded,
|
|
20
|
+
onBreakoutRoomsClose,
|
|
21
|
+
meetingDisplayType,
|
|
22
|
+
updateMeetingDisplayType
|
|
23
|
+
}) => {
|
|
24
|
+
const emitName = breakOutRoomStarted && !breakOutRoomEnded ? "updateBreakout" : "startBreakout";
|
|
25
|
+
const filteredBreakoutRooms = breakoutRooms.map(
|
|
26
|
+
(room) => room.map(({ name, breakRoom }) => ({ name, breakRoom }))
|
|
27
|
+
);
|
|
28
|
+
socket.emit(
|
|
29
|
+
emitName,
|
|
30
|
+
{ breakoutRooms: filteredBreakoutRooms, newParticipantAction, roomName },
|
|
31
|
+
(response) => {
|
|
32
|
+
if (response.success) {
|
|
33
|
+
showAlert?.({ message: "Breakout rooms active", type: "success" });
|
|
34
|
+
updateBreakOutRoomStarted(true);
|
|
35
|
+
updateBreakOutRoomEnded(false);
|
|
36
|
+
onBreakoutRoomsClose();
|
|
37
|
+
if (meetingDisplayType !== "all") {
|
|
38
|
+
updateMeetingDisplayType("all");
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
showAlert?.({ message: response.reason, type: "danger" });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
if (localSocket && localSocket.id) {
|
|
46
|
+
try {
|
|
47
|
+
localSocket.emit(
|
|
48
|
+
emitName,
|
|
49
|
+
{ breakoutRooms: filteredBreakoutRooms, newParticipantAction, roomName },
|
|
50
|
+
(response) => {
|
|
51
|
+
if (response.success) {
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
} catch {
|
|
56
|
+
console.log("Error starting local breakout rooms:");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const handleStopBreakout = ({
|
|
61
|
+
socket,
|
|
62
|
+
localSocket,
|
|
63
|
+
roomName,
|
|
64
|
+
showAlert,
|
|
65
|
+
updateBreakOutRoomStarted,
|
|
66
|
+
updateBreakOutRoomEnded,
|
|
67
|
+
onBreakoutRoomsClose,
|
|
68
|
+
meetingDisplayType,
|
|
69
|
+
prevMeetingDisplayType,
|
|
70
|
+
updateMeetingDisplayType
|
|
71
|
+
}) => {
|
|
72
|
+
socket.emit("stopBreakout", { roomName }, (response) => {
|
|
73
|
+
if (response.success) {
|
|
74
|
+
showAlert?.({ message: "Breakout rooms stopped", type: "success" });
|
|
75
|
+
updateBreakOutRoomStarted(false);
|
|
76
|
+
updateBreakOutRoomEnded(true);
|
|
77
|
+
onBreakoutRoomsClose();
|
|
78
|
+
if (meetingDisplayType !== prevMeetingDisplayType) {
|
|
79
|
+
updateMeetingDisplayType(prevMeetingDisplayType);
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
showAlert?.({ message: response.reason, type: "danger" });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
if (localSocket && localSocket.id) {
|
|
86
|
+
try {
|
|
87
|
+
localSocket.emit("stopBreakout", { roomName }, (response) => {
|
|
88
|
+
if (response.success) {
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
} catch {
|
|
92
|
+
console.log("Error stopping local breakout rooms:");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const launchBreakoutRooms = ({
|
|
97
|
+
updateIsBreakoutRoomsModalVisible,
|
|
98
|
+
isBreakoutRoomsModalVisible
|
|
99
|
+
}) => {
|
|
100
|
+
updateIsBreakoutRoomsModalVisible(!isBreakoutRoomsModalVisible);
|
|
101
|
+
};
|
|
102
|
+
const launchCoHost = ({ updateIsCoHostModalVisible, isCoHostModalVisible }) => {
|
|
103
|
+
updateIsCoHostModalVisible(!isCoHostModalVisible);
|
|
104
|
+
};
|
|
105
|
+
const modifyCoHostSettings = async ({
|
|
106
|
+
roomName,
|
|
107
|
+
// showAlert,
|
|
108
|
+
selectedParticipant,
|
|
109
|
+
coHost,
|
|
110
|
+
coHostResponsibility,
|
|
111
|
+
updateIsCoHostModalVisible,
|
|
112
|
+
updateCoHostResponsibility,
|
|
113
|
+
updateCoHost,
|
|
114
|
+
socket
|
|
115
|
+
}) => {
|
|
116
|
+
let newCoHost = coHost;
|
|
117
|
+
if (coHost !== "No coHost" || selectedParticipant && selectedParticipant !== "Select a participant") {
|
|
118
|
+
if (selectedParticipant && selectedParticipant !== "Select a participant") {
|
|
119
|
+
newCoHost = selectedParticipant;
|
|
120
|
+
updateCoHost(newCoHost);
|
|
121
|
+
}
|
|
122
|
+
updateCoHostResponsibility(coHostResponsibility);
|
|
123
|
+
socket.emit("updateCoHost", {
|
|
124
|
+
roomName,
|
|
125
|
+
coHost: newCoHost,
|
|
126
|
+
coHostResponsibility
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
updateIsCoHostModalVisible(false);
|
|
130
|
+
};
|
|
131
|
+
const launchDisplaySettings = ({
|
|
132
|
+
updateIsDisplaySettingsModalVisible,
|
|
133
|
+
isDisplaySettingsModalVisible
|
|
134
|
+
}) => {
|
|
135
|
+
updateIsDisplaySettingsModalVisible(!isDisplaySettingsModalVisible);
|
|
136
|
+
};
|
|
137
|
+
const modifyDisplaySettings = async ({
|
|
138
|
+
parameters
|
|
139
|
+
}) => {
|
|
140
|
+
let {
|
|
141
|
+
showAlert,
|
|
142
|
+
meetingDisplayType,
|
|
143
|
+
autoWave,
|
|
144
|
+
forceFullDisplay,
|
|
145
|
+
showSubtitlesOnCards = true,
|
|
146
|
+
meetingVideoOptimized,
|
|
147
|
+
islevel,
|
|
148
|
+
recordStarted,
|
|
149
|
+
recordResumed,
|
|
150
|
+
recordStopped,
|
|
151
|
+
recordPaused,
|
|
152
|
+
recordingDisplayType,
|
|
153
|
+
recordingVideoOptimized,
|
|
154
|
+
prevForceFullDisplay,
|
|
155
|
+
prevMeetingDisplayType,
|
|
156
|
+
updateMeetingDisplayType,
|
|
157
|
+
updateAutoWave,
|
|
158
|
+
updateForceFullDisplay,
|
|
159
|
+
updateShowSubtitlesOnCards,
|
|
160
|
+
updateMeetingVideoOptimized,
|
|
161
|
+
updatePrevForceFullDisplay,
|
|
162
|
+
updatePrevMeetingDisplayType,
|
|
163
|
+
updateIsDisplaySettingsModalVisible,
|
|
164
|
+
updateFirstAll,
|
|
165
|
+
updateUpdateMainWindow,
|
|
166
|
+
breakOutRoomStarted,
|
|
167
|
+
breakOutRoomEnded,
|
|
168
|
+
onScreenChanges
|
|
169
|
+
} = parameters;
|
|
170
|
+
updateAutoWave(autoWave);
|
|
171
|
+
updateForceFullDisplay(forceFullDisplay);
|
|
172
|
+
updateShowSubtitlesOnCards?.(showSubtitlesOnCards);
|
|
173
|
+
if (islevel === "2" && (recordStarted || recordResumed) && !recordStopped && !recordPaused) {
|
|
174
|
+
if (recordingDisplayType === "video" && meetingDisplayType === "video" && meetingVideoOptimized && !recordingVideoOptimized) {
|
|
175
|
+
showAlert?.({
|
|
176
|
+
message: "Meeting display type can be either video, media, or all when recording display type is non-optimized video.",
|
|
177
|
+
type: "danger",
|
|
178
|
+
duration: 3e3
|
|
179
|
+
});
|
|
180
|
+
meetingDisplayType = recordingDisplayType;
|
|
181
|
+
updateMeetingDisplayType(meetingDisplayType);
|
|
182
|
+
meetingVideoOptimized = recordingVideoOptimized;
|
|
183
|
+
updateMeetingVideoOptimized(meetingVideoOptimized);
|
|
184
|
+
return;
|
|
185
|
+
} else if (recordingDisplayType === "media" && meetingDisplayType === "video") {
|
|
186
|
+
showAlert?.({
|
|
187
|
+
message: "Meeting display type can be either media or all when recording display type is media.",
|
|
188
|
+
type: "danger",
|
|
189
|
+
duration: 3e3
|
|
190
|
+
});
|
|
191
|
+
meetingDisplayType = recordingDisplayType;
|
|
192
|
+
updateMeetingDisplayType(meetingDisplayType);
|
|
193
|
+
return;
|
|
194
|
+
} else if (recordingDisplayType === "all" && (meetingDisplayType === "video" || meetingDisplayType === "media")) {
|
|
195
|
+
showAlert?.({
|
|
196
|
+
message: "Meeting display type can be only all when recording display type is all.",
|
|
197
|
+
type: "danger",
|
|
198
|
+
duration: 3e3
|
|
199
|
+
});
|
|
200
|
+
meetingDisplayType = recordingDisplayType;
|
|
201
|
+
updateMeetingDisplayType(meetingDisplayType);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
updateMeetingDisplayType(meetingDisplayType);
|
|
206
|
+
updateMeetingVideoOptimized(meetingVideoOptimized);
|
|
207
|
+
updateIsDisplaySettingsModalVisible(false);
|
|
208
|
+
if (prevMeetingDisplayType !== meetingDisplayType || prevForceFullDisplay !== forceFullDisplay) {
|
|
209
|
+
if (breakOutRoomStarted && !breakOutRoomEnded && meetingDisplayType !== "all") {
|
|
210
|
+
showAlert?.({
|
|
211
|
+
message: "Breakout room is active. Display type can only be all.",
|
|
212
|
+
type: "danger"
|
|
213
|
+
});
|
|
214
|
+
meetingDisplayType = prevMeetingDisplayType;
|
|
215
|
+
updateMeetingDisplayType(prevMeetingDisplayType);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
updateFirstAll(meetingDisplayType !== "all" ? true : false);
|
|
219
|
+
updateUpdateMainWindow(true);
|
|
220
|
+
await onScreenChanges({
|
|
221
|
+
changed: true,
|
|
222
|
+
parameters: { ...parameters, meetingDisplayType, forceFullDisplay }
|
|
223
|
+
});
|
|
224
|
+
updatePrevForceFullDisplay(forceFullDisplay);
|
|
225
|
+
updatePrevMeetingDisplayType(meetingDisplayType);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
const confirmExit = async ({
|
|
229
|
+
socket,
|
|
230
|
+
localSocket,
|
|
231
|
+
member,
|
|
232
|
+
roomName,
|
|
233
|
+
ban = false,
|
|
234
|
+
endRoomOnHostExit = true
|
|
235
|
+
}) => {
|
|
236
|
+
socket.emit("disconnectUser", {
|
|
237
|
+
member,
|
|
238
|
+
roomName,
|
|
239
|
+
ban,
|
|
240
|
+
endRoomOnHostExit
|
|
241
|
+
});
|
|
242
|
+
if (localSocket && localSocket.id) {
|
|
243
|
+
localSocket.emit("disconnectUser", {
|
|
244
|
+
member,
|
|
245
|
+
roomName,
|
|
246
|
+
ban,
|
|
247
|
+
endRoomOnHostExit
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
const launchConfirmExit = ({
|
|
252
|
+
updateIsConfirmExitModalVisible,
|
|
253
|
+
isConfirmExitModalVisible
|
|
254
|
+
}) => {
|
|
255
|
+
updateIsConfirmExitModalVisible(!isConfirmExitModalVisible);
|
|
256
|
+
};
|
|
257
|
+
const launchMediaSettings = async ({
|
|
258
|
+
updateIsMediaSettingsModalVisible,
|
|
259
|
+
isMediaSettingsModalVisible,
|
|
260
|
+
mediaDevices,
|
|
261
|
+
audioInputs,
|
|
262
|
+
videoInputs,
|
|
263
|
+
updateAudioInputs,
|
|
264
|
+
updateVideoInputs
|
|
265
|
+
}) => {
|
|
266
|
+
if (!isMediaSettingsModalVisible) {
|
|
267
|
+
try {
|
|
268
|
+
const devices = await mediaDevices.enumerateDevices();
|
|
269
|
+
videoInputs = devices.filter((device) => device.kind === "videoinput");
|
|
270
|
+
audioInputs = devices.filter((device) => device.kind === "audioinput");
|
|
271
|
+
updateVideoInputs(videoInputs);
|
|
272
|
+
updateAudioInputs(audioInputs);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.log("Error getting media devices", error);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
updateIsMediaSettingsModalVisible(!isMediaSettingsModalVisible);
|
|
278
|
+
};
|
|
279
|
+
const launchMenuModal = ({
|
|
280
|
+
updateIsMenuModalVisible,
|
|
281
|
+
isMenuModalVisible
|
|
282
|
+
}) => {
|
|
283
|
+
updateIsMenuModalVisible(!isMenuModalVisible);
|
|
284
|
+
};
|
|
285
|
+
const launchMessages = ({ updateIsMessagesModalVisible, isMessagesModalVisible }) => {
|
|
286
|
+
updateIsMessagesModalVisible(!isMessagesModalVisible);
|
|
287
|
+
};
|
|
288
|
+
const sendMessage = async ({
|
|
289
|
+
message,
|
|
290
|
+
receivers,
|
|
291
|
+
group,
|
|
292
|
+
messagesLength,
|
|
293
|
+
member,
|
|
294
|
+
sender,
|
|
295
|
+
islevel,
|
|
296
|
+
showAlert,
|
|
297
|
+
coHostResponsibility,
|
|
298
|
+
coHost,
|
|
299
|
+
roomName,
|
|
300
|
+
socket,
|
|
301
|
+
chatSetting
|
|
302
|
+
}) => {
|
|
303
|
+
let chatValue = false;
|
|
304
|
+
const normalizedReceivers = (receivers ?? []).filter(
|
|
305
|
+
(receiver) => typeof receiver === "string" && receiver.trim().length > 0
|
|
306
|
+
);
|
|
307
|
+
if (messagesLength > 100 && roomName.startsWith("d") || messagesLength > 500 && roomName.startsWith("s") || messagesLength > 1e5 && roomName.startsWith("p")) {
|
|
308
|
+
showAlert?.({
|
|
309
|
+
message: "You have reached the maximum number of messages allowed.",
|
|
310
|
+
type: "danger",
|
|
311
|
+
duration: 3e3
|
|
312
|
+
});
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (!message || message === "") {
|
|
316
|
+
showAlert?.({
|
|
317
|
+
message: "Message is not valid.",
|
|
318
|
+
type: "danger",
|
|
319
|
+
duration: 3e3
|
|
320
|
+
});
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (normalizedReceivers.length < 1 && group === false && islevel === "2") {
|
|
324
|
+
showAlert?.({
|
|
325
|
+
message: "Please select a message to reply to",
|
|
326
|
+
type: "danger",
|
|
327
|
+
duration: 3e3
|
|
328
|
+
});
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
const messageObject = {
|
|
332
|
+
sender: sender ? sender : member,
|
|
333
|
+
receivers: normalizedReceivers,
|
|
334
|
+
message,
|
|
335
|
+
timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
|
|
336
|
+
group: group !== void 0 && group !== null ? group : false
|
|
337
|
+
};
|
|
338
|
+
try {
|
|
339
|
+
chatValue = coHostResponsibility.find((item) => item.name === "chat")?.value ?? false;
|
|
340
|
+
} catch (error) {
|
|
341
|
+
console.error(error);
|
|
342
|
+
}
|
|
343
|
+
if (islevel === "2" || coHost === member && chatValue === true) ;
|
|
344
|
+
else {
|
|
345
|
+
if (!chatSetting) {
|
|
346
|
+
showAlert?.({
|
|
347
|
+
message: "You are not allowed to send a message in this event room",
|
|
348
|
+
type: "danger",
|
|
349
|
+
duration: 3e3
|
|
350
|
+
});
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
socket.emit("sendMessage", {
|
|
355
|
+
messageObject,
|
|
356
|
+
roomName
|
|
357
|
+
});
|
|
358
|
+
};
|
|
359
|
+
const launchParticipants = ({ updateIsParticipantsModalVisible, isParticipantsModalVisible }) => {
|
|
360
|
+
updateIsParticipantsModalVisible(!isParticipantsModalVisible);
|
|
361
|
+
};
|
|
362
|
+
const messageParticipants = ({
|
|
363
|
+
coHostResponsibility = [],
|
|
364
|
+
participant,
|
|
365
|
+
member,
|
|
366
|
+
islevel,
|
|
367
|
+
showAlert,
|
|
368
|
+
coHost,
|
|
369
|
+
updateIsMessagesModalVisible,
|
|
370
|
+
updateDirectMessageDetails,
|
|
371
|
+
updateStartDirectMessage
|
|
372
|
+
}) => {
|
|
373
|
+
let chatValue = false;
|
|
374
|
+
try {
|
|
375
|
+
chatValue = coHostResponsibility.find((item) => item.name === "chat")?.value ?? false;
|
|
376
|
+
} catch (error) {
|
|
377
|
+
console.error(error);
|
|
378
|
+
}
|
|
379
|
+
if (islevel === "2" || coHost === member && chatValue === true) {
|
|
380
|
+
if (participant.islevel !== "2") {
|
|
381
|
+
updateDirectMessageDetails(participant);
|
|
382
|
+
updateStartDirectMessage(true);
|
|
383
|
+
updateIsMessagesModalVisible(true);
|
|
384
|
+
}
|
|
385
|
+
} else {
|
|
386
|
+
showAlert?.({
|
|
387
|
+
message: "You are not allowed to send this message",
|
|
388
|
+
type: "danger",
|
|
389
|
+
duration: 3e3
|
|
390
|
+
});
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
const muteParticipants = async ({
|
|
395
|
+
socket,
|
|
396
|
+
coHostResponsibility = [],
|
|
397
|
+
participant,
|
|
398
|
+
member,
|
|
399
|
+
islevel,
|
|
400
|
+
showAlert,
|
|
401
|
+
coHost,
|
|
402
|
+
roomName
|
|
403
|
+
}) => {
|
|
404
|
+
let mediaValue = false;
|
|
405
|
+
try {
|
|
406
|
+
mediaValue = coHostResponsibility.find((item) => item.name === "media")?.value ?? false;
|
|
407
|
+
} catch (error) {
|
|
408
|
+
console.error(error);
|
|
409
|
+
}
|
|
410
|
+
if (islevel === "2" || coHost === member && mediaValue) {
|
|
411
|
+
if (!participant.muted && participant.islevel !== "2") {
|
|
412
|
+
const participantId = participant.id;
|
|
413
|
+
socket.emit("controlMedia", {
|
|
414
|
+
participantId,
|
|
415
|
+
participantName: participant.name,
|
|
416
|
+
type: "all",
|
|
417
|
+
roomName
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
} else {
|
|
421
|
+
showAlert?.({
|
|
422
|
+
message: "You are not allowed to mute other participants",
|
|
423
|
+
type: "danger",
|
|
424
|
+
duration: 3e3
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
const removeParticipants = async ({
|
|
429
|
+
coHostResponsibility,
|
|
430
|
+
participant,
|
|
431
|
+
member,
|
|
432
|
+
islevel,
|
|
433
|
+
showAlert,
|
|
434
|
+
coHost,
|
|
435
|
+
participants,
|
|
436
|
+
socket,
|
|
437
|
+
roomName,
|
|
438
|
+
updateParticipants
|
|
439
|
+
}) => {
|
|
440
|
+
let participantsValue = false;
|
|
441
|
+
try {
|
|
442
|
+
participantsValue = coHostResponsibility.find((item) => item.name === "participants")?.value ?? false;
|
|
443
|
+
} catch {
|
|
444
|
+
participantsValue = false;
|
|
445
|
+
}
|
|
446
|
+
if (islevel === "2" || coHost === member && participantsValue === true) {
|
|
447
|
+
if (participant.islevel !== "2") {
|
|
448
|
+
const participantId = participant.id;
|
|
449
|
+
socket.emit("disconnectUserInitiate", {
|
|
450
|
+
member: participant.name,
|
|
451
|
+
roomName,
|
|
452
|
+
id: participantId
|
|
453
|
+
});
|
|
454
|
+
const index = participants.findIndex((obj) => obj.name === participant.name);
|
|
455
|
+
if (index !== -1) {
|
|
456
|
+
participants.splice(index, 1);
|
|
457
|
+
}
|
|
458
|
+
updateParticipants(participants);
|
|
459
|
+
}
|
|
460
|
+
} else {
|
|
461
|
+
showAlert?.({
|
|
462
|
+
message: "You are not allowed to remove other participants",
|
|
463
|
+
type: "danger",
|
|
464
|
+
duration: 3e3
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
const handleCreatePoll = async ({
|
|
469
|
+
poll,
|
|
470
|
+
socket,
|
|
471
|
+
roomName,
|
|
472
|
+
showAlert,
|
|
473
|
+
updateIsPollModalVisible
|
|
474
|
+
}) => {
|
|
475
|
+
try {
|
|
476
|
+
socket.emit(
|
|
477
|
+
"createPoll",
|
|
478
|
+
{ roomName, poll },
|
|
479
|
+
(response) => {
|
|
480
|
+
if (response.success) {
|
|
481
|
+
showAlert?.({ message: "Poll created successfully", type: "success" });
|
|
482
|
+
updateIsPollModalVisible(false);
|
|
483
|
+
} else {
|
|
484
|
+
showAlert?.({ message: response.reason || "Failed to create poll", type: "danger" });
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
);
|
|
488
|
+
} catch (error) {
|
|
489
|
+
console.error("Error creating poll:", error);
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
const handleEndPoll = async ({
|
|
493
|
+
pollId,
|
|
494
|
+
socket,
|
|
495
|
+
showAlert,
|
|
496
|
+
roomName,
|
|
497
|
+
updateIsPollModalVisible
|
|
498
|
+
}) => {
|
|
499
|
+
try {
|
|
500
|
+
socket.emit(
|
|
501
|
+
"endPoll",
|
|
502
|
+
{ roomName, poll_id: pollId },
|
|
503
|
+
(response) => {
|
|
504
|
+
if (response.success) {
|
|
505
|
+
showAlert?.({
|
|
506
|
+
message: "Poll ended successfully",
|
|
507
|
+
type: "success"
|
|
508
|
+
});
|
|
509
|
+
updateIsPollModalVisible(false);
|
|
510
|
+
} else {
|
|
511
|
+
showAlert?.({ message: response.reason || "Failed to end poll", type: "danger" });
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
);
|
|
515
|
+
} catch (error) {
|
|
516
|
+
console.error("Error ending poll:", error);
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
const handleVotePoll = async ({
|
|
520
|
+
pollId,
|
|
521
|
+
optionIndex,
|
|
522
|
+
socket,
|
|
523
|
+
showAlert,
|
|
524
|
+
member,
|
|
525
|
+
roomName,
|
|
526
|
+
updateIsPollModalVisible
|
|
527
|
+
}) => {
|
|
528
|
+
try {
|
|
529
|
+
socket.emit(
|
|
530
|
+
"votePoll",
|
|
531
|
+
{
|
|
532
|
+
roomName,
|
|
533
|
+
poll_id: pollId,
|
|
534
|
+
member,
|
|
535
|
+
choice: optionIndex
|
|
536
|
+
},
|
|
537
|
+
(response) => {
|
|
538
|
+
if (response.success) {
|
|
539
|
+
showAlert?.({
|
|
540
|
+
message: "Vote submitted successfully",
|
|
541
|
+
type: "success"
|
|
542
|
+
});
|
|
543
|
+
updateIsPollModalVisible(false);
|
|
544
|
+
} else {
|
|
545
|
+
showAlert?.({ message: response.reason || "Failed to submit vote", type: "danger" });
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
);
|
|
549
|
+
} catch (error) {
|
|
550
|
+
console.error("Error submitting vote:", error);
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
const launchPoll = ({ updateIsPollModalVisible, isPollModalVisible }) => {
|
|
554
|
+
updateIsPollModalVisible(!isPollModalVisible);
|
|
555
|
+
};
|
|
556
|
+
const checkPauseState = async ({
|
|
557
|
+
recordingMediaOptions,
|
|
558
|
+
recordingVideoPausesLimit,
|
|
559
|
+
recordingAudioPausesLimit,
|
|
560
|
+
pauseRecordCount,
|
|
561
|
+
showAlert
|
|
562
|
+
}) => {
|
|
563
|
+
const refLimit = recordingMediaOptions === "video" ? recordingVideoPausesLimit : recordingAudioPausesLimit;
|
|
564
|
+
if (pauseRecordCount < refLimit) {
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
showAlert?.({
|
|
568
|
+
message: "You have reached the limit of pauses - you can choose to stop recording.",
|
|
569
|
+
type: "danger",
|
|
570
|
+
duration: 3e3
|
|
571
|
+
});
|
|
572
|
+
return false;
|
|
573
|
+
};
|
|
574
|
+
const checkResumeState = async ({
|
|
575
|
+
recordingMediaOptions,
|
|
576
|
+
recordingVideoPausesLimit,
|
|
577
|
+
recordingAudioPausesLimit,
|
|
578
|
+
pauseRecordCount
|
|
579
|
+
}) => {
|
|
580
|
+
const refLimit = recordingMediaOptions === "video" ? recordingVideoPausesLimit : recordingAudioPausesLimit;
|
|
581
|
+
return pauseRecordCount <= refLimit;
|
|
582
|
+
};
|
|
583
|
+
const ALERT_DURATION = 6e3;
|
|
584
|
+
const FULL_PARTICIPANT_RECORDING_ALERT_MESSAGE = "You are not allowed to record videos of all participants while the meeting display is set to All. Switch the meeting display to Media and try again.";
|
|
585
|
+
const confirmRecording = async ({
|
|
586
|
+
parameters
|
|
587
|
+
}) => {
|
|
588
|
+
parameters = parameters.getUpdatedAllParams();
|
|
589
|
+
let {
|
|
590
|
+
showAlert,
|
|
591
|
+
recordingMediaOptions,
|
|
592
|
+
recordingAudioOptions,
|
|
593
|
+
recordingVideoOptions,
|
|
594
|
+
recordingVideoType,
|
|
595
|
+
recordingDisplayType,
|
|
596
|
+
recordingNameTags,
|
|
597
|
+
recordingBackgroundColor,
|
|
598
|
+
recordingNameTagsColor,
|
|
599
|
+
recordingOrientationVideo,
|
|
600
|
+
recordingAddHLS,
|
|
601
|
+
recordingAddText,
|
|
602
|
+
recordingCustomText,
|
|
603
|
+
recordingCustomTextPosition,
|
|
604
|
+
recordingCustomTextColor,
|
|
605
|
+
meetingDisplayType,
|
|
606
|
+
recordingVideoParticipantsFullRoomSupport,
|
|
607
|
+
recordingAllParticipantsSupport,
|
|
608
|
+
recordingVideoParticipantsSupport,
|
|
609
|
+
recordingSupportForOtherOrientation,
|
|
610
|
+
recordingPreferredOrientation,
|
|
611
|
+
recordingMultiFormatsSupport,
|
|
612
|
+
recordingVideoOptimized,
|
|
613
|
+
recordingAllParticipantsFullRoomSupport,
|
|
614
|
+
meetingVideoOptimized,
|
|
615
|
+
eventType,
|
|
616
|
+
breakOutRoomStarted,
|
|
617
|
+
breakOutRoomEnded,
|
|
618
|
+
updateRecordingDisplayType,
|
|
619
|
+
updateRecordingVideoOptimized,
|
|
620
|
+
updateUserRecordingParams,
|
|
621
|
+
updateConfirmedToRecord
|
|
622
|
+
} = parameters;
|
|
623
|
+
if (!recordingVideoParticipantsFullRoomSupport && recordingVideoOptions === "all" && recordingMediaOptions === "video") {
|
|
624
|
+
if (meetingDisplayType === "all" && !(breakOutRoomStarted && !breakOutRoomEnded)) {
|
|
625
|
+
showAlert?.({
|
|
626
|
+
message: FULL_PARTICIPANT_RECORDING_ALERT_MESSAGE,
|
|
627
|
+
type: "danger",
|
|
628
|
+
duration: ALERT_DURATION
|
|
629
|
+
});
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
if (!recordingAllParticipantsSupport && recordingVideoOptions === "all") {
|
|
634
|
+
showAlert?.({
|
|
635
|
+
message: "You are only allowed to record yourself.",
|
|
636
|
+
type: "danger",
|
|
637
|
+
duration: ALERT_DURATION
|
|
638
|
+
});
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
if (!recordingVideoParticipantsSupport && recordingDisplayType === "video") {
|
|
642
|
+
showAlert?.({
|
|
643
|
+
message: "You are not allowed to record other video participants.",
|
|
644
|
+
type: "danger",
|
|
645
|
+
duration: ALERT_DURATION
|
|
646
|
+
});
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
if (!recordingSupportForOtherOrientation && recordingOrientationVideo === "all") {
|
|
650
|
+
showAlert?.({
|
|
651
|
+
message: "You are not allowed to record all orientations.",
|
|
652
|
+
type: "danger",
|
|
653
|
+
duration: ALERT_DURATION
|
|
654
|
+
});
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
if (recordingPreferredOrientation === "landscape" && recordingOrientationVideo === "portrait" || recordingPreferredOrientation === "portrait" && recordingOrientationVideo === "landscape") {
|
|
658
|
+
if (!recordingSupportForOtherOrientation) {
|
|
659
|
+
showAlert?.({
|
|
660
|
+
message: "You are not allowed to record this orientation.",
|
|
661
|
+
type: "danger",
|
|
662
|
+
duration: ALERT_DURATION
|
|
663
|
+
});
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
if (!recordingMultiFormatsSupport && recordingVideoType === "all") {
|
|
668
|
+
showAlert?.({
|
|
669
|
+
message: "You are not allowed to record all formats.",
|
|
670
|
+
type: "danger",
|
|
671
|
+
duration: ALERT_DURATION
|
|
672
|
+
});
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
if (eventType !== "broadcast") {
|
|
676
|
+
if (recordingMediaOptions === "video") {
|
|
677
|
+
if (meetingDisplayType === "media" && recordingDisplayType === "all") {
|
|
678
|
+
showAlert?.({
|
|
679
|
+
message: "Recording display type can be either video, video optimized, or media when meeting display type is media.",
|
|
680
|
+
type: "danger",
|
|
681
|
+
duration: ALERT_DURATION
|
|
682
|
+
});
|
|
683
|
+
updateRecordingDisplayType(meetingDisplayType);
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
if (meetingDisplayType === "video") {
|
|
687
|
+
if (recordingDisplayType === "all" || recordingDisplayType === "media") {
|
|
688
|
+
showAlert?.({
|
|
689
|
+
message: "Recording display type can be either video or video optimized when meeting display type is video.",
|
|
690
|
+
type: "danger",
|
|
691
|
+
duration: ALERT_DURATION
|
|
692
|
+
});
|
|
693
|
+
updateRecordingDisplayType(meetingDisplayType);
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
if (meetingVideoOptimized && !recordingVideoOptimized) {
|
|
697
|
+
showAlert?.({
|
|
698
|
+
message: "Recording display type can only be video optimized when meeting display type is video optimized.",
|
|
699
|
+
type: "danger",
|
|
700
|
+
duration: ALERT_DURATION
|
|
701
|
+
});
|
|
702
|
+
updateRecordingVideoOptimized(meetingVideoOptimized);
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
} else {
|
|
707
|
+
updateRecordingDisplayType("media");
|
|
708
|
+
updateRecordingVideoOptimized(false);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
if (recordingDisplayType === "all" && !recordingAllParticipantsFullRoomSupport) {
|
|
712
|
+
showAlert?.({
|
|
713
|
+
message: "You can only record all participants with media.",
|
|
714
|
+
type: "danger",
|
|
715
|
+
duration: ALERT_DURATION
|
|
716
|
+
});
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
const mainSpecs = {
|
|
720
|
+
mediaOptions: recordingMediaOptions,
|
|
721
|
+
audioOptions: recordingAudioOptions,
|
|
722
|
+
videoOptions: recordingVideoOptions,
|
|
723
|
+
videoType: recordingVideoType,
|
|
724
|
+
videoOptimized: recordingVideoOptimized,
|
|
725
|
+
recordingDisplayType,
|
|
726
|
+
addHLS: recordingAddHLS
|
|
727
|
+
};
|
|
728
|
+
const dispSpecs = {
|
|
729
|
+
nameTags: recordingNameTags,
|
|
730
|
+
backgroundColor: recordingBackgroundColor,
|
|
731
|
+
nameTagsColor: recordingNameTagsColor,
|
|
732
|
+
orientationVideo: recordingOrientationVideo
|
|
733
|
+
};
|
|
734
|
+
const textSpecs = {
|
|
735
|
+
addText: recordingAddText,
|
|
736
|
+
customText: recordingCustomText,
|
|
737
|
+
customTextPosition: recordingCustomTextPosition,
|
|
738
|
+
customTextColor: recordingCustomTextColor
|
|
739
|
+
};
|
|
740
|
+
const userRecordingParams = { mainSpecs, dispSpecs, textSpecs };
|
|
741
|
+
updateUserRecordingParams(userRecordingParams);
|
|
742
|
+
updateConfirmedToRecord(true);
|
|
743
|
+
};
|
|
744
|
+
const launchRecording = ({
|
|
745
|
+
updateIsRecordingModalVisible,
|
|
746
|
+
isRecordingModalVisible,
|
|
747
|
+
showAlert,
|
|
748
|
+
stopLaunchRecord,
|
|
749
|
+
canLaunchRecord,
|
|
750
|
+
recordingAudioSupport,
|
|
751
|
+
recordingVideoSupport,
|
|
752
|
+
updateCanRecord,
|
|
753
|
+
updateClearedToRecord,
|
|
754
|
+
recordStarted,
|
|
755
|
+
recordPaused,
|
|
756
|
+
localUIMode
|
|
757
|
+
}) => {
|
|
758
|
+
if (!isRecordingModalVisible && stopLaunchRecord && !localUIMode) {
|
|
759
|
+
showAlert?.({
|
|
760
|
+
message: "Recording has already ended or you are not allowed to record",
|
|
761
|
+
type: "danger",
|
|
762
|
+
duration: 3e3
|
|
763
|
+
});
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
if (!isRecordingModalVisible && canLaunchRecord && !localUIMode) {
|
|
767
|
+
if (!recordingAudioSupport && !recordingVideoSupport) {
|
|
768
|
+
showAlert?.({
|
|
769
|
+
message: "You are not allowed to record",
|
|
770
|
+
type: "danger",
|
|
771
|
+
duration: 3e3
|
|
772
|
+
});
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
updateClearedToRecord(false);
|
|
776
|
+
updateCanRecord(false);
|
|
777
|
+
}
|
|
778
|
+
if (!isRecordingModalVisible && recordStarted && !recordPaused) {
|
|
779
|
+
showAlert?.({
|
|
780
|
+
message: "You can only re-configure recording after pausing it",
|
|
781
|
+
type: "danger",
|
|
782
|
+
duration: 3e3
|
|
783
|
+
});
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
if (!isRecordingModalVisible && !recordingAudioSupport && !recordingVideoSupport && !localUIMode) {
|
|
787
|
+
showAlert?.({
|
|
788
|
+
message: "You are not allowed to record",
|
|
789
|
+
type: "danger",
|
|
790
|
+
duration: 3e3
|
|
791
|
+
});
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
updateIsRecordingModalVisible(!isRecordingModalVisible);
|
|
795
|
+
};
|
|
796
|
+
const recordPauseTimer = ({
|
|
797
|
+
stop = false,
|
|
798
|
+
isTimerRunning,
|
|
799
|
+
canPauseResume,
|
|
800
|
+
showAlert
|
|
801
|
+
}) => {
|
|
802
|
+
if (isTimerRunning && canPauseResume) {
|
|
803
|
+
return true;
|
|
804
|
+
}
|
|
805
|
+
const message = stop ? "Can only stop after 15 seconds of starting or pausing or resuming recording" : "Can only pause or resume after 15 seconds of starting or pausing or resuming recording";
|
|
806
|
+
showAlert?.({
|
|
807
|
+
message,
|
|
808
|
+
type: "danger"
|
|
809
|
+
});
|
|
810
|
+
return false;
|
|
811
|
+
};
|
|
812
|
+
const recordUpdateTimer = ({
|
|
813
|
+
recordElapsedTime,
|
|
814
|
+
recordStartTime,
|
|
815
|
+
updateRecordElapsedTime,
|
|
816
|
+
updateRecordingProgressTime
|
|
817
|
+
}) => {
|
|
818
|
+
const padNumber = (value) => value.toString().padStart(2, "0");
|
|
819
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
820
|
+
let elapsedSeconds = recordElapsedTime;
|
|
821
|
+
elapsedSeconds = Math.floor((currentTime - recordStartTime) / 1e3);
|
|
822
|
+
updateRecordElapsedTime(elapsedSeconds);
|
|
823
|
+
const hours = Math.floor(elapsedSeconds / 3600);
|
|
824
|
+
const minutes = Math.floor(elapsedSeconds % 3600 / 60);
|
|
825
|
+
const seconds = elapsedSeconds % 60;
|
|
826
|
+
const formattedTime = `${padNumber(hours)}:${padNumber(minutes)}:${padNumber(seconds)}`;
|
|
827
|
+
updateRecordingProgressTime(formattedTime);
|
|
828
|
+
};
|
|
829
|
+
const recordResumeTimer = async ({ parameters }) => {
|
|
830
|
+
const { getUpdatedAllParams } = parameters;
|
|
831
|
+
parameters = getUpdatedAllParams();
|
|
832
|
+
let {
|
|
833
|
+
isTimerRunning,
|
|
834
|
+
canPauseResume,
|
|
835
|
+
recordElapsedTime,
|
|
836
|
+
recordStartTime,
|
|
837
|
+
recordTimerInterval,
|
|
838
|
+
showAlert,
|
|
839
|
+
updateRecordStartTime,
|
|
840
|
+
updateRecordTimerInterval,
|
|
841
|
+
updateIsTimerRunning,
|
|
842
|
+
updateCanPauseResume
|
|
843
|
+
} = parameters;
|
|
844
|
+
if (!isTimerRunning && canPauseResume) {
|
|
845
|
+
recordStartTime = (/* @__PURE__ */ new Date()).getTime() - recordElapsedTime * 1e3;
|
|
846
|
+
updateRecordStartTime(recordStartTime);
|
|
847
|
+
recordTimerInterval = setInterval(() => {
|
|
848
|
+
recordUpdateTimer({
|
|
849
|
+
recordElapsedTime,
|
|
850
|
+
recordStartTime,
|
|
851
|
+
updateRecordElapsedTime: parameters.updateRecordElapsedTime,
|
|
852
|
+
updateRecordingProgressTime: parameters.updateRecordingProgressTime
|
|
853
|
+
});
|
|
854
|
+
parameters = getUpdatedAllParams();
|
|
855
|
+
if (parameters.recordPaused || parameters.recordStopped || parameters.roomName === "" || parameters.roomName === null) {
|
|
856
|
+
clearInterval(recordTimerInterval);
|
|
857
|
+
updateRecordTimerInterval(null);
|
|
858
|
+
isTimerRunning = false;
|
|
859
|
+
updateIsTimerRunning(isTimerRunning);
|
|
860
|
+
canPauseResume = false;
|
|
861
|
+
updateCanPauseResume(canPauseResume);
|
|
862
|
+
}
|
|
863
|
+
}, 1e3);
|
|
864
|
+
updateRecordTimerInterval(recordTimerInterval);
|
|
865
|
+
isTimerRunning = true;
|
|
866
|
+
updateIsTimerRunning(isTimerRunning);
|
|
867
|
+
canPauseResume = false;
|
|
868
|
+
updateCanPauseResume(canPauseResume);
|
|
869
|
+
return true;
|
|
870
|
+
}
|
|
871
|
+
showAlert?.({
|
|
872
|
+
type: "danger",
|
|
873
|
+
message: "Can only pause or resume after 15 seconds of starting or pausing or resuming recording"
|
|
874
|
+
});
|
|
875
|
+
return false;
|
|
876
|
+
};
|
|
877
|
+
const recordStartTimer = async ({ parameters }) => {
|
|
878
|
+
const { getUpdatedAllParams } = parameters;
|
|
879
|
+
parameters = getUpdatedAllParams();
|
|
880
|
+
let {
|
|
881
|
+
recordStartTime,
|
|
882
|
+
recordTimerInterval,
|
|
883
|
+
isTimerRunning,
|
|
884
|
+
canPauseResume,
|
|
885
|
+
recordChangeSeconds,
|
|
886
|
+
updateRecordStartTime,
|
|
887
|
+
updateRecordTimerInterval,
|
|
888
|
+
updateIsTimerRunning,
|
|
889
|
+
updateCanPauseResume
|
|
890
|
+
} = parameters;
|
|
891
|
+
const enablePauseResume = () => {
|
|
892
|
+
canPauseResume = true;
|
|
893
|
+
updateCanPauseResume(canPauseResume);
|
|
894
|
+
};
|
|
895
|
+
if (!isTimerRunning) {
|
|
896
|
+
recordStartTime = (/* @__PURE__ */ new Date()).getTime();
|
|
897
|
+
updateRecordStartTime(recordStartTime);
|
|
898
|
+
recordTimerInterval = setInterval(() => {
|
|
899
|
+
recordUpdateTimer({
|
|
900
|
+
recordElapsedTime: parameters.recordElapsedTime,
|
|
901
|
+
recordStartTime,
|
|
902
|
+
updateRecordElapsedTime: parameters.updateRecordElapsedTime,
|
|
903
|
+
updateRecordingProgressTime: parameters.updateRecordingProgressTime
|
|
904
|
+
});
|
|
905
|
+
parameters = getUpdatedAllParams();
|
|
906
|
+
if (parameters.recordPaused || parameters.recordStopped || parameters.roomName === "" || parameters.roomName === null) {
|
|
907
|
+
clearInterval(recordTimerInterval);
|
|
908
|
+
updateRecordTimerInterval(null);
|
|
909
|
+
isTimerRunning = false;
|
|
910
|
+
updateIsTimerRunning(isTimerRunning);
|
|
911
|
+
canPauseResume = false;
|
|
912
|
+
updateCanPauseResume(canPauseResume);
|
|
913
|
+
}
|
|
914
|
+
}, 1e3);
|
|
915
|
+
updateRecordTimerInterval(recordTimerInterval);
|
|
916
|
+
isTimerRunning = true;
|
|
917
|
+
updateIsTimerRunning(isTimerRunning);
|
|
918
|
+
canPauseResume = false;
|
|
919
|
+
updateCanPauseResume(canPauseResume);
|
|
920
|
+
setTimeout(enablePauseResume, recordChangeSeconds);
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
const startRecording = async ({
|
|
924
|
+
parameters
|
|
925
|
+
}) => {
|
|
926
|
+
parameters = parameters.getUpdatedAllParams();
|
|
927
|
+
let {
|
|
928
|
+
roomName,
|
|
929
|
+
userRecordingParams,
|
|
930
|
+
socket,
|
|
931
|
+
localSocket,
|
|
932
|
+
updateIsRecordingModalVisible,
|
|
933
|
+
confirmedToRecord,
|
|
934
|
+
showAlert,
|
|
935
|
+
recordingMediaOptions,
|
|
936
|
+
videoAlreadyOn,
|
|
937
|
+
audioAlreadyOn,
|
|
938
|
+
recordStarted,
|
|
939
|
+
recordPaused,
|
|
940
|
+
recordResumed,
|
|
941
|
+
recordStopped,
|
|
942
|
+
startReport,
|
|
943
|
+
endReport,
|
|
944
|
+
canRecord,
|
|
945
|
+
updateClearedToRecord,
|
|
946
|
+
updateRecordStarted,
|
|
947
|
+
updateRecordPaused,
|
|
948
|
+
updateRecordResumed,
|
|
949
|
+
updateStartReport,
|
|
950
|
+
updateEndReport,
|
|
951
|
+
updateCanRecord,
|
|
952
|
+
whiteboardStarted,
|
|
953
|
+
whiteboardEnded,
|
|
954
|
+
rePort,
|
|
955
|
+
captureCanvasStream
|
|
956
|
+
} = parameters;
|
|
957
|
+
if (!confirmedToRecord) {
|
|
958
|
+
showAlert?.({
|
|
959
|
+
message: "You must click confirm before you can start recording",
|
|
960
|
+
type: "danger"
|
|
961
|
+
});
|
|
962
|
+
return false;
|
|
963
|
+
}
|
|
964
|
+
if (recordingMediaOptions === "video" && !videoAlreadyOn) {
|
|
965
|
+
showAlert?.({
|
|
966
|
+
message: "You must turn on your video before you can start recording",
|
|
967
|
+
type: "danger"
|
|
968
|
+
});
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
if (recordingMediaOptions === "audio" && !audioAlreadyOn) {
|
|
972
|
+
showAlert?.({
|
|
973
|
+
message: "You must turn on your audio before you can start recording",
|
|
974
|
+
type: "danger"
|
|
975
|
+
});
|
|
976
|
+
return false;
|
|
977
|
+
}
|
|
978
|
+
updateClearedToRecord(true);
|
|
979
|
+
let action = "startRecord";
|
|
980
|
+
if (recordStarted && recordPaused && !recordResumed && !recordStopped) {
|
|
981
|
+
action = "resumeRecord";
|
|
982
|
+
}
|
|
983
|
+
let recAttempt = false;
|
|
984
|
+
const socketRef = localSocket && localSocket.connected ? localSocket : socket;
|
|
985
|
+
await new Promise((resolve) => {
|
|
986
|
+
socketRef.emit(
|
|
987
|
+
action,
|
|
988
|
+
{ roomName, userRecordingParams },
|
|
989
|
+
async ({ success, reason }) => {
|
|
990
|
+
if (success) {
|
|
991
|
+
recordStarted = true;
|
|
992
|
+
startReport = true;
|
|
993
|
+
endReport = false;
|
|
994
|
+
recordPaused = false;
|
|
995
|
+
recAttempt = true;
|
|
996
|
+
updateRecordStarted(recordStarted);
|
|
997
|
+
updateStartReport(startReport);
|
|
998
|
+
updateEndReport(endReport);
|
|
999
|
+
updateRecordPaused(recordPaused);
|
|
1000
|
+
if (action === "startRecord") {
|
|
1001
|
+
await rePort({ parameters: parameters.getUpdatedAllParams() });
|
|
1002
|
+
await recordStartTimer({ parameters });
|
|
1003
|
+
} else {
|
|
1004
|
+
updateRecordResumed(true);
|
|
1005
|
+
await rePort({ restart: true, parameters: parameters.getUpdatedAllParams() });
|
|
1006
|
+
await recordResumeTimer({ parameters });
|
|
1007
|
+
}
|
|
1008
|
+
} else {
|
|
1009
|
+
showAlert?.({
|
|
1010
|
+
message: `Recording could not start - ${reason}`,
|
|
1011
|
+
type: "danger"
|
|
1012
|
+
});
|
|
1013
|
+
canRecord = true;
|
|
1014
|
+
startReport = false;
|
|
1015
|
+
endReport = true;
|
|
1016
|
+
recAttempt = false;
|
|
1017
|
+
updateCanRecord(canRecord);
|
|
1018
|
+
updateStartReport(startReport);
|
|
1019
|
+
updateEndReport(endReport);
|
|
1020
|
+
}
|
|
1021
|
+
resolve();
|
|
1022
|
+
}
|
|
1023
|
+
);
|
|
1024
|
+
});
|
|
1025
|
+
try {
|
|
1026
|
+
if (recAttempt && whiteboardStarted && !whiteboardEnded && recordingMediaOptions === "video") {
|
|
1027
|
+
await captureCanvasStream({ parameters: parameters.getUpdatedAllParams() });
|
|
1028
|
+
}
|
|
1029
|
+
} catch (error) {
|
|
1030
|
+
console.error("Error capturing canvas stream:", error);
|
|
1031
|
+
}
|
|
1032
|
+
updateIsRecordingModalVisible(false);
|
|
1033
|
+
return recAttempt;
|
|
1034
|
+
};
|
|
1035
|
+
const stopRecording = async ({ parameters }) => {
|
|
1036
|
+
let {
|
|
1037
|
+
roomName,
|
|
1038
|
+
socket,
|
|
1039
|
+
localSocket,
|
|
1040
|
+
showAlert,
|
|
1041
|
+
startReport,
|
|
1042
|
+
endReport,
|
|
1043
|
+
recordStarted,
|
|
1044
|
+
recordPaused,
|
|
1045
|
+
recordStopped,
|
|
1046
|
+
updateRecordPaused,
|
|
1047
|
+
updateRecordStopped,
|
|
1048
|
+
updateStartReport,
|
|
1049
|
+
updateEndReport,
|
|
1050
|
+
updateShowRecordButtons,
|
|
1051
|
+
whiteboardStarted,
|
|
1052
|
+
whiteboardEnded,
|
|
1053
|
+
recordingMediaOptions,
|
|
1054
|
+
captureCanvasStream
|
|
1055
|
+
} = parameters;
|
|
1056
|
+
let recAttempt = false;
|
|
1057
|
+
if (recordStarted && !recordStopped) {
|
|
1058
|
+
const stop = recordPauseTimer({
|
|
1059
|
+
stop: true,
|
|
1060
|
+
isTimerRunning: parameters.isTimerRunning,
|
|
1061
|
+
canPauseResume: parameters.canPauseResume,
|
|
1062
|
+
showAlert: parameters.showAlert
|
|
1063
|
+
});
|
|
1064
|
+
if (stop) {
|
|
1065
|
+
const action = "stopRecord";
|
|
1066
|
+
const socketRef = localSocket && localSocket.connected ? localSocket : socket;
|
|
1067
|
+
await new Promise((resolve) => {
|
|
1068
|
+
socketRef.emit(
|
|
1069
|
+
action,
|
|
1070
|
+
{ roomName },
|
|
1071
|
+
({ success, reason, recordState }) => {
|
|
1072
|
+
if (success) {
|
|
1073
|
+
startReport = false;
|
|
1074
|
+
endReport = true;
|
|
1075
|
+
recordPaused = false;
|
|
1076
|
+
recordStopped = true;
|
|
1077
|
+
recAttempt = true;
|
|
1078
|
+
updateStartReport(startReport);
|
|
1079
|
+
updateEndReport(endReport);
|
|
1080
|
+
updateRecordPaused(recordPaused);
|
|
1081
|
+
updateRecordStopped(recordStopped);
|
|
1082
|
+
showAlert?.({ message: "Recording Stopped", type: "success" });
|
|
1083
|
+
updateShowRecordButtons(false);
|
|
1084
|
+
} else {
|
|
1085
|
+
const reasonMessage = `Recording Stop Failed: ${reason}; the recording is currently ${recordState}`;
|
|
1086
|
+
showAlert?.({ message: reasonMessage, type: "danger" });
|
|
1087
|
+
recAttempt = false;
|
|
1088
|
+
}
|
|
1089
|
+
resolve();
|
|
1090
|
+
}
|
|
1091
|
+
);
|
|
1092
|
+
});
|
|
1093
|
+
try {
|
|
1094
|
+
if (recAttempt && whiteboardStarted && !whiteboardEnded && recordingMediaOptions === "video") {
|
|
1095
|
+
captureCanvasStream({ parameters: parameters.getUpdatedAllParams(), start: false });
|
|
1096
|
+
}
|
|
1097
|
+
} catch (error) {
|
|
1098
|
+
console.error("Error capturing canvas stream:", error);
|
|
1099
|
+
}
|
|
1100
|
+
} else {
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
} else {
|
|
1104
|
+
showAlert?.({
|
|
1105
|
+
message: "Recording is not started yet or already stopped",
|
|
1106
|
+
type: "danger"
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
const updateRecording = async ({ parameters }) => {
|
|
1111
|
+
let {
|
|
1112
|
+
roomName,
|
|
1113
|
+
userRecordingParams,
|
|
1114
|
+
socket,
|
|
1115
|
+
localSocket,
|
|
1116
|
+
updateIsRecordingModalVisible,
|
|
1117
|
+
confirmedToRecord,
|
|
1118
|
+
showAlert,
|
|
1119
|
+
recordingMediaOptions,
|
|
1120
|
+
videoAlreadyOn,
|
|
1121
|
+
audioAlreadyOn,
|
|
1122
|
+
recordStarted,
|
|
1123
|
+
recordPaused,
|
|
1124
|
+
recordResumed,
|
|
1125
|
+
recordStopped,
|
|
1126
|
+
recordChangeSeconds,
|
|
1127
|
+
pauseRecordCount,
|
|
1128
|
+
startReport,
|
|
1129
|
+
endReport,
|
|
1130
|
+
canRecord,
|
|
1131
|
+
canPauseResume,
|
|
1132
|
+
updateCanPauseResume,
|
|
1133
|
+
updatePauseRecordCount,
|
|
1134
|
+
updateClearedToRecord,
|
|
1135
|
+
updateRecordPaused,
|
|
1136
|
+
updateRecordResumed,
|
|
1137
|
+
updateStartReport,
|
|
1138
|
+
updateEndReport,
|
|
1139
|
+
updateCanRecord,
|
|
1140
|
+
rePort
|
|
1141
|
+
} = parameters;
|
|
1142
|
+
if (recordStopped) {
|
|
1143
|
+
showAlert?.({
|
|
1144
|
+
message: "Recording has already stopped",
|
|
1145
|
+
type: "danger",
|
|
1146
|
+
duration: 3e3
|
|
1147
|
+
});
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
if (recordingMediaOptions === "video" && !videoAlreadyOn) {
|
|
1151
|
+
showAlert?.({
|
|
1152
|
+
message: "You must turn on your video before you can start recording",
|
|
1153
|
+
type: "danger",
|
|
1154
|
+
duration: 3e3
|
|
1155
|
+
});
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
if (recordingMediaOptions === "audio" && !audioAlreadyOn) {
|
|
1159
|
+
showAlert?.({
|
|
1160
|
+
message: "You must turn on your audio before you can start recording",
|
|
1161
|
+
type: "danger",
|
|
1162
|
+
duration: 3e3
|
|
1163
|
+
});
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
const socketRef = localSocket && localSocket.connected ? localSocket : socket;
|
|
1167
|
+
if (recordStarted && !recordPaused && !recordStopped) {
|
|
1168
|
+
const proceed = await checkPauseState({
|
|
1169
|
+
recordingMediaOptions,
|
|
1170
|
+
recordingVideoPausesLimit: parameters.recordingVideoPausesLimit,
|
|
1171
|
+
recordingAudioPausesLimit: parameters.recordingAudioPausesLimit,
|
|
1172
|
+
pauseRecordCount,
|
|
1173
|
+
showAlert
|
|
1174
|
+
});
|
|
1175
|
+
if (!proceed) return;
|
|
1176
|
+
const record = recordPauseTimer({
|
|
1177
|
+
stop: false,
|
|
1178
|
+
isTimerRunning: parameters.isTimerRunning,
|
|
1179
|
+
canPauseResume: parameters.canPauseResume,
|
|
1180
|
+
showAlert
|
|
1181
|
+
});
|
|
1182
|
+
if (record) {
|
|
1183
|
+
const action = "pauseRecord";
|
|
1184
|
+
await new Promise((resolve) => {
|
|
1185
|
+
socketRef.emit(
|
|
1186
|
+
action,
|
|
1187
|
+
{ roomName },
|
|
1188
|
+
async ({ success, reason, recordState, pauseCount }) => {
|
|
1189
|
+
pauseRecordCount = pauseCount;
|
|
1190
|
+
updatePauseRecordCount(pauseRecordCount);
|
|
1191
|
+
if (success) {
|
|
1192
|
+
startReport = false;
|
|
1193
|
+
endReport = true;
|
|
1194
|
+
recordPaused = true;
|
|
1195
|
+
updateStartReport(startReport);
|
|
1196
|
+
updateEndReport(endReport);
|
|
1197
|
+
updateRecordPaused(recordPaused);
|
|
1198
|
+
showAlert?.({
|
|
1199
|
+
message: "Recording paused",
|
|
1200
|
+
type: "success",
|
|
1201
|
+
duration: 3e3
|
|
1202
|
+
});
|
|
1203
|
+
updateIsRecordingModalVisible(false);
|
|
1204
|
+
setTimeout(() => {
|
|
1205
|
+
canPauseResume = true;
|
|
1206
|
+
updateCanPauseResume(canPauseResume);
|
|
1207
|
+
}, recordChangeSeconds);
|
|
1208
|
+
} else {
|
|
1209
|
+
showAlert?.({
|
|
1210
|
+
message: `Recording Pause Failed: ${reason}; the current state is: ${recordState}`,
|
|
1211
|
+
type: "danger",
|
|
1212
|
+
duration: 3e3
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
resolve();
|
|
1216
|
+
}
|
|
1217
|
+
);
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
} else if (recordStarted && recordPaused && !recordStopped) {
|
|
1221
|
+
if (!confirmedToRecord) {
|
|
1222
|
+
showAlert?.({
|
|
1223
|
+
message: "You must click confirm before you can start recording",
|
|
1224
|
+
type: "danger",
|
|
1225
|
+
duration: 3e3
|
|
1226
|
+
});
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1229
|
+
const proceed = await checkResumeState({
|
|
1230
|
+
recordingMediaOptions,
|
|
1231
|
+
recordingVideoPausesLimit: parameters.recordingVideoPausesLimit,
|
|
1232
|
+
recordingAudioPausesLimit: parameters.recordingAudioPausesLimit,
|
|
1233
|
+
pauseRecordCount
|
|
1234
|
+
});
|
|
1235
|
+
if (!proceed) return;
|
|
1236
|
+
const resume = await recordResumeTimer({ parameters });
|
|
1237
|
+
if (resume) {
|
|
1238
|
+
updateClearedToRecord(true);
|
|
1239
|
+
const action = "resumeRecord";
|
|
1240
|
+
await new Promise((resolve) => {
|
|
1241
|
+
socketRef.emit(
|
|
1242
|
+
action,
|
|
1243
|
+
{ roomName, userRecordingParams },
|
|
1244
|
+
async ({ success, reason }) => {
|
|
1245
|
+
if (success) {
|
|
1246
|
+
recordResumed = true;
|
|
1247
|
+
recordPaused = false;
|
|
1248
|
+
updateRecordPaused(recordPaused);
|
|
1249
|
+
updateRecordResumed(recordResumed);
|
|
1250
|
+
await rePort({ restart: true, parameters: parameters.getUpdatedAllParams() });
|
|
1251
|
+
} else {
|
|
1252
|
+
showAlert?.({
|
|
1253
|
+
message: `Recording could not resume - ${reason}`,
|
|
1254
|
+
type: "danger",
|
|
1255
|
+
duration: 3e3
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
canRecord = true;
|
|
1259
|
+
startReport = false;
|
|
1260
|
+
endReport = true;
|
|
1261
|
+
updateCanRecord(canRecord);
|
|
1262
|
+
updateStartReport(startReport);
|
|
1263
|
+
updateEndReport(endReport);
|
|
1264
|
+
resolve();
|
|
1265
|
+
}
|
|
1266
|
+
);
|
|
1267
|
+
});
|
|
1268
|
+
updateIsRecordingModalVisible(false);
|
|
1269
|
+
setTimeout(() => {
|
|
1270
|
+
updateCanPauseResume(true);
|
|
1271
|
+
}, recordChangeSeconds);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
const launchRequests = ({ updateIsRequestsModalVisible, isRequestsModalVisible }) => {
|
|
1276
|
+
updateIsRequestsModalVisible(!isRequestsModalVisible);
|
|
1277
|
+
};
|
|
1278
|
+
const respondToRequests = async ({
|
|
1279
|
+
socket,
|
|
1280
|
+
request,
|
|
1281
|
+
updateRequestList,
|
|
1282
|
+
requestList = [],
|
|
1283
|
+
action,
|
|
1284
|
+
roomName
|
|
1285
|
+
}) => {
|
|
1286
|
+
if (!request || typeof request !== "object") {
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
if (!updateRequestList) {
|
|
1290
|
+
console.warn("[respondToRequests] Missing updateRequestList handler; aborting emit.");
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
const currentList = Array.isArray(requestList) ? requestList : [];
|
|
1294
|
+
const requestIdRaw = request.id;
|
|
1295
|
+
const requestIcon = request.icon;
|
|
1296
|
+
const requestName = request.name;
|
|
1297
|
+
if (requestIdRaw === void 0 || requestIcon === void 0 || requestName === void 0) {
|
|
1298
|
+
console.warn("[respondToRequests] Request payload is missing required fields; aborting emit.", request);
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1301
|
+
const requestId = String(requestIdRaw);
|
|
1302
|
+
if (!requestId || !requestIcon || !requestName) {
|
|
1303
|
+
console.warn("[respondToRequests] Request payload contains empty fields; aborting emit.", request);
|
|
1304
|
+
return;
|
|
1305
|
+
}
|
|
1306
|
+
const newRequestList = currentList.filter(
|
|
1307
|
+
(request_) => !(request_ && request_.id === requestId && request_.icon === requestIcon && request_.name === requestName)
|
|
1308
|
+
);
|
|
1309
|
+
updateRequestList(newRequestList);
|
|
1310
|
+
const requestResponse = {
|
|
1311
|
+
id: requestId,
|
|
1312
|
+
name: requestName,
|
|
1313
|
+
type: requestIcon,
|
|
1314
|
+
action
|
|
1315
|
+
};
|
|
1316
|
+
const socketReady = socket && typeof socket.emit === "function";
|
|
1317
|
+
if (!socketReady) {
|
|
1318
|
+
console.warn("[respondToRequests] Socket is not ready; skipping emit.");
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
socket.emit("updateUserofRequestStatus", { requestResponse, roomName });
|
|
1322
|
+
};
|
|
1323
|
+
const launchSettings = ({ updateIsSettingsModalVisible, isSettingsModalVisible }) => {
|
|
1324
|
+
updateIsSettingsModalVisible(!isSettingsModalVisible);
|
|
1325
|
+
};
|
|
1326
|
+
const switchAudio = async ({
|
|
1327
|
+
audioPreference,
|
|
1328
|
+
parameters
|
|
1329
|
+
}) => {
|
|
1330
|
+
let {
|
|
1331
|
+
defAudioID,
|
|
1332
|
+
userDefaultAudioInputDevice,
|
|
1333
|
+
prevAudioInputDevice,
|
|
1334
|
+
updateUserDefaultAudioInputDevice,
|
|
1335
|
+
updatePrevAudioInputDevice,
|
|
1336
|
+
//mediasfu functions
|
|
1337
|
+
switchUserAudio
|
|
1338
|
+
} = parameters;
|
|
1339
|
+
if (audioPreference !== defAudioID) {
|
|
1340
|
+
prevAudioInputDevice = userDefaultAudioInputDevice;
|
|
1341
|
+
updatePrevAudioInputDevice(prevAudioInputDevice);
|
|
1342
|
+
userDefaultAudioInputDevice = audioPreference;
|
|
1343
|
+
updateUserDefaultAudioInputDevice(userDefaultAudioInputDevice);
|
|
1344
|
+
if (defAudioID) {
|
|
1345
|
+
await switchUserAudio({ audioPreference, parameters });
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
};
|
|
1349
|
+
const switchVideo = async ({
|
|
1350
|
+
videoPreference,
|
|
1351
|
+
parameters
|
|
1352
|
+
}) => {
|
|
1353
|
+
let {
|
|
1354
|
+
recordStarted,
|
|
1355
|
+
recordResumed,
|
|
1356
|
+
recordStopped,
|
|
1357
|
+
recordPaused,
|
|
1358
|
+
recordingMediaOptions,
|
|
1359
|
+
videoAlreadyOn,
|
|
1360
|
+
userDefaultVideoInputDevice,
|
|
1361
|
+
defVideoID,
|
|
1362
|
+
allowed,
|
|
1363
|
+
updateDefVideoID,
|
|
1364
|
+
updatePrevVideoInputDevice,
|
|
1365
|
+
updateUserDefaultVideoInputDevice,
|
|
1366
|
+
updateIsMediaSettingsModalVisible,
|
|
1367
|
+
//mediasfu functions
|
|
1368
|
+
showAlert,
|
|
1369
|
+
switchUserVideo
|
|
1370
|
+
} = parameters;
|
|
1371
|
+
let checkoff = false;
|
|
1372
|
+
if ((recordStarted || recordResumed) && !recordStopped && !recordPaused) {
|
|
1373
|
+
if (recordingMediaOptions === "video") {
|
|
1374
|
+
checkoff = true;
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
if (!allowed) {
|
|
1378
|
+
showAlert?.({
|
|
1379
|
+
message: "Allow access to your camera by starting it for the first time.",
|
|
1380
|
+
type: "danger",
|
|
1381
|
+
duration: 3e3
|
|
1382
|
+
});
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
if (checkoff) {
|
|
1386
|
+
if (videoAlreadyOn) {
|
|
1387
|
+
showAlert?.({
|
|
1388
|
+
message: "Please turn off your video before switching.",
|
|
1389
|
+
type: "danger",
|
|
1390
|
+
duration: 3e3
|
|
1391
|
+
});
|
|
1392
|
+
return;
|
|
1393
|
+
}
|
|
1394
|
+
} else {
|
|
1395
|
+
if (!videoAlreadyOn) {
|
|
1396
|
+
showAlert?.({
|
|
1397
|
+
message: "Please turn on your video before switching.",
|
|
1398
|
+
type: "danger",
|
|
1399
|
+
duration: 3e3
|
|
1400
|
+
});
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
if (!defVideoID) {
|
|
1405
|
+
defVideoID = userDefaultVideoInputDevice ?? "default";
|
|
1406
|
+
updateDefVideoID(defVideoID);
|
|
1407
|
+
}
|
|
1408
|
+
if (videoPreference !== defVideoID) {
|
|
1409
|
+
const prevVideoInputDevice = userDefaultVideoInputDevice;
|
|
1410
|
+
updatePrevVideoInputDevice(prevVideoInputDevice);
|
|
1411
|
+
userDefaultVideoInputDevice = videoPreference;
|
|
1412
|
+
updateUserDefaultVideoInputDevice(userDefaultVideoInputDevice);
|
|
1413
|
+
if (defVideoID) {
|
|
1414
|
+
updateIsMediaSettingsModalVisible(false);
|
|
1415
|
+
await switchUserVideo({ videoPreference, checkoff, parameters });
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
const switchVideoAlt = async ({
|
|
1420
|
+
parameters
|
|
1421
|
+
}) => {
|
|
1422
|
+
let {
|
|
1423
|
+
recordStarted,
|
|
1424
|
+
recordResumed,
|
|
1425
|
+
recordStopped,
|
|
1426
|
+
recordPaused,
|
|
1427
|
+
recordingMediaOptions,
|
|
1428
|
+
videoAlreadyOn,
|
|
1429
|
+
currentFacingMode,
|
|
1430
|
+
prevFacingMode,
|
|
1431
|
+
allowed,
|
|
1432
|
+
audioOnlyRoom,
|
|
1433
|
+
updateCurrentFacingMode,
|
|
1434
|
+
updateIsMediaSettingsModalVisible,
|
|
1435
|
+
updatePrevFacingMode,
|
|
1436
|
+
showAlert,
|
|
1437
|
+
//media functions
|
|
1438
|
+
switchUserVideoAlt
|
|
1439
|
+
} = parameters;
|
|
1440
|
+
if (audioOnlyRoom) {
|
|
1441
|
+
showAlert?.({
|
|
1442
|
+
message: "You cannot turn on your camera in an audio-only event.",
|
|
1443
|
+
type: "danger",
|
|
1444
|
+
duration: 3e3
|
|
1445
|
+
});
|
|
1446
|
+
return;
|
|
1447
|
+
}
|
|
1448
|
+
let checkoff = false;
|
|
1449
|
+
if ((recordStarted || recordResumed) && !recordStopped && !recordPaused && recordingMediaOptions === "video") {
|
|
1450
|
+
checkoff = true;
|
|
1451
|
+
}
|
|
1452
|
+
if (!allowed) {
|
|
1453
|
+
showAlert?.({
|
|
1454
|
+
message: "Allow access to your camera by starting it for the first time.",
|
|
1455
|
+
type: "danger",
|
|
1456
|
+
duration: 3e3
|
|
1457
|
+
});
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
if (checkoff) {
|
|
1461
|
+
if (videoAlreadyOn) {
|
|
1462
|
+
showAlert?.({
|
|
1463
|
+
message: "Please turn off your video before switching.",
|
|
1464
|
+
type: "danger",
|
|
1465
|
+
duration: 3e3
|
|
1466
|
+
});
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1469
|
+
} else {
|
|
1470
|
+
if (!videoAlreadyOn) {
|
|
1471
|
+
showAlert?.({
|
|
1472
|
+
message: "Please turn on your video before switching.",
|
|
1473
|
+
type: "danger",
|
|
1474
|
+
duration: 3e3
|
|
1475
|
+
});
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
prevFacingMode = currentFacingMode;
|
|
1480
|
+
updatePrevFacingMode(prevFacingMode);
|
|
1481
|
+
currentFacingMode = currentFacingMode === "environment" ? "user" : "environment";
|
|
1482
|
+
updateCurrentFacingMode(currentFacingMode);
|
|
1483
|
+
updateIsMediaSettingsModalVisible(false);
|
|
1484
|
+
await switchUserVideoAlt({
|
|
1485
|
+
videoPreference: currentFacingMode,
|
|
1486
|
+
checkoff,
|
|
1487
|
+
parameters
|
|
1488
|
+
});
|
|
1489
|
+
};
|
|
1490
|
+
const getModalPosition = ({ position }) => {
|
|
1491
|
+
switch (position) {
|
|
1492
|
+
case "center":
|
|
1493
|
+
return { justifyContent: "center", alignItems: "center" };
|
|
1494
|
+
case "topLeft":
|
|
1495
|
+
return { justifyContent: "flex-start", alignItems: "flex-start" };
|
|
1496
|
+
case "topRight":
|
|
1497
|
+
return { justifyContent: "flex-start", alignItems: "flex-end" };
|
|
1498
|
+
case "bottomLeft":
|
|
1499
|
+
return { justifyContent: "flex-end", alignItems: "flex-start" };
|
|
1500
|
+
case "bottomRight":
|
|
1501
|
+
default:
|
|
1502
|
+
return { justifyContent: "flex-end", alignItems: "flex-end" };
|
|
1503
|
+
}
|
|
1504
|
+
};
|
|
1505
|
+
const launchWaiting = ({ updateIsWaitingModalVisible, isWaitingModalVisible }) => {
|
|
1506
|
+
updateIsWaitingModalVisible(!isWaitingModalVisible);
|
|
1507
|
+
};
|
|
1508
|
+
const respondToWaiting = async ({
|
|
1509
|
+
participantId,
|
|
1510
|
+
participantName,
|
|
1511
|
+
updateWaitingList,
|
|
1512
|
+
waitingList = [],
|
|
1513
|
+
type,
|
|
1514
|
+
roomName,
|
|
1515
|
+
socket
|
|
1516
|
+
}) => {
|
|
1517
|
+
if (!participantId || !participantName) {
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
if (!updateWaitingList) {
|
|
1521
|
+
console.warn("[respondToWaiting] Missing updateWaitingList handler; aborting emit.");
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
if (!socket || typeof socket.emit !== "function") {
|
|
1525
|
+
console.warn("[respondToWaiting] Socket is not ready; skipping emit.");
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1528
|
+
const newWaitingList = waitingList.filter((item) => item.name !== participantName);
|
|
1529
|
+
updateWaitingList(newWaitingList);
|
|
1530
|
+
const responseType = type === "true" || type === true ? "true" : "false";
|
|
1531
|
+
socket.emit("allowUserIn", {
|
|
1532
|
+
participantId,
|
|
1533
|
+
participantName,
|
|
1534
|
+
type: responseType,
|
|
1535
|
+
roomName
|
|
1536
|
+
});
|
|
1537
|
+
};
|
|
1538
|
+
const handleStartWhiteboard = async ({
|
|
1539
|
+
socket,
|
|
1540
|
+
whiteboardUsers,
|
|
1541
|
+
roomName,
|
|
1542
|
+
whiteboardStarted,
|
|
1543
|
+
whiteboardEnded,
|
|
1544
|
+
showAlert,
|
|
1545
|
+
updateWhiteboardStarted,
|
|
1546
|
+
updateWhiteboardEnded,
|
|
1547
|
+
updateIsConfigureWhiteboardModalVisible
|
|
1548
|
+
}) => {
|
|
1549
|
+
const emitName = whiteboardStarted && !whiteboardEnded ? "updateWhiteboard" : "startWhiteboard";
|
|
1550
|
+
const filteredWhiteboardUsers = whiteboardUsers.map(({ name, useBoard }) => ({ name, useBoard }));
|
|
1551
|
+
return new Promise((resolve) => {
|
|
1552
|
+
socket.emit(
|
|
1553
|
+
emitName,
|
|
1554
|
+
{ whiteboardUsers: filteredWhiteboardUsers, roomName },
|
|
1555
|
+
(response) => {
|
|
1556
|
+
if (response.success) {
|
|
1557
|
+
showAlert?.({ message: "Whiteboard active", type: "success" });
|
|
1558
|
+
updateWhiteboardStarted(true);
|
|
1559
|
+
updateWhiteboardEnded(false);
|
|
1560
|
+
updateIsConfigureWhiteboardModalVisible(false);
|
|
1561
|
+
} else {
|
|
1562
|
+
showAlert?.({ message: response.reason || "Failed to start whiteboard", type: "danger" });
|
|
1563
|
+
}
|
|
1564
|
+
resolve(response.success);
|
|
1565
|
+
}
|
|
1566
|
+
);
|
|
1567
|
+
});
|
|
1568
|
+
};
|
|
1569
|
+
const handleStopWhiteboard = async ({
|
|
1570
|
+
socket,
|
|
1571
|
+
roomName,
|
|
1572
|
+
showAlert,
|
|
1573
|
+
updateWhiteboardStarted,
|
|
1574
|
+
updateWhiteboardEnded,
|
|
1575
|
+
updateIsConfigureWhiteboardModalVisible
|
|
1576
|
+
}) => {
|
|
1577
|
+
return new Promise((resolve) => {
|
|
1578
|
+
socket.emit("stopWhiteboard", { roomName }, (response) => {
|
|
1579
|
+
if (response.success) {
|
|
1580
|
+
showAlert?.({ message: "Whiteboard stopped", type: "success" });
|
|
1581
|
+
updateWhiteboardStarted(false);
|
|
1582
|
+
updateWhiteboardEnded(true);
|
|
1583
|
+
updateIsConfigureWhiteboardModalVisible(false);
|
|
1584
|
+
} else {
|
|
1585
|
+
showAlert?.({ message: response.reason || "Failed to stop whiteboard", type: "danger" });
|
|
1586
|
+
}
|
|
1587
|
+
resolve(response.success);
|
|
1588
|
+
});
|
|
1589
|
+
});
|
|
1590
|
+
};
|
|
1591
|
+
const launchConfigureWhiteboard = ({
|
|
1592
|
+
updateIsConfigureWhiteboardModalVisible,
|
|
1593
|
+
isConfigureWhiteboardModalVisible
|
|
1594
|
+
}) => {
|
|
1595
|
+
updateIsConfigureWhiteboardModalVisible(!isConfigureWhiteboardModalVisible);
|
|
1596
|
+
};
|
|
1597
|
+
function getRoomReadiness({ parameters }) {
|
|
1598
|
+
const source = parameters || {};
|
|
1599
|
+
if (!source.roomName) {
|
|
1600
|
+
return { ready: false, reason: "Waiting for the room name." };
|
|
1601
|
+
}
|
|
1602
|
+
if (!source.member) {
|
|
1603
|
+
return { ready: false, reason: "Waiting for the participant identity." };
|
|
1604
|
+
}
|
|
1605
|
+
if (source.validated !== true) {
|
|
1606
|
+
return { ready: false, reason: "Waiting for MediaSFU to validate the room." };
|
|
1607
|
+
}
|
|
1608
|
+
const socket = source.socket;
|
|
1609
|
+
if (!socket || socket.connected !== true) {
|
|
1610
|
+
return { ready: false, reason: "Connecting to the MediaSFU room." };
|
|
1611
|
+
}
|
|
1612
|
+
if (typeof socket.emit !== "function") {
|
|
1613
|
+
return { ready: false, reason: "The room signal is not ready yet." };
|
|
1614
|
+
}
|
|
1615
|
+
if (source.device?.loaded !== true) {
|
|
1616
|
+
return { ready: false, reason: "Waiting for the MediaSFU media device." };
|
|
1617
|
+
}
|
|
1618
|
+
return { ready: true, reason: "" };
|
|
1619
|
+
}
|
|
1620
|
+
const SELF_PRODUCER_IDS = /* @__PURE__ */ new Set(["youyou", "youyouyou"]);
|
|
1621
|
+
function toMediaStream(value) {
|
|
1622
|
+
if (value && typeof value.getTracks === "function") return value;
|
|
1623
|
+
const nested = value?.stream;
|
|
1624
|
+
return nested && typeof nested.getTracks === "function" ? nested : null;
|
|
1625
|
+
}
|
|
1626
|
+
function hasRenderableTrack(stream, kind, requireEnabled) {
|
|
1627
|
+
if (!stream || typeof stream.getTracks !== "function") return false;
|
|
1628
|
+
try {
|
|
1629
|
+
return stream.getTracks().some(
|
|
1630
|
+
(track) => track.kind === kind && track.readyState === "live" && (!requireEnabled || track.enabled !== false)
|
|
1631
|
+
);
|
|
1632
|
+
} catch {
|
|
1633
|
+
return false;
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
function collect(entries) {
|
|
1637
|
+
return Array.isArray(entries) ? entries : [];
|
|
1638
|
+
}
|
|
1639
|
+
function dedupe(entries) {
|
|
1640
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1641
|
+
const resolved = [];
|
|
1642
|
+
for (const entry of entries) {
|
|
1643
|
+
const producerId = entry?.producerId || "";
|
|
1644
|
+
if (SELF_PRODUCER_IDS.has(producerId)) continue;
|
|
1645
|
+
const stream = toMediaStream(entry);
|
|
1646
|
+
if (!hasRenderableTrack(stream, "video", false)) continue;
|
|
1647
|
+
const key = producerId || stream.id || "";
|
|
1648
|
+
if (key && seen.has(key)) continue;
|
|
1649
|
+
if (key) seen.add(key);
|
|
1650
|
+
resolved.push({
|
|
1651
|
+
stream,
|
|
1652
|
+
producerId,
|
|
1653
|
+
name: entry?.name || ""
|
|
1654
|
+
});
|
|
1655
|
+
}
|
|
1656
|
+
return resolved;
|
|
1657
|
+
}
|
|
1658
|
+
function getRemoteVideoStreams({
|
|
1659
|
+
parameters
|
|
1660
|
+
}) {
|
|
1661
|
+
const source = parameters || {};
|
|
1662
|
+
return dedupe([
|
|
1663
|
+
...collect(source.oldAllStreams),
|
|
1664
|
+
...collect(source.allVideoStreams)
|
|
1665
|
+
]);
|
|
1666
|
+
}
|
|
1667
|
+
function getRemoteAudioStreams({
|
|
1668
|
+
parameters
|
|
1669
|
+
}) {
|
|
1670
|
+
const source = parameters || {};
|
|
1671
|
+
return dedupe(collect(source.allAudioStreams));
|
|
1672
|
+
}
|
|
1673
|
+
function getLocalVideoStream({
|
|
1674
|
+
parameters
|
|
1675
|
+
}) {
|
|
1676
|
+
const source = parameters || {};
|
|
1677
|
+
if (source.keepBackground && source.virtualStream) {
|
|
1678
|
+
const virtual = toMediaStream(source.virtualStream);
|
|
1679
|
+
if (hasRenderableTrack(virtual, "video", true)) return virtual;
|
|
1680
|
+
}
|
|
1681
|
+
const camera = toMediaStream(source.localStreamVideo);
|
|
1682
|
+
if (hasRenderableTrack(camera, "video", true)) return camera;
|
|
1683
|
+
const combined = toMediaStream(source.localStream);
|
|
1684
|
+
return hasRenderableTrack(combined, "video", true) ? combined : null;
|
|
1685
|
+
}
|
|
1686
|
+
function getLocalAudioStream({
|
|
1687
|
+
parameters
|
|
1688
|
+
}) {
|
|
1689
|
+
const source = parameters || {};
|
|
1690
|
+
const mic = toMediaStream(source.localStreamAudio);
|
|
1691
|
+
if (hasRenderableTrack(mic, "audio", true)) return mic;
|
|
1692
|
+
const combined = toMediaStream(source.localStream);
|
|
1693
|
+
return hasRenderableTrack(combined, "audio", true) ? combined : null;
|
|
1694
|
+
}
|
|
1695
|
+
function getScreenShareStream({
|
|
1696
|
+
parameters
|
|
1697
|
+
}) {
|
|
1698
|
+
const source = parameters || {};
|
|
1699
|
+
const remoteRaw = source.remoteScreenStream;
|
|
1700
|
+
const remote = Array.isArray(remoteRaw) ? toMediaStream(remoteRaw[0]) : toMediaStream(remoteRaw);
|
|
1701
|
+
if (hasRenderableTrack(remote, "video", false)) {
|
|
1702
|
+
return { stream: remote, isLocal: false, active: true };
|
|
1703
|
+
}
|
|
1704
|
+
const local = toMediaStream(source.localStreamScreen);
|
|
1705
|
+
if (hasRenderableTrack(local, "video", true)) {
|
|
1706
|
+
return { stream: local, isLocal: true, active: true };
|
|
1707
|
+
}
|
|
1708
|
+
return {
|
|
1709
|
+
stream: null,
|
|
1710
|
+
isLocal: false,
|
|
1711
|
+
active: Boolean(source.shareScreenStarted || source.shared)
|
|
1712
|
+
};
|
|
1713
|
+
}
|
|
1714
|
+
function getAudioGridComponents({ parameters }) {
|
|
1715
|
+
const source = parameters || {};
|
|
1716
|
+
return [
|
|
1717
|
+
...Array.isArray(source.audioOnlyStreams) ? source.audioOnlyStreams : [],
|
|
1718
|
+
...Array.isArray(source.translationStreams) ? source.translationStreams : []
|
|
1719
|
+
].filter(Boolean);
|
|
1720
|
+
}
|
|
1721
|
+
function getCurrentParams({
|
|
1722
|
+
parameters
|
|
1723
|
+
}) {
|
|
1724
|
+
const source = parameters || {};
|
|
1725
|
+
if (typeof source.getCurrentParams === "function") {
|
|
1726
|
+
try {
|
|
1727
|
+
const refreshed = source.getCurrentParams();
|
|
1728
|
+
if (refreshed && typeof refreshed === "object") return refreshed;
|
|
1729
|
+
} catch {
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
return source;
|
|
1733
|
+
}
|
|
1734
|
+
function usableSocket(parameters) {
|
|
1735
|
+
return [parameters?.localSocket, parameters?.socket].find(
|
|
1736
|
+
(socket) => socket?.connected === true && typeof socket.emit === "function"
|
|
1737
|
+
) || null;
|
|
1738
|
+
}
|
|
1739
|
+
async function leaveRoom({
|
|
1740
|
+
parameters,
|
|
1741
|
+
ban = false,
|
|
1742
|
+
endRoomOnHostExit = true
|
|
1743
|
+
}) {
|
|
1744
|
+
try {
|
|
1745
|
+
const live = getCurrentParams({ parameters });
|
|
1746
|
+
const socket = live?.socket;
|
|
1747
|
+
if (!socket || typeof socket.emit !== "function") {
|
|
1748
|
+
return {
|
|
1749
|
+
ok: false,
|
|
1750
|
+
error: "Room exit is unavailable until the signaling connection is ready."
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
if (!live?.member || !live?.roomName) {
|
|
1754
|
+
return { ok: false, error: "Room exit is unavailable until the room is joined." };
|
|
1755
|
+
}
|
|
1756
|
+
await confirmExit({
|
|
1757
|
+
socket,
|
|
1758
|
+
localSocket: live.localSocket,
|
|
1759
|
+
member: live.member,
|
|
1760
|
+
roomName: live.roomName,
|
|
1761
|
+
ban,
|
|
1762
|
+
endRoomOnHostExit
|
|
1763
|
+
});
|
|
1764
|
+
return { ok: true, error: "" };
|
|
1765
|
+
} catch (error) {
|
|
1766
|
+
return { ok: false, error: error?.message || "The room exit request failed." };
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
async function sendChatMessage({
|
|
1770
|
+
parameters,
|
|
1771
|
+
message,
|
|
1772
|
+
receivers = [],
|
|
1773
|
+
group
|
|
1774
|
+
}) {
|
|
1775
|
+
try {
|
|
1776
|
+
const trimmed = String(message ?? "").trim();
|
|
1777
|
+
if (!trimmed) return { ok: false, error: "The message is empty." };
|
|
1778
|
+
const live = getCurrentParams({ parameters });
|
|
1779
|
+
const socket = usableSocket(live);
|
|
1780
|
+
if (!socket) {
|
|
1781
|
+
return { ok: false, error: "Chat is unavailable until the room connection is ready." };
|
|
1782
|
+
}
|
|
1783
|
+
if (!live?.roomName) {
|
|
1784
|
+
return { ok: false, error: "Chat is unavailable until the room is joined." };
|
|
1785
|
+
}
|
|
1786
|
+
await sendMessage({
|
|
1787
|
+
member: live.member || "",
|
|
1788
|
+
islevel: live.islevel || "1",
|
|
1789
|
+
showAlert: live.showAlert,
|
|
1790
|
+
coHostResponsibility: live.coHostResponsibility || [],
|
|
1791
|
+
coHost: live.coHost || "",
|
|
1792
|
+
chatSetting: live.chatSetting || "",
|
|
1793
|
+
message: trimmed,
|
|
1794
|
+
roomName: live.roomName,
|
|
1795
|
+
messagesLength: Array.isArray(live.messages) ? live.messages.length : 0,
|
|
1796
|
+
receivers,
|
|
1797
|
+
group: group ?? receivers.length === 0,
|
|
1798
|
+
sender: live.member || "",
|
|
1799
|
+
socket
|
|
1800
|
+
});
|
|
1801
|
+
return { ok: true, error: "" };
|
|
1802
|
+
} catch (error) {
|
|
1803
|
+
return { ok: false, error: error?.message || "The message could not be sent." };
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
async function runMediaControl({
|
|
1807
|
+
parameters,
|
|
1808
|
+
control,
|
|
1809
|
+
extra
|
|
1810
|
+
}) {
|
|
1811
|
+
const live = getCurrentParams({ parameters });
|
|
1812
|
+
const readiness = getRoomReadiness({ parameters: live });
|
|
1813
|
+
if (!readiness.ready) return { ok: false, error: readiness.reason };
|
|
1814
|
+
const method = live?.[control];
|
|
1815
|
+
if (typeof method !== "function") {
|
|
1816
|
+
return { ok: false, error: `The SDK ${control} control is unavailable.` };
|
|
1817
|
+
}
|
|
1818
|
+
const alertBefore = live?.alertMessage || "";
|
|
1819
|
+
try {
|
|
1820
|
+
await method({ ...extra || {}, parameters: live });
|
|
1821
|
+
} catch (error) {
|
|
1822
|
+
return { ok: false, error: error?.message || "The media control failed." };
|
|
1823
|
+
}
|
|
1824
|
+
const settled = getCurrentParams({ parameters: live });
|
|
1825
|
+
const alertAfter = settled?.alertMessage || "";
|
|
1826
|
+
const alertType = settled?.alertType;
|
|
1827
|
+
if (alertAfter && alertAfter !== alertBefore && (alertType === "danger" || alertType === "warning")) {
|
|
1828
|
+
return { ok: false, error: alertAfter };
|
|
1829
|
+
}
|
|
1830
|
+
return { ok: true, error: "" };
|
|
1831
|
+
}
|
|
1832
|
+
function hasProducer(value) {
|
|
1833
|
+
return typeof value === "string" && value.length > 3 && value.toLowerCase() !== "none";
|
|
1834
|
+
}
|
|
1835
|
+
function participantList$1(parameters) {
|
|
1836
|
+
const source = parameters || {};
|
|
1837
|
+
const primary = Array.isArray(source.participants) ? source.participants : [];
|
|
1838
|
+
if (primary.length > 0) return primary;
|
|
1839
|
+
return Array.isArray(source.participantsAll) ? source.participantsAll : [];
|
|
1840
|
+
}
|
|
1841
|
+
function getParticipantMediaState({
|
|
1842
|
+
parameters,
|
|
1843
|
+
name = "",
|
|
1844
|
+
id = ""
|
|
1845
|
+
}) {
|
|
1846
|
+
const source = parameters || {};
|
|
1847
|
+
const participants = participantList$1(source);
|
|
1848
|
+
const participant = (id ? participants.find((part) => part.id === id) : void 0) || (name ? participants.find((part) => part.name === name) : void 0) || null;
|
|
1849
|
+
const videoProducerId = hasProducer(participant?.videoID) ? participant.videoID : "";
|
|
1850
|
+
const audioProducerId = hasProducer(participant?.audioID) ? participant.audioID : "";
|
|
1851
|
+
return {
|
|
1852
|
+
participant,
|
|
1853
|
+
name: participant?.name || "",
|
|
1854
|
+
isSelf: Boolean(participant?.name && participant.name === source.member),
|
|
1855
|
+
isHost: String(participant?.islevel) === "2",
|
|
1856
|
+
hasVideo: Boolean(videoProducerId),
|
|
1857
|
+
hasAudio: Boolean(audioProducerId),
|
|
1858
|
+
muted: participant?.muted === true,
|
|
1859
|
+
videoProducerId,
|
|
1860
|
+
audioProducerId
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
function listParticipantMediaStates({
|
|
1864
|
+
parameters
|
|
1865
|
+
}) {
|
|
1866
|
+
const source = parameters || {};
|
|
1867
|
+
return participantList$1(source).map(
|
|
1868
|
+
(participant) => getParticipantMediaState({
|
|
1869
|
+
parameters: source,
|
|
1870
|
+
id: participant.id,
|
|
1871
|
+
name: participant.name
|
|
1872
|
+
})
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
function getActiveSpeaker({ parameters }) {
|
|
1876
|
+
const source = parameters || {};
|
|
1877
|
+
const decibels = Array.isArray(source.audioDecibels) ? source.audioDecibels : [];
|
|
1878
|
+
const participants = participantList$1(source);
|
|
1879
|
+
let best = null;
|
|
1880
|
+
for (const entry of decibels) {
|
|
1881
|
+
if (!entry?.name || typeof entry.averageLoudness !== "number") continue;
|
|
1882
|
+
if (entry.averageLoudness <= 127.5) continue;
|
|
1883
|
+
if (!best || entry.averageLoudness > best.averageLoudness) best = entry;
|
|
1884
|
+
}
|
|
1885
|
+
if (!best) return { name: "", level: 0, participant: null };
|
|
1886
|
+
return {
|
|
1887
|
+
name: best.name,
|
|
1888
|
+
level: best.averageLoudness,
|
|
1889
|
+
participant: participants.find((part) => part.name === best.name) || null
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1892
|
+
async function listMediaDevices({
|
|
1893
|
+
parameters
|
|
1894
|
+
}) {
|
|
1895
|
+
const source = parameters || {};
|
|
1896
|
+
try {
|
|
1897
|
+
if (typeof source.getMediaDevicesList === "function") {
|
|
1898
|
+
const [cameras, microphones] = await Promise.all([
|
|
1899
|
+
source.getMediaDevicesList("videoinput"),
|
|
1900
|
+
source.getMediaDevicesList("audioinput")
|
|
1901
|
+
]);
|
|
1902
|
+
return {
|
|
1903
|
+
cameras: Array.isArray(cameras) ? cameras : [],
|
|
1904
|
+
microphones: Array.isArray(microphones) ? microphones : []
|
|
1905
|
+
};
|
|
1906
|
+
}
|
|
1907
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
1908
|
+
return {
|
|
1909
|
+
cameras: devices.filter((device) => device.kind === "videoinput"),
|
|
1910
|
+
microphones: devices.filter((device) => device.kind === "audioinput")
|
|
1911
|
+
};
|
|
1912
|
+
} catch {
|
|
1913
|
+
return { cameras: [], microphones: [] };
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
function getSelectedDevices({ parameters }) {
|
|
1917
|
+
const source = parameters || {};
|
|
1918
|
+
return {
|
|
1919
|
+
cameraId: source.userDefaultVideoInputDevice || "",
|
|
1920
|
+
microphoneId: source.userDefaultAudioInputDevice || "",
|
|
1921
|
+
cameras: Array.isArray(source.videoInputs) ? source.videoInputs : [],
|
|
1922
|
+
microphones: Array.isArray(source.audioInputs) ? source.audioInputs : []
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
function isPanelist(parameters) {
|
|
1926
|
+
const panelists = Array.isArray(parameters.panelists) ? parameters.panelists : [];
|
|
1927
|
+
return panelists.some((entry) => entry?.name === parameters.member);
|
|
1928
|
+
}
|
|
1929
|
+
function getMediaPermissions({ parameters }) {
|
|
1930
|
+
const source = parameters || {};
|
|
1931
|
+
const isHost = String(source.islevel) === "2";
|
|
1932
|
+
const recording = Boolean(source.recordStarted || source.recordResumed) && !(source.recordPaused || source.recordStopped);
|
|
1933
|
+
const focusModeBlocked = Boolean(source.panelistsFocused) && !isHost && !isPanelist(source);
|
|
1934
|
+
const evaluate = (kind) => {
|
|
1935
|
+
const allow = () => ({ allowed: true, reason: "", needsApproval: false });
|
|
1936
|
+
const deny = (reason) => ({ allowed: false, reason, needsApproval: false });
|
|
1937
|
+
if (source.audioOnlyRoom && kind !== "audio") {
|
|
1938
|
+
return deny("This is an audio-only event.");
|
|
1939
|
+
}
|
|
1940
|
+
if (isHost && recording) {
|
|
1941
|
+
if (kind === "audio" && source.recordingMediaOptions === "audio") {
|
|
1942
|
+
return deny("Pause or stop the recording before changing your microphone.");
|
|
1943
|
+
}
|
|
1944
|
+
if (kind === "video" && source.recordingMediaOptions === "video") {
|
|
1945
|
+
return deny("Pause or stop the recording before changing your camera.");
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
if (isHost) return allow();
|
|
1949
|
+
if (source.adminRestrictSetting) {
|
|
1950
|
+
return deny("Access denied by the host.");
|
|
1951
|
+
}
|
|
1952
|
+
if (focusModeBlocked && kind === "audio" && source.muteOthersMic) {
|
|
1953
|
+
return deny("Only panelists can unmute while focus mode is active.");
|
|
1954
|
+
}
|
|
1955
|
+
if (focusModeBlocked && kind === "video" && source.muteOthersCamera) {
|
|
1956
|
+
return deny("Only panelists can enable video while focus mode is active.");
|
|
1957
|
+
}
|
|
1958
|
+
const setting = kind === "audio" ? source.audioSetting : kind === "video" ? source.videoSetting : source.screenshareSetting;
|
|
1959
|
+
if (setting === "disallow") {
|
|
1960
|
+
return deny("The host has disabled this for participants.");
|
|
1961
|
+
}
|
|
1962
|
+
if (setting === "approval") {
|
|
1963
|
+
return { allowed: true, reason: "The host must approve this.", needsApproval: true };
|
|
1964
|
+
}
|
|
1965
|
+
return allow();
|
|
1966
|
+
};
|
|
1967
|
+
return {
|
|
1968
|
+
microphone: evaluate("audio"),
|
|
1969
|
+
camera: evaluate("video"),
|
|
1970
|
+
screenShare: evaluate("screenshare"),
|
|
1971
|
+
isHost,
|
|
1972
|
+
focusModeBlocked
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
function hasResponsibility(parameters, area) {
|
|
1976
|
+
const list = Array.isArray(parameters?.coHostResponsibility) ? parameters.coHostResponsibility : [];
|
|
1977
|
+
return list.find((item) => item?.name === area)?.value === true;
|
|
1978
|
+
}
|
|
1979
|
+
function getModerationPermissions({
|
|
1980
|
+
parameters
|
|
1981
|
+
}) {
|
|
1982
|
+
const source = parameters || {};
|
|
1983
|
+
const isHost = String(source.islevel) === "2";
|
|
1984
|
+
const isCoHost = Boolean(source.coHost && source.coHost === source.member);
|
|
1985
|
+
const allow = (area) => isHost || isCoHost && hasResponsibility(source, area);
|
|
1986
|
+
return {
|
|
1987
|
+
isHost,
|
|
1988
|
+
isCoHost,
|
|
1989
|
+
canControlMedia: allow("media"),
|
|
1990
|
+
canManageParticipants: allow("participants"),
|
|
1991
|
+
canManageChat: allow("chat"),
|
|
1992
|
+
canManageWaitingRoom: allow("waiting")
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
1995
|
+
function participantList(parameters) {
|
|
1996
|
+
const source = parameters || {};
|
|
1997
|
+
const primary = Array.isArray(source.participants) ? source.participants : [];
|
|
1998
|
+
if (primary.length > 0) return primary;
|
|
1999
|
+
return Array.isArray(source.participantsAll) ? source.participantsAll : [];
|
|
2000
|
+
}
|
|
2001
|
+
function findParticipant(parameters, { id, name }) {
|
|
2002
|
+
const participants = participantList(parameters);
|
|
2003
|
+
return (id ? participants.find((part) => part.id === id) : void 0) || (name ? participants.find((part) => part.name === name) : void 0) || null;
|
|
2004
|
+
}
|
|
2005
|
+
async function setParticipantMedia({
|
|
2006
|
+
parameters,
|
|
2007
|
+
name = "",
|
|
2008
|
+
id = "",
|
|
2009
|
+
kind
|
|
2010
|
+
}) {
|
|
2011
|
+
try {
|
|
2012
|
+
const live = getCurrentParams({ parameters });
|
|
2013
|
+
const permissions = getModerationPermissions({ parameters: live });
|
|
2014
|
+
if (!permissions.canControlMedia) {
|
|
2015
|
+
return {
|
|
2016
|
+
ok: false,
|
|
2017
|
+
error: "You are not allowed to control media for other participants."
|
|
2018
|
+
};
|
|
2019
|
+
}
|
|
2020
|
+
const socket = live?.socket;
|
|
2021
|
+
if (!socket || typeof socket.emit !== "function" || !live?.roomName) {
|
|
2022
|
+
return { ok: false, error: "The room connection is not ready." };
|
|
2023
|
+
}
|
|
2024
|
+
const participant = findParticipant(live, { id, name });
|
|
2025
|
+
if (!participant) return { ok: false, error: "That participant is not in the room." };
|
|
2026
|
+
if (String(participant.islevel) === "2") {
|
|
2027
|
+
return { ok: false, error: "A host’s media cannot be turned off." };
|
|
2028
|
+
}
|
|
2029
|
+
socket.emit("controlMedia", {
|
|
2030
|
+
participantId: participant.id,
|
|
2031
|
+
participantName: participant.name,
|
|
2032
|
+
type: kind,
|
|
2033
|
+
roomName: live.roomName
|
|
2034
|
+
});
|
|
2035
|
+
return { ok: true, error: "" };
|
|
2036
|
+
} catch (error) {
|
|
2037
|
+
return { ok: false, error: error?.message || "The media control failed." };
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
function muteParticipant(options) {
|
|
2041
|
+
return setParticipantMedia({ ...options, kind: "audio" });
|
|
2042
|
+
}
|
|
2043
|
+
function disableParticipantVideo(options) {
|
|
2044
|
+
return setParticipantMedia({ ...options, kind: "video" });
|
|
2045
|
+
}
|
|
2046
|
+
function stopParticipantScreenShare(options) {
|
|
2047
|
+
return setParticipantMedia({ ...options, kind: "screenshare" });
|
|
2048
|
+
}
|
|
2049
|
+
async function muteEveryone({
|
|
2050
|
+
parameters,
|
|
2051
|
+
kind = "audio"
|
|
2052
|
+
}) {
|
|
2053
|
+
const live = getCurrentParams({ parameters });
|
|
2054
|
+
const permissions = getModerationPermissions({ parameters: live });
|
|
2055
|
+
if (!permissions.canControlMedia) {
|
|
2056
|
+
return {
|
|
2057
|
+
ok: false,
|
|
2058
|
+
error: "You are not allowed to control media for other participants."
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
const targets = participantList(live).filter(
|
|
2062
|
+
(part) => String(part.islevel) !== "2" && part.name !== live.member
|
|
2063
|
+
);
|
|
2064
|
+
if (targets.length === 0) return { ok: false, error: "There is nobody else to mute." };
|
|
2065
|
+
const results = await Promise.all(
|
|
2066
|
+
targets.map(
|
|
2067
|
+
(part) => setParticipantMedia({ parameters: live, id: part.id, name: part.name, kind })
|
|
2068
|
+
)
|
|
2069
|
+
);
|
|
2070
|
+
const failed = results.filter((result) => !result.ok);
|
|
2071
|
+
if (failed.length === results.length) {
|
|
2072
|
+
return { ok: false, error: failed[0]?.error || "No participant could be muted." };
|
|
2073
|
+
}
|
|
2074
|
+
return { ok: true, error: "" };
|
|
2075
|
+
}
|
|
2076
|
+
async function removeParticipant({
|
|
2077
|
+
parameters,
|
|
2078
|
+
name = "",
|
|
2079
|
+
id = ""
|
|
2080
|
+
}) {
|
|
2081
|
+
try {
|
|
2082
|
+
const live = getCurrentParams({ parameters });
|
|
2083
|
+
const permissions = getModerationPermissions({ parameters: live });
|
|
2084
|
+
if (!permissions.canManageParticipants) {
|
|
2085
|
+
return { ok: false, error: "You are not allowed to remove participants." };
|
|
2086
|
+
}
|
|
2087
|
+
const participant = findParticipant(live, { id, name });
|
|
2088
|
+
if (!participant) return { ok: false, error: "That participant is not in the room." };
|
|
2089
|
+
if (String(participant.islevel) === "2") {
|
|
2090
|
+
return { ok: false, error: "A host cannot be removed." };
|
|
2091
|
+
}
|
|
2092
|
+
await removeParticipants({
|
|
2093
|
+
coHostResponsibility: live.coHostResponsibility || [],
|
|
2094
|
+
participant,
|
|
2095
|
+
member: live.member || "",
|
|
2096
|
+
islevel: live.islevel || "1",
|
|
2097
|
+
showAlert: live.showAlert,
|
|
2098
|
+
coHost: live.coHost || "",
|
|
2099
|
+
participants: participantList(live),
|
|
2100
|
+
socket: live.socket,
|
|
2101
|
+
roomName: live.roomName || "",
|
|
2102
|
+
updateParticipants: live.updateParticipants
|
|
2103
|
+
});
|
|
2104
|
+
return { ok: true, error: "" };
|
|
2105
|
+
} catch (error) {
|
|
2106
|
+
return { ok: false, error: error?.message || "The participant could not be removed." };
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
async function respondToWaitingParticipant({
|
|
2110
|
+
parameters,
|
|
2111
|
+
name = "",
|
|
2112
|
+
id = "",
|
|
2113
|
+
admit
|
|
2114
|
+
}) {
|
|
2115
|
+
try {
|
|
2116
|
+
const live = getCurrentParams({ parameters });
|
|
2117
|
+
const permissions = getModerationPermissions({ parameters: live });
|
|
2118
|
+
if (!permissions.canManageWaitingRoom) {
|
|
2119
|
+
return { ok: false, error: "You are not allowed to manage the waiting room." };
|
|
2120
|
+
}
|
|
2121
|
+
const waitingList = Array.isArray(live.waitingRoomList) ? live.waitingRoomList : [];
|
|
2122
|
+
const entry = (id ? waitingList.find((person) => person?.id === id) : void 0) || (name ? waitingList.find((person) => person?.name === name) : void 0);
|
|
2123
|
+
if (!entry) return { ok: false, error: "That person is no longer waiting to join." };
|
|
2124
|
+
await respondToWaiting({
|
|
2125
|
+
participantId: entry.id,
|
|
2126
|
+
participantName: entry.name,
|
|
2127
|
+
updateWaitingList: live.updateWaitingRoomList,
|
|
2128
|
+
waitingList,
|
|
2129
|
+
type: admit,
|
|
2130
|
+
roomName: live.roomName || "",
|
|
2131
|
+
socket: live.socket
|
|
2132
|
+
});
|
|
2133
|
+
return { ok: true, error: "" };
|
|
2134
|
+
} catch (error) {
|
|
2135
|
+
return {
|
|
2136
|
+
ok: false,
|
|
2137
|
+
error: error?.message || "The waiting-room response failed."
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
async function respondToParticipantRequest({
|
|
2142
|
+
parameters,
|
|
2143
|
+
requestId = "",
|
|
2144
|
+
name = "",
|
|
2145
|
+
approve
|
|
2146
|
+
}) {
|
|
2147
|
+
try {
|
|
2148
|
+
const live = getCurrentParams({ parameters });
|
|
2149
|
+
const permissions = getModerationPermissions({ parameters: live });
|
|
2150
|
+
if (!permissions.canManageParticipants) {
|
|
2151
|
+
return { ok: false, error: "You are not allowed to respond to requests." };
|
|
2152
|
+
}
|
|
2153
|
+
const requestList = Array.isArray(live.requestList) ? live.requestList : [];
|
|
2154
|
+
const request = (requestId ? requestList.find((item) => item?.id === requestId) : void 0) || (name ? requestList.find(
|
|
2155
|
+
(item) => item?.name === name || item?.username === name
|
|
2156
|
+
) : void 0);
|
|
2157
|
+
if (!request) return { ok: false, error: "That request is no longer pending." };
|
|
2158
|
+
await respondToRequests({
|
|
2159
|
+
socket: live.socket,
|
|
2160
|
+
request,
|
|
2161
|
+
updateRequestList: live.updateRequestList,
|
|
2162
|
+
requestList,
|
|
2163
|
+
action: approve ? "accepted" : "rejected",
|
|
2164
|
+
roomName: live.roomName || ""
|
|
2165
|
+
});
|
|
2166
|
+
return { ok: true, error: "" };
|
|
2167
|
+
} catch (error) {
|
|
2168
|
+
return { ok: false, error: error?.message || "The request response failed." };
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
async function setCoHost({
|
|
2172
|
+
parameters,
|
|
2173
|
+
name,
|
|
2174
|
+
areas = ["media", "participants"]
|
|
2175
|
+
}) {
|
|
2176
|
+
try {
|
|
2177
|
+
const live = getCurrentParams({ parameters });
|
|
2178
|
+
if (String(live.islevel) !== "2") {
|
|
2179
|
+
return { ok: false, error: "Only the host can assign a co-host." };
|
|
2180
|
+
}
|
|
2181
|
+
const all = ["media", "participants", "chat", "waiting"];
|
|
2182
|
+
const responsibilities = all.map((area) => ({
|
|
2183
|
+
name: area,
|
|
2184
|
+
value: areas.includes(area),
|
|
2185
|
+
dedicated: false
|
|
2186
|
+
}));
|
|
2187
|
+
await modifyCoHostSettings({
|
|
2188
|
+
roomName: live.roomName || "",
|
|
2189
|
+
showAlert: live.showAlert,
|
|
2190
|
+
selectedParticipant: name,
|
|
2191
|
+
coHost: live.coHost || "",
|
|
2192
|
+
coHostResponsibility: responsibilities,
|
|
2193
|
+
updateIsCoHostModalVisible: live.updateIsCoHostModalVisible || (() => void 0),
|
|
2194
|
+
updateCoHostResponsibility: live.updateCoHostResponsibility,
|
|
2195
|
+
updateCoHost: live.updateCoHost,
|
|
2196
|
+
socket: live.socket
|
|
2197
|
+
});
|
|
2198
|
+
return { ok: true, error: "" };
|
|
2199
|
+
} catch (error) {
|
|
2200
|
+
return { ok: false, error: error?.message || "The co-host update failed." };
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
const noop = () => void 0;
|
|
2204
|
+
function getRecordingState({ parameters }) {
|
|
2205
|
+
const source = parameters || {};
|
|
2206
|
+
const canRecord = source.canRecord === true;
|
|
2207
|
+
let status = "idle";
|
|
2208
|
+
if (!canRecord && !source.recordStarted) status = "unavailable";
|
|
2209
|
+
else if (source.recordStopped) status = "stopped";
|
|
2210
|
+
else if (source.recordStarted && source.recordPaused) status = "paused";
|
|
2211
|
+
else if (source.recordStarted) status = "recording";
|
|
2212
|
+
return {
|
|
2213
|
+
status,
|
|
2214
|
+
active: status === "recording",
|
|
2215
|
+
canRecord,
|
|
2216
|
+
mediaOptions: source.recordingMediaOptions || "video",
|
|
2217
|
+
elapsedSeconds: Number(source.recordElapsedTime) || 0
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2220
|
+
async function startRoomRecording({
|
|
2221
|
+
parameters
|
|
2222
|
+
}) {
|
|
2223
|
+
try {
|
|
2224
|
+
const live = getCurrentParams({ parameters });
|
|
2225
|
+
if (live.canRecord !== true) {
|
|
2226
|
+
return { ok: false, error: "Recording is not available in this room." };
|
|
2227
|
+
}
|
|
2228
|
+
if (live.recordStarted && !live.recordStopped) {
|
|
2229
|
+
return { ok: false, error: "Recording has already started." };
|
|
2230
|
+
}
|
|
2231
|
+
await confirmRecording({ parameters: live });
|
|
2232
|
+
const refreshed = getCurrentParams({ parameters: live });
|
|
2233
|
+
await startRecording({ parameters: refreshed });
|
|
2234
|
+
return { ok: true, error: "" };
|
|
2235
|
+
} catch (error) {
|
|
2236
|
+
return { ok: false, error: error?.message || "Recording could not be started." };
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
async function pauseRoomRecording({
|
|
2240
|
+
parameters
|
|
2241
|
+
}) {
|
|
2242
|
+
return toggleRecordingPause(parameters, true);
|
|
2243
|
+
}
|
|
2244
|
+
async function resumeRoomRecording({
|
|
2245
|
+
parameters
|
|
2246
|
+
}) {
|
|
2247
|
+
return toggleRecordingPause(parameters, false);
|
|
2248
|
+
}
|
|
2249
|
+
async function toggleRecordingPause(parameters, pause) {
|
|
2250
|
+
try {
|
|
2251
|
+
const live = getCurrentParams({ parameters });
|
|
2252
|
+
const state = getRecordingState({ parameters: live });
|
|
2253
|
+
if (state.status !== (pause ? "recording" : "paused")) {
|
|
2254
|
+
return {
|
|
2255
|
+
ok: false,
|
|
2256
|
+
error: pause ? "There is no active recording to pause." : "There is no paused recording to resume."
|
|
2257
|
+
};
|
|
2258
|
+
}
|
|
2259
|
+
await updateRecording({ parameters: live });
|
|
2260
|
+
return { ok: true, error: "" };
|
|
2261
|
+
} catch (error) {
|
|
2262
|
+
return {
|
|
2263
|
+
ok: false,
|
|
2264
|
+
error: error?.message || "The recording state could not be changed."
|
|
2265
|
+
};
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
async function stopRoomRecording({
|
|
2269
|
+
parameters
|
|
2270
|
+
}) {
|
|
2271
|
+
try {
|
|
2272
|
+
const live = getCurrentParams({ parameters });
|
|
2273
|
+
if (!live.recordStarted || live.recordStopped) {
|
|
2274
|
+
return { ok: false, error: "There is no active recording to stop." };
|
|
2275
|
+
}
|
|
2276
|
+
await stopRecording({ parameters: live });
|
|
2277
|
+
return { ok: true, error: "" };
|
|
2278
|
+
} catch (error) {
|
|
2279
|
+
return { ok: false, error: error?.message || "Recording could not be stopped." };
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
function getWhiteboardState({ parameters }) {
|
|
2283
|
+
const source = parameters || {};
|
|
2284
|
+
return {
|
|
2285
|
+
active: source.whiteboardStarted === true && source.whiteboardEnded !== true,
|
|
2286
|
+
canStart: source.canStartWhiteboard === true,
|
|
2287
|
+
users: Array.isArray(source.whiteboardUsers) ? source.whiteboardUsers : [],
|
|
2288
|
+
limit: Number(source.whiteboardLimit) || 0,
|
|
2289
|
+
canvas: source.canvasWhiteboard || null
|
|
2290
|
+
};
|
|
2291
|
+
}
|
|
2292
|
+
async function startWhiteboard({
|
|
2293
|
+
parameters,
|
|
2294
|
+
users
|
|
2295
|
+
}) {
|
|
2296
|
+
try {
|
|
2297
|
+
const live = getCurrentParams({ parameters });
|
|
2298
|
+
if (live.breakOutRoomStarted && !live.breakOutRoomEnded) {
|
|
2299
|
+
return {
|
|
2300
|
+
ok: false,
|
|
2301
|
+
error: "The whiteboard cannot start while breakout rooms are active."
|
|
2302
|
+
};
|
|
2303
|
+
}
|
|
2304
|
+
const socket = live?.socket;
|
|
2305
|
+
if (!socket || typeof socket.emit !== "function" || !live?.roomName) {
|
|
2306
|
+
return { ok: false, error: "The room connection is not ready." };
|
|
2307
|
+
}
|
|
2308
|
+
const state = getWhiteboardState({ parameters: live });
|
|
2309
|
+
if (!state.active && !state.canStart) {
|
|
2310
|
+
return { ok: false, error: "You are not allowed to start the whiteboard." };
|
|
2311
|
+
}
|
|
2312
|
+
const whiteboardUsers = users ?? state.users;
|
|
2313
|
+
if (state.limit > 0 && whiteboardUsers.length > state.limit) {
|
|
2314
|
+
return {
|
|
2315
|
+
ok: false,
|
|
2316
|
+
error: `The whiteboard allows at most ${state.limit} participants.`
|
|
2317
|
+
};
|
|
2318
|
+
}
|
|
2319
|
+
const event = state.active ? "updateWhiteboard" : "startWhiteboard";
|
|
2320
|
+
const response = await new Promise((resolve) => {
|
|
2321
|
+
socket.emit(event, { whiteboardUsers, roomName: live.roomName }, resolve);
|
|
2322
|
+
});
|
|
2323
|
+
if (!response?.success) {
|
|
2324
|
+
return {
|
|
2325
|
+
ok: false,
|
|
2326
|
+
error: response?.reason || "The whiteboard could not be started."
|
|
2327
|
+
};
|
|
2328
|
+
}
|
|
2329
|
+
live.updateWhiteboardStarted?.(true);
|
|
2330
|
+
live.updateWhiteboardEnded?.(false);
|
|
2331
|
+
live.updateWhiteboardUsers?.(whiteboardUsers);
|
|
2332
|
+
live.updateCanStartWhiteboard?.(false);
|
|
2333
|
+
return { ok: true, error: "" };
|
|
2334
|
+
} catch (error) {
|
|
2335
|
+
return {
|
|
2336
|
+
ok: false,
|
|
2337
|
+
error: error?.message || "The whiteboard could not be started."
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
async function stopWhiteboard({
|
|
2342
|
+
parameters
|
|
2343
|
+
}) {
|
|
2344
|
+
try {
|
|
2345
|
+
const live = getCurrentParams({ parameters });
|
|
2346
|
+
const socket = live?.socket;
|
|
2347
|
+
if (!socket || typeof socket.emit !== "function" || !live?.roomName) {
|
|
2348
|
+
return { ok: false, error: "The room connection is not ready." };
|
|
2349
|
+
}
|
|
2350
|
+
if (!getWhiteboardState({ parameters: live }).active) {
|
|
2351
|
+
return { ok: false, error: "The whiteboard is not running." };
|
|
2352
|
+
}
|
|
2353
|
+
const response = await new Promise((resolve) => {
|
|
2354
|
+
socket.emit("stopWhiteboard", { roomName: live.roomName }, resolve);
|
|
2355
|
+
});
|
|
2356
|
+
if (!response?.success) {
|
|
2357
|
+
return {
|
|
2358
|
+
ok: false,
|
|
2359
|
+
error: response?.reason || "The whiteboard could not be stopped."
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
live.updateWhiteboardStarted?.(false);
|
|
2363
|
+
live.updateWhiteboardEnded?.(true);
|
|
2364
|
+
return { ok: true, error: "" };
|
|
2365
|
+
} catch (error) {
|
|
2366
|
+
return {
|
|
2367
|
+
ok: false,
|
|
2368
|
+
error: error?.message || "The whiteboard could not be stopped."
|
|
2369
|
+
};
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
function getPollState({ parameters }) {
|
|
2373
|
+
const source = parameters || {};
|
|
2374
|
+
const polls = Array.isArray(source.polls) ? source.polls : [];
|
|
2375
|
+
const active = source.poll && source.poll.status === "active" ? source.poll : polls.find((entry) => entry?.status === "active") || null;
|
|
2376
|
+
return { polls, active };
|
|
2377
|
+
}
|
|
2378
|
+
async function createRoomPoll({
|
|
2379
|
+
parameters,
|
|
2380
|
+
question,
|
|
2381
|
+
options,
|
|
2382
|
+
type = "custom"
|
|
2383
|
+
}) {
|
|
2384
|
+
try {
|
|
2385
|
+
const live = getCurrentParams({ parameters });
|
|
2386
|
+
if (!question?.trim()) return { ok: false, error: "The poll needs a question." };
|
|
2387
|
+
if (!Array.isArray(options) || options.length < 2) {
|
|
2388
|
+
return { ok: false, error: "The poll needs at least two options." };
|
|
2389
|
+
}
|
|
2390
|
+
await handleCreatePoll({
|
|
2391
|
+
poll: { question, options, type },
|
|
2392
|
+
socket: live.socket,
|
|
2393
|
+
roomName: live.roomName || "",
|
|
2394
|
+
showAlert: live.showAlert,
|
|
2395
|
+
updateIsPollModalVisible: live.updateIsPollModalVisible || noop
|
|
2396
|
+
});
|
|
2397
|
+
return { ok: true, error: "" };
|
|
2398
|
+
} catch (error) {
|
|
2399
|
+
return { ok: false, error: error?.message || "The poll could not be created." };
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
async function voteInRoomPoll({
|
|
2403
|
+
parameters,
|
|
2404
|
+
pollId,
|
|
2405
|
+
optionIndex
|
|
2406
|
+
}) {
|
|
2407
|
+
try {
|
|
2408
|
+
const live = getCurrentParams({ parameters });
|
|
2409
|
+
await handleVotePoll({
|
|
2410
|
+
pollId,
|
|
2411
|
+
optionIndex,
|
|
2412
|
+
socket: live.socket,
|
|
2413
|
+
showAlert: live.showAlert,
|
|
2414
|
+
member: live.member || "",
|
|
2415
|
+
roomName: live.roomName || "",
|
|
2416
|
+
updateIsPollModalVisible: live.updateIsPollModalVisible || noop
|
|
2417
|
+
});
|
|
2418
|
+
return { ok: true, error: "" };
|
|
2419
|
+
} catch (error) {
|
|
2420
|
+
return { ok: false, error: error?.message || "The vote could not be cast." };
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
async function endRoomPoll({
|
|
2424
|
+
parameters,
|
|
2425
|
+
pollId
|
|
2426
|
+
}) {
|
|
2427
|
+
try {
|
|
2428
|
+
const live = getCurrentParams({ parameters });
|
|
2429
|
+
if (String(live.islevel) !== "2") {
|
|
2430
|
+
return { ok: false, error: "Only the host can end a poll." };
|
|
2431
|
+
}
|
|
2432
|
+
await handleEndPoll({
|
|
2433
|
+
pollId,
|
|
2434
|
+
socket: live.socket,
|
|
2435
|
+
showAlert: live.showAlert,
|
|
2436
|
+
roomName: live.roomName || "",
|
|
2437
|
+
updateIsPollModalVisible: live.updateIsPollModalVisible || noop
|
|
2438
|
+
});
|
|
2439
|
+
return { ok: true, error: "" };
|
|
2440
|
+
} catch (error) {
|
|
2441
|
+
return { ok: false, error: error?.message || "The poll could not be ended." };
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
function getBreakoutState({ parameters }) {
|
|
2445
|
+
const source = parameters || {};
|
|
2446
|
+
return {
|
|
2447
|
+
active: source.breakOutRoomStarted === true && source.breakOutRoomEnded !== true,
|
|
2448
|
+
canStart: source.canStartBreakout === true,
|
|
2449
|
+
rooms: Array.isArray(source.breakoutRooms) ? source.breakoutRooms : [],
|
|
2450
|
+
currentRoom: typeof source.hostNewRoom === "number" ? source.hostNewRoom : -1
|
|
2451
|
+
};
|
|
2452
|
+
}
|
|
2453
|
+
function getRecordingNotice({ parameters }) {
|
|
2454
|
+
const source = parameters || {};
|
|
2455
|
+
const isAudio = source.recordingMediaOptions === "audio";
|
|
2456
|
+
const pauseLimit = Number(
|
|
2457
|
+
isAudio ? source.recordingAudioPausesLimit : source.recordingVideoPausesLimit
|
|
2458
|
+
) || 0;
|
|
2459
|
+
const pausesUsed = Number(source.pauseRecordCount) || 0;
|
|
2460
|
+
return {
|
|
2461
|
+
message: source.recordingNotice || "",
|
|
2462
|
+
elapsed: source.recordingProgressTime || "00:00:00",
|
|
2463
|
+
elapsedSeconds: Number(source.recordElapsedTime) || 0,
|
|
2464
|
+
canPauseResume: source.canPauseResume === true,
|
|
2465
|
+
pausesUsed,
|
|
2466
|
+
pauseLimit,
|
|
2467
|
+
pauseLimitReached: pauseLimit > 0 && pausesUsed >= pauseLimit
|
|
2468
|
+
};
|
|
2469
|
+
}
|
|
2470
|
+
function getRecordingCapabilities({
|
|
2471
|
+
parameters
|
|
2472
|
+
}) {
|
|
2473
|
+
const source = parameters || {};
|
|
2474
|
+
return {
|
|
2475
|
+
audio: source.recordingAudioSupport === true,
|
|
2476
|
+
video: source.recordingVideoSupport === true,
|
|
2477
|
+
allParticipants: source.recordingAllParticipantsSupport === true,
|
|
2478
|
+
videoParticipants: source.recordingVideoParticipantsSupport === true,
|
|
2479
|
+
hls: source.recordingAddHLS === true,
|
|
2480
|
+
audioPeopleLimit: Number(source.recordingAudioPeopleLimit) || 0,
|
|
2481
|
+
videoPeopleLimit: Number(source.recordingVideoPeopleLimit) || 0
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
function getTranslationState({ parameters }) {
|
|
2485
|
+
const source = parameters || {};
|
|
2486
|
+
const preferences = source.listenerTranslationPreferences || {};
|
|
2487
|
+
const perSpeakerMap = preferences.perSpeaker;
|
|
2488
|
+
const perSpeaker = perSpeakerMap instanceof Map ? Array.from(perSpeakerMap.values()) : Array.isArray(perSpeakerMap) ? perSpeakerMap : [];
|
|
2489
|
+
const speakerStates = source.speakerTranslationStates;
|
|
2490
|
+
const languages = /* @__PURE__ */ new Set();
|
|
2491
|
+
const collect2 = (value) => {
|
|
2492
|
+
if (value?.language) languages.add(value.language);
|
|
2493
|
+
};
|
|
2494
|
+
if (speakerStates instanceof Map) speakerStates.forEach(collect2);
|
|
2495
|
+
else if (Array.isArray(speakerStates)) speakerStates.forEach(collect2);
|
|
2496
|
+
perSpeaker.forEach(collect2);
|
|
2497
|
+
if (preferences.globalLanguage) languages.add(preferences.globalLanguage);
|
|
2498
|
+
return {
|
|
2499
|
+
globalLanguage: preferences.globalLanguage ?? null,
|
|
2500
|
+
perSpeaker,
|
|
2501
|
+
active: Boolean(
|
|
2502
|
+
preferences.globalLanguage || perSpeaker.some((entry) => entry?.language && !entry.wantOriginal)
|
|
2503
|
+
),
|
|
2504
|
+
availableLanguages: Array.from(languages)
|
|
2505
|
+
};
|
|
2506
|
+
}
|
|
2507
|
+
function setTranslationPreference({
|
|
2508
|
+
parameters,
|
|
2509
|
+
language = null,
|
|
2510
|
+
speakerId,
|
|
2511
|
+
wantOriginal = false
|
|
2512
|
+
}) {
|
|
2513
|
+
const source = parameters || {};
|
|
2514
|
+
const update = source.updateListenerTranslationPreferences;
|
|
2515
|
+
if (typeof update !== "function") {
|
|
2516
|
+
return { ok: false, error: "Translation is not available in this room." };
|
|
2517
|
+
}
|
|
2518
|
+
try {
|
|
2519
|
+
const current = source.listenerTranslationPreferences || {};
|
|
2520
|
+
const perSpeaker = current.perSpeaker instanceof Map ? new Map(current.perSpeaker) : /* @__PURE__ */ new Map();
|
|
2521
|
+
if (speakerId) {
|
|
2522
|
+
perSpeaker.set(speakerId, { speakerId, language, wantOriginal });
|
|
2523
|
+
update({ perSpeaker, globalLanguage: current.globalLanguage ?? null });
|
|
2524
|
+
} else {
|
|
2525
|
+
update({ perSpeaker, globalLanguage: language });
|
|
2526
|
+
}
|
|
2527
|
+
return { ok: true, error: "" };
|
|
2528
|
+
} catch (error) {
|
|
2529
|
+
return { ok: false, error: error?.message || "The translation preference could not be set." };
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
function getFocusModeState({ parameters }) {
|
|
2533
|
+
const source = parameters || {};
|
|
2534
|
+
const panelists = Array.isArray(source.panelists) ? source.panelists : [];
|
|
2535
|
+
return {
|
|
2536
|
+
active: source.panelistsFocused === true,
|
|
2537
|
+
panelists,
|
|
2538
|
+
selfIsPanelist: panelists.some((entry) => entry?.name === source.member),
|
|
2539
|
+
mutesMicrophones: source.muteOthersMic === true,
|
|
2540
|
+
mutesCameras: source.muteOthersCamera === true
|
|
2541
|
+
};
|
|
2542
|
+
}
|
|
2543
|
+
function getVirtualBackgroundState({
|
|
2544
|
+
parameters
|
|
2545
|
+
}) {
|
|
2546
|
+
const source = parameters || {};
|
|
2547
|
+
const stream = source.virtualStream || source.processedStream;
|
|
2548
|
+
return {
|
|
2549
|
+
active: source.keepBackground === true && Boolean(stream),
|
|
2550
|
+
stream: stream || null,
|
|
2551
|
+
appliedBackground: source.appliedBackground ?? null,
|
|
2552
|
+
selectedImage: source.selectedImage ?? null
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
const LOCALLY_PAUSED = /* @__PURE__ */ new Set();
|
|
2556
|
+
async function setParticipantPlayback({
|
|
2557
|
+
parameters,
|
|
2558
|
+
name = "",
|
|
2559
|
+
producerId = "",
|
|
2560
|
+
kind = "all",
|
|
2561
|
+
paused
|
|
2562
|
+
}) {
|
|
2563
|
+
try {
|
|
2564
|
+
const source = parameters || {};
|
|
2565
|
+
const participants = Array.isArray(source.participants) ? source.participants : [];
|
|
2566
|
+
const participant = name ? participants.find((part) => part?.name === name) : void 0;
|
|
2567
|
+
const targets = /* @__PURE__ */ new Set();
|
|
2568
|
+
if (producerId) targets.add(producerId);
|
|
2569
|
+
const usable = (value) => typeof value === "string" && value.length > 3 && value.toLowerCase() !== "none";
|
|
2570
|
+
if (participant) {
|
|
2571
|
+
if (kind !== "video" && usable(participant.audioID)) targets.add(participant.audioID);
|
|
2572
|
+
if (kind !== "audio" && usable(participant.videoID)) targets.add(participant.videoID);
|
|
2573
|
+
}
|
|
2574
|
+
if (targets.size === 0) {
|
|
2575
|
+
return { ok: false, error: "That participant is not publishing anything to pause.", affected: 0 };
|
|
2576
|
+
}
|
|
2577
|
+
const transports = Array.isArray(source.consumerTransports) ? source.consumerTransports : [];
|
|
2578
|
+
let affected = 0;
|
|
2579
|
+
for (const entry of transports) {
|
|
2580
|
+
const consumer = entry?.consumer;
|
|
2581
|
+
const id = entry?.producerId || consumer?.producerId;
|
|
2582
|
+
if (!consumer || !targets.has(id)) continue;
|
|
2583
|
+
if (kind !== "all" && consumer.track?.kind !== kind) continue;
|
|
2584
|
+
try {
|
|
2585
|
+
if (paused && typeof consumer.pause === "function") {
|
|
2586
|
+
await consumer.pause();
|
|
2587
|
+
LOCALLY_PAUSED.add(id);
|
|
2588
|
+
affected += 1;
|
|
2589
|
+
} else if (!paused && typeof consumer.resume === "function") {
|
|
2590
|
+
await consumer.resume();
|
|
2591
|
+
LOCALLY_PAUSED.delete(id);
|
|
2592
|
+
affected += 1;
|
|
2593
|
+
}
|
|
2594
|
+
} catch {
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
return affected > 0 ? { ok: true, error: "", affected } : { ok: false, error: "No matching incoming stream was found.", affected: 0 };
|
|
2598
|
+
} catch (error) {
|
|
2599
|
+
return { ok: false, error: error?.message || "The playback change failed.", affected: 0 };
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
async function setBreakoutRooms({
|
|
2603
|
+
parameters,
|
|
2604
|
+
rooms,
|
|
2605
|
+
newParticipantAction
|
|
2606
|
+
}) {
|
|
2607
|
+
try {
|
|
2608
|
+
const source = parameters || {};
|
|
2609
|
+
const socket = source.socket;
|
|
2610
|
+
if (!socket || typeof socket.emit !== "function" || !source.roomName) {
|
|
2611
|
+
return { ok: false, error: "The room connection is not ready." };
|
|
2612
|
+
}
|
|
2613
|
+
if (String(source.islevel) !== "2") {
|
|
2614
|
+
return { ok: false, error: "Only the host can change breakout rooms." };
|
|
2615
|
+
}
|
|
2616
|
+
const running = source.breakOutRoomStarted === true && source.breakOutRoomEnded !== true;
|
|
2617
|
+
const event = running ? "updateBreakout" : "startBreakout";
|
|
2618
|
+
const payload = (Array.isArray(rooms) ? rooms : []).map(
|
|
2619
|
+
(room) => (Array.isArray(room) ? room : []).map(({ name, breakRoom }) => ({ name, breakRoom }))
|
|
2620
|
+
);
|
|
2621
|
+
const response = await new Promise((resolve) => {
|
|
2622
|
+
socket.emit(
|
|
2623
|
+
event,
|
|
2624
|
+
{
|
|
2625
|
+
breakoutRooms: payload,
|
|
2626
|
+
newParticipantAction: newParticipantAction || source.newParticipantAction || "autoAssignNewRoom",
|
|
2627
|
+
roomName: source.roomName
|
|
2628
|
+
},
|
|
2629
|
+
resolve
|
|
2630
|
+
);
|
|
2631
|
+
});
|
|
2632
|
+
if (!response?.success) {
|
|
2633
|
+
return { ok: false, error: response?.reason || "The breakout rooms could not be updated." };
|
|
2634
|
+
}
|
|
2635
|
+
source.updateBreakoutRooms?.(payload);
|
|
2636
|
+
source.updateBreakOutRoomStarted?.(true);
|
|
2637
|
+
source.updateBreakOutRoomEnded?.(false);
|
|
2638
|
+
return { ok: true, error: "" };
|
|
2639
|
+
} catch (error) {
|
|
2640
|
+
return { ok: false, error: error?.message || "The breakout rooms could not be updated." };
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
async function assignParticipantToBreakoutRoom({
|
|
2644
|
+
parameters,
|
|
2645
|
+
name,
|
|
2646
|
+
room,
|
|
2647
|
+
newParticipantAction
|
|
2648
|
+
}) {
|
|
2649
|
+
const source = parameters || {};
|
|
2650
|
+
if (!name) return { ok: false, error: "A participant name is required." };
|
|
2651
|
+
const current = Array.isArray(source.breakoutRooms) ? source.breakoutRooms.map((entry) => Array.isArray(entry) ? [...entry] : []) : [];
|
|
2652
|
+
const next = current.map((entry) => entry.filter((person) => person?.name !== name));
|
|
2653
|
+
if (room !== null && room !== void 0) {
|
|
2654
|
+
if (!Number.isInteger(room) || room < 0) {
|
|
2655
|
+
return { ok: false, error: "The destination room must be a room index." };
|
|
2656
|
+
}
|
|
2657
|
+
while (next.length <= room) next.push([]);
|
|
2658
|
+
next[room].push({ name, breakRoom: room });
|
|
2659
|
+
}
|
|
2660
|
+
return setBreakoutRooms({ parameters: source, rooms: next, newParticipantAction });
|
|
2661
|
+
}
|
|
2662
|
+
async function stopBreakoutRooms({
|
|
2663
|
+
parameters
|
|
2664
|
+
}) {
|
|
2665
|
+
try {
|
|
2666
|
+
const source = parameters || {};
|
|
2667
|
+
const socket = source.socket;
|
|
2668
|
+
if (!socket || typeof socket.emit !== "function" || !source.roomName) {
|
|
2669
|
+
return { ok: false, error: "The room connection is not ready." };
|
|
2670
|
+
}
|
|
2671
|
+
if (String(source.islevel) !== "2") {
|
|
2672
|
+
return { ok: false, error: "Only the host can stop breakout rooms." };
|
|
2673
|
+
}
|
|
2674
|
+
const response = await new Promise((resolve) => {
|
|
2675
|
+
socket.emit("stopBreakout", { roomName: source.roomName }, resolve);
|
|
2676
|
+
});
|
|
2677
|
+
if (!response?.success) {
|
|
2678
|
+
return { ok: false, error: response?.reason || "The breakout rooms could not be stopped." };
|
|
2679
|
+
}
|
|
2680
|
+
source.updateBreakOutRoomStarted?.(false);
|
|
2681
|
+
source.updateBreakOutRoomEnded?.(true);
|
|
2682
|
+
return { ok: true, error: "" };
|
|
2683
|
+
} catch (error) {
|
|
2684
|
+
return { ok: false, error: error?.message || "The breakout rooms could not be stopped." };
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
async function reapplyLocalPlayback({
|
|
2688
|
+
parameters
|
|
2689
|
+
}) {
|
|
2690
|
+
if (LOCALLY_PAUSED.size === 0) return { ok: true, error: "", affected: 0 };
|
|
2691
|
+
try {
|
|
2692
|
+
const source = parameters || {};
|
|
2693
|
+
const transports = Array.isArray(source.consumerTransports) ? source.consumerTransports : [];
|
|
2694
|
+
let affected = 0;
|
|
2695
|
+
for (const entry of transports) {
|
|
2696
|
+
const consumer = entry?.consumer;
|
|
2697
|
+
const id = entry?.producerId || consumer?.producerId;
|
|
2698
|
+
if (!consumer || !LOCALLY_PAUSED.has(id)) continue;
|
|
2699
|
+
if (consumer.paused === true) continue;
|
|
2700
|
+
try {
|
|
2701
|
+
if (typeof consumer.pause === "function") {
|
|
2702
|
+
await consumer.pause();
|
|
2703
|
+
affected += 1;
|
|
2704
|
+
}
|
|
2705
|
+
} catch {
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
return { ok: true, error: "", affected };
|
|
2709
|
+
} catch (error) {
|
|
2710
|
+
return { ok: false, error: error?.message || "Playback could not be re-applied.", affected: 0 };
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
function getLocallyPausedProducerIds() {
|
|
2714
|
+
return Array.from(LOCALLY_PAUSED);
|
|
2715
|
+
}
|
|
2716
|
+
async function invokeChecked(live, run) {
|
|
2717
|
+
const alertBefore = live?.alertMessage || "";
|
|
2718
|
+
try {
|
|
2719
|
+
await run();
|
|
2720
|
+
} catch (error) {
|
|
2721
|
+
return { ok: false, error: error?.message || "The device switch failed." };
|
|
2722
|
+
}
|
|
2723
|
+
const settled = getCurrentParams({ parameters: live });
|
|
2724
|
+
const alertAfter = settled?.alertMessage || "";
|
|
2725
|
+
const alertType = settled?.alertType;
|
|
2726
|
+
if (alertAfter && alertAfter !== alertBefore && (alertType === "danger" || alertType === "warning")) {
|
|
2727
|
+
return { ok: false, error: alertAfter };
|
|
2728
|
+
}
|
|
2729
|
+
return { ok: true, error: "" };
|
|
2730
|
+
}
|
|
2731
|
+
async function switchCamera({
|
|
2732
|
+
parameters,
|
|
2733
|
+
deviceId
|
|
2734
|
+
}) {
|
|
2735
|
+
if (!deviceId) return { ok: false, error: "A camera deviceId is required." };
|
|
2736
|
+
const live = getCurrentParams({ parameters });
|
|
2737
|
+
return invokeChecked(live, () => switchVideo({ videoPreference: deviceId, parameters: live }));
|
|
2738
|
+
}
|
|
2739
|
+
async function flipCamera({ parameters }) {
|
|
2740
|
+
const live = getCurrentParams({ parameters });
|
|
2741
|
+
return invokeChecked(live, () => switchVideoAlt({ parameters: live }));
|
|
2742
|
+
}
|
|
2743
|
+
async function switchMicrophone({
|
|
2744
|
+
parameters,
|
|
2745
|
+
deviceId
|
|
2746
|
+
}) {
|
|
2747
|
+
if (!deviceId) return { ok: false, error: "A microphone deviceId is required." };
|
|
2748
|
+
const live = getCurrentParams({ parameters });
|
|
2749
|
+
return invokeChecked(live, () => switchAudio({ audioPreference: deviceId, parameters: live }));
|
|
2750
|
+
}
|
|
2751
|
+
async function setRoomMediaPolicy({
|
|
2752
|
+
parameters,
|
|
2753
|
+
audio,
|
|
2754
|
+
video,
|
|
2755
|
+
screenshare,
|
|
2756
|
+
chat
|
|
2757
|
+
}) {
|
|
2758
|
+
const live = getCurrentParams({ parameters });
|
|
2759
|
+
if (String(live.islevel) !== "2") {
|
|
2760
|
+
return { ok: false, error: "Only the host can change room settings." };
|
|
2761
|
+
}
|
|
2762
|
+
if (!live.socket) {
|
|
2763
|
+
return { ok: false, error: "The room connection is not ready yet." };
|
|
2764
|
+
}
|
|
2765
|
+
try {
|
|
2766
|
+
await modifySettings({
|
|
2767
|
+
roomName: live.roomName || "",
|
|
2768
|
+
// The SDK requires all four on every call, so unspecified values are
|
|
2769
|
+
// filled from current state — otherwise changing one would blank the rest.
|
|
2770
|
+
audioSet: audio || live.audioSetting || "allow",
|
|
2771
|
+
videoSet: video || live.videoSetting || "allow",
|
|
2772
|
+
screenshareSet: screenshare || live.screenshareSetting || "allow",
|
|
2773
|
+
chatSet: chat || live.chatSetting || "allow",
|
|
2774
|
+
socket: live.socket,
|
|
2775
|
+
showAlert: live.showAlert,
|
|
2776
|
+
updateAudioSetting: live.updateAudioSetting,
|
|
2777
|
+
updateVideoSetting: live.updateVideoSetting,
|
|
2778
|
+
updateScreenshareSetting: live.updateScreenshareSetting,
|
|
2779
|
+
updateChatSetting: live.updateChatSetting,
|
|
2780
|
+
updateIsSettingsModalVisible: live.updateIsSettingsModalVisible || (() => {
|
|
2781
|
+
})
|
|
2782
|
+
});
|
|
2783
|
+
return { ok: true, error: "" };
|
|
2784
|
+
} catch (error) {
|
|
2785
|
+
return { ok: false, error: error?.message || "The room settings could not be updated." };
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
function getChatMessages({
|
|
2789
|
+
parameters,
|
|
2790
|
+
scope = "all",
|
|
2791
|
+
withPerson = ""
|
|
2792
|
+
}) {
|
|
2793
|
+
const source = parameters || {};
|
|
2794
|
+
const raw = Array.isArray(source.messages) ? source.messages : [];
|
|
2795
|
+
const me = source.member || "";
|
|
2796
|
+
return raw.map((entry) => {
|
|
2797
|
+
const receivers = Array.isArray(entry?.receivers) ? entry.receivers : [];
|
|
2798
|
+
return {
|
|
2799
|
+
sender: entry?.sender || "",
|
|
2800
|
+
message: entry?.message || "",
|
|
2801
|
+
timestamp: entry?.timestamp || "",
|
|
2802
|
+
receivers,
|
|
2803
|
+
// MediaSFU marks group messages with an empty receivers list; anything
|
|
2804
|
+
// addressed is a DM.
|
|
2805
|
+
direct: receivers.length > 0,
|
|
2806
|
+
mine: entry?.sender === me
|
|
2807
|
+
};
|
|
2808
|
+
}).filter((message) => {
|
|
2809
|
+
if (scope === "group" && message.direct) return false;
|
|
2810
|
+
if (scope === "direct" && !message.direct) return false;
|
|
2811
|
+
if (withPerson) {
|
|
2812
|
+
return message.sender === withPerson || message.receivers.includes(withPerson);
|
|
2813
|
+
}
|
|
2814
|
+
return true;
|
|
2815
|
+
});
|
|
2816
|
+
}
|
|
2817
|
+
function getPendingApprovals({ parameters }) {
|
|
2818
|
+
const source = parameters || {};
|
|
2819
|
+
const waitingRaw = Array.isArray(source.waitingRoomList) ? source.waitingRoomList : [];
|
|
2820
|
+
const requestRaw = Array.isArray(source.requestList) ? source.requestList : [];
|
|
2821
|
+
const waiting = waitingRaw.map((entry) => ({
|
|
2822
|
+
name: entry?.name || "",
|
|
2823
|
+
id: entry?.id || ""
|
|
2824
|
+
}));
|
|
2825
|
+
const requests = requestRaw.map((entry) => ({
|
|
2826
|
+
id: entry?.id || "",
|
|
2827
|
+
name: entry?.name || "",
|
|
2828
|
+
// 'fa-microphone' | 'fa-video' | 'fa-desktop' | 'fa-comments' — what they asked for.
|
|
2829
|
+
icon: entry?.icon || "",
|
|
2830
|
+
username: entry?.username || entry?.name || ""
|
|
2831
|
+
}));
|
|
2832
|
+
return { waiting, requests, total: waiting.length + requests.length };
|
|
2833
|
+
}
|
|
2834
|
+
function getSessionTimer({ parameters }) {
|
|
2835
|
+
const source = parameters || {};
|
|
2836
|
+
return {
|
|
2837
|
+
elapsed: source.meetingProgressTime || "00:00",
|
|
2838
|
+
presenceCheckPending: Boolean(source.isConfirmHereModalVisible)
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
function getPresenceCheck({ parameters }) {
|
|
2842
|
+
const source = parameters || {};
|
|
2843
|
+
return { pending: Boolean(source.isConfirmHereModalVisible) };
|
|
2844
|
+
}
|
|
2845
|
+
function confirmStillHere({ parameters }) {
|
|
2846
|
+
const live = getCurrentParams({ parameters });
|
|
2847
|
+
const update = live.updateIsConfirmHereModalVisible;
|
|
2848
|
+
if (typeof update !== "function") {
|
|
2849
|
+
return { ok: false, error: "The presence check control is unavailable." };
|
|
2850
|
+
}
|
|
2851
|
+
update(false);
|
|
2852
|
+
return { ok: true, error: "" };
|
|
2853
|
+
}
|
|
2854
|
+
function getPlaybackSources({ parameters }) {
|
|
2855
|
+
const source = parameters || {};
|
|
2856
|
+
const sources = [];
|
|
2857
|
+
const push = (protocol, url) => {
|
|
2858
|
+
if (typeof url === "string" && /^https:\/\//i.test(url)) sources.push({ protocol, url });
|
|
2859
|
+
};
|
|
2860
|
+
push("hls", source.hlsUrl || source.hlsPlaybackUrl || source.playbackUrl);
|
|
2861
|
+
push("whep", source.whepUrl || source.whepPlaybackUrl);
|
|
2862
|
+
return sources;
|
|
2863
|
+
}
|
|
2864
|
+
function inferProtocol(url, explicit) {
|
|
2865
|
+
if (explicit) return explicit;
|
|
2866
|
+
return /\.m3u8(\?|$)/i.test(url) ? "hls" : "whep";
|
|
2867
|
+
}
|
|
2868
|
+
function canPlayHlsNatively(video) {
|
|
2869
|
+
const claimsSupport = typeof video.canPlayType === "function" && video.canPlayType("application/vnd.apple.mpegurl") !== "";
|
|
2870
|
+
const hasMse = typeof MediaSource !== "undefined" || typeof globalThis.ManagedMediaSource !== "undefined";
|
|
2871
|
+
return claimsSupport && !hasMse;
|
|
2872
|
+
}
|
|
2873
|
+
async function attachHls(url, video, hlsFactory) {
|
|
2874
|
+
if (!video) throw new Error("HLS playback needs a <video> element.");
|
|
2875
|
+
if (typeof hlsFactory !== "function" && canPlayHlsNatively(video)) {
|
|
2876
|
+
video.src = url;
|
|
2877
|
+
const play = video.play?.();
|
|
2878
|
+
play?.catch?.(() => {
|
|
2879
|
+
});
|
|
2880
|
+
return {
|
|
2881
|
+
protocol: "hls",
|
|
2882
|
+
url,
|
|
2883
|
+
stream: null,
|
|
2884
|
+
detach: () => {
|
|
2885
|
+
video.removeAttribute("src");
|
|
2886
|
+
video.load?.();
|
|
2887
|
+
}
|
|
2888
|
+
};
|
|
2889
|
+
}
|
|
2890
|
+
if (typeof hlsFactory !== "function") {
|
|
2891
|
+
throw new Error(
|
|
2892
|
+
"HLS needs an hlsFactory on this browser. Pass () => new Hls(...) from hls.js; it is not bundled with the SDK. Only iOS Safari, which has no Media Source Extensions, plays HLS without one — Chrome reports that it can and then plays nothing."
|
|
2893
|
+
);
|
|
2894
|
+
}
|
|
2895
|
+
const hls = hlsFactory();
|
|
2896
|
+
hls.loadSource(url);
|
|
2897
|
+
hls.attachMedia(video);
|
|
2898
|
+
return {
|
|
2899
|
+
protocol: "hls",
|
|
2900
|
+
url,
|
|
2901
|
+
stream: null,
|
|
2902
|
+
detach: () => {
|
|
2903
|
+
try {
|
|
2904
|
+
hls.destroy();
|
|
2905
|
+
} catch {
|
|
2906
|
+
}
|
|
2907
|
+
video.removeAttribute("src");
|
|
2908
|
+
}
|
|
2909
|
+
};
|
|
2910
|
+
}
|
|
2911
|
+
async function attachWhep(url, video, headers = {}, iceServers) {
|
|
2912
|
+
if (typeof RTCPeerConnection === "undefined") {
|
|
2913
|
+
throw new Error("WHEP playback needs WebRTC support.");
|
|
2914
|
+
}
|
|
2915
|
+
const pc = new RTCPeerConnection(iceServers?.length ? { iceServers } : void 0);
|
|
2916
|
+
const stream = new MediaStream();
|
|
2917
|
+
pc.addTransceiver("video", { direction: "recvonly" });
|
|
2918
|
+
pc.addTransceiver("audio", { direction: "recvonly" });
|
|
2919
|
+
pc.ontrack = (event) => {
|
|
2920
|
+
if (event.track) stream.addTrack(event.track);
|
|
2921
|
+
if (video && video.srcObject !== stream) {
|
|
2922
|
+
video.srcObject = stream;
|
|
2923
|
+
const play = video.play?.();
|
|
2924
|
+
play?.catch?.(() => {
|
|
2925
|
+
});
|
|
2926
|
+
}
|
|
2927
|
+
};
|
|
2928
|
+
let resourceUrl = "";
|
|
2929
|
+
try {
|
|
2930
|
+
const offer = await pc.createOffer();
|
|
2931
|
+
await pc.setLocalDescription(offer);
|
|
2932
|
+
const response = await fetch(url, {
|
|
2933
|
+
method: "POST",
|
|
2934
|
+
headers: { "Content-Type": "application/sdp", ...headers },
|
|
2935
|
+
body: offer.sdp || ""
|
|
2936
|
+
});
|
|
2937
|
+
if (!response.ok) {
|
|
2938
|
+
throw new Error(`The WHEP endpoint refused the request (${response.status}).`);
|
|
2939
|
+
}
|
|
2940
|
+
const location = response.headers.get("Location") || "";
|
|
2941
|
+
resourceUrl = location ? new URL(location, url).toString() : "";
|
|
2942
|
+
const answer = await response.text();
|
|
2943
|
+
await pc.setRemoteDescription({ type: "answer", sdp: answer });
|
|
2944
|
+
} catch (error) {
|
|
2945
|
+
pc.close();
|
|
2946
|
+
throw error;
|
|
2947
|
+
}
|
|
2948
|
+
return {
|
|
2949
|
+
protocol: "whep",
|
|
2950
|
+
url,
|
|
2951
|
+
stream,
|
|
2952
|
+
detach: () => {
|
|
2953
|
+
if (resourceUrl) {
|
|
2954
|
+
try {
|
|
2955
|
+
void fetch(resourceUrl, { method: "DELETE", headers });
|
|
2956
|
+
} catch {
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
try {
|
|
2960
|
+
pc.close();
|
|
2961
|
+
} catch {
|
|
2962
|
+
}
|
|
2963
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
2964
|
+
if (video && video.srcObject === stream) video.srcObject = null;
|
|
2965
|
+
}
|
|
2966
|
+
};
|
|
2967
|
+
}
|
|
2968
|
+
async function attachPlayback({
|
|
2969
|
+
source,
|
|
2970
|
+
video,
|
|
2971
|
+
protocol,
|
|
2972
|
+
hlsFactory,
|
|
2973
|
+
headers,
|
|
2974
|
+
iceServers
|
|
2975
|
+
}) {
|
|
2976
|
+
const url = typeof source === "string" ? source : source?.url || "";
|
|
2977
|
+
if (!url) throw new Error("A playback URL is required.");
|
|
2978
|
+
const resolved = typeof source === "string" ? inferProtocol(url, protocol) : protocol || source.protocol || inferProtocol(url);
|
|
2979
|
+
return resolved === "hls" ? attachHls(url, video, hlsFactory) : attachWhep(url, video, headers, iceServers);
|
|
2980
|
+
}
|
|
2981
|
+
function detachPlayback(handle) {
|
|
2982
|
+
if (!handle || typeof handle.detach !== "function") return;
|
|
2983
|
+
try {
|
|
2984
|
+
handle.detach();
|
|
2985
|
+
} catch {
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
async function publishWhip({
|
|
2989
|
+
url,
|
|
2990
|
+
stream,
|
|
2991
|
+
headers = {},
|
|
2992
|
+
iceServers
|
|
2993
|
+
}) {
|
|
2994
|
+
if (typeof RTCPeerConnection === "undefined") {
|
|
2995
|
+
throw new Error("WHIP publishing needs WebRTC support.");
|
|
2996
|
+
}
|
|
2997
|
+
if (!stream?.getTracks?.().length) throw new Error("A stream with at least one track is required.");
|
|
2998
|
+
const pc = new RTCPeerConnection(iceServers?.length ? { iceServers } : void 0);
|
|
2999
|
+
stream.getTracks().forEach((track) => pc.addTrack(track, stream));
|
|
3000
|
+
let resourceUrl = "";
|
|
3001
|
+
try {
|
|
3002
|
+
const offer = await pc.createOffer();
|
|
3003
|
+
await pc.setLocalDescription(offer);
|
|
3004
|
+
const response = await fetch(url, {
|
|
3005
|
+
method: "POST",
|
|
3006
|
+
headers: { "Content-Type": "application/sdp", ...headers },
|
|
3007
|
+
body: offer.sdp || ""
|
|
3008
|
+
});
|
|
3009
|
+
if (!response.ok) throw new Error(`The WHIP endpoint refused the request (${response.status}).`);
|
|
3010
|
+
const location = response.headers.get("Location") || "";
|
|
3011
|
+
resourceUrl = location ? new URL(location, url).toString() : "";
|
|
3012
|
+
await pc.setRemoteDescription({ type: "answer", sdp: await response.text() });
|
|
3013
|
+
} catch (error) {
|
|
3014
|
+
pc.close();
|
|
3015
|
+
throw error;
|
|
3016
|
+
}
|
|
3017
|
+
return {
|
|
3018
|
+
protocol: "whep",
|
|
3019
|
+
url,
|
|
3020
|
+
stream,
|
|
3021
|
+
detach: () => {
|
|
3022
|
+
if (resourceUrl) {
|
|
3023
|
+
try {
|
|
3024
|
+
void fetch(resourceUrl, { method: "DELETE", headers });
|
|
3025
|
+
} catch {
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
try {
|
|
3029
|
+
pc.close();
|
|
3030
|
+
} catch {
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
};
|
|
3034
|
+
}
|
|
3035
|
+
const MIN_INTERVAL_MS = 1e3;
|
|
3036
|
+
function createViewerSession({
|
|
3037
|
+
provider,
|
|
3038
|
+
roomName,
|
|
3039
|
+
displayName,
|
|
3040
|
+
pollIntervalMs = 5e3,
|
|
3041
|
+
heartbeatIntervalMs = 3e4,
|
|
3042
|
+
onChange
|
|
3043
|
+
}) {
|
|
3044
|
+
let snapshot = {
|
|
3045
|
+
phase: "idle",
|
|
3046
|
+
session: null,
|
|
3047
|
+
status: null,
|
|
3048
|
+
error: "",
|
|
3049
|
+
canRequestPromotion: typeof provider?.requestPromotion === "function"
|
|
3050
|
+
};
|
|
3051
|
+
let pollTimer = null;
|
|
3052
|
+
let heartbeatTimer = null;
|
|
3053
|
+
let stopped = false;
|
|
3054
|
+
const emit = (next) => {
|
|
3055
|
+
snapshot = { ...snapshot, ...next };
|
|
3056
|
+
try {
|
|
3057
|
+
onChange?.(snapshot);
|
|
3058
|
+
} catch {
|
|
3059
|
+
}
|
|
3060
|
+
};
|
|
3061
|
+
const clearTimers = () => {
|
|
3062
|
+
if (pollTimer) {
|
|
3063
|
+
clearInterval(pollTimer);
|
|
3064
|
+
pollTimer = null;
|
|
3065
|
+
}
|
|
3066
|
+
if (heartbeatTimer) {
|
|
3067
|
+
clearInterval(heartbeatTimer);
|
|
3068
|
+
heartbeatTimer = null;
|
|
3069
|
+
}
|
|
3070
|
+
};
|
|
3071
|
+
const startTimers = () => {
|
|
3072
|
+
clearTimers();
|
|
3073
|
+
if (typeof provider.poll === "function") {
|
|
3074
|
+
pollTimer = setInterval(async () => {
|
|
3075
|
+
if (stopped || !snapshot.session) return;
|
|
3076
|
+
try {
|
|
3077
|
+
const status = await provider.poll({ session: snapshot.session });
|
|
3078
|
+
if (stopped) return;
|
|
3079
|
+
const session = status?.playbackUrl ? { ...snapshot.session, playbackUrl: status.playbackUrl } : snapshot.session;
|
|
3080
|
+
emit({
|
|
3081
|
+
status,
|
|
3082
|
+
session,
|
|
3083
|
+
phase: status?.approved ? "approved" : snapshot.phase === "requested" ? "requested" : "watching"
|
|
3084
|
+
});
|
|
3085
|
+
if (status?.approved) clearTimers();
|
|
3086
|
+
} catch {
|
|
3087
|
+
}
|
|
3088
|
+
}, Math.max(MIN_INTERVAL_MS, pollIntervalMs));
|
|
3089
|
+
}
|
|
3090
|
+
if (typeof provider.heartbeat === "function") {
|
|
3091
|
+
heartbeatTimer = setInterval(() => {
|
|
3092
|
+
if (stopped || !snapshot.session) return;
|
|
3093
|
+
Promise.resolve(provider.heartbeat({ session: snapshot.session })).catch(() => {
|
|
3094
|
+
});
|
|
3095
|
+
}, Math.max(MIN_INTERVAL_MS, heartbeatIntervalMs));
|
|
3096
|
+
}
|
|
3097
|
+
};
|
|
3098
|
+
return {
|
|
3099
|
+
getSnapshot: () => snapshot,
|
|
3100
|
+
async start() {
|
|
3101
|
+
if (snapshot.phase !== "idle" && snapshot.phase !== "left" && snapshot.phase !== "error") {
|
|
3102
|
+
return snapshot;
|
|
3103
|
+
}
|
|
3104
|
+
stopped = false;
|
|
3105
|
+
emit({ phase: "joining", error: "" });
|
|
3106
|
+
try {
|
|
3107
|
+
const session = await provider.join({ roomName, displayName });
|
|
3108
|
+
if (stopped) return snapshot;
|
|
3109
|
+
if (!session?.viewerId) throw new Error("The viewer session provider returned no viewerId.");
|
|
3110
|
+
emit({ phase: "watching", session, error: "" });
|
|
3111
|
+
startTimers();
|
|
3112
|
+
} catch (error) {
|
|
3113
|
+
emit({ phase: "error", error: error?.message || "The viewer session could not start." });
|
|
3114
|
+
}
|
|
3115
|
+
return snapshot;
|
|
3116
|
+
},
|
|
3117
|
+
async requestPromotion() {
|
|
3118
|
+
if (!snapshot.session) {
|
|
3119
|
+
emit({ error: "Start the viewer session before requesting the floor." });
|
|
3120
|
+
return snapshot;
|
|
3121
|
+
}
|
|
3122
|
+
if (typeof provider.requestPromotion !== "function") {
|
|
3123
|
+
emit({ error: "This viewer session provider does not support promotion." });
|
|
3124
|
+
return snapshot;
|
|
3125
|
+
}
|
|
3126
|
+
try {
|
|
3127
|
+
await provider.requestPromotion({ session: snapshot.session });
|
|
3128
|
+
emit({ phase: "requested", error: "" });
|
|
3129
|
+
} catch (error) {
|
|
3130
|
+
emit({ error: error?.message || "The request could not be sent." });
|
|
3131
|
+
}
|
|
3132
|
+
return snapshot;
|
|
3133
|
+
},
|
|
3134
|
+
async stop() {
|
|
3135
|
+
stopped = true;
|
|
3136
|
+
clearTimers();
|
|
3137
|
+
const session = snapshot.session;
|
|
3138
|
+
emit({ phase: "left" });
|
|
3139
|
+
if (session && typeof provider.leave === "function") {
|
|
3140
|
+
try {
|
|
3141
|
+
await provider.leave({ session });
|
|
3142
|
+
} catch {
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
};
|
|
3147
|
+
}
|
|
3148
|
+
function hasLiveTrack(stream, kind) {
|
|
3149
|
+
if (!stream || typeof stream.getTracks !== "function") return false;
|
|
3150
|
+
try {
|
|
3151
|
+
return stream.getTracks().some((track) => track.kind === kind && track.readyState === "live");
|
|
3152
|
+
} catch {
|
|
3153
|
+
return false;
|
|
3154
|
+
}
|
|
3155
|
+
}
|
|
3156
|
+
function capOf(value) {
|
|
3157
|
+
if (typeof value === "number") return value;
|
|
3158
|
+
if (value && typeof value === "object") {
|
|
3159
|
+
const candidate = value.max ?? value.ideal;
|
|
3160
|
+
if (typeof candidate === "number") return candidate;
|
|
3161
|
+
}
|
|
3162
|
+
return 0;
|
|
3163
|
+
}
|
|
3164
|
+
function getCaptureLimits({ parameters, kind = "video" }) {
|
|
3165
|
+
const source = parameters || {};
|
|
3166
|
+
if (kind === "screen") {
|
|
3167
|
+
return {
|
|
3168
|
+
width: Number(source.targetWidth) || 0,
|
|
3169
|
+
height: Number(source.targetHeight) || 0,
|
|
3170
|
+
frameRate: Number(source.frameRate) || 30
|
|
3171
|
+
};
|
|
3172
|
+
}
|
|
3173
|
+
const vidCons = source.vidCons || {};
|
|
3174
|
+
return {
|
|
3175
|
+
width: capOf(vidCons.width),
|
|
3176
|
+
height: capOf(vidCons.height),
|
|
3177
|
+
frameRate: Number(source.frameRate) || 0
|
|
3178
|
+
};
|
|
3179
|
+
}
|
|
3180
|
+
async function enforceCaptureLimits(stream, parameters, kind, allowUnconstrained) {
|
|
3181
|
+
if (kind === "audio") return { ok: true, error: "" };
|
|
3182
|
+
const limits = getCaptureLimits({ parameters, kind });
|
|
3183
|
+
if (!limits.width && !limits.height && !limits.frameRate) return { ok: true, error: "" };
|
|
3184
|
+
let track;
|
|
3185
|
+
try {
|
|
3186
|
+
track = stream.getVideoTracks()[0];
|
|
3187
|
+
} catch {
|
|
3188
|
+
return { ok: true, error: "" };
|
|
3189
|
+
}
|
|
3190
|
+
if (!track) return { ok: true, error: "" };
|
|
3191
|
+
const constraints = {};
|
|
3192
|
+
if (limits.width) constraints.width = { max: limits.width };
|
|
3193
|
+
if (limits.height) constraints.height = { max: limits.height };
|
|
3194
|
+
if (limits.frameRate) constraints.frameRate = { max: limits.frameRate };
|
|
3195
|
+
try {
|
|
3196
|
+
await track.applyConstraints(constraints);
|
|
3197
|
+
} catch {
|
|
3198
|
+
}
|
|
3199
|
+
let settings = {};
|
|
3200
|
+
try {
|
|
3201
|
+
settings = track.getSettings?.() || {};
|
|
3202
|
+
} catch {
|
|
3203
|
+
return { ok: true, error: "" };
|
|
3204
|
+
}
|
|
3205
|
+
if (!settings.width && !settings.height && !settings.frameRate) {
|
|
3206
|
+
return { ok: true, error: "" };
|
|
3207
|
+
}
|
|
3208
|
+
const over = [];
|
|
3209
|
+
if (limits.width && settings.width && settings.width > limits.width) {
|
|
3210
|
+
over.push(`width ${settings.width} > ${limits.width}`);
|
|
3211
|
+
}
|
|
3212
|
+
if (limits.height && settings.height && settings.height > limits.height) {
|
|
3213
|
+
over.push(`height ${settings.height} > ${limits.height}`);
|
|
3214
|
+
}
|
|
3215
|
+
if (limits.frameRate && settings.frameRate && settings.frameRate > limits.frameRate + 1) {
|
|
3216
|
+
over.push(`frameRate ${Math.round(settings.frameRate)} > ${limits.frameRate}`);
|
|
3217
|
+
}
|
|
3218
|
+
if (over.length === 0) return { ok: true, error: "" };
|
|
3219
|
+
if (allowUnconstrained) return { ok: true, error: "" };
|
|
3220
|
+
return {
|
|
3221
|
+
ok: false,
|
|
3222
|
+
error: `This source exceeds the room's capture allowance (${over.join(", ")}). Reduce the source size or frame rate before publishing.`
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
async function produceMedia({
|
|
3226
|
+
parameters,
|
|
3227
|
+
stream,
|
|
3228
|
+
kind,
|
|
3229
|
+
allowUnconstrained = false
|
|
3230
|
+
}) {
|
|
3231
|
+
try {
|
|
3232
|
+
const live = getCurrentParams({ parameters });
|
|
3233
|
+
const readiness = getRoomReadiness({ parameters: live });
|
|
3234
|
+
if (!readiness.ready) return { ok: false, error: readiness.reason };
|
|
3235
|
+
const trackKind = kind === "audio" ? "audio" : "video";
|
|
3236
|
+
if (!hasLiveTrack(stream, trackKind)) {
|
|
3237
|
+
return {
|
|
3238
|
+
ok: false,
|
|
3239
|
+
error: `The stream has no live ${trackKind} track to publish.`
|
|
3240
|
+
};
|
|
3241
|
+
}
|
|
3242
|
+
const limited = await enforceCaptureLimits(stream, live, kind, allowUnconstrained);
|
|
3243
|
+
if (!limited.ok) return limited;
|
|
3244
|
+
if (kind === "audio") {
|
|
3245
|
+
await streamSuccessAudio({ stream, parameters: live });
|
|
3246
|
+
} else if (kind === "screen") {
|
|
3247
|
+
await streamSuccessScreen({ stream, parameters: live });
|
|
3248
|
+
} else {
|
|
3249
|
+
await streamSuccessVideo({ stream, parameters: live });
|
|
3250
|
+
}
|
|
3251
|
+
return { ok: true, error: "" };
|
|
3252
|
+
} catch (error) {
|
|
3253
|
+
return { ok: false, error: error?.message || "The media could not be published." };
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
async function stopProducing({
|
|
3257
|
+
parameters,
|
|
3258
|
+
kind
|
|
3259
|
+
}) {
|
|
3260
|
+
try {
|
|
3261
|
+
const live = getCurrentParams({ parameters });
|
|
3262
|
+
if (kind === "audio") {
|
|
3263
|
+
await disconnectSendTransportAudio({ parameters: live });
|
|
3264
|
+
} else if (kind === "screen") {
|
|
3265
|
+
await disconnectSendTransportScreen({ parameters: live });
|
|
3266
|
+
} else {
|
|
3267
|
+
await disconnectSendTransportVideo({ parameters: live });
|
|
3268
|
+
}
|
|
3269
|
+
return { ok: true, error: "" };
|
|
3270
|
+
} catch (error) {
|
|
3271
|
+
return { ok: false, error: error?.message || "The producer could not be stopped." };
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
3274
|
+
async function produceCanvas({
|
|
3275
|
+
parameters,
|
|
3276
|
+
canvas,
|
|
3277
|
+
frameRate = 30,
|
|
3278
|
+
as = "video"
|
|
3279
|
+
}) {
|
|
3280
|
+
try {
|
|
3281
|
+
if (!canvas || typeof canvas.captureStream !== "function") {
|
|
3282
|
+
return {
|
|
3283
|
+
ok: false,
|
|
3284
|
+
error: "This canvas cannot be captured in the current browser.",
|
|
3285
|
+
stream: null
|
|
3286
|
+
};
|
|
3287
|
+
}
|
|
3288
|
+
const stream = canvas.captureStream(frameRate);
|
|
3289
|
+
const result = await produceMedia({ parameters, stream, kind: as });
|
|
3290
|
+
if (!result.ok) {
|
|
3291
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
3292
|
+
return { ...result, stream: null };
|
|
3293
|
+
}
|
|
3294
|
+
return { ...result, stream };
|
|
3295
|
+
} catch (error) {
|
|
3296
|
+
return {
|
|
3297
|
+
ok: false,
|
|
3298
|
+
error: error?.message || "The canvas could not be published.",
|
|
3299
|
+
stream: null
|
|
3300
|
+
};
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
async function produceElement({
|
|
3304
|
+
parameters,
|
|
3305
|
+
element,
|
|
3306
|
+
withVideo,
|
|
3307
|
+
withAudio = true
|
|
3308
|
+
}) {
|
|
3309
|
+
try {
|
|
3310
|
+
const capture = element?.captureStream || element?.mozCaptureStream;
|
|
3311
|
+
if (typeof capture !== "function") {
|
|
3312
|
+
return {
|
|
3313
|
+
ok: false,
|
|
3314
|
+
error: "This element cannot be captured in the current browser.",
|
|
3315
|
+
stream: null
|
|
3316
|
+
};
|
|
3317
|
+
}
|
|
3318
|
+
const stream = capture.call(element);
|
|
3319
|
+
const wantsVideo = withVideo ?? hasLiveTrack(stream, "video");
|
|
3320
|
+
const results = [];
|
|
3321
|
+
if (wantsVideo && hasLiveTrack(stream, "video")) {
|
|
3322
|
+
results.push(await produceMedia({ parameters, stream, kind: "video" }));
|
|
3323
|
+
}
|
|
3324
|
+
if (withAudio && hasLiveTrack(stream, "audio")) {
|
|
3325
|
+
results.push(await produceMedia({ parameters, stream, kind: "audio" }));
|
|
3326
|
+
}
|
|
3327
|
+
if (results.length === 0) {
|
|
3328
|
+
return { ok: false, error: "The element has no live tracks yet.", stream: null };
|
|
3329
|
+
}
|
|
3330
|
+
const failure = results.find((result) => !result.ok);
|
|
3331
|
+
if (failure) return { ...failure, stream };
|
|
3332
|
+
return { ok: true, error: "", stream };
|
|
3333
|
+
} catch (error) {
|
|
3334
|
+
return {
|
|
3335
|
+
ok: false,
|
|
3336
|
+
error: error?.message || "The element could not be published.",
|
|
3337
|
+
stream: null
|
|
3338
|
+
};
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3341
|
+
async function produceDisplay({
|
|
3342
|
+
parameters,
|
|
3343
|
+
constraints = { video: true },
|
|
3344
|
+
withAudio = false
|
|
3345
|
+
}) {
|
|
3346
|
+
try {
|
|
3347
|
+
const mediaDevices = parameters?.mediaDevices || (typeof navigator !== "undefined" ? navigator.mediaDevices : null);
|
|
3348
|
+
if (!mediaDevices || typeof mediaDevices.getDisplayMedia !== "function") {
|
|
3349
|
+
return {
|
|
3350
|
+
ok: false,
|
|
3351
|
+
error: "Screen capture is unavailable in this browser.",
|
|
3352
|
+
stream: null
|
|
3353
|
+
};
|
|
3354
|
+
}
|
|
3355
|
+
const stream = await mediaDevices.getDisplayMedia({
|
|
3356
|
+
...constraints,
|
|
3357
|
+
...withAudio ? { audio: true } : {}
|
|
3358
|
+
});
|
|
3359
|
+
const result = await produceMedia({ parameters, stream, kind: "screen" });
|
|
3360
|
+
if (!result.ok) {
|
|
3361
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
3362
|
+
return { ...result, stream: null };
|
|
3363
|
+
}
|
|
3364
|
+
if (withAudio && hasLiveTrack(stream, "audio")) {
|
|
3365
|
+
await produceMedia({ parameters, stream, kind: "audio" });
|
|
3366
|
+
}
|
|
3367
|
+
return { ...result, stream };
|
|
3368
|
+
} catch (error) {
|
|
3369
|
+
const name = error?.name || "";
|
|
3370
|
+
if (name === "NotAllowedError" || name === "AbortError") {
|
|
3371
|
+
return { ok: false, error: "Screen sharing was cancelled.", stream: null };
|
|
3372
|
+
}
|
|
3373
|
+
return {
|
|
3374
|
+
ok: false,
|
|
3375
|
+
error: error?.message || "The screen could not be shared.",
|
|
3376
|
+
stream: null
|
|
3377
|
+
};
|
|
3378
|
+
}
|
|
3379
|
+
}
|
|
3380
|
+
async function replaceProducerTrack({
|
|
3381
|
+
parameters,
|
|
3382
|
+
track
|
|
3383
|
+
}) {
|
|
3384
|
+
try {
|
|
3385
|
+
if (!track || track.readyState !== "live") {
|
|
3386
|
+
return { ok: false, error: "The replacement track is not live." };
|
|
3387
|
+
}
|
|
3388
|
+
const live = getCurrentParams({ parameters });
|
|
3389
|
+
const producer = track.kind === "audio" ? live.audioProducer || live.localAudioProducer : live.videoProducer || live.localVideoProducer;
|
|
3390
|
+
if (!producer || typeof producer.replaceTrack !== "function") {
|
|
3391
|
+
return {
|
|
3392
|
+
ok: false,
|
|
3393
|
+
error: `There is no live ${track.kind} producer to replace.`
|
|
3394
|
+
};
|
|
3395
|
+
}
|
|
3396
|
+
await producer.replaceTrack({ track });
|
|
3397
|
+
return { ok: true, error: "" };
|
|
3398
|
+
} catch (error) {
|
|
3399
|
+
return { ok: false, error: error?.message || "The track could not be replaced." };
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
async function getParticipantMedia({
|
|
3403
|
+
id = "",
|
|
3404
|
+
name = "",
|
|
3405
|
+
kind = "video",
|
|
3406
|
+
parameters
|
|
3407
|
+
}) {
|
|
3408
|
+
try {
|
|
3409
|
+
if (!parameters) return null;
|
|
3410
|
+
const live = typeof parameters.getCurrentParams === "function" ? parameters.getCurrentParams() || parameters : parameters;
|
|
3411
|
+
const participants = Array.isArray(live.participants) ? live.participants : [];
|
|
3412
|
+
const streams = Array.isArray(
|
|
3413
|
+
kind === "video" ? live.allVideoStreams : live.allAudioStreams
|
|
3414
|
+
) ? kind === "video" ? live.allVideoStreams : live.allAudioStreams : [];
|
|
3415
|
+
if (streams.length === 0) return null;
|
|
3416
|
+
let participant = id ? participants.find((part) => part.id === id) : void 0;
|
|
3417
|
+
if (!participant && name) {
|
|
3418
|
+
participant = participants.find((part) => part.name === name);
|
|
3419
|
+
}
|
|
3420
|
+
const producerId = participant ? kind === "video" ? participant.videoID : participant.audioID : "";
|
|
3421
|
+
if (producerId) {
|
|
3422
|
+
const match = streams.find((stream) => stream.producerId === producerId);
|
|
3423
|
+
if (match && match.stream) return match.stream;
|
|
3424
|
+
}
|
|
3425
|
+
if (id) {
|
|
3426
|
+
const direct = streams.find((stream) => stream.producerId === id);
|
|
3427
|
+
if (direct && direct.stream) return direct.stream;
|
|
3428
|
+
}
|
|
3429
|
+
return null;
|
|
3430
|
+
} catch {
|
|
3431
|
+
return null;
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
export {
|
|
3435
|
+
leaveRoom as $,
|
|
3436
|
+
recordPauseTimer as A,
|
|
3437
|
+
recordResumeTimer as B,
|
|
3438
|
+
recordStartTimer as C,
|
|
3439
|
+
recordUpdateTimer as D,
|
|
3440
|
+
startRecording as E,
|
|
3441
|
+
stopRecording as F,
|
|
3442
|
+
updateRecording as G,
|
|
3443
|
+
launchRequests as H,
|
|
3444
|
+
respondToRequests as I,
|
|
3445
|
+
launchSettings as J,
|
|
3446
|
+
switchAudio as K,
|
|
3447
|
+
switchVideo as L,
|
|
3448
|
+
switchVideoAlt as M,
|
|
3449
|
+
getModalPosition as N,
|
|
3450
|
+
launchWaiting as O,
|
|
3451
|
+
respondToWaiting as P,
|
|
3452
|
+
handleStartWhiteboard as Q,
|
|
3453
|
+
handleStopWhiteboard as R,
|
|
3454
|
+
launchConfigureWhiteboard as S,
|
|
3455
|
+
getRoomReadiness as T,
|
|
3456
|
+
getRemoteVideoStreams as U,
|
|
3457
|
+
getRemoteAudioStreams as V,
|
|
3458
|
+
getLocalVideoStream as W,
|
|
3459
|
+
getLocalAudioStream as X,
|
|
3460
|
+
getScreenShareStream as Y,
|
|
3461
|
+
getAudioGridComponents as Z,
|
|
3462
|
+
getCurrentParams as _,
|
|
3463
|
+
handleStopBreakout as a,
|
|
3464
|
+
replaceProducerTrack as a$,
|
|
3465
|
+
sendChatMessage as a0,
|
|
3466
|
+
runMediaControl as a1,
|
|
3467
|
+
getParticipantMediaState as a2,
|
|
3468
|
+
listParticipantMediaStates as a3,
|
|
3469
|
+
getActiveSpeaker as a4,
|
|
3470
|
+
listMediaDevices as a5,
|
|
3471
|
+
getSelectedDevices as a6,
|
|
3472
|
+
getMediaPermissions as a7,
|
|
3473
|
+
getModerationPermissions as a8,
|
|
3474
|
+
setParticipantMedia as a9,
|
|
3475
|
+
getVirtualBackgroundState as aA,
|
|
3476
|
+
setParticipantPlayback as aB,
|
|
3477
|
+
setBreakoutRooms as aC,
|
|
3478
|
+
assignParticipantToBreakoutRoom as aD,
|
|
3479
|
+
stopBreakoutRooms as aE,
|
|
3480
|
+
reapplyLocalPlayback as aF,
|
|
3481
|
+
getLocallyPausedProducerIds as aG,
|
|
3482
|
+
switchCamera as aH,
|
|
3483
|
+
flipCamera as aI,
|
|
3484
|
+
switchMicrophone as aJ,
|
|
3485
|
+
setRoomMediaPolicy as aK,
|
|
3486
|
+
getChatMessages as aL,
|
|
3487
|
+
getPendingApprovals as aM,
|
|
3488
|
+
getSessionTimer as aN,
|
|
3489
|
+
getPresenceCheck as aO,
|
|
3490
|
+
confirmStillHere as aP,
|
|
3491
|
+
getPlaybackSources as aQ,
|
|
3492
|
+
attachPlayback as aR,
|
|
3493
|
+
detachPlayback as aS,
|
|
3494
|
+
publishWhip as aT,
|
|
3495
|
+
createViewerSession as aU,
|
|
3496
|
+
getCaptureLimits as aV,
|
|
3497
|
+
produceMedia as aW,
|
|
3498
|
+
stopProducing as aX,
|
|
3499
|
+
produceCanvas as aY,
|
|
3500
|
+
produceElement as aZ,
|
|
3501
|
+
produceDisplay as a_,
|
|
3502
|
+
muteParticipant as aa,
|
|
3503
|
+
disableParticipantVideo as ab,
|
|
3504
|
+
stopParticipantScreenShare as ac,
|
|
3505
|
+
muteEveryone as ad,
|
|
3506
|
+
removeParticipant as ae,
|
|
3507
|
+
respondToWaitingParticipant as af,
|
|
3508
|
+
respondToParticipantRequest as ag,
|
|
3509
|
+
setCoHost as ah,
|
|
3510
|
+
getRecordingState as ai,
|
|
3511
|
+
startRoomRecording as aj,
|
|
3512
|
+
pauseRoomRecording as ak,
|
|
3513
|
+
resumeRoomRecording as al,
|
|
3514
|
+
stopRoomRecording as am,
|
|
3515
|
+
getWhiteboardState as an,
|
|
3516
|
+
startWhiteboard as ao,
|
|
3517
|
+
stopWhiteboard as ap,
|
|
3518
|
+
getPollState as aq,
|
|
3519
|
+
createRoomPoll as ar,
|
|
3520
|
+
voteInRoomPoll as as,
|
|
3521
|
+
endRoomPoll as at,
|
|
3522
|
+
getBreakoutState as au,
|
|
3523
|
+
getRecordingNotice as av,
|
|
3524
|
+
getRecordingCapabilities as aw,
|
|
3525
|
+
getTranslationState as ax,
|
|
3526
|
+
setTranslationPreference as ay,
|
|
3527
|
+
getFocusModeState as az,
|
|
3528
|
+
launchBreakoutRooms as b,
|
|
3529
|
+
getParticipantMedia as b0,
|
|
3530
|
+
launchCoHost as c,
|
|
3531
|
+
launchDisplaySettings as d,
|
|
3532
|
+
modifyDisplaySettings as e,
|
|
3533
|
+
confirmExit as f,
|
|
3534
|
+
launchConfirmExit as g,
|
|
3535
|
+
handleStartBreakout as h,
|
|
3536
|
+
launchMediaSettings as i,
|
|
3537
|
+
launchMenuModal as j,
|
|
3538
|
+
launchMessages as k,
|
|
3539
|
+
launchBackground as l,
|
|
3540
|
+
modifyCoHostSettings as m,
|
|
3541
|
+
launchParticipants as n,
|
|
3542
|
+
messageParticipants as o,
|
|
3543
|
+
muteParticipants as p,
|
|
3544
|
+
handleCreatePoll as q,
|
|
3545
|
+
removeParticipants as r,
|
|
3546
|
+
sendMessage as s,
|
|
3547
|
+
handleEndPoll as t,
|
|
3548
|
+
handleVotePoll as u,
|
|
3549
|
+
launchPoll as v,
|
|
3550
|
+
checkPauseState as w,
|
|
3551
|
+
checkResumeState as x,
|
|
3552
|
+
confirmRecording as y,
|
|
3553
|
+
launchRecording as z
|
|
3554
|
+
};
|
|
3555
|
+
//# sourceMappingURL=getParticipantMedia-B0JS6d2b.js.map
|