adds double-click to reset view to 100% (#2436)

Adds double-click to reset canvas view to 100%.

- Adds hook to manage single and double clicks
- Single Click `Reset Canvas View` --> scale to fit, no change to
current behaviour
- Double Click `Reset Canvas View` --> set scale to 1
This commit is contained in:
psychedelicious 2023-01-28 00:56:24 +11:00 committed by GitHub
commit 1ceb7a60db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 12 deletions

View File

@ -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);
}

View File

@ -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={<FaCrosshairs />}
onClick={handleResetCanvasView}
onClick={handleClickResetCanvasView}
/>
</ButtonGroup>

View File

@ -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,

View File

@ -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={<FaCrosshairs />}
onClick={handleResetCanvasView}
onClick={handleClickResetCanvasView}
/>
);
}