Skip to content

Commit e798d9c

Browse files
refactor(ui): use image names for selection instead of dtos
Update the frontend to incorporate the previous changes to how image selection and general image identification is handled in the frontend.
1 parent 34cef23 commit e798d9c

File tree

51 files changed

+550
-614
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+550
-614
lines changed

invokeai/frontend/web/src/app/components/GlobalImageHotkeys.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import { selectLastSelectedImage } from 'features/gallery/store/gallerySelectors
77
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
88
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
99
import { memo } from 'react';
10+
import { useImageDTO } from 'services/api/endpoints/images';
1011
import type { ImageDTO } from 'services/api/types';
1112

1213
export const GlobalImageHotkeys = memo(() => {
1314
useAssertSingleton('GlobalImageHotkeys');
14-
const imageDTO = useAppSelector(selectLastSelectedImage);
15+
const imageName = useAppSelector(selectLastSelectedImage);
16+
const imageDTO = useImageDTO(imageName);
1517

1618
if (!imageDTO) {
1719
return null;

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addArchivedOrDeletedBoardListener.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const addArchivedOrDeletedBoardListener = (startAppListening: AppStartLis
2525
matcher: matchAnyBoardDeleted,
2626
effect: (action, { dispatch, getState }) => {
2727
const state = getState();
28-
const deletedBoardId = action.meta.arg.originalArgs;
28+
const deletedBoardId = action.meta.arg.originalArgs.board_id;
2929
const { autoAddBoardId, selectedBoardId } = state.gallery;
3030

3131
// If the deleted board was currently selected, we should reset the selected board to uncategorized

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ export const addBoardIdSelectedListener = (startAppListening: AppStartListening)
3030
const selectedImage = boardImagesData.items.find(
3131
(item) => item.image_name === action.payload.selectedImageName
3232
);
33-
dispatch(imageSelected(selectedImage || null));
33+
dispatch(imageSelected(selectedImage?.image_name ?? null));
3434
} else if (boardImagesData) {
35-
dispatch(imageSelected(boardImagesData.items[0] || null));
35+
dispatch(imageSelected(boardImagesData.items[0]?.image_name ?? null));
3636
} else {
3737
// board has no images - deselect
3838
dispatch(imageSelected(null));

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/ensureImageIsSelectedListener.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const addEnsureImageIsSelectedListener = (startAppListening: AppStartList
99
effect: (action, { dispatch, getState }) => {
1010
const selection = getState().gallery.selection;
1111
if (selection.length === 0) {
12-
dispatch(imageSelected(action.payload.items[0] ?? null));
12+
dispatch(imageSelected(action.payload.items[0]?.image_name ?? null));
1313
}
1414
},
1515
});

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/galleryImageClicked.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { createAction } from '@reduxjs/toolkit';
22
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
33
import { selectListImagesQueryArgs } from 'features/gallery/store/gallerySelectors';
44
import { imageToCompareChanged, selectionChanged } from 'features/gallery/store/gallerySlice';
5+
import { uniq } from 'lodash-es';
56
import { imagesApi } from 'services/api/endpoints/images';
6-
import type { ImageDTO } from 'services/api/types';
77

88
export const galleryImageClicked = createAction<{
9-
imageDTO: ImageDTO;
9+
imageName: string;
1010
shiftKey: boolean;
1111
ctrlKey: boolean;
1212
metaKey: boolean;
@@ -28,7 +28,7 @@ export const addGalleryImageClickedListener = (startAppListening: AppStartListen
2828
startAppListening({
2929
actionCreator: galleryImageClicked,
3030
effect: (action, { dispatch, getState }) => {
31-
const { imageDTO, shiftKey, ctrlKey, metaKey, altKey } = action.payload;
31+
const { imageName, shiftKey, ctrlKey, metaKey, altKey } = action.payload;
3232
const state = getState();
3333
const queryArgs = selectListImagesQueryArgs(state);
3434
const queryResult = imagesApi.endpoints.listImages.select(queryArgs)(state);
@@ -42,31 +42,31 @@ export const addGalleryImageClickedListener = (startAppListening: AppStartListen
4242
const selection = state.gallery.selection;
4343

4444
if (altKey) {
45-
if (state.gallery.imageToCompare?.image_name === imageDTO.image_name) {
45+
if (state.gallery.imageToCompare === imageName) {
4646
dispatch(imageToCompareChanged(null));
4747
} else {
48-
dispatch(imageToCompareChanged(imageDTO));
48+
dispatch(imageToCompareChanged(imageName));
4949
}
5050
} else if (shiftKey) {
51-
const rangeEndImageName = imageDTO.image_name;
52-
const lastSelectedImage = selection[selection.length - 1]?.image_name;
51+
const rangeEndImageName = imageName;
52+
const lastSelectedImage = selection.at(-1);
5353
const lastClickedIndex = imageDTOs.findIndex((n) => n.image_name === lastSelectedImage);
5454
const currentClickedIndex = imageDTOs.findIndex((n) => n.image_name === rangeEndImageName);
5555
if (lastClickedIndex > -1 && currentClickedIndex > -1) {
5656
// We have a valid range!
5757
const start = Math.min(lastClickedIndex, currentClickedIndex);
5858
const end = Math.max(lastClickedIndex, currentClickedIndex);
59-
const imagesToSelect = imageDTOs.slice(start, end + 1);
60-
dispatch(selectionChanged(selection.concat(imagesToSelect)));
59+
const imagesToSelect = imageDTOs.slice(start, end + 1).map(({ image_name }) => image_name);
60+
dispatch(selectionChanged(uniq(selection.concat(imagesToSelect))));
6161
}
6262
} else if (ctrlKey || metaKey) {
63-
if (selection.some((i) => i.image_name === imageDTO.image_name) && selection.length > 1) {
64-
dispatch(selectionChanged(selection.filter((n) => n.image_name !== imageDTO.image_name)));
63+
if (selection.some((n) => n === imageName) && selection.length > 1) {
64+
dispatch(selectionChanged(uniq(selection.filter((n) => n !== imageName))));
6565
} else {
66-
dispatch(selectionChanged(selection.concat(imageDTO)));
66+
dispatch(selectionChanged(uniq(selection.concat(imageName))));
6767
}
6868
} else {
69-
dispatch(selectionChanged([imageDTO]));
69+
dispatch(selectionChanged([imageName]));
7070
}
7171
},
7272
});

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/galleryOffsetChanged.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ export const addGalleryOffsetChangedListener = (startAppListening: AppStartListe
8484
if (offset < prevOffset) {
8585
// We've gone backwards
8686
const lastImage = imageDTOs[imageDTOs.length - 1];
87-
if (!selection.some((selectedImage) => selectedImage.image_name === lastImage?.image_name)) {
88-
dispatch(selectionChanged(lastImage ? [lastImage] : []));
87+
if (!selection.some((selectedImage) => selectedImage === lastImage?.image_name)) {
88+
dispatch(selectionChanged(lastImage ? [lastImage.image_name] : []));
8989
}
9090
} else {
9191
// We've gone forwards
9292
const firstImage = imageDTOs[0];
93-
if (!selection.some((selectedImage) => selectedImage.image_name === firstImage?.image_name)) {
94-
dispatch(selectionChanged(firstImage ? [firstImage] : []));
93+
if (!selection.some((selectedImage) => selectedImage === firstImage?.image_name)) {
94+
dispatch(selectionChanged(firstImage ? [firstImage.image_name] : []));
9595
}
9696
}
9797
return;
@@ -102,14 +102,14 @@ export const addGalleryOffsetChangedListener = (startAppListening: AppStartListe
102102
if (offset < prevOffset) {
103103
// We've gone backwards
104104
const lastImage = imageDTOs[imageDTOs.length - 1];
105-
if (lastImage && imageToCompare?.image_name !== lastImage.image_name) {
106-
dispatch(imageToCompareChanged(lastImage));
105+
if (lastImage && imageToCompare !== lastImage.image_name) {
106+
dispatch(imageToCompareChanged(lastImage.image_name));
107107
}
108108
} else {
109109
// We've gone forwards
110110
const firstImage = imageDTOs[0];
111-
if (firstImage && imageToCompare?.image_name !== firstImage.image_name) {
112-
dispatch(imageToCompareChanged(firstImage));
111+
if (firstImage && imageToCompare !== firstImage.image_name) {
112+
dispatch(imageToCompareChanged(firstImage.image_name));
113113
}
114114
}
115115
return;

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ export const addImageAddedToBoardFulfilledListener = (startAppListening: AppStar
88
startAppListening({
99
matcher: imagesApi.endpoints.addImageToBoard.matchFulfilled,
1010
effect: (action) => {
11-
const { board_id, imageDTO } = action.meta.arg.originalArgs;
12-
log.debug({ board_id, imageDTO }, 'Image added to board');
11+
const { board_id, image_name } = action.meta.arg.originalArgs;
12+
log.debug({ board_id, image_name }, 'Image added to board');
1313
},
1414
});
1515

1616
startAppListening({
1717
matcher: imagesApi.endpoints.addImageToBoard.matchRejected,
1818
effect: (action) => {
19-
const { board_id, imageDTO } = action.meta.arg.originalArgs;
20-
log.debug({ board_id, imageDTO }, 'Problem adding image to board');
19+
const { board_id, image_name } = action.meta.arg.originalArgs;
20+
log.debug({ board_id, image_name }, 'Problem adding image to board');
2121
},
2222
});
2323
};
Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,25 @@
11
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
2-
import { selectionChanged } from 'features/gallery/store/gallerySlice';
32
import { imagesApi } from 'services/api/endpoints/images';
4-
import type { ImageDTO } from 'services/api/types';
53

64
export const addImagesStarredListener = (startAppListening: AppStartListening) => {
75
startAppListening({
86
matcher: imagesApi.endpoints.starImages.matchFulfilled,
97
effect: (action, { dispatch, getState }) => {
10-
const { updated_image_names: starredImages } = action.payload;
11-
12-
const state = getState();
13-
14-
const { selection } = state.gallery;
15-
const updatedSelection: ImageDTO[] = [];
16-
17-
selection.forEach((selectedImageDTO) => {
18-
if (starredImages.includes(selectedImageDTO.image_name)) {
19-
updatedSelection.push({
20-
...selectedImageDTO,
21-
starred: true,
22-
});
23-
} else {
24-
updatedSelection.push(selectedImageDTO);
25-
}
26-
});
27-
dispatch(selectionChanged(updatedSelection));
8+
// const { updated_image_names: starredImages } = action.payload;
9+
// const state = getState();
10+
// const { selection } = state.gallery;
11+
// const updatedSelection: ImageDTO[] = [];
12+
// selection.forEach((selectedImageDTO) => {
13+
// if (starredImages.includes(selectedImageDTO.image_name)) {
14+
// updatedSelection.push({
15+
// ...selectedImageDTO,
16+
// starred: true,
17+
// });
18+
// } else {
19+
// updatedSelection.push(selectedImageDTO);
20+
// }
21+
// });
22+
// dispatch(selectionChanged(updatedSelection));
2823
},
2924
});
3025
};
Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,25 @@
11
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
2-
import { selectionChanged } from 'features/gallery/store/gallerySlice';
32
import { imagesApi } from 'services/api/endpoints/images';
4-
import type { ImageDTO } from 'services/api/types';
53

64
export const addImagesUnstarredListener = (startAppListening: AppStartListening) => {
75
startAppListening({
86
matcher: imagesApi.endpoints.unstarImages.matchFulfilled,
97
effect: (action, { dispatch, getState }) => {
10-
const { updated_image_names: unstarredImages } = action.payload;
11-
12-
const state = getState();
13-
14-
const { selection } = state.gallery;
15-
const updatedSelection: ImageDTO[] = [];
16-
17-
selection.forEach((selectedImageDTO) => {
18-
if (unstarredImages.includes(selectedImageDTO.image_name)) {
19-
updatedSelection.push({
20-
...selectedImageDTO,
21-
starred: false,
22-
});
23-
} else {
24-
updatedSelection.push(selectedImageDTO);
25-
}
26-
});
27-
dispatch(selectionChanged(updatedSelection));
8+
// const { updated_image_names: unstarredImages } = action.payload;
9+
// const state = getState();
10+
// const { selection } = state.gallery;
11+
// const updatedSelection: ImageDTO[] = [];
12+
// selection.forEach((selectedImageDTO) => {
13+
// if (unstarredImages.includes(selectedImageDTO.image_name)) {
14+
// updatedSelection.push({
15+
// ...selectedImageDTO,
16+
// starred: false,
17+
// });
18+
// } else {
19+
// updatedSelection.push(selectedImageDTO);
20+
// }
21+
// });
22+
// dispatch(selectionChanged(updatedSelection));
2823
},
2924
});
3025
};

invokeai/frontend/web/src/app/store/store.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { authToastMiddleware } from 'services/api/authToastMiddleware';
3939
import type { JsonObject } from 'type-fest';
4040

4141
import { STORAGE_PREFIX } from './constants';
42+
import { getDebugLoggerMiddleware } from './middleware/debugLoggerMiddleware';
4243
import { actionSanitizer } from './middleware/devtools/actionSanitizer';
4344
import { actionsDenylist } from './middleware/devtools/actionsDenylist';
4445
import { stateSanitizer } from './middleware/devtools/stateSanitizer';
@@ -176,7 +177,7 @@ export const createStore = (uniqueStoreKey?: string, persist = true) =>
176177
.concat(api.middleware)
177178
.concat(dynamicMiddlewares)
178179
.concat(authToastMiddleware)
179-
// .concat(getDebugLoggerMiddleware())
180+
.concat(getDebugLoggerMiddleware())
180181
.prepend(listenerMiddleware.middleware),
181182
enhancers: (getDefaultEnhancers) => {
182183
const _enhancers = getDefaultEnhancers().concat(autoBatchEnhancer());

0 commit comments

Comments
 (0)