bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/join-handler/presenceManager/component.tsx
Tainan Felipe 3bc40df230
Add: useDeduplicatedSubscription hook (#20376)
* Add: useDeduplicatedSubscription hook

* Fix: TS error

* Add: components using useDeduplicatedSubscription

* Change: Move to useDeduplicatedSubscription

* Change: unsubscribe logic to own useEffect

* Change: remove file import over package

* Fix: TS errors

* Fix: private chat not loading

* Change: revert changes on queries

* Fix: eslint error

* Remove: html-webpack-plugin package

* Fix: external video

* Add: comment about the stringToHash function

* Fix: video player showing tools over presentation
2024-06-04 10:40:54 -03:00

223 lines
5.7 KiB
TypeScript

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<PresenceManagerProps> = ({
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<ReturnType<typeof setTimeout>>();
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
? (
<MeetingEndedContainer
meetingEndedCode={endedReasonCode}
endedBy={endedBy}
joinErrorCode={errorCode}
/>
)
: null
}
</>
);
};
const PresenceManagerContainer: React.FC<PresenceManagerContainerProps> = ({ children }) => {
const { loading, error, data } = useDeduplicatedSubscription<GetUserCurrentResponse>(getUserCurrent);
const {
loading: userInfoLoading,
error: userInfoError,
data: userInfoData,
} = useQuery<GetUserInfoResponse>(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 (
<PresenceManager
authToken={authToken}
logoutUrl={logoutUrl}
meetingId={meetingId}
meetingName={meetingName}
userName={userName}
extId={extId}
userId={userId}
joined={joined}
joinErrorCode={joinErrorCode}
joinErrorMessage={joinErrorMessage}
meetingEnded={meeting.ended}
endedReasonCode={meeting.endedReasonCode}
endedBy={meeting.endedByUserName}
ejectReasonCode={ejectReasonCode}
bannerColor={bannerColor}
bannerText={bannerText}
loggedOut={loggedOut}
customLogoUrl={customLogoUrl}
>
{children}
</PresenceManager>
);
};
export default PresenceManagerContainer;