tidy(ui): rename canvas session slice to staging area slice

This commit is contained in:
psychedelicious
2024-09-08 06:31:15 +10:00
parent 60d2541934
commit 5ab4818eb6
15 changed files with 82 additions and 76 deletions

View File

@@ -1,5 +1,5 @@
import { useAppSelector } from 'app/store/storeHooks';
import { selectIsStaging } from 'features/controlLayers/store/canvasSessionSlice';
import { selectIsStaging } from 'features/controlLayers/store/canvasStagingAreaSlice';
import type { PropsWithChildren } from 'react';
import { memo } from 'react';

View File

@@ -5,13 +5,13 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { INTERACTION_SCOPES, useScopeOnMount } from 'common/hooks/interactionScopes';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import {
selectCanvasSessionSlice,
sessionNextStagedImageSelected,
sessionPrevStagedImageSelected,
sessionStagedImageDiscarded,
sessionStagingAreaImageAccepted,
sessionStagingAreaReset,
} from 'features/controlLayers/store/canvasSessionSlice';
selectCanvasStagingAreaSlice,
stagingAreaImageAccepted,
stagingAreaNextStagedImageSelected,
stagingAreaPrevStagedImageSelected,
stagingAreaReset,
stagingAreaStagedImageDiscarded,
} from 'features/controlLayers/store/canvasStagingAreaSlice';
import { memo, useCallback, useMemo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
@@ -28,16 +28,16 @@ import {
import { useChangeImageIsIntermediateMutation } from 'services/api/endpoints/images';
const selectStagedImageIndex = createSelector(
selectCanvasSessionSlice,
(canvasSession) => canvasSession.selectedStagedImageIndex
selectCanvasStagingAreaSlice,
(stagingArea) => stagingArea.selectedStagedImageIndex
);
const selectSelectedImage = createSelector(
[selectCanvasSessionSlice, selectStagedImageIndex],
(canvasSession, index) => canvasSession.stagedImages[index] ?? null
[selectCanvasStagingAreaSlice, selectStagedImageIndex],
(stagingArea, index) => stagingArea.stagedImages[index] ?? null
);
const selectImageCount = createSelector(selectCanvasSessionSlice, (canvasSession) => canvasSession.stagedImages.length);
const selectImageCount = createSelector(selectCanvasStagingAreaSlice, (stagingArea) => stagingArea.stagedImages.length);
export const StagingAreaToolbar = memo(() => {
const dispatch = useAppDispatch();
@@ -53,18 +53,18 @@ export const StagingAreaToolbar = memo(() => {
const { t } = useTranslation();
const onPrev = useCallback(() => {
dispatch(sessionPrevStagedImageSelected());
dispatch(stagingAreaPrevStagedImageSelected());
}, [dispatch]);
const onNext = useCallback(() => {
dispatch(sessionNextStagedImageSelected());
dispatch(stagingAreaNextStagedImageSelected());
}, [dispatch]);
const onAccept = useCallback(() => {
if (!selectedImage) {
return;
}
dispatch(sessionStagingAreaImageAccepted({ index }));
dispatch(stagingAreaImageAccepted({ index }));
}, [dispatch, index, selectedImage]);
const onDiscardOne = useCallback(() => {
@@ -72,14 +72,14 @@ export const StagingAreaToolbar = memo(() => {
return;
}
if (imageCount === 1) {
dispatch(sessionStagingAreaReset());
dispatch(stagingAreaReset());
} else {
dispatch(sessionStagedImageDiscarded({ index }));
dispatch(stagingAreaStagedImageDiscarded({ index }));
}
}, [selectedImage, imageCount, dispatch, index]);
const onDiscardAll = useCallback(() => {
dispatch(sessionStagingAreaReset());
dispatch(stagingAreaReset());
}, [dispatch]);
const onToggleShouldShowStagedImage = useCallback(() => {

View File

@@ -5,8 +5,8 @@ import { isOk, withResultAsync } from 'common/util/result';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
import { useEntityTypeCount } from 'features/controlLayers/hooks/useEntityTypeCount';
import { selectIsStaging } from 'features/controlLayers/store/canvasSessionSlice';
import { inpaintMaskAdded, rasterLayerAdded } from 'features/controlLayers/store/canvasSlice';
import { selectIsStaging } from 'features/controlLayers/store/canvasStagingAreaSlice';
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
import { imageDTOToImageObject } from 'features/controlLayers/store/types';
import { toast } from 'features/toast/toast';

View File

@@ -1,7 +1,7 @@
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { useAssertSingleton } from 'common/hooks/useAssertSingleton';
import { selectIsStaging } from 'features/controlLayers/store/canvasSessionSlice';
import { entityDeleted } from 'features/controlLayers/store/canvasSlice';
import { selectIsStaging } from 'features/controlLayers/store/canvasStagingAreaSlice';
import { selectSelectedEntityIdentifier } from 'features/controlLayers/store/selectors';
import { useCallback, useMemo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';

View File

@@ -6,7 +6,7 @@ import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
import { useEntityAdapterSafe } from 'features/controlLayers/hooks/useEntityAdapter';
import type { AnyObjectRenderer } from 'features/controlLayers/konva/CanvasEntityObjectRenderer';
import { getEmptyRect } from 'features/controlLayers/konva/util';
import { selectIsStaging } from 'features/controlLayers/store/canvasSessionSlice';
import { selectIsStaging } from 'features/controlLayers/store/canvasStagingAreaSlice';
import type { CanvasEntityIdentifier, Rect } from 'features/controlLayers/store/types';
import { isFilterableEntityIdentifier } from 'features/controlLayers/store/types';
import { atom } from 'nanostores';

View File

@@ -6,7 +6,7 @@ import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
import { useEntityAdapterSafe } from 'features/controlLayers/hooks/useEntityAdapter';
import type { AnyObjectRenderer } from 'features/controlLayers/konva/CanvasEntityObjectRenderer';
import { getEmptyRect } from 'features/controlLayers/konva/util';
import { selectIsStaging } from 'features/controlLayers/store/canvasSessionSlice';
import { selectIsStaging } from 'features/controlLayers/store/canvasStagingAreaSlice';
import type { CanvasEntityIdentifier, Rect } from 'features/controlLayers/store/types';
import { isTransformableEntityIdentifier } from 'features/controlLayers/store/types';
import { atom } from 'nanostores';

View File

@@ -2,7 +2,7 @@ import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager';
import { CanvasModuleBase } from 'features/controlLayers/konva/CanvasModuleBase';
import { CanvasObjectImage } from 'features/controlLayers/konva/CanvasObjectImage';
import { getPrefixedId } from 'features/controlLayers/konva/util';
import { selectCanvasSessionSlice } from 'features/controlLayers/store/canvasSessionSlice';
import { selectCanvasStagingAreaSlice } from 'features/controlLayers/store/canvasStagingAreaSlice';
import { imageDTOToImageWithDims, type StagingAreaImage } from 'features/controlLayers/store/types';
import Konva from 'konva';
import { atom } from 'nanostores';
@@ -38,7 +38,7 @@ export class CanvasStagingAreaModule extends CanvasModuleBase {
this.selectedImage = null;
this.subscriptions.add(this.$shouldShowStagedImage.listen(this.render));
this.subscriptions.add(this.manager.stateApi.createStoreSubscription(selectCanvasSessionSlice, this.render));
this.subscriptions.add(this.manager.stateApi.createStoreSubscription(selectCanvasStagingAreaSlice, this.render));
}
initialize = () => {
@@ -48,7 +48,7 @@ export class CanvasStagingAreaModule extends CanvasModuleBase {
render = async () => {
this.log.trace('Rendering staging area');
const stagingArea = this.manager.stateApi.runSelector(selectCanvasSessionSlice);
const stagingArea = this.manager.stateApi.runSelector(selectCanvasStagingAreaSlice);
const { x, y, width, height } = this.manager.stateApi.getBbox().rect;
const shouldShowStagedImage = this.$shouldShowStagedImage.get();

View File

@@ -22,6 +22,7 @@ import {
entityRectAdded,
entityReset,
} from 'features/controlLayers/store/canvasSlice';
import { selectCanvasStagingAreaSlice } from 'features/controlLayers/store/canvasStagingAreaSlice';
import { selectAllRenderableEntities, selectCanvasSlice } from 'features/controlLayers/store/selectors';
import type {
CanvasEntityType,
@@ -210,10 +211,10 @@ export class CanvasStateApiModule extends CanvasModuleBase {
};
/**
* Gets the canvas session state from redux.
* Gets the canvas staging area state from redux.
*/
getSession = () => {
return this.store.getState().canvasSession;
getStagingArea = () => {
return selectCanvasStagingAreaSlice(this.store.getState());
};
/**

View File

@@ -1,43 +1,43 @@
import { createAction, createSelector, createSlice, type PayloadAction } from '@reduxjs/toolkit';
import { createSelector, createSlice, type PayloadAction } from '@reduxjs/toolkit';
import type { PersistConfig, RootState } from 'app/store/store';
import { deepClone } from 'common/util/deepClone';
import { canvasReset, canvasSlice } from 'features/controlLayers/store/canvasSlice';
import { canvasReset } from 'features/controlLayers/store/canvasSlice';
import type { StagingAreaImage } from 'features/controlLayers/store/types';
type CanvasSessionState = {
type CanvasStagingAreaState = {
isStaging: boolean;
stagedImages: StagingAreaImage[];
selectedStagedImageIndex: number;
};
const initialState: CanvasSessionState = {
const initialState: CanvasStagingAreaState = {
isStaging: false,
stagedImages: [],
selectedStagedImageIndex: 0,
};
export const canvasSessionSlice = createSlice({
name: 'canvasSession',
export const canvasStagingAreaSlice = createSlice({
name: 'canvasStagingArea',
initialState,
reducers: {
sessionStartedStaging: (state) => {
stagingAreaStartedStaging: (state) => {
state.isStaging = true;
state.selectedStagedImageIndex = 0;
},
sessionImageStaged: (state, action: PayloadAction<{ stagingAreaImage: StagingAreaImage }>) => {
stagingAreaImageStaged: (state, action: PayloadAction<{ stagingAreaImage: StagingAreaImage }>) => {
const { stagingAreaImage } = action.payload;
state.isStaging = true;
state.stagedImages.push(stagingAreaImage);
state.selectedStagedImageIndex = state.stagedImages.length - 1;
},
sessionNextStagedImageSelected: (state) => {
stagingAreaNextStagedImageSelected: (state) => {
state.selectedStagedImageIndex = (state.selectedStagedImageIndex + 1) % state.stagedImages.length;
},
sessionPrevStagedImageSelected: (state) => {
stagingAreaPrevStagedImageSelected: (state) => {
state.selectedStagedImageIndex =
(state.selectedStagedImageIndex - 1 + state.stagedImages.length) % state.stagedImages.length;
},
sessionStagedImageDiscarded: (state, action: PayloadAction<{ index: number }>) => {
stagingAreaStagedImageDiscarded: (state, action: PayloadAction<{ index: number }>) => {
const { index } = action.payload;
state.stagedImages.splice(index, 1);
state.selectedStagedImageIndex = Math.min(state.selectedStagedImageIndex, state.stagedImages.length - 1);
@@ -45,11 +45,14 @@ export const canvasSessionSlice = createSlice({
state.isStaging = false;
}
},
sessionStagingAreaReset: (state) => {
stagingAreaReset: (state) => {
state.isStaging = false;
state.stagedImages = [];
state.selectedStagedImageIndex = 0;
},
stagingAreaImageAccepted: (_state, _action: PayloadAction<{ index: number }>) => {
// no-op, handled in a listener
},
},
extraReducers(builder) {
builder.addCase(canvasReset, () => deepClone(initialState));
@@ -57,29 +60,27 @@ export const canvasSessionSlice = createSlice({
});
export const {
sessionStartedStaging,
sessionImageStaged,
sessionStagedImageDiscarded,
sessionStagingAreaReset,
sessionNextStagedImageSelected,
sessionPrevStagedImageSelected,
} = canvasSessionSlice.actions;
stagingAreaStartedStaging,
stagingAreaImageStaged,
stagingAreaStagedImageDiscarded,
stagingAreaReset,
stagingAreaNextStagedImageSelected,
stagingAreaPrevStagedImageSelected,
stagingAreaImageAccepted,
} = canvasStagingAreaSlice.actions;
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const migrate = (state: any): any => {
return state;
};
export const canvasSessionPersistConfig: PersistConfig<CanvasSessionState> = {
name: canvasSessionSlice.name,
export const canvasStagingAreaPersistConfig: PersistConfig<CanvasStagingAreaState> = {
name: canvasStagingAreaSlice.name,
initialState,
migrate,
persistDenylist: [],
};
export const sessionStagingAreaImageAccepted = createAction<{ index: number }>(
`${canvasSlice.name}/sessionStagingAreaImageAccepted`
);
export const selectCanvasSessionSlice = (s: RootState) => s.canvasSession;
export const selectCanvasStagingAreaSlice = (s: RootState) => s.canvasStagingArea;
export const selectIsStaging = createSelector(selectCanvasSessionSlice, (canvasSession) => canvasSession.isStaging);
export const selectIsStaging = createSelector(selectCanvasStagingAreaSlice, (stagingaArea) => stagingaArea.isStaging);