From 708d7ec5cdd582ce3dd574ed4d6112241fb537d8 Mon Sep 17 00:00:00 2001 From: PCCCCCCC Date: Tue, 12 Apr 2022 16:50:50 +0800 Subject: [PATCH] feat:enable the left or right keyboard to switch image (#117) --- src/Preview.tsx | 42 ++++++++++++++++++++++++++++------ tests/previewGroup.test.tsx | 45 ++++++++++++++++++++++--------------- 2 files changed, 62 insertions(+), 25 deletions(-) diff --git a/src/Preview.tsx b/src/Preview.tsx index 8c92e4b1..df5ac458 100644 --- a/src/Preview.tsx +++ b/src/Preview.tsx @@ -3,12 +3,13 @@ import type { DialogProps as IDialogPropTypes } from 'rc-dialog'; import Dialog from 'rc-dialog'; import classnames from 'classnames'; import addEventListener from 'rc-util/lib/Dom/addEventListener'; +import KeyCode from 'rc-util/lib/KeyCode'; import { warning } from 'rc-util/lib/warning'; import useFrameSetState from './hooks/useFrameSetState'; import getFixScaleEleTransPosition from './getFixScaleEleTransPosition'; import { context } from './PreviewGroup'; -const { useState, useEffect } = React; +const { useState, useEffect, useCallback, useRef, useContext } = React; export interface PreviewProps extends Omit { onClose?: (e: React.SyntheticEvent) => void; @@ -50,8 +51,8 @@ const Preview: React.FC = props => { x: number; y: number; }>(initialPosition); - const imgRef = React.useRef(); - const originPositionRef = React.useRef<{ + const imgRef = useRef(); + const originPositionRef = useRef<{ originX: number; originY: number; deltaX: number; @@ -62,14 +63,14 @@ const Preview: React.FC = props => { deltaX: 0, deltaY: 0, }); - const [isMoving, setMoving] = React.useState(false); - const { previewUrls, current, isPreviewGroup, setCurrent } = React.useContext(context); + const [isMoving, setMoving] = useState(false); + const { previewUrls, current, isPreviewGroup, setCurrent } = useContext(context); const previewGroupCount = previewUrls.size; const previewUrlsKeys = Array.from(previewUrls.keys()); const currentPreviewIndex = previewUrlsKeys.indexOf(current); const combinationSrc = isPreviewGroup ? previewUrls.get(current) : src; const showLeftOrRightSwitches = isPreviewGroup && previewGroupCount > 1; - const [lastWheelZoomDirection, setLastWheelZoomDirection] = React.useState({ wheelDirection: 0 }); + const [lastWheelZoomDirection, setLastWheelZoomDirection] = useState({ wheelDirection: 0 }); const onAfterClose = () => { setScale(1); @@ -201,6 +202,31 @@ const Preview: React.FC = props => { setLastWheelZoomDirection({ wheelDirection }); }; + const onKeyDown = useCallback( + (event: KeyboardEvent) => { + if (!visible || !showLeftOrRightSwitches) return; + + event.preventDefault(); + if (event.keyCode === KeyCode.LEFT) { + if (currentPreviewIndex > 0) { + setCurrent(previewUrlsKeys[currentPreviewIndex - 1]); + } + } else if (event.keyCode === KeyCode.RIGHT) { + if (currentPreviewIndex < previewGroupCount - 1) { + setCurrent(previewUrlsKeys[currentPreviewIndex + 1]); + } + } + }, + [ + currentPreviewIndex, + previewGroupCount, + previewUrlsKeys, + setCurrent, + showLeftOrRightSwitches, + visible, + ], + ); + useEffect(() => { const { wheelDirection } = lastWheelZoomDirection; if (wheelDirection > 0) { @@ -219,6 +245,7 @@ const Preview: React.FC = props => { const onScrollWheelListener = addEventListener(window, 'wheel', onWheelMove, { passive: false, }); + const onKeyDownListener = addEventListener(window, 'keydown', onKeyDown, false); try { // Resolve if in iframe lost event @@ -236,13 +263,14 @@ const Preview: React.FC = props => { onMouseUpListener.remove(); onMouseMoveListener.remove(); onScrollWheelListener.remove(); + onKeyDownListener.remove(); /* istanbul ignore next */ if (onTopMouseUpListener) onTopMouseUpListener.remove(); /* istanbul ignore next */ if (onTopMouseMoveListener) onTopMouseMoveListener.remove(); }; - }, [visible, isMoving]); + }, [visible, isMoving, onKeyDown]); return ( { @@ -21,10 +22,7 @@ describe('Preview', () => { ); act(() => { - wrapper - .find('.rc-image') - .at(0) - .simulate('click'); + wrapper.find('.rc-image').at(0).simulate('click'); jest.runAllTimers(); wrapper.update(); }); @@ -44,10 +42,7 @@ describe('Preview', () => { ); act(() => { - wrapper - .find('.rc-image') - .at(0) - .simulate('click'); + wrapper.find('.rc-image').at(0).simulate('click'); jest.runAllTimers(); wrapper.update(); }); @@ -65,10 +60,7 @@ describe('Preview', () => { ); act(() => { - wrapper - .find('.rc-image') - .at(0) - .simulate('click'); + wrapper.find('.rc-image').at(0).simulate('click'); jest.runAllTimers(); wrapper.update(); }); @@ -96,6 +88,28 @@ describe('Preview', () => { expect( wrapper.find('.rc-image-preview .rc-image-preview-switch-left-disabled').get(0), ).toBeTruthy(); + + act(() => { + const event = new KeyboardEvent('keydown', { keyCode: KeyCode.RIGHT }); + global.dispatchEvent(event); + jest.runAllTimers(); + wrapper.update(); + }); + + expect( + wrapper.find('.rc-image-preview .rc-image-preview-switch-right-disabled').get(0), + ).toBeTruthy(); + + act(() => { + const event = new KeyboardEvent('keydown', { keyCode: KeyCode.LEFT }); + global.dispatchEvent(event); + jest.runAllTimers(); + wrapper.update(); + }); + + expect( + wrapper.find('.rc-image-preview .rc-image-preview-switch-left-disabled').get(0), + ).toBeTruthy(); }); it('With Controlled', () => { @@ -113,11 +127,6 @@ describe('Preview', () => { wrapper.update(); }); - expect( - wrapper - .find('.rc-image-preview') - .at(0) - .render(), - ).toMatchSnapshot(); + expect(wrapper.find('.rc-image-preview').at(0).render()).toMatchSnapshot(); }); });