bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/zoom-tool/component.jsx

254 lines
7.3 KiB
React
Raw Normal View History

import React, { PureComponent } from 'react';
2018-08-23 01:49:33 +08:00
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
2021-11-08 21:09:56 +08:00
import Styled from './styles';
2018-09-28 22:42:07 +08:00
import HoldButton from './holdButton/component';
2018-08-23 01:49:33 +08:00
2018-08-29 00:09:52 +08:00
const DELAY_MILLISECONDS = 200;
2018-08-23 01:49:33 +08:00
const STEP_TIME = 100;
const ZOOM_INCREMENT = .1;
2018-08-23 01:49:33 +08:00
2019-02-07 00:42:12 +08:00
const intlMessages = defineMessages({
resetZoomLabel: {
id: 'app.presentation.presentationToolbar.zoomReset',
description: 'Reset zoom button label',
},
zoomInLabel: {
id: 'app.presentation.presentationToolbar.zoomInLabel',
2019-01-28 21:33:50 +08:00
description: 'Aria label for increment zoom level',
},
zoomInDesc: {
id: 'app.presentation.presentationToolbar.zoomInDesc',
description: 'Aria description for increment zoom level',
},
zoomOutLabel: {
id: 'app.presentation.presentationToolbar.zoomOutLabel',
description: 'Aria label for decrement zoom level',
},
2019-01-28 21:33:50 +08:00
zoomOutDesc: {
id: 'app.presentation.presentationToolbar.zoomOutDesc',
description: 'Aria description for decrement zoom level',
},
2019-06-06 23:52:05 +08:00
currentValue: {
id: 'app.submenu.application.currentSize',
description: 'current presentation zoom percentage aria description',
2019-01-28 21:33:50 +08:00
},
2019-02-07 00:42:12 +08:00
});
class ZoomTool extends PureComponent {
2018-08-23 01:49:33 +08:00
constructor(props) {
super(props);
this.increment = this.increment.bind(this);
this.decrement = this.decrement.bind(this);
this.mouseDownHandler = this.mouseDownHandler.bind(this);
this.mouseUpHandler = this.mouseUpHandler.bind(this);
this.execInterval = this.execInterval.bind(this);
this.onChanger = this.onChanger.bind(this);
this.setInt = 0;
this.state = {
2019-02-07 00:05:24 +08:00
stateZoomValue: props.zoomValue,
initialstateZoomValue: props.zoomValue,
2018-08-23 01:49:33 +08:00
mouseHolding: false,
};
}
2019-02-06 22:03:30 +08:00
2018-08-23 01:49:33 +08:00
componentDidUpdate() {
2022-06-13 23:39:34 +08:00
const { zoomValue, tldrawAPI } = this.props;
2019-02-07 00:05:24 +08:00
const { stateZoomValue } = this.state;
const isDifferent = zoomValue !== stateZoomValue;
2022-06-13 23:39:34 +08:00
if (isDifferent) {
this.onChanger(zoomValue);
if (tldrawAPI && zoomValue === 1 && tldrawAPI?.getPageState()?.camera?.zoom === 1) {
tldrawAPI?.zoomToFit();
}
}
2018-08-23 01:49:33 +08:00
}
2019-02-07 00:05:24 +08:00
onChanger(value) {
2018-08-23 01:49:33 +08:00
const {
maxBound,
minBound,
change,
2019-02-07 00:05:24 +08:00
zoomValue,
2018-08-23 01:49:33 +08:00
} = this.props;
2019-02-07 00:05:24 +08:00
const { stateZoomValue } = this.state;
let newValue = value;
const isDifferent = newValue !== stateZoomValue;
2018-08-23 01:49:33 +08:00
if (newValue <= minBound) {
newValue = minBound;
} else if (newValue >= maxBound) {
newValue = maxBound;
}
2019-02-07 00:05:24 +08:00
const propsIsDifferente = zoomValue !== newValue;
2018-08-23 01:49:33 +08:00
if (isDifferent && propsIsDifferente) {
2019-02-07 00:05:24 +08:00
this.setState({ stateZoomValue: newValue }, () => {
2018-08-23 01:49:33 +08:00
change(newValue);
});
}
2019-02-07 00:05:24 +08:00
if (isDifferent && !propsIsDifferente) this.setState({ stateZoomValue: newValue });
2018-08-23 01:49:33 +08:00
}
increment() {
const {
step,
} = this.props;
2019-02-07 00:05:24 +08:00
const { stateZoomValue } = this.state;
const increaseZoom = stateZoomValue + step;
2018-08-23 01:49:33 +08:00
this.onChanger(increaseZoom);
}
2019-02-06 22:03:30 +08:00
2018-08-23 01:49:33 +08:00
decrement() {
const {
step,
} = this.props;
2019-02-07 00:05:24 +08:00
const { stateZoomValue } = this.state;
const decreaseZoom = stateZoomValue - step;
2018-08-23 01:49:33 +08:00
this.onChanger(decreaseZoom);
}
execInterval(inc) {
2019-02-06 22:03:30 +08:00
const { mouseHolding } = this.state;
2018-08-23 01:49:33 +08:00
const exec = inc ? this.increment : this.decrement;
const interval = () => {
clearInterval(this.setInt);
this.setInt = setInterval(exec, STEP_TIME);
};
setTimeout(() => {
2019-02-06 22:03:30 +08:00
if (mouseHolding) {
2018-08-23 01:49:33 +08:00
interval();
}
}, DELAY_MILLISECONDS);
}
mouseDownHandler(bool) {
this.setState({
mouseHolding: true,
}, () => {
this.execInterval(bool);
});
}
mouseUpHandler() {
this.setState({
mouseHolding: false,
}, () => clearInterval(this.setInt));
}
2019-02-06 22:03:30 +08:00
resetZoom() {
2019-02-07 00:05:24 +08:00
const { stateZoomValue, initialstateZoomValue } = this.state;
if (stateZoomValue !== initialstateZoomValue) this.onChanger(initialstateZoomValue);
2019-02-06 22:03:30 +08:00
}
2018-08-23 01:49:33 +08:00
render() {
const {
2019-02-07 00:05:24 +08:00
zoomValue,
2018-08-23 01:49:33 +08:00
minBound,
maxBound,
2019-02-07 00:42:12 +08:00
intl,
2019-06-27 00:29:34 +08:00
isMeteorConnected,
2019-06-06 23:04:02 +08:00
step,
2022-05-16 10:35:17 +08:00
tldrawAPI,
slidePosition,
2018-08-23 01:49:33 +08:00
} = this.props;
2019-02-07 00:05:24 +08:00
const { stateZoomValue } = this.state;
2019-06-06 23:52:05 +08:00
let zoomOutAriaLabel = intl.formatMessage(intlMessages.zoomOutLabel);
if (zoomValue > minBound) {
zoomOutAriaLabel += ` ${intl.formatNumber(((zoomValue - step) / 100), { style: 'percent' })}`;
}
let zoomInAriaLabel = intl.formatMessage(intlMessages.zoomInLabel);
if (zoomValue < maxBound) {
zoomInAriaLabel += ` ${intl.formatNumber(((zoomValue + step) / 100), { style: 'percent' })}`;
}
const stateZoomPct = intl.formatNumber((stateZoomValue / 100), { style: 'percent' });
2018-08-23 01:49:33 +08:00
return (
[
2018-09-28 22:42:07 +08:00
(
<HoldButton
key="zoom-tool-1"
exec={this.decrement}
2019-02-07 00:05:24 +08:00
value={zoomValue}
2018-09-28 22:42:07 +08:00
minBound={minBound}
>
2021-11-08 21:09:56 +08:00
<Styled.DecreaseZoomButton
2018-09-28 22:42:07 +08:00
key="zoom-tool-1"
2019-06-06 23:04:02 +08:00
aria-describedby="zoomOutDescription"
2019-06-06 23:52:05 +08:00
aria-label={zoomOutAriaLabel}
label={intl.formatMessage(intlMessages.zoomOutLabel)}
2019-02-12 21:35:52 +08:00
icon="substract"
onClick={() => {
tldrawAPI.zoomTo(tldrawAPI?.getPageState()?.camera?.zoom - ZOOM_INCREMENT);
}}
2019-06-27 00:29:34 +08:00
disabled={(zoomValue <= minBound) || !isMeteorConnected}
2018-09-28 22:42:07 +08:00
hideLabel
/>
2019-06-06 23:04:02 +08:00
<div id="zoomOutDescription" hidden>{intl.formatMessage(intlMessages.zoomOutDesc)}</div>
2018-09-28 22:42:07 +08:00
</HoldButton>
),
2018-08-23 01:49:33 +08:00
(
2019-06-06 23:52:05 +08:00
<span key="zoom-tool-2">
2021-11-08 21:09:56 +08:00
<Styled.ResetZoomButton
2019-06-06 23:52:05 +08:00
aria-label={intl.formatMessage(intlMessages.resetZoomLabel)}
aria-describedby="resetZoomDescription"
2019-06-27 00:29:34 +08:00
disabled={(stateZoomValue === minBound) || !isMeteorConnected}
2019-06-06 23:52:05 +08:00
color="default"
customIcon={`${parseInt(slidePosition?.zoom * 100)}%`}
2019-06-06 23:52:05 +08:00
size="md"
2022-05-16 10:35:17 +08:00
onClick={() => tldrawAPI?.zoomTo(1)}
2019-06-06 23:52:05 +08:00
label={intl.formatMessage(intlMessages.resetZoomLabel)}
hideLabel
/>
<div id="resetZoomDescription" hidden>
{intl.formatMessage(intlMessages.currentValue, ({ 0: stateZoomPct }))}
</div>
</span>
2018-08-23 01:49:33 +08:00
),
2018-09-28 22:42:07 +08:00
(
<HoldButton
key="zoom-tool-3"
exec={this.increment}
2019-02-07 00:05:24 +08:00
value={zoomValue}
2018-09-28 22:42:07 +08:00
maxBound={maxBound}
>
2021-11-08 21:09:56 +08:00
<Styled.IncreaseZoomButton
2018-09-28 22:42:07 +08:00
key="zoom-tool-3"
2019-06-06 23:04:02 +08:00
aria-describedby="zoomInDescription"
2019-06-06 23:52:05 +08:00
aria-label={zoomInAriaLabel}
label={intl.formatMessage(intlMessages.zoomInLabel)}
2022-01-20 21:03:18 +08:00
data-test="zoomInBtn"
2019-02-12 21:35:52 +08:00
icon="add"
onClick={() => {
tldrawAPI.zoomTo(tldrawAPI?.getPageState()?.camera?.zoom + ZOOM_INCREMENT);
}}
2019-06-27 00:29:34 +08:00
disabled={(zoomValue >= maxBound) || !isMeteorConnected}
2018-09-28 22:42:07 +08:00
hideLabel
/>
2019-06-06 23:04:02 +08:00
<div id="zoomInDescription" hidden>{intl.formatMessage(intlMessages.zoomInDesc)}</div>
2018-09-28 22:42:07 +08:00
</HoldButton>
),
2018-08-23 01:49:33 +08:00
]
);
}
}
const propTypes = {
intl: PropTypes.object.isRequired,
2019-02-07 00:05:24 +08:00
zoomValue: PropTypes.number.isRequired,
2018-08-23 01:49:33 +08:00
change: PropTypes.func.isRequired,
minBound: PropTypes.number.isRequired,
maxBound: PropTypes.number.isRequired,
step: PropTypes.number.isRequired,
2019-06-27 00:29:34 +08:00
isMeteorConnected: PropTypes.bool.isRequired,
2018-08-23 01:49:33 +08:00
};
ZoomTool.propTypes = propTypes;
2019-02-07 00:42:12 +08:00
export default injectIntl(ZoomTool);