import { useMutation, useQuery } from '@apollo/client'; import React, { useContext, useEffect } from 'react'; import { Session } from 'meteor/session'; import { getUserCurrent, GetUserCurrentResponse, getUserInfo, GetUserInfoResponse, userJoinMutation, } from './queries'; import { setAuthData } from '/imports/ui/core/local-states/useAuthData'; import MeetingEndedContainer from '../../meeting-ended/component'; import { setUserDataToSessionStorage } from './service'; import { LoadingContext } from '../../common/loading-screen/loading-screen-HOC/component'; import useDeduplicatedSubscription from '/imports/ui/core/hooks/useDeduplicatedSubscription'; import logger from '/imports/startup/client/logger'; import deviceInfo from '/imports/utils/deviceInfo'; const connectionTimeout = 60000; interface PresenceManagerContainerProps { children: React.ReactNode; } interface PresenceManagerProps extends PresenceManagerContainerProps { authToken: string; logoutUrl: string; meetingId: string; meetingName: string; userName: string; extId: string; userId: string; joinErrorCode: string; joinErrorMessage: string; joined: boolean; meetingEnded: boolean; endedReasonCode: string; endedBy: string; ejectReasonCode: string; bannerColor: string; bannerText: string; customLogoUrl: string; loggedOut: boolean; } const PresenceManager: React.FC = ({ authToken, children, logoutUrl, meetingId, meetingName, userName, extId, userId, joinErrorCode, joinErrorMessage, joined, meetingEnded, endedReasonCode, endedBy, ejectReasonCode, bannerColor, bannerText, customLogoUrl, loggedOut, }) => { const [allowToRender, setAllowToRender] = React.useState(false); const [dispatchUserJoin] = useMutation(userJoinMutation); const timeoutRef = React.useRef>(); const loadingContextInfo = useContext(LoadingContext); useEffect(() => { timeoutRef.current = setTimeout(() => { loadingContextInfo.setLoading(false, ''); throw new Error('Authentication timeout'); }, connectionTimeout); const urlParams = new URLSearchParams(window.location.search); const sessionToken = urlParams.get('sessionToken') as string; setAuthData({ meetingId, userId, authToken, logoutUrl, sessionToken, userName, extId, meetingName, }); setUserDataToSessionStorage({ meetingId, userId, authToken, logoutUrl, sessionToken, userName, extId, meetingName, customLogoUrl, }); }, []); useEffect(() => { if (bannerColor || bannerText) { Session.set('bannerText', bannerText); Session.set('bannerColor', bannerColor); } }, [bannerColor, bannerText]); useEffect(() => { if (authToken && !joined) { dispatchUserJoin({ variables: { authToken, clientType: 'HTML5', clientIsMobile: deviceInfo.isMobile, }, }); } }, [joined, authToken]); useEffect(() => { if (joined) { clearTimeout(timeoutRef.current); setAllowToRender(true); } }, [joined]); useEffect(() => { if (joinErrorCode) { loadingContextInfo.setLoading(false, ''); } }, [joinErrorCode, joinErrorMessage]); const errorCode = loggedOut ? 'user_logged_out_reason' : joinErrorCode || ejectReasonCode; return ( <> {allowToRender && !(meetingEnded || joinErrorCode || ejectReasonCode || loggedOut) ? children : null} { meetingEnded || joinErrorCode || ejectReasonCode || loggedOut ? ( ) : null } ); }; const PresenceManagerContainer: React.FC = ({ children }) => { const { loading, error, data } = useDeduplicatedSubscription(getUserCurrent); const { loading: userInfoLoading, error: userInfoError, data: userInfoData, } = useQuery(getUserInfo); const loadingContextInfo = useContext(LoadingContext); if (loading || userInfoLoading) return null; if (error || userInfoError) { loadingContextInfo.setLoading(false, ''); logger.debug(`Error on user authentication: ${error}`); throw new Error('Error on user authentication'); } if (!data || data.user_current.length === 0) return null; if (!userInfoData || userInfoData.meeting.length === 0 || userInfoData.user_current.length === 0) return null; const { authToken, joinErrorCode, joinErrorMessage, joined, ejectReasonCode, meeting, loggedOut, } = data.user_current[0]; const { logoutUrl, meetingId, name: meetingName, bannerColor, bannerText, customLogoUrl, } = userInfoData.meeting[0]; const { extId, name: userName, userId } = userInfoData.user_current[0]; return ( {children} ); }; export default PresenceManagerContainer;