@@ -35,6 +35,15 @@ type PayloadActionWithId<T = void> = T extends void
3535 } & T
3636 > ;
3737
38+ /** Fingerprint used to match the same reference image entry after recall when ids are regenerated. */
39+ /** Empty configs of the same type may collide; the worst case is selecting an equivalent empty entity. */
40+ const getRefImageRecallMatchKey = ( entity : RefImageState ) : string => {
41+ const { config } = entity ;
42+ const imageName = config . image ?. original . image . image_name ?? '' ;
43+ const modelKey = 'model' in config && config . model ? config . model . key : '' ;
44+ return `${ config . type } \0${ modelKey } \0${ imageName } ` ;
45+ } ;
46+
3847const slice = createSlice ( {
3948 name : 'refImages' ,
4049 initialState : getInitialRefImagesState ( ) ,
@@ -54,13 +63,41 @@ const slice = createSlice({
5463 } ,
5564 refImagesRecalled : ( state , action : PayloadAction < { entities : RefImageState [ ] ; replace : boolean } > ) => {
5665 const { entities, replace } = action . payload ;
57- if ( replace ) {
58- state . entities = entities ;
66+ if ( ! replace ) {
67+ state . entities . push ( ...entities ) ;
68+ return ;
69+ }
70+ const wasPanelOpen = state . isPanelOpen ;
71+ const previousSelectedId = state . selectedEntityId ;
72+ let previousEntity : RefImageState | null = null ;
73+ if ( previousSelectedId !== null ) {
74+ previousEntity = state . entities . find ( ( e ) => e . id === previousSelectedId ) ?? null ;
75+ }
76+ state . entities = entities ;
77+ if ( entities . length === 0 ) {
78+ state . selectedEntityId = null ;
5979 state . isPanelOpen = false ;
80+ return ;
81+ }
82+ if ( ! wasPanelOpen ) {
6083 state . selectedEntityId = null ;
61- } else {
62- state . entities . push ( ...entities ) ;
84+ return ;
85+ }
86+ const firstEntity = entities [ 0 ] ;
87+ assert ( firstEntity ) ;
88+ if ( previousSelectedId === null ) {
89+ // Open panel must have a selection; otherwise, fall back to the first entity.
90+ state . selectedEntityId = firstEntity . id ;
91+ return ;
92+ }
93+ if ( previousSelectedId !== null && entities . some ( ( e ) => e . id === previousSelectedId ) ) {
94+ state . selectedEntityId = previousSelectedId ;
95+ return ;
6396 }
97+ const previousKey = previousEntity ? getRefImageRecallMatchKey ( previousEntity ) : null ;
98+ const matched =
99+ previousKey !== null ? entities . find ( ( e ) => getRefImageRecallMatchKey ( e ) === previousKey ) : undefined ;
100+ state . selectedEntityId = matched ?. id ?? firstEntity . id ;
64101 } ,
65102 refImageImageChanged : ( state , action : PayloadActionWithId < { croppableImage : CroppableImageWithDims | null } > ) => {
66103 const { id, croppableImage } = action . payload ;
0 commit comments