diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx index 8648962c8c..bd69425525 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx @@ -56,36 +56,39 @@ import { imageCategoriesChanged, selectImagesAll, } from '../store/imagesSlice'; -import { receivedPageOfImages } from 'services/thunks/image'; +import { + IMAGES_PER_PAGE, + receivedImages, + receivedPageOfImages, +} from 'services/thunks/image'; import BoardsList from './Boards/BoardsList'; -import { boardsSelector, selectBoardsById } from '../store/boardSlice'; +import { boardsSelector } from '../store/boardSlice'; import { ChevronUpIcon } from '@chakra-ui/icons'; import { useListAllBoardsQuery } from 'services/apiSlice'; const itemSelector = createSelector( [(state: RootState) => state], (state) => { - const { images, boards } = state; - - const { categories } = images; + const { categories, total, isLoading } = state.images; + const { selectedBoardId } = state.boards; const allImages = selectImagesAll(state); - const items = allImages.filter((i) => - categories.includes(i.image_category) - ); - const areMoreAvailable = items.length < images.total; - const isLoading = images.isLoading; - const selectedBoard = boards.selectedBoardId - ? selectBoardsById(state, boards.selectedBoardId) - : undefined; + const images = allImages.filter((i) => { + const isInCategory = categories.includes(i.image_category); + const isInSelectedBoard = selectedBoardId + ? i.board_id === selectedBoardId + : true; + return isInCategory && isInSelectedBoard; + }); + + const areMoreAvailable = images.length < total; return { - items, + images, isLoading, areMoreAvailable, - categories: images.categories, - selectedBoard, + categories, }; }, defaultSelectorOptions @@ -148,7 +151,7 @@ const ImageGalleryContent = () => { selectedBoardId, } = useAppSelector(mainSelector); - const { items, areMoreAvailable, isLoading, categories } = + const { images, areMoreAvailable, isLoading, categories } = useAppSelector(itemSelector); const { selectedBoard } = useListAllBoardsQuery(undefined, { @@ -158,7 +161,7 @@ const ImageGalleryContent = () => { }); const handleLoadMoreImages = useCallback(() => { - dispatch(receivedPageOfImages()); + dispatch(receivedPageOfImages({})); }, [dispatch]); const handleEndReached = useMemo(() => { @@ -208,6 +211,17 @@ const ImageGalleryContent = () => { dispatch(setGalleryView('assets')); }, [dispatch]); + useEffect(() => { + if (images.length < 20) { + dispatch( + receivedPageOfImages({ + categories, + boardId: selectedBoardId, + }) + ); + } + }, [categories, dispatch, images.length, selectedBoardId]); + return ( { - {items.length || areMoreAvailable ? ( + {images.length || areMoreAvailable ? ( <> {shouldUseSingleGalleryColumn ? ( setScrollerRef(ref)} itemContent={(index, item) => ( @@ -357,7 +371,7 @@ const ImageGalleryContent = () => { ) : ( { + async (arg: ImagesListedArg, { getState }) => { const state = getState(); const { categories } = state.images; + const { selectedBoardId } = state.boards; - const totalImagesInFilter = selectImagesAll(state).filter((i) => - categories.includes(i.image_category) - ).length; - - const response = await ImagesService.listImagesWithMetadata({ - categories, - isIntermediate: false, - offset: totalImagesInFilter, - limit: IMAGES_PER_PAGE, + const images = selectImagesAll(state).filter((i) => { + const isInCategory = categories.includes(i.image_category); + const isInSelectedBoard = selectedBoardId + ? i.board_id === selectedBoardId + : true; + return isInCategory && isInSelectedBoard; }); + + let queryArg: ReceivedImagesArg = {}; + + if (size(arg)) { + queryArg = { ...DEFAULT_IMAGES_LISTED_ARG, ...arg }; + } else { + queryArg = { + ...DEFAULT_IMAGES_LISTED_ARG, + categories, + offset: images.length, + }; + } + + const response = await ImagesService.listImagesWithMetadata(queryArg); + return response; + } +); + +type ReceivedImagesArg = Parameters< + (typeof ImagesService)['listImagesWithMetadata'] +>[0]; + +/** + * `ImagesService.listImagesWithMetadata()` thunk + */ +export const receivedImages = createAppAsyncThunk( + 'api/receivedImages', + async (arg: ReceivedImagesArg, { getState }) => { + const response = await ImagesService.listImagesWithMetadata(arg); return response; } );