From f509650ec51e1d6f8821a7cf51d6a86307dc3b5d Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 27 Jan 2023 21:19:23 +1100 Subject: [PATCH] adds double-click to reset view to 100% --- .../common/hooks/useSingleAndDoubleClick.ts | 28 +++++++++++++++++++ .../IAICanvasToolbar/IAICanvasToolbar.tsx | 11 ++++++-- .../src/features/canvas/store/canvasSlice.ts | 19 +++++++------ .../UnifiedCanvasResetView.tsx | 11 ++++++-- 4 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 frontend/src/common/hooks/useSingleAndDoubleClick.ts diff --git a/frontend/src/common/hooks/useSingleAndDoubleClick.ts b/frontend/src/common/hooks/useSingleAndDoubleClick.ts new file mode 100644 index 00000000000..8b2b35bcb1f --- /dev/null +++ b/frontend/src/common/hooks/useSingleAndDoubleClick.ts @@ -0,0 +1,28 @@ +// https://stackoverflow.com/a/73731908 + +import { useEffect, useState } from 'react'; + +export function useSingleAndDoubleClick( + handleSingleClick: () => void, + handleDoubleClick: () => void, + delay = 250 +) { + const [click, setClick] = useState(0); + + useEffect(() => { + const timer = setTimeout(() => { + if (click === 1) { + handleSingleClick(); + } + setClick(0); + }, delay); + + if (click === 2) { + handleDoubleClick(); + } + + return () => clearTimeout(timer); + }, [click, handleSingleClick, handleDoubleClick, delay]); + + return () => setClick((prev) => prev + 1); +} diff --git a/frontend/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx b/frontend/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx index 531abd0820c..9b1eb034a4c 100644 --- a/frontend/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx +++ b/frontend/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx @@ -42,6 +42,7 @@ import { } from 'features/canvas/store/canvasTypes'; import { ChangeEvent } from 'react'; import { useTranslation } from 'react-i18next'; +import { useSingleAndDoubleClick } from 'common/hooks/useSingleAndDoubleClick'; export const selector = createSelector( [systemSelector, canvasSelector, isStagingSelector], @@ -156,7 +157,12 @@ const IAICanvasOutpaintingControls = () => { const handleSelectMoveTool = () => dispatch(setTool('move')); - const handleResetCanvasView = () => { + const handleClickResetCanvasView = useSingleAndDoubleClick( + () => handleResetCanvasView(false), + () => handleResetCanvasView(true) + ); + + const handleResetCanvasView = (shouldScaleTo1 = false) => { const canvasBaseLayer = getCanvasBaseLayer(); if (!canvasBaseLayer) return; const clientRect = canvasBaseLayer.getClientRect({ @@ -165,6 +171,7 @@ const IAICanvasOutpaintingControls = () => { dispatch( resetCanvasView({ contentRect: clientRect, + shouldScaleTo1, }) ); }; @@ -247,7 +254,7 @@ const IAICanvasOutpaintingControls = () => { aria-label={`${t('unifiedcanvas:resetView')} (R)`} tooltip={`${t('unifiedcanvas:resetView')} (R)`} icon={} - onClick={handleResetCanvasView} + onClick={handleClickResetCanvasView} /> diff --git a/frontend/src/features/canvas/store/canvasSlice.ts b/frontend/src/features/canvas/store/canvasSlice.ts index 31d02d27906..29aaa6342d0 100644 --- a/frontend/src/features/canvas/store/canvasSlice.ts +++ b/frontend/src/features/canvas/store/canvasSlice.ts @@ -602,9 +602,10 @@ export const canvasSlice = createSlice({ state, action: PayloadAction<{ contentRect: IRect; + shouldScaleTo1?: boolean; }> ) => { - const { contentRect } = action.payload; + const { contentRect, shouldScaleTo1 } = action.payload; const { stageDimensions: { width: stageWidth, height: stageHeight }, } = state; @@ -612,13 +613,15 @@ export const canvasSlice = createSlice({ const { x, y, width, height } = contentRect; if (width !== 0 && height !== 0) { - const newScale = calculateScale( - stageWidth, - stageHeight, - width, - height, - STAGE_PADDING_PERCENTAGE - ); + const newScale = shouldScaleTo1 + ? 1 + : calculateScale( + stageWidth, + stageHeight, + width, + height, + STAGE_PADDING_PERCENTAGE + ); const newCoordinates = calculateCoordinates( stageWidth, diff --git a/frontend/src/features/tabs/components/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetView.tsx b/frontend/src/features/tabs/components/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetView.tsx index c13d26e96cc..54a6c320a24 100644 --- a/frontend/src/features/tabs/components/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetView.tsx +++ b/frontend/src/features/tabs/components/UnifiedCanvas/UnifiedCanvasBeta/UnifiedCanvasToolbar/UnifiedCanvasResetView.tsx @@ -1,5 +1,6 @@ import { useAppDispatch } from 'app/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; +import { useSingleAndDoubleClick } from 'common/hooks/useSingleAndDoubleClick'; import { resetCanvasView } from 'features/canvas/store/canvasSlice'; import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider'; import React from 'react'; @@ -24,7 +25,12 @@ export default function UnifiedCanvasResetView() { [canvasBaseLayer] ); - const handleResetCanvasView = () => { + const handleClickResetCanvasView = useSingleAndDoubleClick( + () => handleResetCanvasView(false), + () => handleResetCanvasView(true) + ); + + const handleResetCanvasView = (shouldScaleTo1 = false) => { const canvasBaseLayer = getCanvasBaseLayer(); if (!canvasBaseLayer) return; const clientRect = canvasBaseLayer.getClientRect({ @@ -33,6 +39,7 @@ export default function UnifiedCanvasResetView() { dispatch( resetCanvasView({ contentRect: clientRect, + shouldScaleTo1, }) ); }; @@ -41,7 +48,7 @@ export default function UnifiedCanvasResetView() { aria-label={`${t('unifiedcanvas:resetView')} (R)`} tooltip={`${t('unifiedcanvas:resetView')} (R)`} icon={} - onClick={handleResetCanvasView} + onClick={handleClickResetCanvasView} /> ); }