feat(ui): disable most interaction while filtering

This commit is contained in:
psychedelicious 2024-08-23 20:32:49 +10:00
parent c62ede5878
commit 181e40926d
11 changed files with 42 additions and 18 deletions

View File

@ -11,8 +11,8 @@ import { PiCheckBold, PiShootingStarBold, PiXBold } from 'react-icons/pi';
export const Filter = memo(() => {
const { t } = useTranslation();
const canvasManager = useCanvasManager();
const adapter = useStore(canvasManager.filter.$adapter);
const config = useStore(canvasManager.filter.$config);
const isFiltering = useStore(canvasManager.filter.$isFiltering);
const isProcessing = useStore(canvasManager.filter.$isProcessing);
const previewFilter = useCallback(() => {
@ -41,7 +41,7 @@ export const Filter = memo(() => {
[canvasManager.filter.$config]
);
if (!adapter) {
if (!isFiltering) {
return null;
}

View File

@ -1,5 +1,6 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useIsFiltering } from 'features/controlLayers/hooks/useIsFiltering';
import { useIsTransforming } from 'features/controlLayers/hooks/useIsTransforming';
import { toolChanged } from 'features/controlLayers/store/canvasV2Slice';
import { memo, useCallback, useMemo } from 'react';
@ -10,12 +11,13 @@ import { PiBoundingBoxBold } from 'react-icons/pi';
export const ToolBboxButton = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const isFiltering = useIsFiltering();
const isTransforming = useIsTransforming();
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
const isSelected = useAppSelector((s) => s.canvasV2.tool.selected === 'bbox');
const isDisabled = useMemo(() => {
return isTransforming || isStaging;
}, [isStaging, isTransforming]);
return isTransforming || isFiltering || isStaging;
}, [isFiltering, isStaging, isTransforming]);
const onClick = useCallback(() => {
dispatch(toolChanged('bbox'));

View File

@ -1,5 +1,6 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useIsFiltering } from 'features/controlLayers/hooks/useIsFiltering';
import { useIsTransforming } from 'features/controlLayers/hooks/useIsTransforming';
import { toolChanged } from 'features/controlLayers/store/canvasV2Slice';
import { isDrawableEntityType } from 'features/controlLayers/store/types';
@ -11,6 +12,7 @@ import { PiPaintBrushBold } from 'react-icons/pi';
export const ToolBrushButton = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const isFiltering = useIsFiltering();
const isTransforming = useIsTransforming();
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
const isSelected = useAppSelector((s) => s.canvasV2.tool.selected === 'brush');
@ -22,8 +24,8 @@ export const ToolBrushButton = memo(() => {
});
const isDisabled = useMemo(() => {
return isTransforming || isStaging || !isDrawingToolAllowed;
}, [isDrawingToolAllowed, isStaging, isTransforming]);
return isTransforming || isFiltering || isStaging || !isDrawingToolAllowed;
}, [isDrawingToolAllowed, isFiltering, isStaging, isTransforming]);
const onClick = useCallback(() => {
dispatch(toolChanged('brush'));

View File

@ -1,7 +1,7 @@
import { ButtonGroup } from '@invoke-ai/ui-library';
import { ToolBboxButton } from 'features/controlLayers/components/Tool/ToolBboxButton';
import { ToolBrushButton } from 'features/controlLayers/components/Tool/ToolBrushButton';
import { ToolColorPickerButton } from 'features/controlLayers/components/Tool/ToolEyeDropperButton';
import { ToolColorPickerButton } from 'features/controlLayers/components/Tool/ToolColorPickerButton';
import { ToolMoveButton } from 'features/controlLayers/components/Tool/ToolMoveButton';
import { ToolRectButton } from 'features/controlLayers/components/Tool/ToolRectButton';
import { useCanvasDeleteLayerHotkey } from 'features/controlLayers/hooks/useCanvasDeleteLayerHotkey';

View File

@ -1,5 +1,6 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useIsFiltering } from 'features/controlLayers/hooks/useIsFiltering';
import { useIsTransforming } from 'features/controlLayers/hooks/useIsTransforming';
import { toolChanged } from 'features/controlLayers/store/canvasV2Slice';
import { memo, useCallback, useMemo } from 'react';
@ -10,13 +11,14 @@ import { PiEyedropperBold } from 'react-icons/pi';
export const ToolColorPickerButton = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const isFiltering = useIsFiltering();
const isTransforming = useIsTransforming();
const isSelected = useAppSelector((s) => s.canvasV2.tool.selected === 'colorPicker');
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
const isDisabled = useMemo(() => {
return isTransforming || isStaging;
}, [isStaging, isTransforming]);
return isTransforming || isFiltering || isStaging;
}, [isFiltering, isStaging, isTransforming]);
const onClick = useCallback(() => {
dispatch(toolChanged('colorPicker'));

View File

@ -1,5 +1,6 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useIsFiltering } from 'features/controlLayers/hooks/useIsFiltering';
import { useIsTransforming } from 'features/controlLayers/hooks/useIsTransforming';
import { toolChanged } from 'features/controlLayers/store/canvasV2Slice';
import { isDrawableEntityType } from 'features/controlLayers/store/types';
@ -11,6 +12,7 @@ import { PiEraserBold } from 'react-icons/pi';
export const ToolEraserButton = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const isFiltering = useIsFiltering();
const isTransforming = useIsTransforming();
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
const isSelected = useAppSelector((s) => s.canvasV2.tool.selected === 'eraser');
@ -21,8 +23,8 @@ export const ToolEraserButton = memo(() => {
return isDrawableEntityType(s.canvasV2.selectedEntityIdentifier.type);
});
const isDisabled = useMemo(() => {
return isTransforming || isStaging || !isDrawingToolAllowed;
}, [isDrawingToolAllowed, isStaging, isTransforming]);
return isTransforming || isFiltering || isStaging || !isDrawingToolAllowed;
}, [isDrawingToolAllowed, isFiltering, isStaging, isTransforming]);
const onClick = useCallback(() => {
dispatch(toolChanged('eraser'));

View File

@ -1,5 +1,6 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useIsFiltering } from 'features/controlLayers/hooks/useIsFiltering';
import { useIsTransforming } from 'features/controlLayers/hooks/useIsTransforming';
import { toolChanged } from 'features/controlLayers/store/canvasV2Slice';
import { isDrawableEntityType } from 'features/controlLayers/store/types';
@ -11,6 +12,7 @@ import { PiCursorBold } from 'react-icons/pi';
export const ToolMoveButton = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const isFiltering = useIsFiltering();
const isTransforming = useIsTransforming();
const isSelected = useAppSelector((s) => s.canvasV2.tool.selected === 'move');
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
@ -21,8 +23,8 @@ export const ToolMoveButton = memo(() => {
return isDrawableEntityType(s.canvasV2.selectedEntityIdentifier.type);
});
const isDisabled = useMemo(() => {
return isTransforming || isStaging || !isDrawingToolAllowed;
}, [isDrawingToolAllowed, isStaging, isTransforming]);
return isTransforming || isFiltering || isStaging || !isDrawingToolAllowed;
}, [isDrawingToolAllowed, isFiltering, isStaging, isTransforming]);
const onClick = useCallback(() => {
dispatch(toolChanged('move'));

View File

@ -1,5 +1,6 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useIsFiltering } from 'features/controlLayers/hooks/useIsFiltering';
import { useIsTransforming } from 'features/controlLayers/hooks/useIsTransforming';
import { toolChanged } from 'features/controlLayers/store/canvasV2Slice';
import { isDrawableEntityType } from 'features/controlLayers/store/types';
@ -12,6 +13,7 @@ export const ToolRectButton = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const isSelected = useAppSelector((s) => s.canvasV2.tool.selected === 'rect');
const isFiltering = useIsFiltering();
const isTransforming = useIsTransforming();
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
const isDrawingToolAllowed = useAppSelector((s) => {
@ -22,8 +24,8 @@ export const ToolRectButton = memo(() => {
});
const isDisabled = useMemo(() => {
return isTransforming || isStaging || !isDrawingToolAllowed;
}, [isDrawingToolAllowed, isStaging, isTransforming]);
return isTransforming || isFiltering || isStaging || !isDrawingToolAllowed;
}, [isDrawingToolAllowed, isFiltering, isStaging, isTransforming]);
const onClick = useCallback(() => {
dispatch(toolChanged('rect'));

View File

@ -1,5 +1,6 @@
import { IconButton } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useIsFiltering } from 'features/controlLayers/hooks/useIsFiltering';
import { useIsTransforming } from 'features/controlLayers/hooks/useIsTransforming';
import { toolChanged } from 'features/controlLayers/store/canvasV2Slice';
import { memo, useCallback, useMemo } from 'react';
@ -11,11 +12,12 @@ export const ToolViewButton = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const isTransforming = useIsTransforming();
const isFiltering = useIsFiltering();
const isStaging = useAppSelector((s) => s.canvasV2.session.isStaging);
const isSelected = useAppSelector((s) => s.canvasV2.tool.selected === 'view');
const isDisabled = useMemo(() => {
return isTransforming || isStaging;
}, [isStaging, isTransforming]);
return isTransforming || isFiltering || isStaging;
}, [isFiltering, isStaging, isTransforming]);
const onClick = useCallback(() => {
dispatch(toolChanged('view'));
}, [dispatch]);

View File

@ -0,0 +1,8 @@
import { useStore } from '@nanostores/react';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
export const useIsFiltering = () => {
const canvasManager = useCanvasManager();
const isFiltering = useStore(canvasManager.filter.$isFiltering);
return isFiltering;
};

View File

@ -4,7 +4,7 @@ import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import { getPrefixedId } from 'features/controlLayers/konva/util';
import type { CanvasEntityIdentifier, CanvasImageState, FilterConfig } from 'features/controlLayers/store/types';
import { IMAGE_FILTERS, imageDTOToImageObject } from 'features/controlLayers/store/types';
import { atom } from 'nanostores';
import { atom, computed } from 'nanostores';
import type { Logger } from 'roarr';
import { getImageDTO } from 'services/api/endpoints/images';
import type { BatchConfig, ImageDTO, S } from 'services/api/types';
@ -23,6 +23,7 @@ export class CanvasFilterModule {
imageState: CanvasImageState | null = null;
$adapter = atom<CanvasLayerAdapter | null>(null);
$isFiltering = computed(this.$adapter, (adapter) => Boolean(adapter));
$isProcessing = atom<boolean>(false);
$config = atom<FilterConfig>(IMAGE_FILTERS.canny_image_processor.buildDefaults());
@ -46,6 +47,7 @@ export class CanvasFilterModule {
return;
}
this.$adapter.set(entity.adapter);
this.manager.stateApi.setTool('view');
};
previewFilter = async () => {