diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasScale.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasScale.tsx index 5d8d2ee11b..05157b577b 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/CanvasScale.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasScale.tsx @@ -14,10 +14,9 @@ import { PopoverTrigger, } from '@invoke-ai/ui-library'; import { useStore } from '@nanostores/react'; -import { $canvasManager } from 'features/controlLayers/konva/CanvasManager'; +import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate'; import { MAX_CANVAS_SCALE, MIN_CANVAS_SCALE } from 'features/controlLayers/konva/constants'; import { snapToNearest } from 'features/controlLayers/konva/util'; -import { $stageAttrs } from 'features/controlLayers/store/canvasV2Slice'; import { clamp, round } from 'lodash-es'; import { computed } from 'nanostores'; import type { KeyboardEvent } from 'react'; @@ -72,12 +71,10 @@ const sliderDefaultValue = mapScaleToSliderValue(100); const snapCandidates = marks.slice(1, marks.length - 1); -const $scale = computed($stageAttrs, (attrs) => attrs.scale); - export const CanvasScale = memo(() => { const { t } = useTranslation(); - const canvasManager = useStore($canvasManager); - const scale = useStore($scale); + const canvasManager = useCanvasManager(); + const scale = useStore(computed(canvasManager.stateApi.$stageAttrs, (attrs) => attrs.scale)); const [localScale, setLocalScale] = useState(scale * 100); const onChangeSlider = useCallback( diff --git a/invokeai/frontend/web/src/features/controlLayers/components/HeadsUpDisplay.tsx b/invokeai/frontend/web/src/features/controlLayers/components/HeadsUpDisplay.tsx index 5f3bcab13c..ec7bcdaa25 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/HeadsUpDisplay.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/HeadsUpDisplay.tsx @@ -1,24 +1,18 @@ import { Box, Flex, Text } from '@invoke-ai/ui-library'; import { useStore } from '@nanostores/react'; import { useAppSelector } from 'app/store/storeHooks'; -import { - $isDrawing, - $isMouseDown, - $lastAddedPoint, - $lastCursorPos, - $lastMouseDownPos, - $stageAttrs, -} from 'features/controlLayers/store/canvasV2Slice'; +import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate'; import { round } from 'lodash-es'; import { memo } from 'react'; export const HeadsUpDisplay = memo(() => { - const stageAttrs = useStore($stageAttrs); - const cursorPos = useStore($lastCursorPos); - const isDrawing = useStore($isDrawing); - const isMouseDown = useStore($isMouseDown); - const lastMouseDownPos = useStore($lastMouseDownPos); - const lastAddedPoint = useStore($lastAddedPoint); + const canvasManager = useCanvasManager(); + const stageAttrs = useStore(canvasManager.stateApi.$stageAttrs); + const cursorPos = useStore(canvasManager.stateApi.$lastCursorPos); + const isDrawing = useStore(canvasManager.stateApi.$isDrawing); + const isMouseDown = useStore(canvasManager.stateApi.$isMouseDown); + const lastMouseDownPos = useStore(canvasManager.stateApi.$lastMouseDownPos); + const lastAddedPoint = useStore(canvasManager.stateApi.$lastAddedPoint); const bbox = useAppSelector((s) => s.canvasV2.bbox); return ( diff --git a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbar.tsx b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbar.tsx index 45e51f59fc..ed4bcb38b3 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbar.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/StagingArea/StagingAreaToolbar.tsx @@ -2,8 +2,8 @@ import { Button, ButtonGroup, IconButton } from '@invoke-ai/ui-library'; import { useStore } from '@nanostores/react'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { INTERACTION_SCOPES, useScopeOnMount } from 'common/hooks/interactionScopes'; +import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate'; import { - $shouldShowStagedImage, sessionNextStagedImageSelected, sessionPrevStagedImageSelected, sessionStagedImageDiscarded, @@ -28,7 +28,8 @@ import { useChangeImageIsIntermediateMutation } from 'services/api/endpoints/ima export const StagingAreaToolbar = memo(() => { const dispatch = useAppDispatch(); const session = useAppSelector((s) => s.canvasV2.session); - const shouldShowStagedImage = useStore($shouldShowStagedImage); + const canvasManager = useCanvasManager(); + const shouldShowStagedImage = useStore(canvasManager.stateApi.$shouldShowStagedImage); const images = useMemo(() => session.stagedImages, [session]); const selectedImage = useMemo(() => { return images[session.selectedStagedImageIndex] ?? null; @@ -70,8 +71,8 @@ export const StagingAreaToolbar = memo(() => { }, [dispatch]); const onToggleShouldShowStagedImage = useCallback(() => { - $shouldShowStagedImage.set(!shouldShowStagedImage); - }, [shouldShowStagedImage]); + canvasManager.stateApi.$shouldShowStagedImage.set(!shouldShowStagedImage); + }, [canvasManager.stateApi.$shouldShowStagedImage, shouldShowStagedImage]); const onSaveStagingImage = useCallback(() => { if (!selectedImage) { diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApiModule.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApiModule.ts index 377c15cebb..c9c20892ec 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApiModule.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApiModule.ts @@ -4,16 +4,6 @@ import type { CanvasLayerAdapter } from 'features/controlLayers/konva/CanvasLaye import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager'; import type { CanvasMaskAdapter } from 'features/controlLayers/konva/CanvasMaskAdapter'; import { - $isDrawing, - $isMouseDown, - $isProcessingTransform, - $lastAddedPoint, - $lastCursorPos, - $lastMouseDownPos, - $shouldShowStagedImage, - $spaceKey, - $stageAttrs, - $transformingEntity, bboxChanged, brushWidthChanged, entityBrushLineAdded, @@ -36,6 +26,7 @@ import type { CanvasRasterLayerState, CanvasRegionalGuidanceState, CanvasV2State, + Coordinate, EntityBrushLineAddedPayload, EntityEraserLineAddedPayload, EntityIdentifierPayload, @@ -45,6 +36,7 @@ import type { Rect, RgbaColor, RgbColor, + StageAttrs, Tool, } from 'features/controlLayers/store/types'; import { RGBA_BLACK } from 'features/controlLayers/store/types'; @@ -243,8 +235,8 @@ export class CanvasStateApiModule { } }; - $transformingEntity = $transformingEntity; - $isProcessingTransform = $isProcessingTransform; + $transformingEntity = atom(null); + $isProcessingTransform = atom(false); $toolState: WritableAtom = atom(); $currentFill: WritableAtom = atom(); @@ -253,17 +245,23 @@ export class CanvasStateApiModule { $colorUnderCursor: WritableAtom = atom(RGBA_BLACK); // Read-write state, ephemeral interaction state - $isDrawing = $isDrawing; - $isMouseDown = $isMouseDown; - $lastAddedPoint = $lastAddedPoint; - $lastMouseDownPos = $lastMouseDownPos; - $lastCursorPos = $lastCursorPos; + $isDrawing = atom(false); + $isMouseDown = atom(false); + $lastAddedPoint = atom(null); + $lastMouseDownPos = atom(null); + $lastCursorPos = atom(null); $lastCanvasProgressEvent = $lastCanvasProgressEvent; - $spaceKey = $spaceKey; + $spaceKey = atom(false); $altKey = $alt; $ctrlKey = $ctrl; $metaKey = $meta; $shiftKey = $shift; - $shouldShowStagedImage = $shouldShowStagedImage; - $stageAttrs = $stageAttrs; + $shouldShowStagedImage = atom(true); + $stageAttrs = atom({ + x: 0, + y: 0, + width: 0, + height: 0, + scale: 0, + }); } diff --git a/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts b/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts index 611cf49622..81b688c950 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts @@ -22,20 +22,17 @@ import { simplifyFlatNumbersArray } from 'features/controlLayers/util/simplify'; import { initialAspectRatioState } from 'features/parameters/components/DocumentSize/constants'; import { getOptimalDimension } from 'features/parameters/util/optimalDimension'; import { pick } from 'lodash-es'; -import { atom } from 'nanostores'; import { assert } from 'tsafe'; import type { CanvasEntityIdentifier, CanvasV2State, - Coordinate, EntityBrushLineAddedPayload, EntityEraserLineAddedPayload, EntityIdentifierPayload, EntityMovedPayload, EntityRasterizedPayload, EntityRectAddedPayload, - StageAttrs, } from './types'; import { getEntityIdentifier, isDrawableEntity } from './types'; @@ -564,25 +561,6 @@ const migrate = (state: any): any => { return state; }; -// Ephemeral state that does not need to be in redux -export const $isPreviewVisible = atom(true); -export const $stageAttrs = atom({ - x: 0, - y: 0, - width: 0, - height: 0, - scale: 0, -}); -export const $shouldShowStagedImage = atom(true); -export const $isDrawing = atom(false); -export const $isMouseDown = atom(false); -export const $lastAddedPoint = atom(null); -export const $lastMouseDownPos = atom(null); -export const $lastCursorPos = atom(null); -export const $spaceKey = atom(false); -export const $transformingEntity = atom(null); -export const $isProcessingTransform = atom(false); - export const canvasV2PersistConfig: PersistConfig = { name: canvasV2Slice.name, initialState, diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersPanels/ParametersPanelTextToImage.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersPanels/ParametersPanelTextToImage.tsx index dad4fdc215..85905142d3 100644 --- a/invokeai/frontend/web/src/features/ui/components/ParametersPanels/ParametersPanelTextToImage.tsx +++ b/invokeai/frontend/web/src/features/ui/components/ParametersPanels/ParametersPanelTextToImage.tsx @@ -5,7 +5,6 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants'; import { CanvasEntityListMenuButton } from 'features/controlLayers/components/CanvasEntityList/CanvasEntityListMenuButton'; import { CanvasPanelContent } from 'features/controlLayers/components/CanvasPanelContent'; -import { $isPreviewVisible } from 'features/controlLayers/store/canvasV2Slice'; import { selectEntityCount } from 'features/controlLayers/store/selectors'; import { isImageViewerOpenChanged } from 'features/gallery/store/gallerySlice'; import { Prompts } from 'features/parameters/components/Prompts/Prompts'; @@ -56,7 +55,6 @@ const ParametersPanelTextToImage = () => { if (i === 1) { dispatch(isImageViewerOpenChanged(false)); } - $isPreviewVisible.set(i === 0); }, [dispatch] );