2017-06-08 05:25:47 +08:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
2017-09-22 07:52:43 +08:00
|
|
|
import { HEXToINTColor, INTToHEXColor } from '/imports/utils/hexInt';
|
2020-05-26 04:00:13 +08:00
|
|
|
import { defineMessages, injectIntl } from 'react-intl';
|
2019-03-28 01:15:19 +08:00
|
|
|
import KEY_CODES from '/imports/utils/keyCodes';
|
2017-09-26 07:45:44 +08:00
|
|
|
import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
|
2021-11-03 04:05:49 +08:00
|
|
|
import Styled from './styles';
|
2017-09-23 14:27:55 +08:00
|
|
|
import ToolbarMenuItem from './toolbar-menu-item/component';
|
|
|
|
import ToolbarSubmenu from './toolbar-submenu/component';
|
2022-04-14 21:52:49 +08:00
|
|
|
import { withModalMounter } from '/imports/ui/components/common/modal/service';
|
|
|
|
import ConfirmationModal from '/imports/ui/components/common/modal/confirmation/component';
|
2017-02-23 08:10:30 +08:00
|
|
|
|
2017-09-21 05:05:17 +08:00
|
|
|
const TRANSITION_DURATION = '0.4s';
|
2017-09-22 07:44:32 +08:00
|
|
|
const TOOLBAR_CONFIG = Meteor.settings.public.whiteboard.toolbar;
|
|
|
|
const ANNOTATION_COLORS = TOOLBAR_CONFIG.colors;
|
|
|
|
const THICKNESS_RADIUSES = TOOLBAR_CONFIG.thickness;
|
|
|
|
const FONT_SIZES = TOOLBAR_CONFIG.font_sizes;
|
2017-09-21 05:05:17 +08:00
|
|
|
|
2017-12-08 21:28:02 +08:00
|
|
|
const intlMessages = defineMessages({
|
|
|
|
toolbarTools: {
|
|
|
|
id: 'app.whiteboard.toolbar.tools',
|
|
|
|
description: 'Whiteboard toolbar tools menu',
|
|
|
|
},
|
|
|
|
toolbarLineThickness: {
|
|
|
|
id: 'app.whiteboard.toolbar.thickness',
|
|
|
|
description: 'Whiteboard toolbar thickness menu',
|
|
|
|
},
|
2018-03-27 02:08:19 +08:00
|
|
|
toolbarLineThicknessDisabled: {
|
|
|
|
id: 'app.whiteboard.toolbar.thicknessDisabled',
|
|
|
|
description: 'Whiteboard toolbar thickness menu',
|
|
|
|
},
|
2017-12-08 21:28:02 +08:00
|
|
|
toolbarLineColor: {
|
|
|
|
id: 'app.whiteboard.toolbar.color',
|
|
|
|
description: 'Whiteboard toolbar colors menu',
|
|
|
|
},
|
2018-03-27 02:08:19 +08:00
|
|
|
toolbarLineColorDisabled: {
|
|
|
|
id: 'app.whiteboard.toolbar.colorDisabled',
|
|
|
|
description: 'Whiteboard toolbar colors menu',
|
|
|
|
},
|
2017-12-08 21:28:02 +08:00
|
|
|
toolbarUndoAnnotation: {
|
|
|
|
id: 'app.whiteboard.toolbar.undo',
|
|
|
|
description: 'Whiteboard toolbar tools menu',
|
|
|
|
},
|
|
|
|
toolbarClearAnnotations: {
|
|
|
|
id: 'app.whiteboard.toolbar.clear',
|
|
|
|
description: 'Whiteboard toolbar clear menu',
|
|
|
|
},
|
2022-04-14 21:52:49 +08:00
|
|
|
toolbarConfirmClearAnnotations: {
|
|
|
|
id: 'app.whiteboard.toolbar.clearConfirmation',
|
|
|
|
description: 'Whiteboard toolbar clear confirmation',
|
|
|
|
},
|
2017-12-08 21:28:02 +08:00
|
|
|
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',
|
|
|
|
},
|
2020-09-18 18:30:27 +08:00
|
|
|
toolbarPalmRejectionOn: {
|
|
|
|
id: 'app.whiteboard.toolbar.palmRejectionOn',
|
|
|
|
description: 'Whiteboard toolbar turn palm rejection on menu',
|
|
|
|
},
|
|
|
|
toolbarPalmRejectionOff: {
|
|
|
|
id: 'app.whiteboard.toolbar.palmRejectionOff',
|
|
|
|
description: 'Whiteboard toolbar turn palm rejection off menu',
|
|
|
|
},
|
2017-12-08 21:28:02 +08:00
|
|
|
toolbarFontSize: {
|
|
|
|
id: 'app.whiteboard.toolbar.fontSize',
|
|
|
|
description: 'Whiteboard toolbar font size menu',
|
|
|
|
},
|
2019-03-28 01:15:19 +08:00
|
|
|
toolbarItemPan: {
|
|
|
|
id: 'app.whiteboard.toolbar.tools.hand',
|
|
|
|
description: 'Label for the pan toolbar item',
|
|
|
|
},
|
2021-09-13 22:03:40 +08:00
|
|
|
toolbarAriaLabel: {
|
|
|
|
id: 'app.whiteboard.toolbarAriaLabel',
|
|
|
|
description: 'aria label for whiteboard toolbar',
|
|
|
|
}
|
2017-12-08 21:28:02 +08:00
|
|
|
});
|
|
|
|
|
2017-09-26 07:45:44 +08:00
|
|
|
class WhiteboardToolbar extends Component {
|
2018-09-22 03:42:39 +08:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
2021-03-05 06:26:25 +08:00
|
|
|
const {
|
|
|
|
annotations,
|
2021-03-19 01:53:11 +08:00
|
|
|
multiUser,
|
2021-03-05 06:26:25 +08:00
|
|
|
isPresenter,
|
|
|
|
} = this.props;
|
2018-09-22 03:42:39 +08:00
|
|
|
|
|
|
|
let annotationSelected = {
|
2019-06-14 06:42:20 +08:00
|
|
|
icon: 'hand',
|
|
|
|
value: 'hand',
|
2018-09-22 03:42:39 +08:00
|
|
|
};
|
|
|
|
|
2021-03-19 01:53:11 +08:00
|
|
|
if (multiUser && !isPresenter) {
|
2019-08-06 21:16:33 +08:00
|
|
|
annotationSelected = {
|
|
|
|
icon: 'pen_tool',
|
|
|
|
value: 'pencil',
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-10-20 01:05:56 +08:00
|
|
|
if (!annotations.some(el => el.value === annotationSelected.value) && annotations.length > 0) {
|
2018-09-22 03:42:39 +08:00
|
|
|
annotationSelected = annotations[annotations.length - 1];
|
|
|
|
}
|
2017-04-19 08:54:51 +08:00
|
|
|
|
|
|
|
this.state = {
|
2017-08-03 09:24:38 +08:00
|
|
|
// a variable to control which list is currently open
|
2017-04-19 08:54:51 +08:00
|
|
|
currentSubmenuOpen: '',
|
2017-05-03 08:05:41 +08:00
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// variables to keep current selected draw settings
|
2018-09-22 03:42:39 +08:00
|
|
|
annotationSelected,
|
2019-03-28 01:15:19 +08:00
|
|
|
prevAnnotationSelected: annotationSelected,
|
2019-06-20 23:07:09 +08:00
|
|
|
thicknessSelected: { value: 1 },
|
2019-01-15 02:11:06 +08:00
|
|
|
colorSelected: { value: '#ff0000' },
|
2017-09-23 14:27:55 +08:00
|
|
|
fontSizeSelected: { value: 20 },
|
2017-05-03 08:05:41 +08:00
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// keeping the previous color and the thickness icon's radius selected for svg animation
|
2019-01-15 02:11:06 +08:00
|
|
|
prevColorSelected: { value: '#ff0000' },
|
2019-01-17 03:17:26 +08:00
|
|
|
prevThicknessSelected: { value: 2 },
|
2017-06-03 08:41:39 +08:00
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// lists of tools/thickness/colors are not direct children of main toolbar buttons
|
|
|
|
// and we want the list to close when onBlur fires at the main toolbar button
|
|
|
|
// (click anywhere on the screen) thus we have to control the blur manually by disabling it
|
|
|
|
// when you hover over the buttons in the list and enabling when the mouse leaves the list
|
2017-04-19 08:54:51 +08:00
|
|
|
onBlurEnabled: true,
|
2019-03-28 01:15:19 +08:00
|
|
|
|
|
|
|
panMode: false,
|
2020-09-18 18:30:27 +08:00
|
|
|
|
|
|
|
palmRejection: false,
|
2017-04-19 08:54:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
this.displaySubMenu = this.displaySubMenu.bind(this);
|
|
|
|
this.closeSubMenu = this.closeSubMenu.bind(this);
|
2020-06-04 02:32:39 +08:00
|
|
|
this.handleClose = this.handleClose.bind(this);
|
2017-04-19 08:54:51 +08:00
|
|
|
this.handleUndo = this.handleUndo.bind(this);
|
2017-04-22 02:01:52 +08:00
|
|
|
this.handleClearAll = this.handleClearAll.bind(this);
|
2017-08-03 09:24:38 +08:00
|
|
|
this.handleSwitchWhiteboardMode = this.handleSwitchWhiteboardMode.bind(this);
|
2020-09-18 18:30:27 +08:00
|
|
|
this.handleSwitchPalmRejectionMode = this.handleSwitchPalmRejectionMode.bind(this);
|
2017-04-19 08:54:51 +08:00
|
|
|
this.handleAnnotationChange = this.handleAnnotationChange.bind(this);
|
|
|
|
this.handleThicknessChange = this.handleThicknessChange.bind(this);
|
2017-06-03 07:46:02 +08:00
|
|
|
this.handleFontSizeChange = this.handleFontSizeChange.bind(this);
|
2017-04-19 08:54:51 +08:00
|
|
|
this.handleColorChange = this.handleColorChange.bind(this);
|
2017-09-21 05:05:17 +08:00
|
|
|
this.handleMouseEnter = this.handleMouseEnter.bind(this);
|
|
|
|
this.handleMouseLeave = this.handleMouseLeave.bind(this);
|
2019-03-28 01:15:19 +08:00
|
|
|
this.panOn = this.panOn.bind(this);
|
|
|
|
this.panOff = this.panOff.bind(this);
|
2017-04-19 08:54:51 +08:00
|
|
|
}
|
|
|
|
|
2019-08-10 02:10:28 +08:00
|
|
|
componentDidMount() {
|
2021-03-05 06:26:25 +08:00
|
|
|
const {
|
|
|
|
actions,
|
2021-03-19 01:53:11 +08:00
|
|
|
multiUser,
|
2021-03-05 06:26:25 +08:00
|
|
|
isPresenter,
|
|
|
|
} = this.props;
|
|
|
|
|
2019-03-28 01:15:19 +08:00
|
|
|
const drawSettings = actions.getCurrentDrawSettings();
|
2020-09-18 18:30:27 +08:00
|
|
|
const palmRejectionMode = actions.getCurrentPalmRejectionMode();
|
2019-08-10 02:10:28 +08:00
|
|
|
const {
|
2020-09-18 18:30:27 +08:00
|
|
|
annotationSelected, thicknessSelected, colorSelected, fontSizeSelected, palmRejection,
|
2019-08-10 02:10:28 +08:00
|
|
|
} = this.state;
|
|
|
|
|
|
|
|
document.addEventListener('keydown', this.panOn);
|
|
|
|
document.addEventListener('keyup', this.panOff);
|
|
|
|
|
2017-09-06 06:55:18 +08:00
|
|
|
// if there are saved drawSettings in the session storage
|
|
|
|
// - retrieve them and update toolbar values
|
|
|
|
if (drawSettings) {
|
2021-03-19 01:53:11 +08:00
|
|
|
if (multiUser && !isPresenter) {
|
2019-08-10 02:10:28 +08:00
|
|
|
drawSettings.whiteboardAnnotationTool = 'pencil';
|
|
|
|
this.handleAnnotationChange({ icon: 'pen_tool', value: 'pencil' });
|
|
|
|
}
|
|
|
|
|
2017-09-06 06:55:18 +08:00
|
|
|
this.setToolbarValues(drawSettings);
|
2019-06-24 21:14:14 +08:00
|
|
|
// no drawSettings in the sessionStorage - setting default values
|
2017-09-06 06:55:18 +08:00
|
|
|
} else {
|
|
|
|
// setting default drawing settings if they haven't been set previously
|
2019-03-28 01:15:19 +08:00
|
|
|
actions.setInitialWhiteboardToolbarValues(
|
2017-09-23 14:27:55 +08:00
|
|
|
annotationSelected.value,
|
|
|
|
thicknessSelected.value * 2,
|
|
|
|
HEXToINTColor(colorSelected.value),
|
|
|
|
fontSizeSelected.value,
|
2017-09-06 06:55:18 +08:00
|
|
|
{
|
|
|
|
textShapeValue: '',
|
|
|
|
textShapeActiveId: '',
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2019-03-28 01:15:19 +08:00
|
|
|
|
2020-09-18 18:30:27 +08:00
|
|
|
if (palmRejectionMode) {
|
|
|
|
this.setState({
|
|
|
|
palmRejection: palmRejectionMode,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
actions.setInitialPalmRejectionMode(palmRejection);
|
|
|
|
}
|
|
|
|
|
2019-03-28 01:15:19 +08:00
|
|
|
if (annotationSelected.value !== 'text') {
|
2017-08-03 09:24:38 +08:00
|
|
|
// trigger initial animation on the thickness circle, otherwise it stays at 0
|
2017-09-06 06:55:18 +08:00
|
|
|
this.thicknessListIconColor.beginElement();
|
2017-08-19 10:47:31 +08:00
|
|
|
this.thicknessListIconRadius.beginElement();
|
2017-09-06 06:55:18 +08:00
|
|
|
this.colorListIconColor.beginElement();
|
|
|
|
} else {
|
|
|
|
this.colorListIconColor.beginElement();
|
2017-06-07 07:47:31 +08:00
|
|
|
}
|
2017-04-19 08:54:51 +08:00
|
|
|
}
|
|
|
|
|
2017-06-03 08:41:39 +08:00
|
|
|
componentDidUpdate(prevProps, prevState) {
|
2018-10-20 01:05:56 +08:00
|
|
|
const { annotations } = this.props;
|
|
|
|
const { annotationSelected } = prevState;
|
|
|
|
const hadInAnnotations = annotations.some(el => el.value === annotationSelected.value);
|
|
|
|
|
2017-06-08 05:40:15 +08:00
|
|
|
// if color or thickness were changed
|
|
|
|
// we might need to trigger svg animation for Color and Thickness icons
|
|
|
|
this.animateSvgIcons(prevState);
|
2018-10-20 01:05:56 +08:00
|
|
|
|
2018-10-26 22:17:41 +08:00
|
|
|
if (prevProps.annotations.length !== annotations.length && annotations.length === 0) {
|
|
|
|
this.handleAnnotationChange({ icon: null, value: null });
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:26:23 +08:00
|
|
|
if (!hadInAnnotations && annotations.length) {
|
2018-10-20 01:05:56 +08:00
|
|
|
this.handleAnnotationChange(annotations[annotations.length - 1]);
|
|
|
|
}
|
2017-06-08 05:40:15 +08:00
|
|
|
}
|
|
|
|
|
2019-03-28 01:15:19 +08:00
|
|
|
componentWillUnmount() {
|
|
|
|
document.removeEventListener('keydown', this.panOn);
|
|
|
|
document.removeEventListener('keyup', this.panOff);
|
|
|
|
}
|
|
|
|
|
2017-09-06 06:55:18 +08:00
|
|
|
setToolbarValues(drawSettings) {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
|
|
|
annotations,
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
const {
|
|
|
|
whiteboardAnnotationThickness,
|
|
|
|
textFontSize, whiteboardAnnotationColor,
|
|
|
|
whiteboardAnnotationTool,
|
|
|
|
} = drawSettings;
|
|
|
|
|
2017-09-06 06:55:18 +08:00
|
|
|
// divide by 2, since we need the radius for the thickness icon
|
2019-03-28 01:15:19 +08:00
|
|
|
const thicknessSelected = { value: whiteboardAnnotationThickness / 2 };
|
|
|
|
const fontSizeSelected = { value: textFontSize };
|
|
|
|
const colorSelected = { value: INTToHEXColor(whiteboardAnnotationColor) };
|
2017-09-06 06:55:18 +08:00
|
|
|
|
|
|
|
let annotationSelected = {};
|
2019-03-28 01:15:19 +08:00
|
|
|
for (let i = 0; i < annotations.length; i += 1) {
|
|
|
|
if (whiteboardAnnotationTool === annotations[i].value) {
|
|
|
|
annotationSelected = annotations[i];
|
2017-09-06 06:55:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.setState({
|
|
|
|
colorSelected,
|
|
|
|
fontSizeSelected,
|
|
|
|
thicknessSelected,
|
|
|
|
annotationSelected,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-03-28 01:15:19 +08:00
|
|
|
panOn(event) {
|
|
|
|
const { annotationSelected } = this.state;
|
|
|
|
const { target, which } = event;
|
2019-04-04 21:55:35 +08:00
|
|
|
const isBody = target.nodeName === 'BODY';
|
2019-03-28 01:15:19 +08:00
|
|
|
|
2019-04-04 21:55:35 +08:00
|
|
|
if (annotationSelected.value === 'hand' || !isBody) return;
|
2019-03-28 01:15:19 +08:00
|
|
|
|
|
|
|
const { annotations } = this.props;
|
|
|
|
|
|
|
|
if ([KEY_CODES.SPACE].includes(which)) {
|
|
|
|
this.setState(
|
|
|
|
{
|
|
|
|
panMode: true,
|
|
|
|
prevAnnotationSelected: annotationSelected,
|
|
|
|
},
|
|
|
|
this.handleAnnotationChange(annotations[annotations.length - 1]),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
panOff(event) {
|
|
|
|
const { target, which } = event;
|
|
|
|
const isInputArea = target.nodeName === 'TEXTAREA' || target.nodeName === 'INPUT';
|
2019-06-14 06:42:20 +08:00
|
|
|
const { panMode } = this.state;
|
2019-03-28 01:15:19 +08:00
|
|
|
|
2019-06-14 06:42:20 +08:00
|
|
|
if (isInputArea || !panMode) return;
|
2019-03-28 01:15:19 +08:00
|
|
|
|
|
|
|
const { prevAnnotationSelected } = this.state;
|
|
|
|
|
|
|
|
if ([KEY_CODES.SPACE].includes(which)) {
|
|
|
|
this.setState({ panMode: false },
|
|
|
|
this.handleAnnotationChange(prevAnnotationSelected));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-08 05:40:15 +08:00
|
|
|
animateSvgIcons(prevState) {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
|
|
|
colorSelected,
|
|
|
|
annotationSelected,
|
|
|
|
thicknessSelected,
|
|
|
|
} = this.state;
|
|
|
|
|
2017-06-17 10:32:41 +08:00
|
|
|
/* Animation for the svg icons that we use for thickness (circle) and color (rectangle)
|
|
|
|
* has to be triggered manually
|
|
|
|
* we have 4 main cases:
|
|
|
|
* 1. Color change -
|
|
|
|
a) Text tool is selected, Font-Size icon substitutes the thickness icon,
|
2017-09-06 09:36:15 +08:00
|
|
|
thus we need to trigger the color change just for the color icon
|
2017-06-17 10:32:41 +08:00
|
|
|
b) Any other tool than Text tool is selected - trigger color change for both icons
|
|
|
|
* 2. Thickness change - trigger radius for the thickness icon
|
|
|
|
* 3. Switch from the Text tool to any other - trigger color and radius for thickness
|
|
|
|
* 4. Trigger initial animation for the icons
|
|
|
|
*/
|
|
|
|
// 1st case
|
2021-03-30 18:49:07 +08:00
|
|
|
if ((this.thicknessListIconRadius && this.thicknessListIconColor) || annotationSelected.value === 'text') {
|
2019-08-24 05:13:15 +08:00
|
|
|
if (colorSelected.value !== prevState.colorSelected.value) {
|
|
|
|
// 1st case b)
|
|
|
|
if (annotationSelected.value !== 'text') {
|
|
|
|
this.thicknessListIconColor.beginElement();
|
|
|
|
}
|
|
|
|
// 1st case a)
|
|
|
|
this.colorListIconColor.beginElement();
|
2021-05-06 02:59:16 +08:00
|
|
|
// 2nd case
|
|
|
|
} else if (thicknessSelected.value !== prevState.thicknessSelected.value && annotationSelected.value !== 'text') {
|
2019-08-24 05:13:15 +08:00
|
|
|
this.thicknessListIconRadius.beginElement();
|
|
|
|
// 3rd case
|
|
|
|
} else if (annotationSelected.value !== 'text'
|
|
|
|
&& prevState.annotationSelected.value === 'text') {
|
|
|
|
this.thicknessListIconRadius.beginElement();
|
2017-08-19 10:47:31 +08:00
|
|
|
this.thicknessListIconColor.beginElement();
|
2017-06-08 05:40:15 +08:00
|
|
|
}
|
2017-06-17 10:32:41 +08:00
|
|
|
}
|
2017-09-06 06:55:18 +08:00
|
|
|
// 4th case, initial animation is triggered in componentDidMount
|
2017-06-03 08:41:39 +08:00
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// open a submenu
|
2017-04-19 08:54:51 +08:00
|
|
|
displaySubMenu(listName) {
|
2019-03-28 01:15:19 +08:00
|
|
|
const { currentSubmenuOpen } = this.state;
|
2019-05-30 03:11:25 +08:00
|
|
|
|
2017-04-19 08:54:51 +08:00
|
|
|
this.setState({
|
2019-03-28 01:15:19 +08:00
|
|
|
currentSubmenuOpen: currentSubmenuOpen === listName ? '' : listName,
|
2019-05-30 03:11:25 +08:00
|
|
|
onBlurEnabled: false,
|
2017-04-19 08:54:51 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// close a current submenu (fires onBlur only, when you click anywhere on the screen)
|
2017-04-19 08:54:51 +08:00
|
|
|
closeSubMenu() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
|
|
|
annotationSelected,
|
|
|
|
onBlurEnabled,
|
|
|
|
} = this.state;
|
|
|
|
|
|
|
|
const {
|
|
|
|
textShapeActiveId,
|
|
|
|
} = this.props;
|
|
|
|
|
2017-06-17 10:32:41 +08:00
|
|
|
// a separate case for the active text shape
|
2019-03-28 01:15:19 +08:00
|
|
|
if (annotationSelected.value === 'text' && textShapeActiveId !== '') return;
|
2017-06-17 10:32:41 +08:00
|
|
|
|
2019-03-28 01:15:19 +08:00
|
|
|
if (onBlurEnabled) {
|
2017-04-19 08:54:51 +08:00
|
|
|
this.setState({
|
|
|
|
currentSubmenuOpen: undefined,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// undo annotation
|
2017-04-19 08:54:51 +08:00
|
|
|
handleUndo() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
|
|
|
actions,
|
|
|
|
whiteboardId,
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
actions.undoAnnotation(whiteboardId);
|
2017-04-19 08:54:51 +08:00
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// clear all annotations
|
2017-04-22 02:01:52 +08:00
|
|
|
handleClearAll() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
|
|
|
actions,
|
|
|
|
whiteboardId,
|
2022-04-14 21:52:49 +08:00
|
|
|
mountModal,
|
|
|
|
intl,
|
2019-03-28 01:15:19 +08:00
|
|
|
} = this.props;
|
|
|
|
|
2022-04-14 21:52:49 +08:00
|
|
|
mountModal(
|
|
|
|
<ConfirmationModal
|
|
|
|
intl={intl}
|
|
|
|
title={intl.formatMessage(intlMessages.toolbarClearAnnotations)}
|
|
|
|
description={intl.formatMessage(intlMessages.toolbarConfirmClearAnnotations)}
|
|
|
|
confirmParam={whiteboardId}
|
|
|
|
onConfirm={actions.clearWhiteboard}
|
|
|
|
/>
|
|
|
|
)
|
2017-04-19 08:54:51 +08:00
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
handleSwitchWhiteboardMode() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
2021-03-19 01:53:11 +08:00
|
|
|
multiUser,
|
2019-03-28 01:15:19 +08:00
|
|
|
whiteboardId,
|
|
|
|
actions,
|
|
|
|
} = this.props;
|
|
|
|
|
2021-03-19 01:53:11 +08:00
|
|
|
if (multiUser) {
|
2021-03-05 06:26:25 +08:00
|
|
|
actions.removeWhiteboardGlobalAccess(whiteboardId);
|
|
|
|
} else {
|
|
|
|
actions.addWhiteboardGlobalAccess(whiteboardId);
|
|
|
|
}
|
2017-08-03 09:24:38 +08:00
|
|
|
}
|
2017-05-03 08:05:41 +08:00
|
|
|
|
2020-09-18 18:30:27 +08:00
|
|
|
handleSwitchPalmRejectionMode() {
|
|
|
|
const {
|
|
|
|
actions,
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
const {
|
|
|
|
palmRejection,
|
|
|
|
} = this.state;
|
|
|
|
|
|
|
|
actions.setPalmRejectionMode(!palmRejection);
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
palmRejection: !palmRejection,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// changes a current selected annotation both in the state and in the session
|
|
|
|
// and closes the annotation list
|
|
|
|
handleAnnotationChange(annotation) {
|
2019-03-28 01:15:19 +08:00
|
|
|
const { actions } = this.props;
|
2017-06-17 10:32:41 +08:00
|
|
|
const obj = {
|
2017-04-19 08:54:51 +08:00
|
|
|
annotationSelected: annotation,
|
|
|
|
onBlurEnabled: true,
|
|
|
|
currentSubmenuOpen: '',
|
2017-06-17 10:32:41 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
// to animate thickness icon properly when you switch the tool back from Text
|
2017-09-23 14:27:55 +08:00
|
|
|
if (annotation.value === 'text') {
|
|
|
|
obj.prevThicknessSelected = { value: 0 };
|
2017-06-17 10:32:41 +08:00
|
|
|
}
|
|
|
|
|
2019-03-28 01:15:19 +08:00
|
|
|
actions.setTool(annotation.value);
|
2017-06-17 10:32:41 +08:00
|
|
|
this.setState(obj);
|
2017-04-19 08:54:51 +08:00
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// changes a current selected thickness both in the state and in the session
|
|
|
|
// and closes the thickness list
|
2019-03-28 01:15:19 +08:00
|
|
|
handleThicknessChange(incomingThickness) {
|
|
|
|
const { actions } = this.props;
|
|
|
|
const { thicknessSelected } = this.state;
|
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
// thickness value * 2 since this is radius, we need to double it
|
2019-03-28 01:15:19 +08:00
|
|
|
actions.setThickness(incomingThickness.value * 2);
|
2017-05-03 08:05:41 +08:00
|
|
|
|
2017-04-19 08:54:51 +08:00
|
|
|
this.setState({
|
2019-03-28 01:15:19 +08:00
|
|
|
prevThicknessSelected: thicknessSelected,
|
2019-05-10 05:36:16 +08:00
|
|
|
thicknessSelected: incomingThickness,
|
2017-04-19 08:54:51 +08:00
|
|
|
onBlurEnabled: true,
|
|
|
|
currentSubmenuOpen: '',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-06-04 02:32:39 +08:00
|
|
|
handleClose() {
|
|
|
|
this.setState({
|
|
|
|
onBlurEnabled: true,
|
|
|
|
currentSubmenuOpen: '',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
handleFontSizeChange(fontSize) {
|
2019-03-28 01:15:19 +08:00
|
|
|
const { actions } = this.props;
|
|
|
|
actions.setFontSize(fontSize.value);
|
2017-06-03 07:46:02 +08:00
|
|
|
|
|
|
|
this.setState({
|
2017-09-23 14:27:55 +08:00
|
|
|
fontSizeSelected: fontSize,
|
2017-06-03 07:46:02 +08:00
|
|
|
onBlurEnabled: true,
|
|
|
|
currentSubmenuOpen: '',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// changes a current selected color both in the state and in the session
|
|
|
|
// and closes the color list
|
2017-04-19 08:54:51 +08:00
|
|
|
handleColorChange(color) {
|
2019-03-28 01:15:19 +08:00
|
|
|
const { actions } = this.props;
|
|
|
|
const { colorSelected } = this.state;
|
|
|
|
actions.setColor(HEXToINTColor(color.value));
|
2017-06-17 10:32:41 +08:00
|
|
|
|
2017-04-19 08:54:51 +08:00
|
|
|
this.setState({
|
2019-03-28 01:15:19 +08:00
|
|
|
prevColorSelected: colorSelected,
|
2017-04-19 08:54:51 +08:00
|
|
|
colorSelected: color,
|
|
|
|
onBlurEnabled: true,
|
|
|
|
currentSubmenuOpen: '',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// disabling onBlur flag when mouse is over the items in the lists
|
2017-09-21 05:05:17 +08:00
|
|
|
handleMouseEnter() {
|
2017-04-19 08:54:51 +08:00
|
|
|
this.setState({
|
|
|
|
onBlurEnabled: false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// enabling the onBlur flag when the mouse leaving the lists
|
2017-09-21 05:05:17 +08:00
|
|
|
handleMouseLeave() {
|
2017-04-19 08:54:51 +08:00
|
|
|
this.setState({
|
|
|
|
onBlurEnabled: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
renderToolItem() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const { panMode, annotationSelected, currentSubmenuOpen } = this.state;
|
2018-10-25 00:26:23 +08:00
|
|
|
const { intl, annotations } = this.props;
|
2018-10-26 22:17:41 +08:00
|
|
|
const isDisabled = !annotations.length;
|
2019-03-28 01:15:19 +08:00
|
|
|
|
|
|
|
return panMode
|
|
|
|
? (
|
|
|
|
<ToolbarMenuItem
|
|
|
|
icon="hand"
|
|
|
|
label={intl.formatMessage(intlMessages.toolbarItemPan)}
|
2019-06-24 21:14:14 +08:00
|
|
|
onItemClick={() => { }}
|
2019-03-28 01:15:19 +08:00
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<ToolbarMenuItem
|
2021-09-13 21:40:22 +08:00
|
|
|
expanded={currentSubmenuOpen === 'annotationList'}
|
2019-03-28 01:15:19 +08:00
|
|
|
disabled={isDisabled}
|
2021-09-13 22:03:40 +08:00
|
|
|
haspopup={true}
|
2019-03-28 01:15:19 +08:00
|
|
|
label={intl.formatMessage(intlMessages.toolbarTools)}
|
|
|
|
icon={annotationSelected.icon}
|
|
|
|
onItemClick={this.displaySubMenu}
|
|
|
|
objectToReturn="annotationList"
|
|
|
|
onBlur={this.closeSubMenu}
|
2019-06-14 06:42:20 +08:00
|
|
|
showCornerTriangle
|
2022-01-20 21:03:18 +08:00
|
|
|
data-test="toolsBtn"
|
2019-03-28 01:15:19 +08:00
|
|
|
>
|
|
|
|
{currentSubmenuOpen === 'annotationList' && annotations.length > 1
|
|
|
|
? (
|
|
|
|
<ToolbarSubmenu
|
|
|
|
type="annotations"
|
|
|
|
customIcon={false}
|
|
|
|
label="Annotations"
|
|
|
|
onItemClick={this.handleAnnotationChange}
|
2021-05-19 20:07:14 +08:00
|
|
|
objectsToRender={annotations}
|
2019-03-28 01:15:19 +08:00
|
|
|
objectSelected={annotationSelected}
|
|
|
|
handleMouseEnter={this.handleMouseEnter}
|
|
|
|
handleMouseLeave={this.handleMouseLeave}
|
2020-06-04 02:32:39 +08:00
|
|
|
handleClose={this.handleClose}
|
2019-03-28 01:15:19 +08:00
|
|
|
/>
|
|
|
|
)
|
|
|
|
: null}
|
|
|
|
</ToolbarMenuItem>
|
|
|
|
);
|
2017-09-23 14:27:55 +08:00
|
|
|
}
|
2017-04-19 08:54:51 +08:00
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
renderFontItem() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const { intl, fontSizes } = this.props;
|
|
|
|
const { currentSubmenuOpen, fontSizeSelected } = this.state;
|
2017-12-08 21:28:02 +08:00
|
|
|
|
2017-04-19 08:54:51 +08:00
|
|
|
return (
|
2017-09-23 14:27:55 +08:00
|
|
|
<ToolbarMenuItem
|
2017-12-08 21:28:02 +08:00
|
|
|
label={intl.formatMessage(intlMessages.toolbarFontSize)}
|
2021-09-13 21:40:22 +08:00
|
|
|
expanded={currentSubmenuOpen === 'fontSizeList'}
|
2021-09-13 22:03:40 +08:00
|
|
|
haspopup={true}
|
2017-09-23 14:27:55 +08:00
|
|
|
customIcon={this.renderFontItemIcon()}
|
|
|
|
onItemClick={this.displaySubMenu}
|
2018-04-12 04:50:00 +08:00
|
|
|
objectToReturn="fontSizeList"
|
2017-09-23 14:27:55 +08:00
|
|
|
onBlur={this.closeSubMenu}
|
2019-06-14 06:42:20 +08:00
|
|
|
showCornerTriangle
|
2017-09-23 14:27:55 +08:00
|
|
|
>
|
2019-03-28 01:15:19 +08:00
|
|
|
{currentSubmenuOpen === 'fontSizeList'
|
2018-12-06 01:42:31 +08:00
|
|
|
? (
|
|
|
|
<ToolbarSubmenu
|
|
|
|
type="font-size"
|
|
|
|
customIcon
|
|
|
|
label="Font Size"
|
|
|
|
onItemClick={this.handleFontSizeChange}
|
2019-03-28 01:15:19 +08:00
|
|
|
objectsToRender={fontSizes}
|
|
|
|
objectSelected={fontSizeSelected}
|
2018-12-06 01:42:31 +08:00
|
|
|
handleMouseEnter={this.handleMouseEnter}
|
|
|
|
handleMouseLeave={this.handleMouseLeave}
|
2020-06-04 02:32:39 +08:00
|
|
|
handleClose={this.handleClose}
|
2018-12-06 01:42:31 +08:00
|
|
|
/>
|
|
|
|
)
|
2018-10-25 00:26:23 +08:00
|
|
|
: null}
|
2017-09-23 14:27:55 +08:00
|
|
|
</ToolbarMenuItem>
|
2017-04-19 08:54:51 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
renderFontItemIcon() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const { fontSizeSelected, colorSelected } = this.state;
|
2017-09-23 14:27:55 +08:00
|
|
|
return (
|
2021-11-03 04:05:49 +08:00
|
|
|
<Styled.TextThickness
|
2017-09-23 14:27:55 +08:00
|
|
|
style={{
|
2021-04-08 00:15:31 +08:00
|
|
|
fontSize: fontSizeSelected.value <= 32 ? fontSizeSelected.value : 32,
|
2019-03-28 01:15:19 +08:00
|
|
|
color: colorSelected.value,
|
2017-09-23 14:27:55 +08:00
|
|
|
WebkitTransition: `color ${TRANSITION_DURATION}, font-size ${TRANSITION_DURATION}`, /* Safari */
|
|
|
|
transition: `color ${TRANSITION_DURATION}, font-size ${TRANSITION_DURATION}`,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
Aa
|
2021-11-03 04:05:49 +08:00
|
|
|
</Styled.TextThickness>
|
2017-09-23 14:27:55 +08:00
|
|
|
);
|
|
|
|
}
|
2017-06-03 07:46:02 +08:00
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
renderThicknessItem() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
|
|
|
intl,
|
|
|
|
annotations,
|
|
|
|
thicknessRadiuses,
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
const {
|
|
|
|
annotationSelected,
|
|
|
|
currentSubmenuOpen,
|
|
|
|
thicknessSelected,
|
|
|
|
} = this.state;
|
|
|
|
|
|
|
|
const isDisabled = annotationSelected.value === 'hand' || !annotations.length;
|
2017-06-03 07:46:02 +08:00
|
|
|
return (
|
2017-09-23 14:27:55 +08:00
|
|
|
<ToolbarMenuItem
|
2018-03-27 02:08:19 +08:00
|
|
|
disabled={isDisabled}
|
2021-09-13 21:40:22 +08:00
|
|
|
expanded={currentSubmenuOpen === 'thicknessList'}
|
2021-09-13 22:03:40 +08:00
|
|
|
haspopup={true}
|
2018-12-06 01:42:31 +08:00
|
|
|
label={isDisabled
|
|
|
|
? intl.formatMessage(intlMessages.toolbarLineThicknessDisabled)
|
2018-03-27 02:08:19 +08:00
|
|
|
: intl.formatMessage(intlMessages.toolbarLineThickness)}
|
2017-09-23 14:27:55 +08:00
|
|
|
onItemClick={this.displaySubMenu}
|
2018-04-12 04:50:00 +08:00
|
|
|
objectToReturn="thicknessList"
|
2017-09-23 14:27:55 +08:00
|
|
|
onBlur={this.closeSubMenu}
|
|
|
|
customIcon={this.renderThicknessItemIcon()}
|
2019-06-14 06:42:20 +08:00
|
|
|
showCornerTriangle
|
2017-09-23 14:27:55 +08:00
|
|
|
>
|
2019-03-28 01:15:19 +08:00
|
|
|
{currentSubmenuOpen === 'thicknessList'
|
2018-12-06 01:42:31 +08:00
|
|
|
? (
|
|
|
|
<ToolbarSubmenu
|
|
|
|
type="thickness"
|
|
|
|
customIcon
|
|
|
|
label="Thickness"
|
|
|
|
onItemClick={this.handleThicknessChange}
|
2019-03-28 01:15:19 +08:00
|
|
|
objectsToRender={thicknessRadiuses}
|
|
|
|
objectSelected={thicknessSelected}
|
2018-12-06 01:42:31 +08:00
|
|
|
handleMouseEnter={this.handleMouseEnter}
|
|
|
|
handleMouseLeave={this.handleMouseLeave}
|
2020-06-04 02:32:39 +08:00
|
|
|
handleClose={this.handleClose}
|
2018-12-06 01:42:31 +08:00
|
|
|
/>
|
|
|
|
)
|
2018-10-25 00:26:23 +08:00
|
|
|
: null}
|
2017-09-23 14:27:55 +08:00
|
|
|
</ToolbarMenuItem>
|
2017-06-03 07:46:02 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
renderThicknessItemIcon() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
|
|
|
colorSelected,
|
|
|
|
thicknessSelected,
|
|
|
|
prevThicknessSelected,
|
|
|
|
prevColorSelected,
|
|
|
|
} = this.state;
|
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
return (
|
2021-11-03 04:05:49 +08:00
|
|
|
<Styled.CustomSvgIcon shapeRendering="geometricPrecision">
|
2021-04-08 03:56:51 +08:00
|
|
|
<circle
|
|
|
|
shapeRendering="geometricPrecision"
|
|
|
|
cx="50%"
|
|
|
|
cy="50%"
|
|
|
|
stroke="black"
|
|
|
|
strokeWidth="1"
|
2021-10-03 09:25:30 +08:00
|
|
|
fill={colorSelected.value}
|
|
|
|
r={thicknessSelected.value}
|
2021-04-08 03:56:51 +08:00
|
|
|
>
|
|
|
|
<animate
|
|
|
|
ref={(ref) => { this.thicknessListIconColor = ref; }}
|
|
|
|
attributeName="fill"
|
|
|
|
attributeType="XML"
|
|
|
|
from={prevColorSelected.value}
|
|
|
|
to={colorSelected.value}
|
|
|
|
begin="indefinite"
|
|
|
|
dur={TRANSITION_DURATION}
|
|
|
|
repeatCount="1"
|
|
|
|
fill="freeze"
|
|
|
|
/>
|
|
|
|
<animate
|
|
|
|
ref={(ref) => { this.thicknessListIconRadius = ref; }}
|
|
|
|
attributeName="r"
|
|
|
|
attributeType="XML"
|
|
|
|
from={prevThicknessSelected.value}
|
|
|
|
to={thicknessSelected.value}
|
|
|
|
begin="indefinite"
|
|
|
|
dur={TRANSITION_DURATION}
|
|
|
|
repeatCount="1"
|
|
|
|
fill="freeze"
|
|
|
|
/>
|
|
|
|
</circle>
|
2021-11-03 04:05:49 +08:00
|
|
|
</Styled.CustomSvgIcon>
|
2017-09-23 14:27:55 +08:00
|
|
|
);
|
|
|
|
}
|
2017-04-19 08:54:51 +08:00
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
renderColorItem() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
|
|
|
intl,
|
|
|
|
annotations,
|
|
|
|
colors,
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
const {
|
|
|
|
annotationSelected,
|
|
|
|
currentSubmenuOpen,
|
|
|
|
colorSelected,
|
|
|
|
} = this.state;
|
|
|
|
|
|
|
|
const isDisabled = annotationSelected.value === 'hand' || !annotations.length;
|
2017-04-19 08:54:51 +08:00
|
|
|
return (
|
2017-09-23 14:27:55 +08:00
|
|
|
<ToolbarMenuItem
|
2018-03-27 02:08:19 +08:00
|
|
|
disabled={isDisabled}
|
2021-09-13 21:40:22 +08:00
|
|
|
expanded={currentSubmenuOpen === 'colorList'}
|
2021-09-13 22:03:40 +08:00
|
|
|
haspopup={true}
|
2018-12-06 01:42:31 +08:00
|
|
|
label={isDisabled
|
|
|
|
? intl.formatMessage(intlMessages.toolbarLineColorDisabled)
|
2018-03-27 02:08:19 +08:00
|
|
|
: intl.formatMessage(intlMessages.toolbarLineColor)}
|
2017-09-23 14:27:55 +08:00
|
|
|
onItemClick={this.displaySubMenu}
|
2018-04-12 04:50:00 +08:00
|
|
|
objectToReturn="colorList"
|
2017-09-23 14:27:55 +08:00
|
|
|
onBlur={this.closeSubMenu}
|
|
|
|
customIcon={this.renderColorItemIcon()}
|
2019-06-14 06:42:20 +08:00
|
|
|
showCornerTriangle
|
2017-09-23 14:27:55 +08:00
|
|
|
>
|
2019-03-28 01:15:19 +08:00
|
|
|
{currentSubmenuOpen === 'colorList'
|
2018-12-06 01:42:31 +08:00
|
|
|
? (
|
|
|
|
<ToolbarSubmenu
|
|
|
|
type="color"
|
|
|
|
customIcon
|
|
|
|
label="Color"
|
|
|
|
onItemClick={this.handleColorChange}
|
2019-03-28 01:15:19 +08:00
|
|
|
objectsToRender={colors}
|
|
|
|
objectSelected={colorSelected}
|
2018-12-06 01:42:31 +08:00
|
|
|
handleMouseEnter={this.handleMouseEnter}
|
|
|
|
handleMouseLeave={this.handleMouseLeave}
|
2020-06-04 02:32:39 +08:00
|
|
|
handleClose={this.handleClose}
|
2018-12-06 01:42:31 +08:00
|
|
|
/>
|
|
|
|
)
|
2018-10-25 00:26:23 +08:00
|
|
|
: null}
|
2017-09-23 14:27:55 +08:00
|
|
|
</ToolbarMenuItem>
|
2017-04-19 08:54:51 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
renderColorItemIcon() {
|
2019-03-28 01:15:19 +08:00
|
|
|
const {
|
|
|
|
colorSelected,
|
|
|
|
prevColorSelected,
|
|
|
|
} = this.state;
|
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
return (
|
2021-11-03 04:05:49 +08:00
|
|
|
<Styled.CustomSvgIcon>
|
2022-04-09 03:05:29 +08:00
|
|
|
<rect x="25%" y="25%" width="50%" height="50%" stroke="black" strokeWidth="1" fill={colorSelected.value} id="colorPicker">
|
2021-04-08 03:56:51 +08:00
|
|
|
<animate
|
|
|
|
ref={(ref) => { this.colorListIconColor = ref; }}
|
|
|
|
attributeName="fill"
|
|
|
|
attributeType="XML"
|
|
|
|
from={prevColorSelected.value}
|
|
|
|
to={colorSelected.value}
|
|
|
|
begin="indefinite"
|
|
|
|
dur={TRANSITION_DURATION}
|
|
|
|
repeatCount="1"
|
|
|
|
fill="freeze"
|
|
|
|
/>
|
|
|
|
</rect>
|
2021-11-03 04:05:49 +08:00
|
|
|
</Styled.CustomSvgIcon>
|
2017-09-23 14:27:55 +08:00
|
|
|
);
|
|
|
|
}
|
2017-04-19 08:54:51 +08:00
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
renderUndoItem() {
|
2019-06-27 00:29:34 +08:00
|
|
|
const { intl, isMeteorConnected } = this.props;
|
2017-12-08 21:28:02 +08:00
|
|
|
|
2017-04-19 08:54:51 +08:00
|
|
|
return (
|
2017-09-23 14:27:55 +08:00
|
|
|
<ToolbarMenuItem
|
2019-06-27 00:29:34 +08:00
|
|
|
disabled={!isMeteorConnected}
|
2017-12-08 21:28:02 +08:00
|
|
|
label={intl.formatMessage(intlMessages.toolbarUndoAnnotation)}
|
2018-04-12 04:50:00 +08:00
|
|
|
icon="undo"
|
2017-09-23 14:27:55 +08:00
|
|
|
onItemClick={this.handleUndo}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderClearAllItem() {
|
2019-06-27 00:29:34 +08:00
|
|
|
const { intl, isMeteorConnected } = this.props;
|
2017-12-08 21:28:02 +08:00
|
|
|
|
2017-09-23 14:27:55 +08:00
|
|
|
return (
|
|
|
|
<ToolbarMenuItem
|
2019-06-27 00:29:34 +08:00
|
|
|
disabled={!isMeteorConnected}
|
2017-12-08 21:28:02 +08:00
|
|
|
label={intl.formatMessage(intlMessages.toolbarClearAnnotations)}
|
2018-11-30 04:35:34 +08:00
|
|
|
icon="delete"
|
2017-09-23 14:27:55 +08:00
|
|
|
onItemClick={this.handleClearAll}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderMultiUserItem() {
|
2020-08-18 01:03:23 +08:00
|
|
|
const {
|
2021-03-05 06:26:25 +08:00
|
|
|
intl,
|
|
|
|
isMeteorConnected,
|
2021-03-19 01:53:11 +08:00
|
|
|
multiUser,
|
2021-03-05 06:26:25 +08:00
|
|
|
multiUserSize,
|
2020-08-18 01:03:23 +08:00
|
|
|
} = this.props;
|
2017-09-23 14:27:55 +08:00
|
|
|
|
|
|
|
return (
|
2021-11-03 04:05:49 +08:00
|
|
|
<span data-test={multiUser ? 'multiWhiteboardTool' : 'whiteboardTool'}>
|
|
|
|
{multiUser && <Styled.MultiUserTool>{multiUserSize}</Styled.MultiUserTool>}
|
2020-08-18 01:03:23 +08:00
|
|
|
<ToolbarMenuItem
|
|
|
|
disabled={!isMeteorConnected}
|
2021-03-19 01:53:11 +08:00
|
|
|
label={multiUser
|
2020-08-18 01:03:23 +08:00
|
|
|
? intl.formatMessage(intlMessages.toolbarMultiUserOff)
|
|
|
|
: intl.formatMessage(intlMessages.toolbarMultiUserOn)
|
|
|
|
}
|
2022-01-20 21:03:18 +08:00
|
|
|
data-test={multiUser ? 'turnMultiUsersWhiteboardOff' : 'turnMultiUsersWhiteboardOn'}
|
2021-03-19 01:53:11 +08:00
|
|
|
icon={multiUser ? 'multi_whiteboard' : 'whiteboard'}
|
2020-08-18 01:03:23 +08:00
|
|
|
onItemClick={this.handleSwitchWhiteboardMode}
|
|
|
|
/>
|
|
|
|
</span>
|
2017-04-19 08:54:51 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-09-18 18:30:27 +08:00
|
|
|
renderPalmRejectionItem() {
|
|
|
|
const { intl, isMeteorConnected } = this.props;
|
|
|
|
|
|
|
|
const { palmRejection } = this.state;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<ToolbarMenuItem
|
|
|
|
disabled={!isMeteorConnected}
|
|
|
|
label={palmRejection
|
|
|
|
? intl.formatMessage(intlMessages.toolbarPalmRejectionOff)
|
|
|
|
: intl.formatMessage(intlMessages.toolbarPalmRejectionOn)
|
|
|
|
}
|
2021-01-26 19:35:02 +08:00
|
|
|
icon={palmRejection ? 'palm_rejection' : 'no_palm_rejection'}
|
2020-09-18 18:30:27 +08:00
|
|
|
onItemClick={this.handleSwitchPalmRejectionMode}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
2021-09-13 22:03:40 +08:00
|
|
|
|
2017-04-19 08:54:51 +08:00
|
|
|
render() {
|
2017-09-23 14:27:55 +08:00
|
|
|
const { annotationSelected } = this.state;
|
2021-09-13 22:03:40 +08:00
|
|
|
const { isPresenter, intl } = this.props;
|
2017-04-19 08:54:51 +08:00
|
|
|
return (
|
2021-11-03 04:05:49 +08:00
|
|
|
<Styled.ToolbarContainer role="region" aria-label={intl.formatMessage(intlMessages.toolbarAriaLabel)}>
|
2021-11-11 19:34:45 +08:00
|
|
|
<Styled.ToolbarWrapper>
|
2017-09-23 14:27:55 +08:00
|
|
|
{this.renderToolItem()}
|
2018-10-25 00:26:23 +08:00
|
|
|
{annotationSelected.value === 'text' ? this.renderFontItem() : this.renderThicknessItem()}
|
2017-09-23 14:27:55 +08:00
|
|
|
{this.renderColorItem()}
|
|
|
|
{this.renderUndoItem()}
|
|
|
|
{this.renderClearAllItem()}
|
2020-09-24 01:29:24 +08:00
|
|
|
{window.PointerEvent ? this.renderPalmRejectionItem() : null}
|
2018-10-25 00:26:23 +08:00
|
|
|
{isPresenter ? this.renderMultiUserItem() : null}
|
2021-11-11 19:34:45 +08:00
|
|
|
</Styled.ToolbarWrapper>
|
2021-11-03 04:05:49 +08:00
|
|
|
</Styled.ToolbarContainer>
|
2017-04-19 08:54:51 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
WhiteboardToolbar.defaultProps = {
|
2017-09-22 07:44:32 +08:00
|
|
|
colors: ANNOTATION_COLORS,
|
|
|
|
thicknessRadiuses: THICKNESS_RADIUSES,
|
|
|
|
fontSizes: FONT_SIZES,
|
2020-05-26 04:00:13 +08:00
|
|
|
intl: {},
|
2017-04-19 08:54:51 +08:00
|
|
|
};
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
WhiteboardToolbar.propTypes = {
|
2021-03-19 01:53:11 +08:00
|
|
|
// defines a current mode of the whiteboard, multi/single user
|
|
|
|
multiUser: PropTypes.bool.isRequired,
|
|
|
|
|
|
|
|
// defines the number of non-presenters that have access to the whiteboard
|
|
|
|
multiUserSize: PropTypes.number.isRequired,
|
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
// defines whether a current user is a presenter or not
|
|
|
|
isPresenter: PropTypes.bool.isRequired,
|
|
|
|
|
|
|
|
// defines an object of available actions
|
|
|
|
actions: PropTypes.objectOf(PropTypes.func).isRequired,
|
|
|
|
|
|
|
|
// defines the id of the active text shape (if any)
|
|
|
|
// for the separate onBlur case in the closeSubMenu()
|
|
|
|
textShapeActiveId: PropTypes.string.isRequired,
|
|
|
|
|
|
|
|
// defines a current whiteboard id
|
|
|
|
whiteboardId: PropTypes.string.isRequired,
|
|
|
|
|
|
|
|
// defines an array of icons for the toolbar as well as their corresponding session values
|
|
|
|
annotations: PropTypes.arrayOf(PropTypes.object).isRequired,
|
|
|
|
|
|
|
|
// defines an array of font-sizes for the Font-size submenu of the text shape
|
2018-04-12 04:50:00 +08:00
|
|
|
fontSizes: PropTypes.arrayOf(PropTypes.shape({
|
|
|
|
value: PropTypes.number.isRequired,
|
2018-10-25 00:26:23 +08:00
|
|
|
}).isRequired),
|
2017-08-03 09:24:38 +08:00
|
|
|
|
|
|
|
// defines an array of colors for the toolbar (color submenu)
|
2018-04-12 04:50:00 +08:00
|
|
|
colors: PropTypes.arrayOf(PropTypes.shape({
|
|
|
|
value: PropTypes.string.isRequired,
|
2018-10-25 00:26:23 +08:00
|
|
|
}).isRequired),
|
2017-08-03 09:24:38 +08:00
|
|
|
// defines an array of thickness values for the toolbar and their corresponding session values
|
2018-04-12 04:50:00 +08:00
|
|
|
thicknessRadiuses: PropTypes.arrayOf(PropTypes.shape({
|
|
|
|
value: PropTypes.number.isRequired,
|
2018-10-25 00:26:23 +08:00
|
|
|
}).isRequired),
|
2017-08-03 09:24:38 +08:00
|
|
|
|
2020-05-26 04:00:13 +08:00
|
|
|
intl: PropTypes.object.isRequired,
|
2017-12-08 21:28:02 +08:00
|
|
|
|
2017-08-03 09:24:38 +08:00
|
|
|
};
|
2017-09-26 07:45:44 +08:00
|
|
|
|
2022-04-14 21:52:49 +08:00
|
|
|
export default injectWbResizeEvent(injectIntl(withModalMounter(WhiteboardToolbar)));
|