roshikhan301's picture
Upload 2113 files
8a37e0a verified
import { useAppDispatch } from 'app/store/storeHooks';
import { buildUseBoolean } from 'common/hooks/useBoolean';
import { useCanvasManagerSafe } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { imageSelected, imageToCompareChanged } from 'features/gallery/store/gallerySlice';
import { useCallback } from 'react';
import type { ImageDTO } from 'services/api/types';
/**
* There's a race condition that causes the canvas to not fit to layers on the very first app startup.
*
* The canvas stage uses a resize observer to fit the stage to the container, and on the first resize event, it also
* fits the layers to the stage. Subsequent resize events only fit the stage to the container, they do not fit layers
* to the stage.
*
* On the very first app startup (new user or after they reset all web UI state), the resizable panels library needs
* to do one extra resize as it initializes and figures out its target size. At this time, the canvas stage has already
* done its one-time fit layers to stage, so the canvas stage does not fit layers to the stage again.
*
* For the end user, this means that the bbox is not centered in the canvas stage on the very first app startup. On
* all subsequent app startups, the bbox is centered in the canvas stage.
*
* We can hack around this, thanks to the fact that the image viewer is always opened on the first app startup. By the
* time the user closes it, the resizable panels library has already done its one extra resize and the DOM layout has
* stablized. So we can track the first time the image viewer is closed and fit the layers to the stage at that time,
* ensuring that the bbox is centered in the canvas stage on that first app startup.
*
* TODO(psyche): Figure out a better way to do handle this...
*/
let didCloseImageViewer = false;
const api = buildUseBoolean(true);
const useImageViewerState = api[0];
export const $imageViewer = api[1];
export const useImageViewer = () => {
const dispatch = useAppDispatch();
const canvasManager = useCanvasManagerSafe();
const imageViewerState = useImageViewerState();
const close = useCallback(() => {
if (!didCloseImageViewer && canvasManager) {
didCloseImageViewer = true;
canvasManager.stage.fitLayersToStage();
}
imageViewerState.setFalse();
}, [canvasManager, imageViewerState]);
const openImageInViewer = useCallback(
(imageDTO: ImageDTO) => {
dispatch(imageToCompareChanged(null));
dispatch(imageSelected(imageDTO));
imageViewerState.setTrue();
},
[dispatch, imageViewerState]
);
return {
isOpen: imageViewerState.isTrue,
open: imageViewerState.setTrue,
close,
toggle: imageViewerState.toggle,
openImageInViewer,
};
};