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 0000000000..8b2b35bcb1
--- /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 531abd0820..9b1eb034a4 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 31d02d2790..29aaa6342d 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 c13d26e96c..54a6c320a2 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}
/>
);
}