import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
import deviceInfo from '/imports/utils/deviceInfo';
import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
import Button from '/imports/ui/components/common/button/component';
import {
HUNDRED_PERCENT,
MAX_PERCENT,
STEP,
} from '/imports/utils/slideCalcUtils';
import * as PluginSdk from 'bigbluebutton-html-plugin-sdk';
import Styled from './styles';
import ZoomTool from './zoom-tool/component';
import SmartMediaShareContainer from './smart-video-share/container';
import TooltipContainer from '/imports/ui/components/common/tooltip/container';
import KEY_CODES from '/imports/utils/keyCodes';
import Spinner from '/imports/ui/components/common/spinner/component';
import Separator from '/imports/ui/components/common/separator/component';
const intlMessages = defineMessages({
previousSlideLabel: {
id: 'app.presentation.presentationToolbar.prevSlideLabel',
description: 'Previous slide button label',
},
previousSlideDesc: {
id: 'app.presentation.presentationToolbar.prevSlideDesc',
description: 'Aria description for when switching to previous slide',
},
nextSlideLabel: {
id: 'app.presentation.presentationToolbar.nextSlideLabel',
description: 'Next slide button label',
},
nextSlideDesc: {
id: 'app.presentation.presentationToolbar.nextSlideDesc',
description: 'Aria description for when switching to next slide',
},
noNextSlideDesc: {
id: 'app.presentation.presentationToolbar.noNextSlideDesc',
description: '',
},
noPrevSlideDesc: {
id: 'app.presentation.presentationToolbar.noPrevSlideDesc',
description: '',
},
skipSlideLabel: {
id: 'app.presentation.presentationToolbar.skipSlideLabel',
description: 'Aria label for when switching to a specific slide',
},
skipSlideDesc: {
id: 'app.presentation.presentationToolbar.skipSlideDesc',
description: 'Aria description for when switching to a specific slide',
},
goToSlide: {
id: 'app.presentation.presentationToolbar.goToSlide',
description: 'button for slide select',
},
selectLabel: {
id: 'app.presentation.presentationToolbar.selectLabel',
description: 'slide select label',
},
fitToWidth: {
id: 'app.presentation.presentationToolbar.fitToWidth',
description: 'button for fit to width',
},
fitToWidthDesc: {
id: 'app.presentation.presentationToolbar.fitWidthDesc',
description: 'Aria description to display the whole width of the slide',
},
fitToPage: {
id: 'app.presentation.presentationToolbar.fitToPage',
description: 'button label for fit to width',
},
fitToPageDesc: {
id: 'app.presentation.presentationToolbar.fitScreenDesc',
description: 'Aria description to display the whole slide',
},
presentationLabel: {
id: 'app.presentationUploder.title',
description: 'presentation area element label',
},
toolbarMultiUserOn: {
id: 'app.whiteboard.toolbar.multiUserOn',
description: 'Whiteboard toolbar turn multi-user on menu',
},
toolbarMultiUserOff: {
id: 'app.whiteboard.toolbar.multiUserOff',
description: 'Whiteboard toolbar turn multi-user off menu',
},
pan: {
id: 'app.whiteboard.toolbar.tools.hand',
description: 'presentation toolbar pan label',
},
});
class PresentationToolbar extends PureComponent {
constructor(props) {
super(props);
this.state = {
wasFTWActive: false,
};
this.setWasActive = this.setWasActive.bind(this);
this.handleFTWSlideChange = this.handleFTWSlideChange.bind(this);
this.handleSkipToSlideChange = this.handleSkipToSlideChange.bind(this);
this.change = this.change.bind(this);
this.renderAriaDescs = this.renderAriaDescs.bind(this);
this.nextSlideHandler = this.nextSlideHandler.bind(this);
this.previousSlideHandler = this.previousSlideHandler.bind(this);
this.fullscreenToggleHandler = this.fullscreenToggleHandler.bind(this);
this.switchSlide = this.switchSlide.bind(this);
this.handleSwitchWhiteboardMode = this.handleSwitchWhiteboardMode.bind(this);
}
componentDidMount() {
document.addEventListener('keydown', this.switchSlide);
}
componentDidUpdate(prevProps) {
const { zoom, setIsPanning, fitToWidth, fitToWidthHandler, currentSlideNum } = this.props;
const { wasFTWActive } = this.state;
if (zoom <= HUNDRED_PERCENT && zoom !== prevProps.zoom && !fitToWidth) setIsPanning();
if ((prevProps?.currentSlideNum !== currentSlideNum) && (!fitToWidth && wasFTWActive)) {
setTimeout(() => {
fitToWidthHandler();
this.setWasActive(false);
}, 150)
}
}
componentWillUnmount() {
document.removeEventListener('keydown', this.switchSlide);
}
setWasActive(wasFTWActive) {
this.setState({ wasFTWActive });
}
handleFTWSlideChange() {
const { fitToWidth, fitToWidthHandler } = this.props;
if (fitToWidth) {
fitToWidthHandler();
this.setWasActive(fitToWidth);
}
}
handleSkipToSlideChange(event) {
const { skipToSlide, podId } = this.props;
const requestedSlideNum = Number.parseInt(event.target.value, 10);
this.handleFTWSlideChange();
if (event) event.currentTarget.blur();
skipToSlide(requestedSlideNum, podId);
}
handleSwitchWhiteboardMode() {
const {
multiUser,
whiteboardId,
removeWhiteboardGlobalAccess,
addWhiteboardGlobalAccess,
} = this.props;
if (multiUser) {
return removeWhiteboardGlobalAccess(whiteboardId);
}
return addWhiteboardGlobalAccess(whiteboardId);
}
fullscreenToggleHandler() {
const {
fullscreenElementId,
isFullscreen,
layoutContextDispatch,
fullscreenAction,
fullscreenRef,
handleToggleFullScreen,
} = this.props;
handleToggleFullScreen(fullscreenRef);
const newElement = isFullscreen ? '' : fullscreenElementId;
layoutContextDispatch({
type: fullscreenAction,
value: {
element: newElement,
group: '',
},
});
}
nextSlideHandler(event) {
const {
nextSlide, currentSlideNum, numberOfSlides, podId, endCurrentPoll
} = this.props;
this.handleFTWSlideChange();
if (event) event.currentTarget.blur();
endCurrentPoll();
nextSlide(currentSlideNum, numberOfSlides, podId);
}
previousSlideHandler(event) {
const {
previousSlide, currentSlideNum, podId, endCurrentPoll
} = this.props;
this.handleFTWSlideChange();
if (event) event.currentTarget.blur();
endCurrentPoll();
previousSlide(currentSlideNum, podId);
}
switchSlide(event) {
const { target, which } = event;
const isBody = target.nodeName === 'BODY';
if (isBody) {
switch (which) {
case KEY_CODES.ARROW_LEFT:
case KEY_CODES.PAGE_UP:
this.previousSlideHandler();
break;
case KEY_CODES.ARROW_RIGHT:
case KEY_CODES.PAGE_DOWN:
this.nextSlideHandler();
break;
case KEY_CODES.ENTER:
this.fullscreenToggleHandler();
break;
default:
}
}
}
change(value) {
const { zoomChanger } = this.props;
zoomChanger(value);
}
renderToolbarPluginItems() {
let pluginProvidedItems = [];
if (this.props) {
const {
pluginProvidedPresentationToolbarItems,
} = this.props;
pluginProvidedItems = pluginProvidedPresentationToolbarItems;
}
return pluginProvidedItems?.map((ppb) => {
let componentToReturn;
const ppbId = ppb.id;
switch (ppb.type) {
case PluginSdk.PresentationToolbarItemType.BUTTON:
componentToReturn = (
);
break;
case PluginSdk.PresentationToolbarItemType.SPINNER:
componentToReturn = (