feat(ui): support reset canvas view when no image on canvas

This commit is contained in:
psychedelicious 2024-01-09 18:41:14 +11:00 committed by Kent Keirsey
parent 68a231afea
commit ebd68b7a6c
3 changed files with 63 additions and 52 deletions

View File

@ -1,27 +1,33 @@
// https://stackoverflow.com/a/73731908 // https://stackoverflow.com/a/73731908
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
export function useSingleAndDoubleClick( export type UseSingleAndDoubleClickOptions = {
handleSingleClick: () => void, onSingleClick: () => void;
handleDoubleClick: () => void, onDoubleClick: () => void;
delay = 250 latency?: number;
) { };
export function useSingleAndDoubleClick({
onSingleClick,
onDoubleClick,
latency = 250,
}: UseSingleAndDoubleClickOptions): () => void {
const [click, setClick] = useState(0); const [click, setClick] = useState(0);
useEffect(() => { useEffect(() => {
const timer = setTimeout(() => { const timer = setTimeout(() => {
if (click === 1) { if (click === 1) {
handleSingleClick(); onSingleClick();
} }
setClick(0); setClick(0);
}, delay); }, latency);
if (click === 2) { if (click === 2) {
handleDoubleClick(); onDoubleClick();
} }
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, [click, handleSingleClick, handleDoubleClick, delay]); }, [click, onDoubleClick, latency, onSingleClick]);
const onClick = useCallback(() => setClick((prev) => prev + 1), []); const onClick = useCallback(() => setClick((prev) => prev + 1), []);

View File

@ -15,7 +15,7 @@ import {
canvasMerged, canvasMerged,
canvasSavedToGallery, canvasSavedToGallery,
} from 'features/canvas/store/actions'; } from 'features/canvas/store/actions';
import { $canvasBaseLayer,$tool } from 'features/canvas/store/canvasNanostore'; import { $canvasBaseLayer, $tool } from 'features/canvas/store/canvasNanostore';
import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
import { import {
resetCanvas, resetCanvas,
@ -135,26 +135,35 @@ const IAICanvasToolbar = () => {
$tool.set('move'); $tool.set('move');
}, []); }, []);
const handleClickResetCanvasView = useSingleAndDoubleClick( const handleResetCanvasView = useCallback(
() => handleResetCanvasView(false), (shouldScaleTo1 = false) => {
() => handleResetCanvasView(true) const canvasBaseLayer = $canvasBaseLayer.get();
if (!canvasBaseLayer) {
return;
}
const clientRect = canvasBaseLayer.getClientRect({
skipTransform: true,
});
dispatch(
resetCanvasView({
contentRect: clientRect,
shouldScaleTo1,
})
);
},
[dispatch]
); );
const onSingleClick = useCallback(() => {
handleResetCanvasView(false);
}, [handleResetCanvasView]);
const onDoubleClick = useCallback(() => {
handleResetCanvasView(true);
}, [handleResetCanvasView]);
const handleResetCanvasView = (shouldScaleTo1 = false) => { const handleClickResetCanvasView = useSingleAndDoubleClick({
const canvasBaseLayer = $canvasBaseLayer.get(); onSingleClick,
if (!canvasBaseLayer) { onDoubleClick,
return; });
}
const clientRect = canvasBaseLayer.getClientRect({
skipTransform: true,
});
dispatch(
resetCanvasView({
contentRect: clientRect,
shouldScaleTo1,
})
);
};
const handleResetCanvas = useCallback(() => { const handleResetCanvas = useCallback(() => {
dispatch(resetCanvas()); dispatch(resetCanvas());

View File

@ -488,32 +488,28 @@ export const canvasSlice = createSlice({
stageDimensions: { width: stageWidth, height: stageHeight }, stageDimensions: { width: stageWidth, height: stageHeight },
} = state; } = state;
const { x, y, width, height } = contentRect; const newScale = shouldScaleTo1
? 1
: calculateScale(
stageWidth,
stageHeight,
contentRect.width || state.boundingBoxDimensions.width,
contentRect.height || state.boundingBoxDimensions.height,
STAGE_PADDING_PERCENTAGE
);
if (width !== 0 && height !== 0) { const newCoordinates = calculateCoordinates(
const newScale = shouldScaleTo1 stageWidth,
? 1 stageHeight,
: calculateScale( contentRect.x || state.boundingBoxCoordinates.x,
stageWidth, contentRect.y || state.boundingBoxCoordinates.y,
stageHeight, contentRect.width || state.boundingBoxDimensions.width,
width, contentRect.height || state.boundingBoxDimensions.height,
height, newScale
STAGE_PADDING_PERCENTAGE );
);
const newCoordinates = calculateCoordinates( state.stageScale = newScale;
stageWidth, state.stageCoordinates = newCoordinates;
stageHeight,
x,
y,
width,
height,
newScale
);
state.stageScale = newScale;
state.stageCoordinates = newCoordinates;
}
}, },
nextStagingAreaImage: (state) => { nextStagingAreaImage: (state) => {
if (!state.layerState.stagingArea.images.length) { if (!state.layerState.stagingArea.images.length) {