update pan tool button after zoom changes

This commit is contained in:
KDSBrowne 2022-08-22 16:55:44 +00:00
parent 1de4b3f644
commit eb7c3dcbc8
5 changed files with 81 additions and 3 deletions

View File

@ -4,6 +4,7 @@ import WhiteboardOverlayContainer from '/imports/ui/components/whiteboard/whiteb
import WhiteboardContainer from '/imports/ui/components/whiteboard/container';
import WhiteboardToolbarContainer from '/imports/ui/components/whiteboard/whiteboard-toolbar/container';
import { HUNDRED_PERCENT, MAX_PERCENT } from '/imports/utils/slideCalcUtils';
import { SPACE } from '/imports/utils/keyCodes';
import { defineMessages, injectIntl } from 'react-intl';
import { toast } from 'react-toastify';
import { Session } from 'meteor/session';
@ -76,6 +77,7 @@ class Presentation extends PureComponent {
fitToWidth: false,
isFullscreen: false,
tldrawAPI: null,
isPanning: false,
};
this.currentPresentationToastId = null;
@ -90,6 +92,8 @@ class Presentation extends PureComponent {
this.getPresentationSizesAvailable = this.getPresentationSizesAvailable.bind(this);
this.handleResize = this.handleResize.bind(this);
this.setTldrawAPI = this.setTldrawAPI.bind(this);
this.setIsPanning = this.setIsPanning.bind(this);
this.handlePanShortcut = this.handlePanShortcut.bind(this);
this.renderPresentationMenu = this.renderPresentationMenu.bind(this);
this.onResize = () => setTimeout(this.handleResize.bind(this), 0);
@ -122,8 +126,28 @@ class Presentation extends PureComponent {
return stateChange;
}
setIsPanning() {
this.setState({
isPanning: !this.state.isPanning,
});
}
handlePanShortcut(e) {
const { userIsPresenter } = this.props;
if (e.keyCode === SPACE && userIsPresenter) {
switch(e.type) {
case 'keyup':
return this.state.isPanning && this.setIsPanning();
case 'keydown':
return !this.state.isPanning && this.setIsPanning();
}
}
}
componentDidMount() {
this.getInitialPresentationSizes();
this.refPresentationContainer.addEventListener('keydown', this.handlePanShortcut);
this.refPresentationContainer.addEventListener('keyup', this.handlePanShortcut);
this.refPresentationContainer
.addEventListener(FULLSCREEN_CHANGE_EVENT, this.onFullscreenChange);
window.addEventListener('resize', this.onResize, false);
@ -267,6 +291,9 @@ class Presentation extends PureComponent {
value: currentSlide.num,
});
}
if (!userIsPresenter && prevProps.userIsPresenter) {
this.setIsPanning();
}
}
componentWillUnmount() {
@ -276,6 +303,8 @@ class Presentation extends PureComponent {
window.removeEventListener('resize', this.onResize, false);
this.refPresentationContainer
.removeEventListener(FULLSCREEN_CHANGE_EVENT, this.onFullscreenChange);
this.refPresentationContainer.removeEventListener('keydown', this.handlePanShortcut);
this.refPresentationContainer.removeEventListener('keyup', this.handlePanShortcut);
if (fullscreenContext) {
layoutContextDispatch({
@ -738,7 +767,8 @@ class Presentation extends PureComponent {
layoutContextDispatch,
presentationIsOpen,
}}
isZoomed={this.state.isZoomed}
setIsPanning={this.setIsPanning}
isPanning={this.state.isPanning}
curPageId={this.state.tldrawAPI?.getPage()?.id}
currentSlideNum={currentSlide.num}
presentationId={currentSlide.presentationId}
@ -992,6 +1022,7 @@ class Presentation extends PureComponent {
presentationWidth={svgWidth}
presentationHeight={svgHeight}
isViewersCursorLocked={isViewersCursorLocked}
isPanning={this.state.isPanning}
zoomChanger={this.zoomChanger}
fitToWidth={fitToWidth}
zoomValue={zoom}

View File

@ -84,6 +84,10 @@ const intlMessages = defineMessages({
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 {
@ -105,6 +109,11 @@ class PresentationToolbar extends PureComponent {
document.addEventListener('keydown', this.switchSlide);
}
componentDidUpdate(prevProps, prevState) {
const { zoom, setIsPanning } = this.props;
if (zoom <= HUNDRED_PERCENT && zoom !== prevProps.zoom) setIsPanning();
}
componentWillUnmount() {
document.removeEventListener('keydown', this.switchSlide);
}
@ -257,6 +266,8 @@ class PresentationToolbar extends PureComponent {
toolbarWidth,
multiUserSize,
multiUser,
setIsPanning,
isPanning,
} = this.props;
const { isMobile } = deviceInfo;
@ -393,6 +404,20 @@ class PresentationToolbar extends PureComponent {
/>
</TooltipContainer>
) : null}
<Styled.FitToWidthButton
role="button"
data-test="panButton"
aria-label={intl.formatMessage(intlMessages.pan)}
color="light"
disabled={(zoom <= HUNDRED_PERCENT)}
icon="hand"
size="md"
circle
onClick={setIsPanning}
label={intl.formatMessage(intlMessages.pan)}
hideLabel
panning={isPanning}
/>
<Styled.FitToWidthButton
role="button"
data-test="fitToWidthButton"

View File

@ -204,6 +204,12 @@ const FitToWidthButton = styled(Button)`
background-color: ${colorOffWhite};
border: 0;
}
${({ panning }) => panning && `
> span {
background-color: #DCE4EC;
}
`}
`;
const MultiUserTool = styled.span`

View File

@ -50,6 +50,7 @@ export default function Whiteboard(props) {
zoomValue,
width,
height,
isPanning,
} = props;
const { pages, pageStates } = initDefaultPages(curPres?.pages.length || 1);
@ -63,6 +64,7 @@ export default function Whiteboard(props) {
assets: {},
});
const [tldrawAPI, setTLDrawAPI] = React.useState(null);
const [forcePanning, setForcePanning] = React.useState(false);
const [zoom, setZoom] = React.useState(HUNDRED_PERCENT);
const [isMounting, setIsMounting] = React.useState(true);
const prevShapes = usePrevious(shapes);
@ -221,8 +223,18 @@ export default function Whiteboard(props) {
// removes image tool from the tldraw toolbar
document.getElementById("TD-PrimaryTools-Image").style.display = 'none';
}
if (tldrawAPI) {
tldrawAPI.isForcePanning = isPanning;
}
});
React.useEffect(() => {
if (tldrawAPI) {
tldrawAPI.isForcePanning = isPanning;
}
}, [isPanning]);
const onMount = (app) => {
app.setSetting('language', document.getElementsByTagName('html')[0]?.lang || 'en');
app.setSetting('dockPosition', isRTL ? 'left' : 'right');
@ -310,7 +322,7 @@ export default function Whiteboard(props) {
const dockPos = webcams?.getAttribute("data-position");
const editableWB = (
<Tldraw
key={`wb-${isRTL}-${width}-${height}-${dockPos}`}
key={`wb-${isRTL}-${width}-${height}-${dockPos}-${forcePanning}`}
document={doc}
// disable the ability to drag and drop files onto the whiteboard
// until we handle saving of assets in akka.
@ -525,6 +537,7 @@ export default function Whiteboard(props) {
whiteboardId={whiteboardId}
isViewersCursorLocked={isViewersCursorLocked}
isMultiUserActive={isMultiUserActive}
isPanning={isPanning}
>
{hasWBAccess || isPresenter ? editableWB : readOnlyWB}
</Cursors>

View File

@ -127,6 +127,7 @@ export default function Cursors(props) {
hasMultiUserAccess,
isMultiUserActive,
application,
isPanning,
} = props;
const start = () => setActive(true);
@ -282,10 +283,12 @@ export default function Cursors(props) {
});
const multiUserAccess = hasMultiUserAccess(whiteboardId, currentUser?.userId);
let cursorType = multiUserAccess || currentUser?.presenter ? "none" : "default";
if (isPanning) cursorType = 'grab';
return (
<span ref={(r) => (cursorWrapper = r)}>
<div style={{ height: "100%", cursor: multiUserAccess || currentUser?.presenter ? "none" : "default" }}>
<div style={{ height: "100%", cursor: cursorType }}>
{(active && multiUserAccess || (active && currentUser?.presenter)) && (
<PositionLabel
pos={pos}