feat(ui): rudimentary categorized gallery image fetching

This commit is contained in:
psychedelicious 2023-06-21 19:57:22 +10:00
parent d501986610
commit f560a462a0
2 changed files with 78 additions and 31 deletions

View File

@ -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 (
<VStack
sx={{
@ -335,13 +349,13 @@ const ImageGalleryContent = () => {
</Box>
</Box>
<Flex direction="column" gap={2} h="full" w="full">
{items.length || areMoreAvailable ? (
{images.length || areMoreAvailable ? (
<>
<Box ref={rootRef} data-overlayscrollbars="" h="100%">
{shouldUseSingleGalleryColumn ? (
<Virtuoso
style={{ height: '100%' }}
data={items}
data={images}
endReached={handleEndReached}
scrollerRef={(ref) => setScrollerRef(ref)}
itemContent={(index, item) => (
@ -357,7 +371,7 @@ const ImageGalleryContent = () => {
) : (
<VirtuosoGrid
style={{ height: '100%' }}
data={items}
data={images}
endReached={handleEndReached}
components={{
Item: ItemContainer,

View File

@ -1,5 +1,6 @@
import { createAppAsyncThunk } from 'app/store/storeUtils';
import { selectImagesAll } from 'features/gallery/store/imagesSlice';
import { size } from 'lodash-es';
import { ImagesService } from 'services/api';
type imageUrlsReceivedArg = Parameters<
@ -121,25 +122,57 @@ type ImagesListedArg = Parameters<
export const IMAGES_PER_PAGE = 20;
const DEFAULT_IMAGES_LISTED_ARG = {
isIntermediate: false,
limit: IMAGES_PER_PAGE,
};
/**
* `ImagesService.listImagesWithMetadata()` thunk
*/
export const receivedPageOfImages = createAppAsyncThunk(
'api/receivedPageOfImages',
async (_, { getState }) => {
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;
}
);