mediasfu-reactnative-expo
Version:
mediasfu-reactnative-expo – Expo-managed React Native WebRTC SDK for video conferencing, webinars, live streaming, broadcast, screen sharing, whiteboard, chat, recording, live subtitles, translation, and AI agent rooms on iOS, Android, and web. Prebuilt r
655 lines • 290 kB
JavaScript
import { StatusBar } from "expo-status-bar";
import React, { useEffect, useState, useRef } from "react";
import { Text, View, Pressable, Platform, Dimensions, StyleSheet } from "react-native";
import Orientation from "react-native-orientation-locker";
import { SafeAreaProvider } from "react-native-safe-area-context";
import Constants from "expo-constants";
import { Camera } from "expo-camera";
import { FontAwesome5 } from "@expo/vector-icons";
// initial values
import { initialValuesState } from "../../methods/utils/initialValuesState";
// import components for display (samples)
import MainAspectComponent from "../../components/displayComponents/MainAspectComponent";
import LoadingModal from "../../components/displayComponents/LoadingModal";
import ControlButtonsComponent from "../../components/displayComponents/ControlButtonsComponent";
import ControlButtonsAltComponent from "../../components/displayComponents/ControlButtonsAltComponent";
import ControlButtonsComponentTouch from "../../components/displayComponents/ControlButtonsComponentTouch";
import OthergridComponent from "../../components/displayComponents/OtherGridComponent";
import MainScreenComponent from "../../components/displayComponents/MainScreenComponent";
import MainGridComponent from "../../components/displayComponents/MainGridComponent";
import SubAspectComponent from "../../components/displayComponents/SubAspectComponent";
import MainContainerComponent from "../../components/displayComponents/MainContainerComponent";
import AlertComponent from "../../components/displayComponents/AlertComponent";
import VideoCard from "../../components/displayComponents/VideoCard";
import AudioCard from "../../components/displayComponents/AudioCard";
import MiniCard from "../../components/displayComponents/MiniCard";
import MiniAudio from "../../components/displayComponents/MiniAudio";
import MiniAudioPlayer from "../../methods/utils/MiniAudioPlayer/MiniAudioPlayer";
import MenuModal from "../../components/menuComponents/MenuModal";
import RecordingModal from "../../components/recordingComponents/RecordingModal";
import RequestsModal from "../../components/requestsComponents/RequestsModal";
import WaitingRoomModal from "../../components/waitingComponents/WaitingModal";
import DisplaySettingsModal from "../../components/displaySettingsComponents/DisplaySettingsModal";
import EventSettingsModal from "../../components/eventSettingsComponents/EventSettingsModal";
import CoHostModal from "../../components/coHostComponents/CoHostModal";
import ParticipantsModal from "../../components/participantsComponents/ParticipantsModal";
import MessagesModal from "../../components/messageComponents/MessagesModal";
import MediaSettingsModal from "../../components/mediaSettingsComponents/MediaSettingsModal";
import ConfirmExitModal from "../../components/exitComponents/ConfirmExitModal";
import ConfirmHereModal from "../../components/miscComponents/ConfirmHereModal";
import ShareEventModal from "../../components/miscComponents/ShareEventModal";
import WelcomePage from "../../components/miscComponents/WelcomePage";
import PollModal from "../../components/pollsComponents/PollModal";
import BackgroundModal from "../../components/backgroundComponents/BackgroundModal";
import BreakoutRoomsModal from "../../components/breakoutComponents/BreakoutRoomsModal";
import PanelistsModal from "../../components/panelistsComponents/PanelistsModal";
import PermissionsModal from "../../components/permissionsComponents/PermissionsModal";
import TranslationSettingsModal from "../../components/translationComponents/TranslationSettingsModal";
import ConfigureWhiteboardModal from "../../components/whiteboardComponents/ConfigureWhiteboardModal";
import Whiteboard from "../../components/whiteboardComponents/Whiteboard";
import Screenboard from "../../components/screenboardComponents/Screenboard";
import ScreenboardModal from "../../components/screenboardComponents/ScreenboardModal";
// Override helpers for UI customization
import { withOverride, withFunctionOverride } from "./overrideHelpers";
// pagination and display of media (samples)
import Pagination from "../../components/displayComponents/Pagination";
import FlexibleGrid from "../../components/displayComponents/FlexibleGrid";
import FlexibleVideo from "../../components/displayComponents/FlexibleVideo";
import AudioGrid from "../../components/displayComponents/AudioGrid";
import MeetingProgressTimer from "../../components/displayComponents/MeetingProgressTimer";
import { ParticipantsCounterBadge } from "../../components_modern/display_components/ParticipantsCounterBadge";
import { createModernExpoOverrides } from "../../components_modern/modernOverrides";
import { LiveSubtitleProvider } from "../../contexts/LiveSubtitleContext";
// import methods for control (samples)
import { launchMenuModal } from "../../methods/menuMethods/launchMenuModal";
import { launchRecording } from "../../methods/recordingMethods/launchRecording";
import { startRecording } from "../../methods/recordingMethods/startRecording";
import { confirmRecording } from "../../methods/recordingMethods/confirmRecording";
import { launchWaiting } from "../../methods/waitingMethods/launchWaiting";
import { launchCoHost } from "../../methods/coHostMethods/launchCoHost";
import { launchMediaSettings } from "../../methods/mediaSettingsMethods/launchMediaSettings";
import { launchDisplaySettings } from "../../methods/displaySettingsMethods/launchDisplaySettings";
import { launchSettings } from "../../methods/settingsMethods/launchSettings";
import { launchRequests } from "../../methods/requestsMethods/launchRequests";
import { launchParticipants } from "../../methods/participantsMethods/launchParticipants";
import { launchMessages } from "../../methods/messageMethods/launchMessages";
import { launchConfirmExit } from "../../methods/exitMethods/launchConfirmExit";
import { launchPoll } from "../../methods/pollsMethods/launchPoll";
import { launchBreakoutRooms } from "../../methods/breakoutRoomsMethods/launchBreakoutRooms";
import { launchBackground } from "../../methods/backgroundMethods/launchBackground";
import { launchConfigureWhiteboard } from "../../methods/whiteboardMethods/launchConfigureWhiteboard";
import { launchPanelists } from "../../methods/panelistsMethods/launchPanelists";
import { launchPermissions } from "../../methods/permissionsMethods/launchPermissions";
// Import the platform-specific WebRTC module (options are for ios, android, web)
import { mediaDevices, registerGlobals, MediaStream as NativeMediaStream, MediaStreamTrack, } from "../../methods/utils/webrtc/webrtc";
// mediasfu functions -- examples
import { connectSocket, connectLocalSocket } from "../../sockets/SocketManager";
import { joinRoomClient } from "../../ProducerClient/producerClientEmits/joinRoomClient";
import { joinLocalRoom } from "../../producers/producerEmits/joinLocalRoom";
import { updateRoomParametersClient } from "../../ProducerClient/producerClientEmits/updateRoomParametersClient";
import { createDeviceClient } from "../../ProducerClient/producerClientEmits/createDeviceClient";
import { switchVideoAlt } from "../../methods/streamMethods/switchVideoAlt";
import { clickVideo } from "../../methods/streamMethods/clickVideo";
import { clickAudio } from "../../methods/streamMethods/clickAudio";
import { clickScreenShare } from "../../methods/streamMethods/clickScreenShare";
import { streamSuccessVideo } from "../../consumers/streamSuccessVideo";
import { streamSuccessAudio } from "../../consumers/streamSuccessAudio";
import { streamSuccessScreen } from "../../consumers/streamSuccessScreen";
import { streamSuccessAudioSwitch } from "../../consumers/streamSuccessAudioSwitch";
import { checkPermission } from "../../consumers/checkPermission";
// mediasfu functions
import { updateMiniCardsGrid } from "../../consumers/updateMiniCardsGrid";
import { mixStreams } from "../../consumers/mixStreams";
import { dispStreams } from "../../consumers/dispStreams";
import { stopShareScreen } from "../../consumers/stopShareScreen";
import { checkScreenShare } from "../../consumers/checkScreenShare";
import { startShareScreen } from "../../consumers/startShareScreen";
import { requestScreenShare } from "../../consumers/requestScreenShare";
import { reorderStreams } from "../../consumers/reorderStreams";
import { prepopulateUserMedia } from "../../consumers/prepopulateUserMedia";
import { getVideos } from "../../consumers/getVideos";
import { rePort } from "../../consumers/rePort";
import { trigger } from "../../consumers/trigger";
import { consumerResume } from "../../consumers/consumerResume";
import { connectSendTransportAudio } from "../../consumers/connectSendTransportAudio";
import { connectSendTransportVideo } from "../../consumers/connectSendTransportVideo";
import { connectSendTransportScreen } from "../../consumers/connectSendTransportScreen";
import { processConsumerTransports } from "../../consumers/processConsumerTransports";
import { resumePauseStreams } from "../../consumers/resumePauseStreams";
import { readjust } from "../../consumers/readjust";
import { checkGrid } from "../../consumers/checkGrid";
import { getEstimate } from "../../consumers/getEstimate";
import { calculateRowsAndColumns } from "../../consumers/calculateRowsAndColumns";
import { addVideosGrid } from "../../consumers/addVideosGrid";
import { onScreenChanges } from "../../consumers/onScreenChanges";
import { sleep } from "../../methods/utils/sleep";
import { changeVids } from "../../consumers/changeVids";
import { compareActiveNames } from "../../consumers/compareActiveNames";
import { compareScreenStates } from "../../consumers/compareScreenStates";
import { createSendTransport } from "../../consumers/createSendTransport";
import { resumeSendTransportAudio } from "../../consumers/resumeSendTransportAudio";
import { receiveAllPipedTransports } from "../../consumers/receiveAllPipedTransports";
import { disconnectSendTransportVideo } from "../../consumers/disconnectSendTransportVideo";
import { disconnectSendTransportAudio } from "../../consumers/disconnectSendTransportAudio";
import { disconnectSendTransportScreen } from "../../consumers/disconnectSendTransportScreen";
import { connectSendTransport } from "../../consumers/connectSendTransport";
import { getPipedProducersAlt } from "../../consumers/getPipedProducersAlt";
import { signalNewConsumerTransport } from "../../consumers/signalNewConsumerTransport";
import { connectRecvTransport } from "../../consumers/connectRecvTransport";
import { reUpdateInter } from "../../consumers/reUpdateInter";
import { updateParticipantAudioDecibels } from "../../consumers/updateParticipantAudioDecibels";
import { closeAndResize } from "../../consumers/closeAndResize";
import { autoAdjust } from "../../consumers/autoAdjust";
import { switchUserVideoAlt } from "../../consumers/switchUserVideoAlt";
import { switchUserVideo } from "../../consumers/switchUserVideo";
import { switchUserAudio } from "../../consumers/switchUserAudio";
import { receiveRoomMessages } from "../../consumers/receiveRoomMessages";
import { formatNumber } from "../../methods/utils/formatNumber";
import { connectIps } from "../../consumers/connectIps";
import { connectLocalIps } from "../../consumers/connectLocalIps";
import { pollUpdated } from "../../methods/pollsMethods/pollUpdated";
import { handleCreatePoll } from "../../methods/pollsMethods/handleCreatePoll";
import { handleEndPoll } from "../../methods/pollsMethods/handleEndPoll";
import { handleVotePoll } from "../../methods/pollsMethods/handleVotePoll";
import { breakoutRoomUpdated } from "../../methods/breakoutRoomsMethods/breakoutRoomUpdated";
import { startMeetingProgressTimer } from "../../methods/utils/meetingTimer/startMeetingProgressTimer";
import { updateRecording } from "../../methods/recordingMethods/updateRecording";
import { stopRecording } from "../../methods/recordingMethods/stopRecording";
import { userWaiting } from "../../producers/socketReceiveMethods/userWaiting";
import { personJoined } from "../../producers/socketReceiveMethods/personJoined";
import { allWaitingRoomMembers } from "../../producers/socketReceiveMethods/allWaitingRoomMembers";
import { roomRecordParams } from "../../producers/socketReceiveMethods/roomRecordParams";
import { banParticipant } from "../../producers/socketReceiveMethods/banParticipant";
import { updatedCoHost } from "../../producers/socketReceiveMethods/updatedCoHost";
import { participantRequested } from "../../producers/socketReceiveMethods/participantRequested";
import { screenProducerId } from "../../producers/socketReceiveMethods/screenProducerId";
import { updateMediaSettings } from "../../producers/socketReceiveMethods/updateMediaSettings";
import { producerMediaPaused } from "../../producers/socketReceiveMethods/producerMediaPaused";
import { producerMediaResumed } from "../../producers/socketReceiveMethods/producerMediaResumed";
import { producerMediaClosed } from "../../producers/socketReceiveMethods/producerMediaClosed";
import { controlMediaHost } from "../../producers/socketReceiveMethods/controlMediaHost";
import { meetingEnded } from "../../producers/socketReceiveMethods/meetingEnded";
import { disconnectUserSelf } from "../../producers/socketReceiveMethods/disconnectUserSelf";
import { receiveMessage } from "../../producers/socketReceiveMethods/receiveMessage";
import { meetingTimeRemaining } from "../../producers/socketReceiveMethods/meetingTimeRemaining";
import { meetingStillThere } from "../../producers/socketReceiveMethods/meetingStillThere";
import { startRecords } from "../../producers/socketReceiveMethods/startRecords";
import { reInitiateRecording } from "../../producers/socketReceiveMethods/reInitiateRecording";
import { getDomains } from "../../producers/socketReceiveMethods/getDomains";
import { updateConsumingDomains } from "../../producers/socketReceiveMethods/updateConsumingDomains";
import { recordingNotice } from "../../producers/socketReceiveMethods/recordingNotice";
import { timeLeftRecording } from "../../producers/socketReceiveMethods/timeLeftRecording";
import { stoppedRecording } from "../../producers/socketReceiveMethods/stoppedRecording";
import { hostRequestResponse } from "../../producers/socketReceiveMethods/hostRequestResponse";
import { allMembers } from "../../producers/socketReceiveMethods/allMembers";
import { allMembersRest } from "../../producers/socketReceiveMethods/allMembersRest";
import { disconnect } from "../../producers/socketReceiveMethods/disconnect";
import { addedAsPanelist, controlMedia as panelistControlMedia, panelistFocusChanged, panelistsUpdated, removedFromPanelists, } from "../../producers/socketReceiveMethods/panelistReceiveMethods";
import { permissionConfigUpdated, permissionUpdated, } from "../../producers/socketReceiveMethods/permissionReceiveMethods";
import { translationChannelsAvailable, translationConfigUpdated, translationError, translationLanguageSet, translationMemberState, translationProducerClosed, translationProducerReady, translationRoomConfig, translationSpeakerOutputChanged, translationSubscribed, translationTranscript, translationUnsubscribed, } from "../../producers/socketReceiveMethods/translationReceiveMethods";
import { pruneExpiredSubtitles, updateLiveSubtitlesFromTranscript, } from "mediasfu-shared";
import { captureCanvasStream } from "../../methods/whiteboardMethods/captureCanvasStream";
import { resumePauseAudioStreams } from "../../consumers/resumePauseAudioStreams";
import { processConsumerTransportsAudio } from "../../consumers/processConsumerTransportsAudio";
import { pauseOriginalProducer, resumeOriginalProducer, stopConsumingTranslation, } from "../../consumers/translationConsumerSwitch";
import { createResponseJoinRoom } from "../../methods/utils/createResponseJoinRoom";
/**
* MediasfuGeneric component optimizes the media experience for conferences.
* Participants can share media (audio, video, screen share) with each other.
* Participants can chat with each other and engage in polls and breakout rooms, share screens, and more during the conference.
*
* @typedef {Object} MediasfuGenericOptions
* @property {function} [PrejoinPage=WelcomePage] - Function to render the prejoin page.
* @property {string} [localLink=""] - Local link for the media server (if using Community Edition).
* @property {boolean} [connectMediaSFU=true] - Flag to connect to the MediaSFU server (if using Community Edition and still need to connect to the server)
* @property {Object} [credentials={ apiUserName: "", apiKey: "" }] - API credentials.
* @property {boolean} [useLocalUIMode=false] - Flag to use local UI mode.
* @property {SeedData} [seedData={}] - Seed data for initial state.
* @property {boolean} [useSeed=false] - Flag to use seed data.
* @property {string} [imgSrc="https://mediasfu.com/images/logo192.png"] - Image source URL.
* @property {Object} [sourceParameters={}] - Source parameters.
* @property {function} [updateSourceParameters] - Function to update source parameters.
* @property {boolean} [returnUI=true] - Flag to return the UI.
* @property {CreateMediaSFURoomOptions | JoinMediaSFURoomOptions} [noUIPreJoinOptions] - Options for the prejoin page.
* @property {JoinRoomOnMediaSFUType} [joinMediaSFURoom] - Function to join a room on MediaSFU.
* @property {CreateRoomOnMediaSFUType} [createMediaSFURoom] - Function to create a room on MediaSFU.
*
* @typedef {Object} SeedData - Data structure to populate initial state in the MediasfuGeneric.
* @property {string} [member] - The member name.
* @property {string} [host] - The host name.
* @property {EventType} [eventType] - The type of event.
* @property {Participant[]} [participants] - The list of participants.
* @property {Message[]} [messages] - The list of messages.
* @property {Poll[]} [polls] - The list of polls.
* @property {BreakoutParticipant[][]} [breakoutRooms] - The list of breakout rooms.
* @property {Request[]} [requests] - The list of requests.
* @property {WaitingRoomParticipant[]} [waitingList] - The list of waiting room participants.
* @property {WhiteboardUser[]} [whiteboardUsers] - The list of whiteboard users.
*
* @component
* @param {MediasfuGenericOptions} props - Component properties.
* @returns {React.FC<MediasfuGenericOptions>} - React functional component.
*
* @example
* ```tsx
* <MediasfuGeneric
* PrejoinPage={WelcomePage}
* credentials={{ apiUserName: "username", apiKey: "apikey" }}
* useLocalUIMode={false}
* seedData={{}}
* useSeed={false}
* imgSrc="https://mediasfu.com/images/logo192.png"
* sourceParameters={{ key: value }}
* updateSourceParameters={updateSourceParameters}
* returnUI={true}
* noUIPreJoinOptions={customPreJoinOptions}
* joinMediaSFURoom={joinRoomOnMediaSFU}
* createMediaSFURoom={createRoomOnMediaSFU}
* />
* ```
*
* @description
* This component handles the generic functionalities for MediaSFU, including joining rooms,
* managing participants, and handling media streams. It uses various hooks and methods to
* manage state and perform actions such as joining a room, updating initial values, and
* handling media streams.
*
*/
const MediasfuGeneric = ({ PrejoinPage = WelcomePage, localLink = "", connectMediaSFU = true, credentials = { apiUserName: "", apiKey: "" }, useLocalUIMode = false, seedData = {}, useSeed = false, imgSrc = "https://mediasfu.com/images/logo192.png", sourceParameters, updateSourceParameters, returnUI = true, noUIPreJoinOptions, autoProceedPreJoin, joinMediaSFURoom, createMediaSFURoom, customVideoCard, customAudioCard, customMiniCard, customComponent, containerStyle, useModernUI = true, uiOverrides: providedUIOverrides, }) => {
const [isDarkMode, setIsDarkMode] = useState(true);
const updateIsDarkMode = (value) => setIsDarkMode(value);
const themedSurfaceColor = React.useMemo(() => (isDarkMode ? "rgba(15, 23, 42, 0.98)" : "rgba(248, 250, 252, 0.98)"), [isDarkMode]);
const themedMenuColor = React.useMemo(() => (isDarkMode ? "rgba(15, 23, 42, 0.98)" : "rgba(248, 250, 252, 0.98)"), [isDarkMode]);
const neutralControlIconColor = isDarkMode ? "#f8fafc" : "#0f172a";
const [windowWidth, setWindowWidth] = useState(Dimensions.get("window").width);
const [windowHeight, setWindowHeight] = useState(Dimensions.get("window").height);
const uiOverrides = React.useMemo(() => useModernUI
? createModernExpoOverrides(providedUIOverrides)
: providedUIOverrides, [providedUIOverrides, useModernUI]);
useEffect(() => {
const subscription = Dimensions.addEventListener("change", ({ window }) => {
setWindowWidth(window.width);
setWindowHeight(window.height);
});
return () => {
subscription?.remove?.();
};
}, []);
const shouldAttachSidebar = (Platform.OS === "web" && windowWidth >= 768)
|| (Platform.OS !== "web" && windowWidth >= 1200 && windowWidth > windowHeight);
const shouldUseSidebar = true;
const sidebarPanelWidth = React.useMemo(() => shouldAttachSidebar
? Math.min(Math.max(windowWidth * 0.2, 280), 420)
: Math.max(Math.min(windowWidth - 24, 520), 280), [shouldAttachSidebar, windowWidth]);
const showButtonLabels = React.useMemo(() => windowWidth >= 576, [windowWidth]);
// Apply UI overrides using useMemo for performance
const MainContainer = React.useMemo(() => withOverride(uiOverrides?.mainContainer, MainContainerComponent), [uiOverrides?.mainContainer]);
const MainAspect = React.useMemo(() => withOverride(uiOverrides?.mainAspect, MainAspectComponent), [uiOverrides?.mainAspect]);
const MainScreen = React.useMemo(() => withOverride(uiOverrides?.mainScreen, MainScreenComponent), [uiOverrides?.mainScreen]);
const MainGrid = React.useMemo(() => withOverride(uiOverrides?.mainGrid, MainGridComponent), [uiOverrides?.mainGrid]);
const SubAspect = React.useMemo(() => withOverride(uiOverrides?.subAspect, SubAspectComponent), [uiOverrides?.subAspect]);
const OtherGrid = React.useMemo(() => withOverride(uiOverrides?.otherGrid, OthergridComponent), [uiOverrides?.otherGrid]);
const FlexibleGridPrimary = React.useMemo(() => withOverride(uiOverrides?.flexibleGrid, FlexibleGrid), [uiOverrides?.flexibleGrid]);
const FlexibleGridAlt = React.useMemo(() => withOverride(uiOverrides?.flexibleGridAlt, FlexibleGrid), [uiOverrides?.flexibleGridAlt]);
const FlexibleVideoComponent = React.useMemo(() => withOverride(uiOverrides?.flexibleVideo, FlexibleVideo), [uiOverrides?.flexibleVideo]);
const MeetingProgressTimerComponentBase = React.useMemo(() => withOverride(uiOverrides?.meetingProgressTimer, MeetingProgressTimer), [uiOverrides?.meetingProgressTimer]);
const MeetingProgressTimerComponent = React.useMemo(() => {
const TimerComponent = MeetingProgressTimerComponentBase;
return (props) => (<TimerComponent {...props} isDarkMode={isDarkMode} parameters={{ ...(props?.parameters || {}), isDarkModeValue: isDarkMode, updateIsDarkMode }}/>);
}, [MeetingProgressTimerComponentBase, isDarkMode]);
const AudioGridComponent = React.useMemo(() => withOverride(uiOverrides?.audioGrid, AudioGrid), [uiOverrides?.audioGrid]);
const PaginationComponent = React.useMemo(() => withOverride(uiOverrides?.pagination, Pagination), [uiOverrides?.pagination]);
const ControlButtons = React.useMemo(() => withOverride(uiOverrides?.controlButtons, ControlButtonsComponent), [uiOverrides?.controlButtons]);
const ControlButtonsAlt = React.useMemo(() => withOverride(uiOverrides?.controlButtonsAlt, ControlButtonsAltComponent), [uiOverrides?.controlButtonsAlt]);
const ControlButtonsTouch = React.useMemo(() => withOverride(uiOverrides?.controlButtonsTouch, ControlButtonsComponentTouch), [uiOverrides?.controlButtonsTouch]);
const LoadingModalComponent = React.useMemo(() => withOverride(uiOverrides?.loadingModal, LoadingModal), [uiOverrides?.loadingModal]);
const AlertComponentOverride = React.useMemo(() => withOverride(uiOverrides?.alert, AlertComponent), [uiOverrides?.alert]);
const MenuModalComponent = React.useMemo(() => withOverride(uiOverrides?.menuModal, MenuModal), [uiOverrides?.menuModal]);
const RecordingModalComponent = React.useMemo(() => withOverride(uiOverrides?.recordingModal, RecordingModal), [uiOverrides?.recordingModal]);
const RequestsModalComponent = React.useMemo(() => withOverride(uiOverrides?.requestsModal, RequestsModal), [uiOverrides?.requestsModal]);
const WaitingRoomModalComponent = React.useMemo(() => withOverride(uiOverrides?.waitingRoomModal, WaitingRoomModal), [uiOverrides?.waitingRoomModal]);
const DisplaySettingsModalComponent = React.useMemo(() => withOverride(uiOverrides?.displaySettingsModal, DisplaySettingsModal), [uiOverrides?.displaySettingsModal]);
const EventSettingsModalComponent = React.useMemo(() => withOverride(uiOverrides?.eventSettingsModal, EventSettingsModal), [uiOverrides?.eventSettingsModal]);
const CoHostModalComponent = React.useMemo(() => withOverride(uiOverrides?.coHostModal, CoHostModal), [uiOverrides?.coHostModal]);
const ParticipantsModalComponent = React.useMemo(() => withOverride(uiOverrides?.participantsModal, ParticipantsModal), [uiOverrides?.participantsModal]);
const MessagesModalComponent = React.useMemo(() => withOverride(uiOverrides?.messagesModal, MessagesModal), [uiOverrides?.messagesModal]);
const MediaSettingsModalComponent = React.useMemo(() => withOverride(uiOverrides?.mediaSettingsModal, MediaSettingsModal), [uiOverrides?.mediaSettingsModal]);
const ConfirmExitModalComponent = React.useMemo(() => withOverride(uiOverrides?.confirmExitModal, ConfirmExitModal), [uiOverrides?.confirmExitModal]);
const ConfirmHereModalComponent = React.useMemo(() => withOverride(uiOverrides?.confirmHereModal, ConfirmHereModal), [uiOverrides?.confirmHereModal]);
const ShareEventModalComponent = React.useMemo(() => withOverride(uiOverrides?.shareEventModal, ShareEventModal), [uiOverrides?.shareEventModal]);
const PollModalComponent = React.useMemo(() => withOverride(uiOverrides?.pollModal, PollModal), [uiOverrides?.pollModal]);
const BackgroundModalComponent = React.useMemo(() => withOverride(uiOverrides?.backgroundModal, BackgroundModal), [uiOverrides?.backgroundModal]);
const TranslationSettingsModalComponent = React.useMemo(() => withOverride(uiOverrides?.translationSettingsModal, TranslationSettingsModal), [uiOverrides?.translationSettingsModal]);
const BreakoutRoomsModalComponent = React.useMemo(() => withOverride(uiOverrides?.breakoutRoomsModal, BreakoutRoomsModal), [uiOverrides?.breakoutRoomsModal]);
const PanelistsModalComponent = React.useMemo(() => withOverride(uiOverrides?.panelistsModal, PanelistsModal), [uiOverrides?.panelistsModal]);
const PermissionsModalComponent = React.useMemo(() => withOverride(uiOverrides?.permissionsModal, PermissionsModal), [uiOverrides?.permissionsModal]);
const ConfigureWhiteboardModalComponent = React.useMemo(() => withOverride(uiOverrides?.configureWhiteboardModal, ConfigureWhiteboardModal), [uiOverrides?.configureWhiteboardModal]);
const WhiteboardComponent = React.useMemo(() => withOverride(uiOverrides?.whiteboard, Whiteboard), [uiOverrides?.whiteboard]);
const ScreenboardComponent = React.useMemo(() => withOverride(uiOverrides?.screenboard, Screenboard), [uiOverrides?.screenboard]);
const ScreenboardModalComponent = React.useMemo(() => withOverride(uiOverrides?.screenboardModal, ScreenboardModal), [uiOverrides?.screenboardModal]);
const VideoCardComponentOverride = React.useMemo(() => withOverride(uiOverrides?.videoCard, VideoCard), [uiOverrides?.videoCard]);
const AudioCardComponentOverride = React.useMemo(() => withOverride(uiOverrides?.audioCard, AudioCard), [uiOverrides?.audioCard]);
const MiniCardComponentOverride = React.useMemo(() => withOverride(uiOverrides?.miniCard, MiniCard), [uiOverrides?.miniCard]);
// Function overrides
const consumerResumeFn = React.useMemo(() => withFunctionOverride(uiOverrides?.consumerResume, consumerResume), [uiOverrides?.consumerResume]);
const addVideosGridFn = React.useMemo(() => withFunctionOverride(uiOverrides?.addVideosGrid, addVideosGrid), [uiOverrides?.addVideosGrid]);
// Additional component overrides for MiniAudio and MiniAudioPlayer
const MiniAudioComponentOverride = React.useMemo(() => withOverride(uiOverrides?.miniAudio, MiniAudio), [uiOverrides?.miniAudio]);
const MiniAudioPlayerComponent = React.useMemo(() => withOverride(uiOverrides?.miniAudioPlayer, MiniAudioPlayer), [uiOverrides?.miniAudioPlayer]);
const updateStatesToInitialValues = async () => {
const initialValues = initialValuesState;
const updateFunctions = getAllParams();
for (const key in initialValues) {
if (Object.prototype.hasOwnProperty.call(initialValues, key)) {
const updateFunctionName = `update${key.charAt(0).toUpperCase() + key.slice(1)}`;
const updateFunction = updateFunctions[updateFunctionName];
if (typeof updateFunction === "function") {
try {
updateFunction(initialValues[key]);
}
catch {
// Do nothing
}
}
}
}
};
//logic to join room using socket
async function joinRoom(data) {
const { socket, roomName, islevel, member, sec, apiUserName } = data;
try {
// Emit the joinRoom event to the server using the provided socket
const response = await joinRoomClient({
socket,
roomName,
islevel,
member,
sec,
apiUserName,
});
return response;
}
catch (error) {
// Handle and log errors during the joinRoom process
console.log("error", error);
throw new Error("Failed to join the room. Please check your connection and try again.");
// throw new Error('Failed to join the room. Please check your connection and try again.');
}
}
registerGlobals(); // Register globals for WebRTC
//validated is true if the user has entered the correct details and checked from the server
const [validated, setValidated] = useState(useLocalUIMode); // Validated state as boolean
// UseRef hooks with type annotations
const localUIMode = useRef(useLocalUIMode); // Local UI mode (desktop or touch) as boolean
const socket = useRef({}); // Socket for the media server, type Socket or null
const localSocket = useRef(null); // Local socket for the media server, type Socket or null
const roomData = useRef(null); // Room data, type ResponseJoinRoom or null
const device = useRef(null); // Mediasoup Device, type Device or null
// String references with useRef
const apiUserName = useRef(""); // API username, type string
const apiToken = useRef(""); // API token, type string
const link = useRef(""); // Link to the media server, type string
//Room Details
const roomName = useRef(""); // Room name as string
const member = useRef(useSeed && seedData?.member ? seedData?.member : ""); // Member name as string
const adminPasscode = useRef(""); // Admin passcode as string
const islevel = useRef(useSeed && seedData?.member
? seedData.member === seedData?.host
? "2"
: "1"
: "1"); // Level of the user as string
const coHost = useRef(""); // Co-host as string
const coHostResponsibility = useRef([
{ name: "participants", value: false, dedicated: false },
{ name: "media", value: false, dedicated: false },
{ name: "waiting", value: false, dedicated: false },
{ name: "chat", value: false, dedicated: false },
]); // Array of co-host responsibilities
const youAreCoHost = useRef(coHost.current ? coHost.current === member.current : false); // True if the user is a co-host as boolean
const youAreHost = useRef(islevel ? islevel.current === "2" : false); // True if the user is a host as boolean
const confirmedToRecord = useRef(false); // True if the user has confirmed to record as boolean
const meetingDisplayType = useRef("media"); // Meeting display type as string
const meetingVideoOptimized = useRef(false); // True if the meeting video is optimized as boolean
const eventType = useRef(useSeed && seedData?.eventType ? seedData?.eventType : "webinar"); // Event type as string
const participants = useRef(useSeed && seedData?.participants ? seedData?.participants : []); // Array of participants
const filteredParticipants = useRef(participants.current); // Filtered participants as array of Participant
const participantsCounter = useRef(0); // Participants counter as number
const participantsFilter = useRef(""); // Participants filter as string
// Media and Room Details
const consume_sockets = useRef([]); // Array of consume sockets
const rtpCapabilities = useRef(null); // RTP capabilities from MediaSoup, type RtpCapabilities or null
const roomRecvIPs = useRef([]); // Receiving IPs (domains) for the room consumer as strings
const meetingRoomParams = useRef(null); // Room parameters for the meeting/event room, type MeetingRoomParams or null
const itemPageLimit = useRef(4); // Number of items to show per page in the media display as number
const audioOnlyRoom = useRef(false); // True if the room is audio-only and does not support video as boolean
const addForBasic = useRef(false); // True if the room supports few producers as boolean
const screenPageLimit = useRef(4); // Number of people on the side-view of screen share as number
const shareScreenStarted = useRef(false); // True if screen share has started and started remotely as boolean
const shared = useRef(false); // True if screen share has started and started locally as boolean
const targetOrientation = useRef("landscape"); // Orientation of the media to be captured as string
const targetResolution = useRef("sd"); // Resolution of the media to be captured as string
const targetResolutionHost = useRef("sd"); // Resolution of the host media to be captured as string
const vidCons = useRef({ width: 640, height: 360 }); // Constraints for video capture as array of VidConsType
const frameRate = useRef(10); // Frame rate for video capture as number
const hParams = useRef({}); // Host video encoding parameters, type HParamsType or null
const vParams = useRef({}); // Rest of members video encoding parameters, type VParamsType or null
const screenParams = useRef({}); // Screen share encoding parameters, type ScreenParamsType or null
const aParams = useRef({}); // Audio encoding parameters, type AParamsType or null
//more room details
// Room Details - Recording
const recordingAudioPausesLimit = useRef(0); // Number of pauses allowed for audio recording
const recordingAudioPausesCount = useRef(0); // Number of pauses for audio recording
const recordingAudioSupport = useRef(false); // True if the room supports audio recording
const recordingAudioPeopleLimit = useRef(0); // Number of people allowed for audio recording
const recordingAudioParticipantsTimeLimit = useRef(0); // Time limit for audio recording
const recordingVideoPausesCount = useRef(0); // Number of pauses for video recording
const recordingVideoPausesLimit = useRef(0); // Number of pauses allowed for video recording
const recordingVideoSupport = useRef(false); // True if the room supports video recording
const recordingVideoPeopleLimit = useRef(0); // Number of people allowed for video recording
const recordingVideoParticipantsTimeLimit = useRef(0); // Time limit for video recording
const recordingAllParticipantsSupport = useRef(false); // True if the room supports recording all participants
const recordingVideoParticipantsSupport = useRef(false); // True if the room supports recording video participants
const recordingAllParticipantsFullRoomSupport = useRef(false); // True if the room supports recording all participants in full room
const recordingVideoParticipantsFullRoomSupport = useRef(false); // True if the room supports recording video participants in full room
const recordingPreferredOrientation = useRef("landscape"); // Preferred orientation for recording
const recordingSupportForOtherOrientation = useRef(false); // True if the room supports recording for other orientations
const recordingMultiFormatsSupport = useRef(false); // True if the room supports recording multiple formats
// User Recording Parameters
const userRecordingParams = useRef({
mainSpecs: {
mediaOptions: "video", // 'audio', 'video',
audioOptions: "all", // 'all', 'onScreen', 'host'
videoOptions: "all", // 'all', 'mainScreen'
videoType: "fullDisplay", // 'all', 'bestDisplay', 'fullDisplay'
videoOptimized: false, // true, false
recordingDisplayType: "media", // 'media', 'video', 'all'
addHLS: false, // true, false
},
dispSpecs: {
nameTags: true, // true, false
backgroundColor: "#000000", // '#000000', '#ffffff'
nameTagsColor: "#ffffff", // '#000000', '#ffffff'
orientationVideo: "portrait", // 'landscape', 'portrait', 'all'
},
}); // User recording parameters with type UserRecordingParams
// More Room Details - Recording
const canRecord = useRef(false); // True if the user can record
const startReport = useRef(false); // True if the user has started recording
const endReport = useRef(false); // True if the user has stopped recording
const recordTimerInterval = useRef(null); // Interval for the recording timer
const recordStartTime = useRef(0); // Start time for the recording timer as timestamp or null
const recordElapsedTime = useRef(0); // Elapsed time for the recording timer
const isTimerRunning = useRef(false); // True if the recording timer is running
const canPauseResume = useRef(false); // True if the user can pause/resume recording
const recordChangeSeconds = useRef(15000); // Number of seconds to change the recording timer by
const pauseLimit = useRef(0); // Number of pauses allowed for recording
const pauseRecordCount = useRef(0); // Number of pauses for recording
const canLaunchRecord = useRef(true); // True if the user can launch recording
const stopLaunchRecord = useRef(false); // True if the user can stop recording
//misc variables
// State and references with type annotations
const firstAll = useRef(false); // True if it is the first time getting all parameters
const updateMainWindow = useRef(false); // Update main window
const first_round = useRef(false); // True if it is the first round of screen share
const landScaped = useRef(false); // True if the screen share is in landscape mode
const lock_screen = useRef(false); // True if the screen is locked in place for screen share
const screenId = useRef(""); // Screen share producer ID
const allVideoStreams = useRef([]); // Array of all video streams
const newLimitedStreams = useRef([]); // Array of new limited streams
const newLimitedStreamsIDs = useRef([]); // Array of new limited stream IDs
const activeSounds = useRef([]); // Array of active sounds
const screenShareIDStream = useRef(""); // Screen share stream ID
const screenShareNameStream = useRef(""); // Screen share stream name
const adminIDStream = useRef(""); // Admin stream ID
const adminNameStream = useRef(""); // Admin stream name
const youYouStream = useRef([]); // YouYou (own) stream
const youYouStreamIDs = useRef([]); // Array of YouYou (own) stream IDs
const localStream = useRef(null); // Local stream
const recordStarted = useRef(false); // True if recording has started
const recordResumed = useRef(false); // True if recording has resumed
const recordPaused = useRef(false); // True if recording has paused
const recordStopped = useRef(false); // True if recording has stopped
const adminRestrictSetting = useRef(false); // Admin's restrict setting
const videoRequestState = useRef(null); // Video request state as string or null
const videoRequestTime = useRef(0); // Video request time
const videoAction = useRef(false); // Video action as string
const localStreamVideo = useRef(null); // Local stream video
const userDefaultVideoInputDevice = useRef(""); // User's default video input device
const currentFacingMode = useRef("user"); // Current facing mode of the video input device
const prevFacingMode = useRef("user"); // Previous facing mode of the video input device
const defVideoID = useRef(""); // Default video ID
const allowed = useRef(false); // True if the user is allowed to turn on their camera
const dispActiveNames = useRef([]); // Display active names
const p_dispActiveNames = useRef([]); // Display active names (previous)
const activeNames = useRef([]); // Active names
const prevActiveNames = useRef([]); // Active names (previous)
const p_activeNames = useRef([]); // Active names (previous)
const membersReceived = useRef(false); // True if members have been received
const deferScreenReceived = useRef(false); // True if receiving the screen share has been deferred
const hostFirstSwitch = useRef(false); // True if the host has switched to the main screen
const micAction = useRef(false); // True if the user has requested to unmute
const screenAction = useRef(false); // True if the user has requested to share their screen
const chatAction = useRef(false); // True if the user has requested to chat
const audioRequestState = useRef(null); // Audio request state as string or null
const screenRequestState = useRef(null); // Screen request state as string or null
const chatRequestState = useRef(null); // Chat request state as string or null
const audioRequestTime = useRef(0); // Audio request time
const screenRequestTime = useRef(0); // Screen request time
const chatRequestTime = useRef(0); // Chat request time
const updateRequestIntervalSeconds = useRef(240); // Update request interval in seconds
const oldSoundIds = useRef([]); // Array of old sound IDs
const hostLabel = useRef("Host"); // Host label as string
const mainScreenFilled = useRef(false); // True if the main screen is filled
const localStreamScreen = useRef(null); // Local stream screen
const [screenAlreadyOn, setScreenAlreadyOn] = useState(false); // True if the screen is already on
const [chatAlreadyOn, setChatAlreadyOn] = useState(false); // True if the chat is already on
const redirectURL = useRef(""); // Redirect URL as string or null
const oldAllStreams = useRef([]); // Array of old all streams
const adminVidID = useRef(""); // Admin video ID as string or null
const streamNames = useRef([]); // Array of stream names
const non_alVideoStreams = useRef([]); // Array of non-al video streams
const sortAudioLoudness = useRef(false); // True if audio loudness is sorted
const audioDecibels = useRef([]); // Array of audio decibels
const mixed_alVideoStreams = useRef([]); // Array of mixed al video streams
const non_alVideoStreams_muted = useRef([]); // Array of non-al video streams muted
const paginatedStreams = useRef([]); // Array of paginated streams
const localStreamAudio = useRef(null); // Local stream audio
const defAudioID = useRef(""); // Default audio ID as string or null
const userDefaultAudioInputDevice = useRef(""); // User's default audio input device
const userDefaultAudioOutputDevice = useRef(""); // User's default audio output device
const prevAudioInputDevice = useRef(""); // Previous audio input device
const prevVideoInputDevice = useRef(""); // Previous video input device
const audioPaused = useRef(false); // True if audio is paused
const mainScreenPerson = useRef(""); // Main screen person as string
const adminOnMainScreen = useRef(false); // True if the admin is on the main screen
const screenStates = useRef([
{
mainScreenPerson: "",
mainScreenProducerId: "",
mainScreenFilled: false,
adminOnMainScreen: false,
},
]); // Array of screen states
const prevScreenStates = useRef([
{
mainScreenPerson: "",
mainScreenProducerId: "",
mainScreenFilled: false,
adminOnMainScreen: false,
},
]); // Array of previous screen states
const updateDateState = useRef(null); // Date state for updating the screen states as number or null
const lastUpdate = useRef(null); // Last update time for updating the screen states as number or null
const nForReadjustRecord = useRef(0); // Number of times for readjusting the recording
const fixedPageLimit = useRef(4); // Fixed page limit for pagination
const removeAltGrid = useRef(false); // True if the alt grid should be removed
const nForReadjust = useRef(0); // Number of times for readjusting the recording
const reorderInterval = useRef(30000); // Reorder interval in milliseconds
const fastReorderInterval = useRef(10000); // Fast reorder interval in milliseconds
const lastReorderTime = useRef(0); // Last reorder time in milliseconds
const audStreamNames = useRef([]); // Array of audio stream names as strings
const currentUserPage = useRef(0); // Current user page
const [mainHeightWidth, setMainHeightWidth] = useState(eventType.current === "webinar"
? 67
: eventType.current === "broadcast"
? 100
: 0); // Main height and width as number
const prevMainHeightWidth = useRef(mainHeightWidth); // Previous main height and width
const prevDoPaginate = useRef(false); // Previous doPaginate as boolean
const doPaginate = useRef(false); // Do paginate as boolean
const shareEnded = useRef(false); // True if the share has ended
const lStreams = useRef([]); // Array of limited streams
const chatRefStreams = useRef([]); // Array of chat ref streams
const [controlHeight, setControlHeight] = useState(0); // Control height as number
const [measuredControlBarHeightPx, setMeasuredControlBarHeightPx] = useState(0);
const isWideScreen = useRef(false); // True if the screen is wide
const isMediumScreen = useRef(false); // True if the screen is medium
const isSmallScreen = useRef(false); // True if the screen is small
const addGrid = useRef(false); // True if the grid should be added
const addAltGrid = useRef(false); // True if the alt grid should be added
const [gridRows, setGridRows] = useState(0); // Grid rows as number
const [gridCols, setGridCols] = useState(0); // Grid columns as number
const [altGridRows, setAltGridRows] = useState(0); // Alt grid rows as number
const [altGridCols, setAltGridCols] = useState(0); // Alt grid columns as number
const [numberPages, setNumberPages] = useState(0); // Number of pages as number
const currentStreams = useRef([]); // Array of current streams
const [showMiniView, setShowMiniView] = useState(false); // True if the mini view should be shown
const nStream = useRef(null); // New stream as MediaStream or null
const defer_receive = useRef(false); // True if receiving the stream has been deferred
const allAudioStreams = useRef([]); // Array of all audio streams
const remoteScreenStream = useRef([]); // Array of remote screen streams
const screenProducer = useRef(null); // Screen producer as Producer or null
const localScreenProducer = useRef(null); // Local screen producer as Producer or null
const gotAllVids = useRef(false); // True if all videos have been received
const paginationHeightWidth = useRef(40); // Pagination height/width as number
const paginationDirection = useRef("horizontal"); // Pagination direction as string
const gridSizes = useRef({
gridWidth: 0,
gridHeight: 0,
altGridWidth: 0,
altGridHeight: 0,
}); // Grid sizes with type GridSizes
const [, setGridSizesVersion] = useState(0);
const screenForceFullDisplay = useRef(false); // True if the screen should be forced to full display
const mainGridStream = useRef([]); // Array of main grid streams as JSX.Element[]
const [otherGridStreams, setOtherGridStreams] = useState([
[],
[],
]); // Other grid streams as 2D array of JSX.Element[]
const audioOnlyStreams = useRef([]); // Array of audio-only streams
const [translationStreams, setTranslationStreams] = useState([]); // Array of translation audio streams
const [videoInputs, setVideoInputs] = useState([]); // Video inputs as array of MediaDeviceInfo
const [audioInputs, setAudioInputs] = useState([]); // Audio inputs as array of MediaDeviceInfo
const [meetingProgressTime, setMeetingProgressTime] = useState("00:00:00"); // Meeting progress time as string
const meetingElapsedTime = useRef(0); // Meeting elapsed time as number
const ref_participants = useRef([]); // Array of participants as Participant[]
// All Participants - Room Details
const participantsAll = useRef([]); // All participants as an array of Participant
//update Room Details Functions
const updateValidated = (value) => {
setValidated(value);
};
const updateSocket = (value) => {
socket.current = value;
};
const updateL