Skip to content

Commit ebd68b7

Browse files
psychedelicioushipsterusername
authored andcommitted
feat(ui): support reset canvas view when no image on canvas
1 parent 68a231a commit ebd68b7

File tree

3 files changed

+63
-52
lines changed

3 files changed

+63
-52
lines changed

invokeai/frontend/web/src/common/hooks/useSingleAndDoubleClick.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,33 @@
11
// https://stackoverflow.com/a/73731908
22
import { useCallback, useEffect, useState } from 'react';
33

4-
export function useSingleAndDoubleClick(
5-
handleSingleClick: () => void,
6-
handleDoubleClick: () => void,
7-
delay = 250
8-
) {
4+
export type UseSingleAndDoubleClickOptions = {
5+
onSingleClick: () => void;
6+
onDoubleClick: () => void;
7+
latency?: number;
8+
};
9+
10+
export function useSingleAndDoubleClick({
11+
onSingleClick,
12+
onDoubleClick,
13+
latency = 250,
14+
}: UseSingleAndDoubleClickOptions): () => void {
915
const [click, setClick] = useState(0);
1016

1117
useEffect(() => {
1218
const timer = setTimeout(() => {
1319
if (click === 1) {
14-
handleSingleClick();
20+
onSingleClick();
1521
}
1622
setClick(0);
17-
}, delay);
23+
}, latency);
1824

1925
if (click === 2) {
20-
handleDoubleClick();
26+
onDoubleClick();
2127
}
2228

2329
return () => clearTimeout(timer);
24-
}, [click, handleSingleClick, handleDoubleClick, delay]);
30+
}, [click, onDoubleClick, latency, onSingleClick]);
2531

2632
const onClick = useCallback(() => setClick((prev) => prev + 1), []);
2733

invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasToolbar.tsx

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
canvasMerged,
1616
canvasSavedToGallery,
1717
} from 'features/canvas/store/actions';
18-
import { $canvasBaseLayer,$tool } from 'features/canvas/store/canvasNanostore';
18+
import { $canvasBaseLayer, $tool } from 'features/canvas/store/canvasNanostore';
1919
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
2020
import {
2121
resetCanvas,
@@ -135,26 +135,35 @@ const IAICanvasToolbar = () => {
135135
$tool.set('move');
136136
}, []);
137137

138-
const handleClickResetCanvasView = useSingleAndDoubleClick(
139-
() => handleResetCanvasView(false),
140-
() => handleResetCanvasView(true)
138+
const handleResetCanvasView = useCallback(
139+
(shouldScaleTo1 = false) => {
140+
const canvasBaseLayer = $canvasBaseLayer.get();
141+
if (!canvasBaseLayer) {
142+
return;
143+
}
144+
const clientRect = canvasBaseLayer.getClientRect({
145+
skipTransform: true,
146+
});
147+
dispatch(
148+
resetCanvasView({
149+
contentRect: clientRect,
150+
shouldScaleTo1,
151+
})
152+
);
153+
},
154+
[dispatch]
141155
);
156+
const onSingleClick = useCallback(() => {
157+
handleResetCanvasView(false);
158+
}, [handleResetCanvasView]);
159+
const onDoubleClick = useCallback(() => {
160+
handleResetCanvasView(true);
161+
}, [handleResetCanvasView]);
142162

143-
const handleResetCanvasView = (shouldScaleTo1 = false) => {
144-
const canvasBaseLayer = $canvasBaseLayer.get();
145-
if (!canvasBaseLayer) {
146-
return;
147-
}
148-
const clientRect = canvasBaseLayer.getClientRect({
149-
skipTransform: true,
150-
});
151-
dispatch(
152-
resetCanvasView({
153-
contentRect: clientRect,
154-
shouldScaleTo1,
155-
})
156-
);
157-
};
163+
const handleClickResetCanvasView = useSingleAndDoubleClick({
164+
onSingleClick,
165+
onDoubleClick,
166+
});
158167

159168
const handleResetCanvas = useCallback(() => {
160169
dispatch(resetCanvas());

invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -488,32 +488,28 @@ export const canvasSlice = createSlice({
488488
stageDimensions: { width: stageWidth, height: stageHeight },
489489
} = state;
490490

491-
const { x, y, width, height } = contentRect;
492-
493-
if (width !== 0 && height !== 0) {
494-
const newScale = shouldScaleTo1
495-
? 1
496-
: calculateScale(
497-
stageWidth,
498-
stageHeight,
499-
width,
500-
height,
501-
STAGE_PADDING_PERCENTAGE
502-
);
491+
const newScale = shouldScaleTo1
492+
? 1
493+
: calculateScale(
494+
stageWidth,
495+
stageHeight,
496+
contentRect.width || state.boundingBoxDimensions.width,
497+
contentRect.height || state.boundingBoxDimensions.height,
498+
STAGE_PADDING_PERCENTAGE
499+
);
503500

504-
const newCoordinates = calculateCoordinates(
505-
stageWidth,
506-
stageHeight,
507-
x,
508-
y,
509-
width,
510-
height,
511-
newScale
512-
);
501+
const newCoordinates = calculateCoordinates(
502+
stageWidth,
503+
stageHeight,
504+
contentRect.x || state.boundingBoxCoordinates.x,
505+
contentRect.y || state.boundingBoxCoordinates.y,
506+
contentRect.width || state.boundingBoxDimensions.width,
507+
contentRect.height || state.boundingBoxDimensions.height,
508+
newScale
509+
);
513510

514-
state.stageScale = newScale;
515-
state.stageCoordinates = newCoordinates;
516-
}
511+
state.stageScale = newScale;
512+
state.stageCoordinates = newCoordinates;
517513
},
518514
nextStagingAreaImage: (state) => {
519515
if (!state.layerState.stagingArea.images.length) {

0 commit comments

Comments
 (0)