mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): rudimentary categorized gallery image fetching
This commit is contained in:
parent
d501986610
commit
f560a462a0
@ -56,36 +56,39 @@ import {
|
|||||||
imageCategoriesChanged,
|
imageCategoriesChanged,
|
||||||
selectImagesAll,
|
selectImagesAll,
|
||||||
} from '../store/imagesSlice';
|
} 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 BoardsList from './Boards/BoardsList';
|
||||||
import { boardsSelector, selectBoardsById } from '../store/boardSlice';
|
import { boardsSelector } from '../store/boardSlice';
|
||||||
import { ChevronUpIcon } from '@chakra-ui/icons';
|
import { ChevronUpIcon } from '@chakra-ui/icons';
|
||||||
import { useListAllBoardsQuery } from 'services/apiSlice';
|
import { useListAllBoardsQuery } from 'services/apiSlice';
|
||||||
|
|
||||||
const itemSelector = createSelector(
|
const itemSelector = createSelector(
|
||||||
[(state: RootState) => state],
|
[(state: RootState) => state],
|
||||||
(state) => {
|
(state) => {
|
||||||
const { images, boards } = state;
|
const { categories, total, isLoading } = state.images;
|
||||||
|
const { selectedBoardId } = state.boards;
|
||||||
const { categories } = images;
|
|
||||||
|
|
||||||
const allImages = selectImagesAll(state);
|
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
|
const images = allImages.filter((i) => {
|
||||||
? selectBoardsById(state, boards.selectedBoardId)
|
const isInCategory = categories.includes(i.image_category);
|
||||||
: undefined;
|
const isInSelectedBoard = selectedBoardId
|
||||||
|
? i.board_id === selectedBoardId
|
||||||
|
: true;
|
||||||
|
return isInCategory && isInSelectedBoard;
|
||||||
|
});
|
||||||
|
|
||||||
|
const areMoreAvailable = images.length < total;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items,
|
images,
|
||||||
isLoading,
|
isLoading,
|
||||||
areMoreAvailable,
|
areMoreAvailable,
|
||||||
categories: images.categories,
|
categories,
|
||||||
selectedBoard,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
defaultSelectorOptions
|
defaultSelectorOptions
|
||||||
@ -148,7 +151,7 @@ const ImageGalleryContent = () => {
|
|||||||
selectedBoardId,
|
selectedBoardId,
|
||||||
} = useAppSelector(mainSelector);
|
} = useAppSelector(mainSelector);
|
||||||
|
|
||||||
const { items, areMoreAvailable, isLoading, categories } =
|
const { images, areMoreAvailable, isLoading, categories } =
|
||||||
useAppSelector(itemSelector);
|
useAppSelector(itemSelector);
|
||||||
|
|
||||||
const { selectedBoard } = useListAllBoardsQuery(undefined, {
|
const { selectedBoard } = useListAllBoardsQuery(undefined, {
|
||||||
@ -158,7 +161,7 @@ const ImageGalleryContent = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleLoadMoreImages = useCallback(() => {
|
const handleLoadMoreImages = useCallback(() => {
|
||||||
dispatch(receivedPageOfImages());
|
dispatch(receivedPageOfImages({}));
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
const handleEndReached = useMemo(() => {
|
const handleEndReached = useMemo(() => {
|
||||||
@ -208,6 +211,17 @@ const ImageGalleryContent = () => {
|
|||||||
dispatch(setGalleryView('assets'));
|
dispatch(setGalleryView('assets'));
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (images.length < 20) {
|
||||||
|
dispatch(
|
||||||
|
receivedPageOfImages({
|
||||||
|
categories,
|
||||||
|
boardId: selectedBoardId,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [categories, dispatch, images.length, selectedBoardId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack
|
<VStack
|
||||||
sx={{
|
sx={{
|
||||||
@ -335,13 +349,13 @@ const ImageGalleryContent = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Flex direction="column" gap={2} h="full" w="full">
|
<Flex direction="column" gap={2} h="full" w="full">
|
||||||
{items.length || areMoreAvailable ? (
|
{images.length || areMoreAvailable ? (
|
||||||
<>
|
<>
|
||||||
<Box ref={rootRef} data-overlayscrollbars="" h="100%">
|
<Box ref={rootRef} data-overlayscrollbars="" h="100%">
|
||||||
{shouldUseSingleGalleryColumn ? (
|
{shouldUseSingleGalleryColumn ? (
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
style={{ height: '100%' }}
|
style={{ height: '100%' }}
|
||||||
data={items}
|
data={images}
|
||||||
endReached={handleEndReached}
|
endReached={handleEndReached}
|
||||||
scrollerRef={(ref) => setScrollerRef(ref)}
|
scrollerRef={(ref) => setScrollerRef(ref)}
|
||||||
itemContent={(index, item) => (
|
itemContent={(index, item) => (
|
||||||
@ -357,7 +371,7 @@ const ImageGalleryContent = () => {
|
|||||||
) : (
|
) : (
|
||||||
<VirtuosoGrid
|
<VirtuosoGrid
|
||||||
style={{ height: '100%' }}
|
style={{ height: '100%' }}
|
||||||
data={items}
|
data={images}
|
||||||
endReached={handleEndReached}
|
endReached={handleEndReached}
|
||||||
components={{
|
components={{
|
||||||
Item: ItemContainer,
|
Item: ItemContainer,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
||||||
import { selectImagesAll } from 'features/gallery/store/imagesSlice';
|
import { selectImagesAll } from 'features/gallery/store/imagesSlice';
|
||||||
|
import { size } from 'lodash-es';
|
||||||
import { ImagesService } from 'services/api';
|
import { ImagesService } from 'services/api';
|
||||||
|
|
||||||
type imageUrlsReceivedArg = Parameters<
|
type imageUrlsReceivedArg = Parameters<
|
||||||
@ -121,25 +122,57 @@ type ImagesListedArg = Parameters<
|
|||||||
|
|
||||||
export const IMAGES_PER_PAGE = 20;
|
export const IMAGES_PER_PAGE = 20;
|
||||||
|
|
||||||
|
const DEFAULT_IMAGES_LISTED_ARG = {
|
||||||
|
isIntermediate: false,
|
||||||
|
limit: IMAGES_PER_PAGE,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `ImagesService.listImagesWithMetadata()` thunk
|
* `ImagesService.listImagesWithMetadata()` thunk
|
||||||
*/
|
*/
|
||||||
export const receivedPageOfImages = createAppAsyncThunk(
|
export const receivedPageOfImages = createAppAsyncThunk(
|
||||||
'api/receivedPageOfImages',
|
'api/receivedPageOfImages',
|
||||||
async (_, { getState }) => {
|
async (arg: ImagesListedArg, { getState }) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { categories } = state.images;
|
const { categories } = state.images;
|
||||||
|
const { selectedBoardId } = state.boards;
|
||||||
|
|
||||||
const totalImagesInFilter = selectImagesAll(state).filter((i) =>
|
const images = selectImagesAll(state).filter((i) => {
|
||||||
categories.includes(i.image_category)
|
const isInCategory = categories.includes(i.image_category);
|
||||||
).length;
|
const isInSelectedBoard = selectedBoardId
|
||||||
|
? i.board_id === selectedBoardId
|
||||||
const response = await ImagesService.listImagesWithMetadata({
|
: true;
|
||||||
categories,
|
return isInCategory && isInSelectedBoard;
|
||||||
isIntermediate: false,
|
|
||||||
offset: totalImagesInFilter,
|
|
||||||
limit: IMAGES_PER_PAGE,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user