Moved part of the presentation display calculations to the server side
This commit is contained in:
parent
d57f60fe09
commit
537175dad2
0
bigbluebutton-html5/imports/api/2.0/meetings/server/methods/endMeeting.js
Executable file → Normal file
0
bigbluebutton-html5/imports/api/2.0/meetings/server/methods/endMeeting.js
Executable file → Normal file
14
bigbluebutton-html5/imports/api/2.0/slides/server/helpers.js
Normal file
14
bigbluebutton-html5/imports/api/2.0/slides/server/helpers.js
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
const calculateSlideData = (slideData) => {
|
||||
const { width, height, xOffset, yOffset, widthRatio, heightRatio } = slideData;
|
||||
|
||||
// calculating viewBox and offsets for the current presentation
|
||||
return {
|
||||
x: ((-xOffset * 2) * width) / 100,
|
||||
y: ((-yOffset * 2) * height) / 100,
|
||||
viewBoxWidth: (width * widthRatio) / 100,
|
||||
viewBoxHeight: (height * heightRatio) / 100,
|
||||
};
|
||||
};
|
||||
|
||||
export default calculateSlideData;
|
@ -6,6 +6,7 @@ import RedisPubSub from '/imports/startup/server/redis2x';
|
||||
import Slides from '/imports/api/2.0/slides';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import { SVG, PNG } from '/imports/utils/mimeTypes';
|
||||
import { calculateSlideData } from '/imports/api/2.0/slides/server/helpers';
|
||||
|
||||
const requestWhiteboardHistory = (meetingId, slideId) => {
|
||||
const REDIS_CONFIG = Meteor.settings.redis;
|
||||
@ -26,7 +27,9 @@ const fetchImageSizes = imageUri =>
|
||||
probe(imageUri)
|
||||
.then((result) => {
|
||||
if (!SUPPORTED_TYPES.includes(result.mime)) {
|
||||
throw `Invalid image type, received ${result.mime} expecting ${SUPPORTED_TYPES.join()}`;
|
||||
throw new Meteor.Error(
|
||||
'invalid-image-type', `received ${result.mime} expecting ${SUPPORTED_TYPES.join()}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
@ -90,8 +93,20 @@ export default function addSlide(meetingId, presentationId, slide) {
|
||||
|
||||
return fetchImageSizes(imageUri)
|
||||
.then(({ width, height }) => {
|
||||
modifier.$set.width = width;
|
||||
modifier.$set.height = height;
|
||||
// pre-calculating the width, height, and vieBox coordinates / dimensions
|
||||
// to unload the client-side
|
||||
const slideData = {
|
||||
width,
|
||||
height,
|
||||
xOffset: modifier.$set.xOffset,
|
||||
yOffset: modifier.$set.yOffset,
|
||||
widthRatio: modifier.$set.widthRatio,
|
||||
heightRatio: modifier.$set.heightRatio,
|
||||
};
|
||||
modifier.$set.calculatedData = calculateSlideData(slideData);
|
||||
modifier.$set.calculatedData.imageUri = imageUri;
|
||||
modifier.$set.calculatedData.width = width;
|
||||
modifier.$set.calculatedData.height = height;
|
||||
|
||||
return Slides.upsert(selector, modifier, cb);
|
||||
})
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { check } from 'meteor/check';
|
||||
import Slides from '/imports/api/2.0/slides';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import { calculateSlideData } from '/imports/api/2.0/slides/server/helpers';
|
||||
|
||||
export default function resizeSlide(meetingId, slide) {
|
||||
check(meetingId, String);
|
||||
@ -23,6 +24,24 @@ export default function resizeSlide(meetingId, slide) {
|
||||
},
|
||||
};
|
||||
|
||||
// fetching the current slide data
|
||||
// and pre-calculating the width, height, and vieBox coordinates / sizes
|
||||
// to reduce the client-side load
|
||||
const _slide = Slides.findOne(selector);
|
||||
const slideData = {
|
||||
width: _slide.calculatedData.width,
|
||||
height: _slide.calculatedData.height,
|
||||
xOffset,
|
||||
yOffset,
|
||||
widthRatio,
|
||||
heightRatio,
|
||||
};
|
||||
const calculatedData = calculateSlideData(slideData);
|
||||
calculatedData.imageUri = _slide.calculatedData.imageUri;
|
||||
calculatedData.width = _slide.calculatedData.width;
|
||||
calculatedData.height = _slide.calculatedData.height;
|
||||
modifier.$set.calculatedData = calculatedData;
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
if (err) {
|
||||
return Logger.error(`Resizing slide id=${pageId}: ${err}`);
|
||||
|
@ -96,8 +96,8 @@ export default class PresentationArea extends React.Component {
|
||||
}
|
||||
|
||||
calculateSize() {
|
||||
const originalWidth = this.props.currentSlide.width;
|
||||
const originalHeight = this.props.currentSlide.height;
|
||||
const originalWidth = this.props.currentSlide.calculatedData.width;
|
||||
const originalHeight = this.props.currentSlide.calculatedData.height;
|
||||
const { presentationHeight, presentationWidth } = this.state;
|
||||
|
||||
let adjustedWidth;
|
||||
@ -133,8 +133,9 @@ export default class PresentationArea extends React.Component {
|
||||
renderPresentationArea() {
|
||||
// sometimes tomcat publishes the slide url, but the actual file is not accessible (why?)
|
||||
if (this.props.currentSlide &&
|
||||
this.props.currentSlide.width &&
|
||||
this.props.currentSlide.height) {
|
||||
this.props.currentSlide.calculatedData &&
|
||||
this.props.currentSlide.calculatedData.width &&
|
||||
this.props.currentSlide.calculatedData.height) {
|
||||
// to control the size of the svg wrapper manually
|
||||
// and adjust cursor's thickness, so that svg didn't scale it automatically
|
||||
const adjustedSizes = this.calculateSize();
|
||||
@ -142,18 +143,16 @@ export default class PresentationArea extends React.Component {
|
||||
// a reference to the slide object
|
||||
const slideObj = this.props.currentSlide;
|
||||
|
||||
// svgWidth and svgHeight are needed to set the svg's coordinate system
|
||||
const svgWidth = slideObj.width;
|
||||
const svgHeight = slideObj.height;
|
||||
|
||||
// calculating viewBox and offsets for the current presentation
|
||||
const x = ((-slideObj.xOffset * 2) * svgWidth) / 100;
|
||||
const y = ((-slideObj.yOffset * 2) * svgHeight) / 100;
|
||||
const viewBoxWidth = (svgWidth * slideObj.widthRatio) / 100;
|
||||
const viewBoxHeight = (svgHeight * slideObj.heightRatio) / 100;
|
||||
|
||||
// Uri for the slide
|
||||
const imageUri = this.props.currentSlide.svgUri || this.props.currentSlide.pngUri;
|
||||
// retrieving the pre-calculated data from the slide object
|
||||
const {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
viewBoxWidth,
|
||||
viewBoxHeight,
|
||||
imageUri,
|
||||
} = slideObj.calculatedData;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -179,8 +178,8 @@ export default class PresentationArea extends React.Component {
|
||||
transitionLeaveTimeout={400}
|
||||
>
|
||||
<svg
|
||||
width={svgWidth}
|
||||
height={svgHeight}
|
||||
width={width}
|
||||
height={height}
|
||||
ref={(ref) => { if (ref != null) { this.svggroup = ref; } }}
|
||||
viewBox={`${x} ${y} ${viewBoxWidth} ${viewBoxHeight}`}
|
||||
version="1.1"
|
||||
@ -197,32 +196,32 @@ export default class PresentationArea extends React.Component {
|
||||
<Slide
|
||||
id="slideComponent"
|
||||
imageUri={imageUri}
|
||||
svgWidth={svgWidth}
|
||||
svgHeight={svgHeight}
|
||||
svgWidth={width}
|
||||
svgHeight={height}
|
||||
/>
|
||||
<AnnotationGroupContainer
|
||||
width={svgWidth}
|
||||
height={svgHeight}
|
||||
width={width}
|
||||
height={height}
|
||||
whiteboardId={slideObj.id}
|
||||
/>
|
||||
<CursorWrapperContainer
|
||||
widthRatio={slideObj.widthRatio}
|
||||
physicalWidthRatio={adjustedSizes.width / svgWidth}
|
||||
slideWidth={svgWidth}
|
||||
slideHeight={svgHeight}
|
||||
physicalWidthRatio={adjustedSizes.width / width}
|
||||
slideWidth={width}
|
||||
slideHeight={height}
|
||||
/>
|
||||
</g>
|
||||
{this.props.userIsPresenter || this.props.multiUser ?
|
||||
<PresentationOverlayContainer
|
||||
slideWidth={svgWidth}
|
||||
slideHeight={svgHeight}
|
||||
slideWidth={width}
|
||||
slideHeight={height}
|
||||
getSvgRef={this.getSvgRef}
|
||||
>
|
||||
<WhiteboardOverlayContainer
|
||||
getSvgRef={this.getSvgRef}
|
||||
whiteboardId={slideObj.id}
|
||||
slideWidth={svgWidth}
|
||||
slideHeight={svgHeight}
|
||||
slideWidth={width}
|
||||
slideHeight={height}
|
||||
viewBoxX={x}
|
||||
viewBoxY={y}
|
||||
viewBoxWidth={viewBoxWidth}
|
||||
@ -299,8 +298,6 @@ PresentationArea.propTypes = {
|
||||
meetingId: PropTypes.string,
|
||||
presentationId: PropTypes.string.isRequired,
|
||||
current: PropTypes.bool.isRequired,
|
||||
height: PropTypes.number.isRequired,
|
||||
width: PropTypes.number.isRequired,
|
||||
heightRatio: PropTypes.number.isRequired,
|
||||
widthRatio: PropTypes.number.isRequired,
|
||||
xOffset: PropTypes.number.isRequired,
|
||||
@ -313,6 +310,15 @@ PresentationArea.propTypes = {
|
||||
swfUri: PropTypes.string.isRequired,
|
||||
thumbUri: PropTypes.string.isRequired,
|
||||
txtUri: PropTypes.string.isRequired,
|
||||
calculatedData: PropTypes.shape({
|
||||
x: PropTypes.number.isRequired,
|
||||
y: PropTypes.number.isRequired,
|
||||
height: PropTypes.number.isRequired,
|
||||
width: PropTypes.number.isRequired,
|
||||
viewBoxWidth: PropTypes.number.isRequired,
|
||||
viewBoxHeight: PropTypes.number.isRequired,
|
||||
imageUri: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
}),
|
||||
// current multi-user status
|
||||
multiUser: PropTypes.bool.isRequired,
|
||||
|
Loading…
Reference in New Issue
Block a user