diff --git a/src/components/App.tsx b/src/components/App.tsx index daa33d0e..e058d36c 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -2008,6 +2008,20 @@ class App extends React.Component { return; } + if (event.key === KEYS.PAGE_UP || event.key === KEYS.PAGE_DOWN) { + let offset = + (event.shiftKey ? this.state.width : this.state.height) / + this.state.zoom.value; + if (event.key === KEYS.PAGE_DOWN) { + offset = -offset; + } + if (event.shiftKey) { + this.setState((state) => ({ scrollX: state.scrollX + offset })); + } else { + this.setState((state) => ({ scrollY: state.scrollY + offset })); + } + } + if (this.actionManager.handleKeyDown(event)) { return; } @@ -2030,12 +2044,6 @@ class App extends React.Component { ? ELEMENT_SHIFT_TRANSLATE_AMOUNT : ELEMENT_TRANSLATE_AMOUNT); - const selectedElements = getSelectedElements( - this.scene.getNonDeletedElements(), - this.state, - true, - ); - let offsetX = 0; let offsetY = 0; @@ -2049,6 +2057,12 @@ class App extends React.Component { offsetY = step; } + const selectedElements = getSelectedElements( + this.scene.getNonDeletedElements(), + this.state, + true, + ); + selectedElements.forEach((element) => { mutateElement(element, { x: element.x + offsetX, diff --git a/src/components/HelpDialog.tsx b/src/components/HelpDialog.tsx index 5e20cf44..344ad393 100644 --- a/src/components/HelpDialog.tsx +++ b/src/components/HelpDialog.tsx @@ -230,6 +230,14 @@ export const HelpDialog = ({ onClose }: { onClose?: () => void }) => { label={t("helpDialog.zoomToSelection")} shortcuts={["Shift+2"]} /> + + { }); restoreOriginalGetBoundingClientRect(); }); + + it("moving by page up/down/left/right", async () => { + mockBoundingClientRect(); + await render(, {}); + + const scrollTest = () => { + const initialScrollY = h.state.scrollY; + const initialScrollX = h.state.scrollX; + const pageStepY = h.state.height / h.state.zoom.value; + const pageStepX = h.state.width / h.state.zoom.value; + // Assert the following assertions have meaning + expect(pageStepY).toBeGreaterThan(0); + expect(pageStepX).toBeGreaterThan(0); + // Assert we scroll up + Keyboard.keyPress(KEYS.PAGE_UP); + expect(h.state.scrollY).toBe(initialScrollY + pageStepY); + // x-axis unchanged + expect(h.state.scrollX).toBe(initialScrollX); + + // Assert we scroll down + Keyboard.keyPress(KEYS.PAGE_DOWN); + Keyboard.keyPress(KEYS.PAGE_DOWN); + expect(h.state.scrollY).toBe(initialScrollY - pageStepY); + // x-axis unchanged + expect(h.state.scrollX).toBe(initialScrollX); + + // Assert we scroll left + Keyboard.withModifierKeys({ shift: true }, () => { + Keyboard.keyPress(KEYS.PAGE_UP); + }); + expect(h.state.scrollX).toBe(initialScrollX + pageStepX); + // y-axis unchanged + expect(h.state.scrollY).toBe(initialScrollY - pageStepY); + + // Assert we scroll right + Keyboard.withModifierKeys({ shift: true }, () => { + Keyboard.keyPress(KEYS.PAGE_DOWN); + Keyboard.keyPress(KEYS.PAGE_DOWN); + }); + expect(h.state.scrollX).toBe(initialScrollX - pageStepX); + // y-axis unchanged + expect(h.state.scrollY).toBe(initialScrollY - pageStepY); + }; + + const zoom = h.state.zoom.value; + // Assert we scroll properly when zoomed in + h.setState({ zoom: { value: (zoom * 1.1) as typeof zoom } }); + scrollTest(); + // Assert we scroll properly when zoomed out + h.setState({ zoom: { value: (zoom * 0.9) as typeof zoom } }); + scrollTest(); + // Assert we scroll properly with normal zoom + h.setState({ zoom: { value: zoom } }); + scrollTest(); + restoreOriginalGetBoundingClientRect(); + }); });