bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/presentation/container.jsx

167 lines
5.9 KiB
React
Raw Normal View History

import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { withTracker } from 'meteor/react-meteor-data';
import { notify } from '/imports/ui/services/notification';
2021-06-09 21:49:59 +08:00
import PresentationService from './service';
2020-04-08 05:19:16 +08:00
import { Slides } from '/imports/api/slides';
2021-06-09 21:49:59 +08:00
import Presentation from '/imports/ui/components/presentation/component';
import PresentationToolbarService from './presentation-toolbar/service';
import { UsersContext } from '../components-data/users-context/context';
import Auth from '/imports/ui/services/auth';
import Meetings from '/imports/api/meetings';
import getFromUserSettings from '/imports/ui/services/users-settings';
2021-09-11 04:48:52 +08:00
import {
layoutSelect,
layoutSelectInput,
layoutSelectOutput,
layoutDispatch,
} from '../layout/context';
import lockContextContainer from '/imports/ui/components/lock-viewers/context/container';
import WhiteboardService from '/imports/ui/components/whiteboard/service';
import { DEVICE_TYPE } from '../layout/enums';
import MediaService from '../media/service';
const PresentationContainer = ({
2023-06-29 03:06:19 +08:00
presentationIsOpen, presentationPodIds, mountPresentation, layoutType, ...props
}) => {
2021-09-11 04:48:52 +08:00
const cameraDock = layoutSelectInput((i) => i.cameraDock);
const presentation = layoutSelectOutput((i) => i.presentation);
const fullscreen = layoutSelect((i) => i.fullscreen);
const deviceType = layoutSelect((i) => i.deviceType);
const layoutContextDispatch = layoutDispatch();
const { numCameras } = cameraDock;
const { element } = fullscreen;
const fullscreenElementId = 'Presentation';
2021-07-06 19:28:17 +08:00
const fullscreenContext = (element === fullscreenElementId);
2021-08-28 02:32:56 +08:00
const isIphone = !!(navigator.userAgent.match(/iPhone/i));
const usingUsersContext = useContext(UsersContext);
const { users } = usingUsersContext;
2021-04-15 20:12:21 +08:00
const currentUser = users[Auth.meetingID][Auth.userID];
const userIsPresenter = currentUser.presenter;
return (
<Presentation
{
...{
layoutContextDispatch,
numCameras,
...props,
userIsPresenter,
presentationBounds: presentation,
layoutType,
fullscreenContext,
fullscreenElementId,
isMobile: deviceType === DEVICE_TYPE.MOBILE,
isIphone,
presentationIsOpen,
}
}
/>
);
};
2020-04-08 05:19:16 +08:00
const APP_CONFIG = Meteor.settings.public.app;
const PRELOAD_NEXT_SLIDE = APP_CONFIG.preloadNextSlides;
const fetchedpresentation = {};
export default lockContextContainer(
2022-06-02 23:00:28 +08:00
withTracker(({ podId, presentationIsOpen, userLocks }) => {
const currentSlide = PresentationService.getCurrentSlide(podId);
const numPages = PresentationService.getSlidesLength(podId);
const presentationIsDownloadable = PresentationService.isPresentationDownloadable(podId);
const isViewersCursorLocked = userLocks?.hideViewersCursor;
2023-06-06 04:02:06 +08:00
const isViewersAnnotationsLocked = userLocks?.hideViewersAnnotation;
let slidePosition;
if (currentSlide) {
const {
2020-04-08 05:19:16 +08:00
presentationId,
id: slideId,
} = currentSlide;
slidePosition = PresentationService.getSlidePosition(podId, presentationId, slideId);
if (PRELOAD_NEXT_SLIDE && !fetchedpresentation[presentationId]) {
fetchedpresentation[presentationId] = {
canFetch: true,
fetchedSlide: {},
};
}
const currentSlideNum = currentSlide.num;
const presentation = fetchedpresentation[presentationId];
2020-04-08 05:19:16 +08:00
if (PRELOAD_NEXT_SLIDE
&& !presentation.fetchedSlide[currentSlide.num + PRELOAD_NEXT_SLIDE]
&& presentation.canFetch) {
const slidesToFetch = Slides.find({
podId,
presentationId,
num: {
$in: Array(PRELOAD_NEXT_SLIDE).fill(1).map((v, idx) => currentSlideNum + (idx + 1)),
},
}).fetch();
const promiseImageGet = slidesToFetch
.filter((s) => !fetchedpresentation[presentationId].fetchedSlide[s.num])
.map(async (slide) => {
if (presentation.canFetch) presentation.canFetch = false;
const image = await fetch(slide.imageUri);
if (image.ok) {
presentation.fetchedSlide[slide.num] = true;
}
});
Promise.all(promiseImageGet).then(() => {
presentation.canFetch = true;
2020-04-08 05:19:16 +08:00
});
}
2020-04-08 05:19:16 +08:00
}
2023-04-13 21:56:54 +08:00
const currentPresentation = PresentationService.getCurrentPresentation(podId);
2024-03-04 21:26:50 +08:00
const downloadPresentationUri = currentPresentation
? `${APP_CONFIG.bbbWebBase}/${currentPresentation?.originalFileURI}`
: null;
return {
currentSlide,
slidePosition,
2024-03-04 21:26:50 +08:00
downloadPresentationUri,
multiUser:
(WhiteboardService.hasMultiUserAccess(currentSlide && currentSlide.id, Auth.userID)
|| WhiteboardService.isMultiUserActive(currentSlide?.id)
) && presentationIsOpen,
presentationIsDownloadable,
mountPresentation: !!currentSlide,
2023-04-13 21:56:54 +08:00
currentPresentation,
currentPresentationId: currentPresentation?.id,
numPages,
notify,
zoomSlide: PresentationToolbarService.zoomSlide,
podId,
publishedPoll: Meetings.findOne({ meetingId: Auth.meetingID }, {
fields: {
publishedPoll: 1,
},
}).publishedPoll,
restoreOnUpdate: getFromUserSettings(
'bbb_force_restore_presentation_on_new_events',
Meteor.settings.public.presentation.restoreOnUpdate,
),
addWhiteboardGlobalAccess: WhiteboardService.addGlobalAccess,
removeWhiteboardGlobalAccess: WhiteboardService.removeGlobalAccess,
multiUserSize: WhiteboardService.getMultiUserSize(currentSlide?.id),
isViewersCursorLocked,
setPresentationIsOpen: MediaService.setPresentationIsOpen,
2023-06-06 04:02:06 +08:00
isViewersAnnotationsLocked,
};
})(PresentationContainer),
);
PresentationContainer.propTypes = {
presentationPodIds: PropTypes.arrayOf(PropTypes.shape({
podId: PropTypes.string.isRequired,
})).isRequired,
presentationIsOpen: PropTypes.bool.isRequired,
mountPresentation: PropTypes.bool.isRequired,
};