2024-07-19 20:52:55 +08:00
|
|
|
import React, { useEffect } from 'react';
|
|
|
|
import { useMutation, useReactiveVar } from '@apollo/client';
|
2024-04-20 04:34:43 +08:00
|
|
|
import useMeeting from '/imports/ui/core/hooks/useMeeting';
|
|
|
|
import useCurrentUser from '/imports/ui/core/hooks/useCurrentUser';
|
|
|
|
import {
|
|
|
|
useCurrentVideoPageIndex,
|
|
|
|
useExitVideo,
|
2024-05-02 03:48:12 +08:00
|
|
|
useInfo,
|
2024-07-19 20:52:55 +08:00
|
|
|
useIsPaginationEnabled,
|
2024-04-20 04:34:43 +08:00
|
|
|
useIsUserLocked,
|
2024-05-02 03:48:12 +08:00
|
|
|
useLockUser,
|
2024-07-19 20:52:55 +08:00
|
|
|
useMyPageSize,
|
2024-06-14 22:35:53 +08:00
|
|
|
useMyRole,
|
2024-05-02 03:48:12 +08:00
|
|
|
useStopVideo,
|
2024-04-20 04:34:43 +08:00
|
|
|
useVideoStreams,
|
|
|
|
} from './hooks';
|
2024-05-02 03:30:29 +08:00
|
|
|
import { CAMERA_BROADCAST_START } from './mutations';
|
2024-04-20 04:34:43 +08:00
|
|
|
import VideoProvider from './component';
|
|
|
|
import VideoService from './service';
|
2024-05-02 03:48:12 +08:00
|
|
|
import { Output } from '/imports/ui/components/layout/layoutTypes';
|
|
|
|
import { VideoItem } from './types';
|
2024-05-29 21:26:11 +08:00
|
|
|
import { debounce } from '/imports/utils/debounce';
|
|
|
|
import WebRtcPeer from '/imports/ui/services/webrtc-base/peer';
|
2024-05-17 22:17:27 +08:00
|
|
|
import useSettings from '/imports/ui/services/settings/hooks/useSettings';
|
|
|
|
import { SETTINGS } from '/imports/ui/services/settings/enums';
|
2024-07-19 20:52:55 +08:00
|
|
|
import { useStorageKey } from '/imports/ui/services/storage/hooks';
|
|
|
|
import ConnectionStatus from '/imports/ui/core/graphql/singletons/connectionStatus';
|
|
|
|
import { setVideoState, useVideoState } from './state';
|
|
|
|
import { VIDEO_TYPES } from './enums';
|
2024-04-20 04:34:43 +08:00
|
|
|
|
2024-06-17 19:58:33 +08:00
|
|
|
interface VideoProviderContainerProps {
|
2024-05-02 03:48:12 +08:00
|
|
|
focusedId: string;
|
|
|
|
swapLayout: boolean;
|
|
|
|
cameraDock: Output['cameraDock'];
|
|
|
|
handleVideoFocus:(id: string) => void;
|
2024-04-20 04:34:43 +08:00
|
|
|
}
|
|
|
|
|
2024-06-17 19:58:33 +08:00
|
|
|
const VideoProviderContainer: React.FC<VideoProviderContainerProps> = (props) => {
|
2024-04-20 04:34:43 +08:00
|
|
|
const {
|
2024-05-02 03:48:12 +08:00
|
|
|
cameraDock,
|
|
|
|
focusedId,
|
|
|
|
handleVideoFocus,
|
|
|
|
swapLayout,
|
2024-04-20 04:34:43 +08:00
|
|
|
} = props;
|
|
|
|
const [cameraBroadcastStart] = useMutation(CAMERA_BROADCAST_START);
|
|
|
|
|
|
|
|
const sendUserShareWebcam = (cameraId: string) => {
|
|
|
|
return cameraBroadcastStart({ variables: { cameraId } });
|
|
|
|
};
|
|
|
|
|
|
|
|
const playStart = (cameraId: string) => {
|
|
|
|
if (VideoService.isLocalStream(cameraId)) {
|
|
|
|
sendUserShareWebcam(cameraId).then(() => {
|
2024-05-07 04:05:37 +08:00
|
|
|
VideoService.joinedVideo();
|
2024-04-20 04:34:43 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-05-29 21:26:11 +08:00
|
|
|
const {
|
|
|
|
debounceTime: CAMERA_QUALITY_THR_DEBOUNCE = 2500,
|
|
|
|
} = window.meetingClientSettings.public.kurento.cameraQualityThresholds;
|
|
|
|
|
|
|
|
const applyCameraProfile = debounce(
|
|
|
|
VideoService.applyCameraProfile,
|
|
|
|
CAMERA_QUALITY_THR_DEBOUNCE,
|
|
|
|
{ leading: false, trailing: true },
|
|
|
|
);
|
|
|
|
|
2024-04-20 04:34:43 +08:00
|
|
|
const { data: currentMeeting } = useMeeting((m) => ({
|
|
|
|
usersPolicies: m.usersPolicies,
|
|
|
|
}));
|
|
|
|
|
|
|
|
const { data: currentUser } = useCurrentUser((user) => ({
|
|
|
|
locked: user.locked,
|
2024-05-17 22:17:27 +08:00
|
|
|
userId: user.userId,
|
2024-04-20 04:34:43 +08:00
|
|
|
}));
|
|
|
|
|
2024-05-17 22:17:27 +08:00
|
|
|
const currentUserId = currentUser?.userId ?? '';
|
|
|
|
// @ts-ignore Untyped object
|
|
|
|
const { paginationEnabled } = useSettings(SETTINGS.APPLICATION);
|
|
|
|
// @ts-ignore Untyped object
|
|
|
|
const { viewParticipantsWebcams } = useSettings(SETTINGS.DATA_SAVING);
|
2024-07-19 20:52:55 +08:00
|
|
|
|
|
|
|
const isClientConnected = useReactiveVar(ConnectionStatus.getConnectedStatusVar());
|
2024-05-17 22:17:27 +08:00
|
|
|
|
2024-04-20 04:34:43 +08:00
|
|
|
const {
|
|
|
|
streams,
|
|
|
|
gridUsers,
|
|
|
|
totalNumberOfStreams,
|
2024-07-19 20:52:55 +08:00
|
|
|
totalNumberOfOtherStreams,
|
|
|
|
} = useVideoStreams();
|
2024-04-20 04:34:43 +08:00
|
|
|
|
2024-05-02 03:48:12 +08:00
|
|
|
let usersVideo: VideoItem[] = streams;
|
2024-04-20 04:34:43 +08:00
|
|
|
|
2024-07-19 20:52:55 +08:00
|
|
|
if (gridUsers.length > 0) {
|
2024-04-20 04:34:43 +08:00
|
|
|
usersVideo = usersVideo.concat(gridUsers);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
currentMeeting?.usersPolicies?.webcamsOnlyForModerator
|
|
|
|
&& currentUser?.locked
|
|
|
|
) {
|
2024-05-02 01:14:10 +08:00
|
|
|
usersVideo = usersVideo.filter(
|
2024-06-08 04:41:36 +08:00
|
|
|
(uv) => (
|
|
|
|
(
|
2024-07-19 20:52:55 +08:00
|
|
|
(uv.type === VIDEO_TYPES.STREAM && uv.user.isModerator)
|
|
|
|
|| (uv.type === VIDEO_TYPES.GRID && uv.isModerator)
|
2024-06-08 04:41:36 +08:00
|
|
|
)
|
|
|
|
|| uv.userId === currentUserId
|
|
|
|
),
|
2024-05-02 01:14:10 +08:00
|
|
|
);
|
2024-04-20 04:34:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const isUserLocked = useIsUserLocked();
|
|
|
|
const currentVideoPageIndex = useCurrentVideoPageIndex();
|
|
|
|
const exitVideo = useExitVideo();
|
2024-05-02 03:48:12 +08:00
|
|
|
const lockUser = useLockUser();
|
|
|
|
const stopVideo = useStopVideo();
|
|
|
|
const info = useInfo();
|
2024-06-14 22:35:53 +08:00
|
|
|
const myRole = useMyRole();
|
2024-07-19 20:52:55 +08:00
|
|
|
const myPageSize = useMyPageSize();
|
|
|
|
const { numberOfPages } = useVideoState();
|
|
|
|
const isPaginationEnabled = useIsPaginationEnabled();
|
|
|
|
const isGridEnabled = useStorageKey('isGridEnabled') as boolean;
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (isPaginationEnabled) {
|
|
|
|
const total = totalNumberOfOtherStreams ?? 0;
|
|
|
|
const nOfPages = Math.ceil(total / myPageSize);
|
|
|
|
|
|
|
|
if (nOfPages !== numberOfPages) {
|
|
|
|
setVideoState({ numberOfPages: nOfPages });
|
|
|
|
|
|
|
|
if (nOfPages === 0) {
|
|
|
|
setVideoState({ currentVideoPageIndex: 0 });
|
|
|
|
} else if (currentVideoPageIndex + 1 > nOfPages) {
|
|
|
|
VideoService.getPreviousVideoPage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
setVideoState({
|
|
|
|
numberOfPages: 0,
|
|
|
|
currentVideoPageIndex: 0,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}, [myPageSize, numberOfPages, totalNumberOfOtherStreams, isPaginationEnabled]);
|
2024-05-02 03:48:12 +08:00
|
|
|
|
|
|
|
if (!usersVideo.length && !isGridEnabled) return null;
|
2024-04-20 04:34:43 +08:00
|
|
|
|
|
|
|
return (
|
2024-05-02 03:48:12 +08:00
|
|
|
<VideoProvider
|
|
|
|
cameraDock={cameraDock}
|
|
|
|
focusedId={focusedId}
|
|
|
|
handleVideoFocus={handleVideoFocus}
|
2024-05-02 03:30:29 +08:00
|
|
|
isGridEnabled={isGridEnabled}
|
2024-07-19 20:52:55 +08:00
|
|
|
isClientConnected={isClientConnected}
|
2024-05-02 03:48:12 +08:00
|
|
|
swapLayout={swapLayout}
|
|
|
|
currentUserId={currentUserId}
|
|
|
|
paginationEnabled={paginationEnabled}
|
|
|
|
viewParticipantsWebcams={viewParticipantsWebcams}
|
|
|
|
totalNumberOfStreams={totalNumberOfStreams}
|
|
|
|
isUserLocked={isUserLocked}
|
|
|
|
currentVideoPageIndex={currentVideoPageIndex}
|
|
|
|
streams={usersVideo}
|
|
|
|
info={info}
|
|
|
|
playStart={playStart}
|
|
|
|
exitVideo={exitVideo}
|
|
|
|
lockUser={lockUser}
|
|
|
|
stopVideo={stopVideo}
|
2024-05-29 21:26:11 +08:00
|
|
|
applyCameraProfile={applyCameraProfile as (peer: WebRtcPeer, profileId: string) => void}
|
2024-06-14 22:35:53 +08:00
|
|
|
myRole={myRole}
|
2024-05-02 03:48:12 +08:00
|
|
|
/>
|
2024-04-20 04:34:43 +08:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2024-06-17 19:58:33 +08:00
|
|
|
export default VideoProviderContainer;
|