1- import { createSelector , createSlice , type PayloadAction } from '@reduxjs/toolkit' ;
1+ import type { PayloadAction , UnknownAction } from '@reduxjs/toolkit' ;
2+ import { createSelector , createSlice , isAnyOf } from '@reduxjs/toolkit' ;
23import { EMPTY_ARRAY } from 'app/store/constants' ;
34import type { RootState } from 'app/store/store' ;
45import type { SliceConfig } from 'app/store/types' ;
@@ -11,64 +12,85 @@ import z from 'zod';
1112import {
1213 canvasAdding ,
1314 canvasDeleted ,
15+ canvasInitialized ,
1416 canvasMultiCanvasMigrated ,
1517 MIGRATION_MULTI_CANVAS_ID_PLACEHOLDER ,
1618} from './canvasSlice' ;
1719import { selectActiveCanvasId } from './selectors' ;
1820
19- const zCanvasSessionState = z . object ( {
21+ const zCanvasSession = z . object ( {
2022 canvasId : z . string ( ) . min ( 1 ) ,
2123 canvasSessionId : z . string ( ) ,
2224 canvasDiscardedQueueItems : z . array ( z . number ( ) . int ( ) ) ,
2325} ) ;
24- type CanvasSessionState = z . infer < typeof zCanvasSessionState > ;
26+ type CanvasSession = z . infer < typeof zCanvasSession > ;
2527const zCanvasStagingAreaState = z . object ( {
2628 _version : z . literal ( 2 ) ,
27- sessions : z . record ( z . string ( ) , zCanvasSessionState ) ,
29+ sessions : z . record ( z . string ( ) , zCanvasSession ) ,
2830} ) ;
2931type CanvasStagingAreaState = z . infer < typeof zCanvasStagingAreaState > ;
3032
3133type CanvasPayload < T > = { canvasId : string } & T ;
3234type CanvasPayloadAction < T > = PayloadAction < CanvasPayload < T > > ;
3335
34- const getInitialCanvasSessionState = ( canvasId : string ) : CanvasSessionState => ( {
36+ const getInitialCanvasSessionState = ( canvasId : string ) : CanvasSession => ( {
3537 canvasId,
3638 canvasSessionId : getPrefixedId ( 'canvas' ) ,
3739 canvasDiscardedQueueItems : [ ] ,
3840} ) ;
3941
40- const getInitialState = ( ) : CanvasStagingAreaState => ( {
42+ const getInitialCanvasStagingAreaState = ( ) : CanvasStagingAreaState => ( {
4143 _version : 2 ,
4244 sessions : { } ,
4345} ) ;
4446
4547const canvasStagingAreaSlice = createSlice ( {
4648 name : 'canvasSession' ,
47- initialState : getInitialState ( ) ,
48- reducers : {
49- canvasQueueItemDiscarded : ( state , action : CanvasPayloadAction < { itemId : number } > ) => {
50- const { canvasId, itemId } = action . payload ;
51-
52- const session = state . sessions [ canvasId ] ;
49+ initialState : getInitialCanvasStagingAreaState ,
50+ reducers : { } ,
51+ extraReducers ( builder ) {
52+ builder . addCase ( canvasAdding , ( state , action ) => {
53+ const session = getInitialCanvasSessionState ( action . payload . canvasId ) ;
54+ state . sessions [ session . canvasId ] = session ;
55+ } ) ;
56+ builder . addCase ( canvasDeleted , ( state , action ) => {
57+ delete state . sessions [ action . payload . canvasId ] ;
58+ } ) ;
59+ builder . addCase ( canvasMultiCanvasMigrated , ( state , action ) => {
60+ const session = state . sessions [ MIGRATION_MULTI_CANVAS_ID_PLACEHOLDER ] ;
5361 if ( ! session ) {
5462 return ;
5563 }
64+ session . canvasId = action . payload . canvasId ;
65+ state . sessions [ session . canvasId ] = session ;
66+ delete state . sessions [ MIGRATION_MULTI_CANVAS_ID_PLACEHOLDER ] ;
67+ } ) ;
68+ builder . addCase ( canvasInitialized , ( state , action ) => {
69+ const canvasId = action . payload . canvasId ;
70+ if ( ! state . sessions [ canvasId ] ) {
71+ state . sessions [ canvasId ] = getInitialCanvasSessionState ( canvasId ) ;
72+ }
73+ } ) ;
74+ } ,
75+ } ) ;
76+
77+ const canvasSessionFragment = createSlice ( {
78+ name : 'canvasSession' ,
79+ initialState : { } as CanvasSession ,
80+ reducers : {
81+ canvasQueueItemDiscarded : ( state , action : CanvasPayloadAction < { itemId : number } > ) => {
82+ const { itemId } = action . payload ;
5683
57- if ( ! session . canvasDiscardedQueueItems . includes ( itemId ) ) {
58- session . canvasDiscardedQueueItems . push ( itemId ) ;
84+ if ( ! state . canvasDiscardedQueueItems . includes ( itemId ) ) {
85+ state . canvasDiscardedQueueItems . push ( itemId ) ;
5986 }
6087 } ,
6188 canvasSessionReset : {
6289 reducer : ( state , action : CanvasPayloadAction < { canvasSessionId : string } > ) => {
63- const { canvasId, canvasSessionId } = action . payload ;
64-
65- const session = state . sessions [ canvasId ] ;
66- if ( ! session ) {
67- return ;
68- }
90+ const { canvasSessionId } = action . payload ;
6991
70- session . canvasSessionId = canvasSessionId ;
71- session . canvasDiscardedQueueItems = [ ] ;
92+ state . canvasSessionId = canvasSessionId ;
93+ state . canvasDiscardedQueueItems = [ ] ;
7294 } ,
7395 prepare : ( payload : CanvasPayload < object > ) => {
7496 return {
@@ -80,32 +102,34 @@ const canvasStagingAreaSlice = createSlice({
80102 } ,
81103 } ,
82104 } ,
83- extraReducers ( builder ) {
84- builder . addCase ( canvasAdding , ( state , action ) => {
85- const session = getInitialCanvasSessionState ( action . payload . canvasId ) ;
86- state . sessions [ session . canvasId ] = session ;
87- } ) ;
88- builder . addCase ( canvasDeleted , ( state , action ) => {
89- delete state . sessions [ action . payload . canvasId ] ;
90- } ) ;
91- builder . addCase ( canvasMultiCanvasMigrated , ( state , action ) => {
92- const session = state . sessions [ MIGRATION_MULTI_CANVAS_ID_PLACEHOLDER ] ;
93- if ( ! session ) {
94- return ;
95- }
96- session . canvasId = action . payload . canvasId ;
97- state . sessions [ session . canvasId ] = session ;
98- delete state . sessions [ MIGRATION_MULTI_CANVAS_ID_PLACEHOLDER ] ;
99- } ) ;
100- } ,
101105} ) ;
102106
103- export const { canvasSessionReset, canvasQueueItemDiscarded } = canvasStagingAreaSlice . actions ;
107+ export const { canvasSessionReset, canvasQueueItemDiscarded } = canvasSessionFragment . actions ;
108+
109+ const isCanvasSessionAction = isAnyOf ( ...Object . values ( canvasSessionFragment . actions ) ) ;
110+
111+ export const canvasSessionReducer = ( state : CanvasStagingAreaState | undefined , action : UnknownAction ) : CanvasStagingAreaState => {
112+ state = canvasStagingAreaSlice . reducer ( state , action ) ;
113+
114+ if ( ! isCanvasSessionAction ( action ) ) {
115+ return state ;
116+ }
117+
118+ const canvasId = action . payload . canvasId ;
119+
120+ return {
121+ ...state ,
122+ sessions : {
123+ ...state . sessions ,
124+ [ canvasId ] : canvasSessionFragment . reducer ( state . sessions [ canvasId ] , action ) ,
125+ } ,
126+ } ;
127+ } ;
104128
105129export const canvasSessionSliceConfig : SliceConfig < typeof canvasStagingAreaSlice > = {
106130 slice : canvasStagingAreaSlice ,
107131 schema : zCanvasStagingAreaState ,
108- getInitialState,
132+ getInitialState : getInitialCanvasStagingAreaState ,
109133 persistConfig : {
110134 migrate : ( state ) => {
111135 assert ( isPlainObject ( state ) ) ;
@@ -117,7 +141,7 @@ export const canvasSessionSliceConfig: SliceConfig<typeof canvasStagingAreaSlice
117141 const session = {
118142 canvasId : MIGRATION_MULTI_CANVAS_ID_PLACEHOLDER ,
119143 ...state ,
120- } as CanvasSessionState ;
144+ } as CanvasSession ;
121145
122146 state = {
123147 _version : 2 ,
@@ -130,7 +154,7 @@ export const canvasSessionSliceConfig: SliceConfig<typeof canvasStagingAreaSlice
130154 } ,
131155} ;
132156
133- const findSessionByCanvasId = ( sessions : Record < string , CanvasSessionState > , canvasId : string ) => {
157+ const findSessionByCanvasId = ( sessions : Record < string , CanvasSession > , canvasId : string ) => {
134158 const session = sessions [ canvasId ] ;
135159 assert ( session , 'Session must exist for a canvas once the canvas has been created' ) ;
136160 return session ;
0 commit comments