mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): remove all calls to getBoardImagesTotals/getBoardAssetsTotals
This caused a crapload of network requests any time an image was generated. The counts are necessary to handle the logic for inserting images into existing image list caches; we have to keep track of the counts. Replace tag invalidation with manual cache updates in all cases, except the initial request (which is necessary to get the initial image counts). One subtle change is to make the counts an object instead of a number. This is required for `immer` to handle draft states. This should be raised as a bug with RTK Query, as no error is thrown when attempting to update a primitive immer draft.
This commit is contained in:
@ -8,6 +8,7 @@ import {
|
|||||||
} from 'features/gallery/store/gallerySlice';
|
} from 'features/gallery/store/gallerySlice';
|
||||||
import { IMAGE_CATEGORIES } from 'features/gallery/store/types';
|
import { IMAGE_CATEGORIES } from 'features/gallery/store/types';
|
||||||
import { CANVAS_OUTPUT } from 'features/nodes/util/graphBuilders/constants';
|
import { CANVAS_OUTPUT } from 'features/nodes/util/graphBuilders/constants';
|
||||||
|
import { boardsApi } from 'services/api/endpoints/boards';
|
||||||
import { imagesApi } from 'services/api/endpoints/images';
|
import { imagesApi } from 'services/api/endpoints/images';
|
||||||
import { isImageOutput } from 'services/api/guards';
|
import { isImageOutput } from 'services/api/guards';
|
||||||
import { imagesAdapter } from 'services/api/util';
|
import { imagesAdapter } from 'services/api/util';
|
||||||
@ -70,11 +71,21 @@ export const addInvocationCompleteEventListener = () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// update the total images for the board
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
'getBoardImagesTotal',
|
||||||
|
imageDTO.board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
draft.total += 1;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
imagesApi.util.invalidateTags([
|
imagesApi.util.invalidateTags([
|
||||||
{ type: 'BoardImagesTotal', id: imageDTO.board_id },
|
{ type: 'Board', id: imageDTO.board_id ?? 'none' },
|
||||||
{ type: 'BoardAssetsTotal', id: imageDTO.board_id },
|
|
||||||
{ type: 'Board', id: imageDTO.board_id },
|
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -77,12 +77,12 @@ const GalleryBoard = ({
|
|||||||
const { data: imagesTotal } = useGetBoardImagesTotalQuery(board.board_id);
|
const { data: imagesTotal } = useGetBoardImagesTotalQuery(board.board_id);
|
||||||
const { data: assetsTotal } = useGetBoardAssetsTotalQuery(board.board_id);
|
const { data: assetsTotal } = useGetBoardAssetsTotalQuery(board.board_id);
|
||||||
const tooltip = useMemo(() => {
|
const tooltip = useMemo(() => {
|
||||||
if (!imagesTotal || !assetsTotal) {
|
if (!imagesTotal?.total || !assetsTotal?.total) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return `${imagesTotal} image${
|
return `${imagesTotal.total} image${imagesTotal.total > 1 ? 's' : ''}, ${
|
||||||
imagesTotal > 1 ? 's' : ''
|
assetsTotal.total
|
||||||
}, ${assetsTotal} asset${assetsTotal > 1 ? 's' : ''}`;
|
} asset${assetsTotal.total > 1 ? 's' : ''}`;
|
||||||
}, [assetsTotal, imagesTotal]);
|
}, [assetsTotal, imagesTotal]);
|
||||||
|
|
||||||
const { currentData: coverImage } = useGetImageDTOQuery(
|
const { currentData: coverImage } = useGetImageDTOQuery(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Box, Flex, Image, Text } from '@chakra-ui/react';
|
import { Box, Flex, Image, Text, Tooltip } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { stateSelector } from 'app/store/store';
|
import { stateSelector } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
@ -15,6 +15,10 @@ import { memo, useCallback, useMemo, useState } from 'react';
|
|||||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||||
import AutoAddIcon from '../AutoAddIcon';
|
import AutoAddIcon from '../AutoAddIcon';
|
||||||
import BoardContextMenu from '../BoardContextMenu';
|
import BoardContextMenu from '../BoardContextMenu';
|
||||||
|
import {
|
||||||
|
useGetBoardAssetsTotalQuery,
|
||||||
|
useGetBoardImagesTotalQuery,
|
||||||
|
} from 'services/api/endpoints/boards';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
@ -41,6 +45,17 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
|
|||||||
}, [dispatch, autoAssignBoardOnClick]);
|
}, [dispatch, autoAssignBoardOnClick]);
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
|
|
||||||
|
const { data: imagesTotal } = useGetBoardImagesTotalQuery('none');
|
||||||
|
const { data: assetsTotal } = useGetBoardAssetsTotalQuery('none');
|
||||||
|
const tooltip = useMemo(() => {
|
||||||
|
if (!imagesTotal?.total || !assetsTotal?.total) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return `${imagesTotal.total} image${imagesTotal.total > 1 ? 's' : ''}, ${
|
||||||
|
assetsTotal.total
|
||||||
|
} asset${assetsTotal.total > 1 ? 's' : ''}`;
|
||||||
|
}, [assetsTotal, imagesTotal]);
|
||||||
|
|
||||||
const handleMouseOver = useCallback(() => {
|
const handleMouseOver = useCallback(() => {
|
||||||
setIsHovered(true);
|
setIsHovered(true);
|
||||||
}, []);
|
}, []);
|
||||||
@ -74,77 +89,82 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
|
|||||||
>
|
>
|
||||||
<BoardContextMenu board_id="none">
|
<BoardContextMenu board_id="none">
|
||||||
{(ref) => (
|
{(ref) => (
|
||||||
<Flex
|
<Tooltip label={tooltip} openDelay={1000} hasArrow>
|
||||||
ref={ref}
|
|
||||||
onClick={handleSelectBoard}
|
|
||||||
sx={{
|
|
||||||
w: 'full',
|
|
||||||
h: 'full',
|
|
||||||
position: 'relative',
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
borderRadius: 'base',
|
|
||||||
cursor: 'pointer',
|
|
||||||
bg: 'base.200',
|
|
||||||
_dark: {
|
|
||||||
bg: 'base.800',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Flex
|
<Flex
|
||||||
|
ref={ref}
|
||||||
|
onClick={handleSelectBoard}
|
||||||
sx={{
|
sx={{
|
||||||
w: 'full',
|
w: 'full',
|
||||||
h: 'full',
|
h: 'full',
|
||||||
|
position: 'relative',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
borderRadius: 'base',
|
||||||
|
cursor: 'pointer',
|
||||||
|
bg: 'base.200',
|
||||||
|
_dark: {
|
||||||
|
bg: 'base.800',
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Image
|
<Flex
|
||||||
src={InvokeAILogoImage}
|
|
||||||
alt="invoke-ai-logo"
|
|
||||||
sx={{
|
sx={{
|
||||||
opacity: 0.4,
|
w: 'full',
|
||||||
filter: 'grayscale(1)',
|
h: 'full',
|
||||||
mt: -6,
|
justifyContent: 'center',
|
||||||
w: 16,
|
alignItems: 'center',
|
||||||
h: 16,
|
|
||||||
minW: 16,
|
|
||||||
minH: 16,
|
|
||||||
userSelect: 'none',
|
|
||||||
}}
|
}}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={InvokeAILogoImage}
|
||||||
|
alt="invoke-ai-logo"
|
||||||
|
sx={{
|
||||||
|
opacity: 0.4,
|
||||||
|
filter: 'grayscale(1)',
|
||||||
|
mt: -6,
|
||||||
|
w: 16,
|
||||||
|
h: 16,
|
||||||
|
minW: 16,
|
||||||
|
minH: 16,
|
||||||
|
userSelect: 'none',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
{autoAddBoardId === 'none' && <AutoAddIcon />}
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
p: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
w: 'full',
|
||||||
|
maxW: 'full',
|
||||||
|
borderBottomRadius: 'base',
|
||||||
|
bg: isSelected ? 'accent.400' : 'base.500',
|
||||||
|
color: isSelected ? 'base.50' : 'base.100',
|
||||||
|
_dark: {
|
||||||
|
bg: isSelected ? 'accent.500' : 'base.600',
|
||||||
|
color: isSelected ? 'base.50' : 'base.100',
|
||||||
|
},
|
||||||
|
lineHeight: 'short',
|
||||||
|
fontSize: 'xs',
|
||||||
|
fontWeight: isSelected ? 700 : 500,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{boardName}
|
||||||
|
</Flex>
|
||||||
|
<SelectionOverlay
|
||||||
|
isSelected={isSelected}
|
||||||
|
isHovered={isHovered}
|
||||||
|
/>
|
||||||
|
<IAIDroppable
|
||||||
|
data={droppableData}
|
||||||
|
dropLabel={<Text fontSize="md">Move</Text>}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
{autoAddBoardId === 'none' && <AutoAddIcon />}
|
</Tooltip>
|
||||||
<Flex
|
|
||||||
sx={{
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
p: 1,
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
w: 'full',
|
|
||||||
maxW: 'full',
|
|
||||||
borderBottomRadius: 'base',
|
|
||||||
bg: isSelected ? 'accent.400' : 'base.500',
|
|
||||||
color: isSelected ? 'base.50' : 'base.100',
|
|
||||||
_dark: {
|
|
||||||
bg: isSelected ? 'accent.500' : 'base.600',
|
|
||||||
color: isSelected ? 'base.50' : 'base.100',
|
|
||||||
},
|
|
||||||
lineHeight: 'short',
|
|
||||||
fontSize: 'xs',
|
|
||||||
fontWeight: isSelected ? 700 : 500,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{boardName}
|
|
||||||
</Flex>
|
|
||||||
<SelectionOverlay isSelected={isSelected} isHovered={isHovered} />
|
|
||||||
<IAIDroppable
|
|
||||||
data={droppableData}
|
|
||||||
dropLabel={<Text fontSize="md">Move</Text>}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
)}
|
)}
|
||||||
</BoardContextMenu>
|
</BoardContextMenu>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@ -20,7 +20,7 @@ export const nextPrevImageButtonsSelector = createSelector(
|
|||||||
const { data, status } =
|
const { data, status } =
|
||||||
imagesApi.endpoints.listImages.select(baseQueryArgs)(state);
|
imagesApi.endpoints.listImages.select(baseQueryArgs)(state);
|
||||||
|
|
||||||
const { data: total } =
|
const { data: totalsData } =
|
||||||
state.gallery.galleryView === 'images'
|
state.gallery.galleryView === 'images'
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
baseQueryArgs.board_id ?? 'none'
|
baseQueryArgs.board_id ?? 'none'
|
||||||
@ -34,7 +34,7 @@ export const nextPrevImageButtonsSelector = createSelector(
|
|||||||
|
|
||||||
const isFetching = status === 'pending';
|
const isFetching = status === 'pending';
|
||||||
|
|
||||||
if (!data || !lastSelectedImage || total === 0) {
|
if (!data || !lastSelectedImage || totalsData?.total === 0) {
|
||||||
return {
|
return {
|
||||||
isFetching,
|
isFetching,
|
||||||
queryArgs: baseQueryArgs,
|
queryArgs: baseQueryArgs,
|
||||||
@ -74,7 +74,7 @@ export const nextPrevImageButtonsSelector = createSelector(
|
|||||||
return {
|
return {
|
||||||
loadedImagesCount: images.length,
|
loadedImagesCount: images.length,
|
||||||
currentImageIndex,
|
currentImageIndex,
|
||||||
areMoreImagesAvailable: (total ?? 0) > imagesLength,
|
areMoreImagesAvailable: (totalsData?.total ?? 0) > imagesLength,
|
||||||
isFetching: status === 'pending',
|
isFetching: status === 'pending',
|
||||||
nextImage,
|
nextImage,
|
||||||
prevImage,
|
prevImage,
|
||||||
|
@ -70,7 +70,7 @@ export const boardsApi = api.injectEndpoints({
|
|||||||
keepUnusedDataFor: 0,
|
keepUnusedDataFor: 0,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getBoardImagesTotal: build.query<number, string | undefined>({
|
getBoardImagesTotal: build.query<{ total: number }, string | undefined>({
|
||||||
query: (board_id) => ({
|
query: (board_id) => ({
|
||||||
url: getListImagesUrl({
|
url: getListImagesUrl({
|
||||||
board_id: board_id ?? 'none',
|
board_id: board_id ?? 'none',
|
||||||
@ -85,11 +85,11 @@ export const boardsApi = api.injectEndpoints({
|
|||||||
{ type: 'BoardImagesTotal', id: arg ?? 'none' },
|
{ type: 'BoardImagesTotal', id: arg ?? 'none' },
|
||||||
],
|
],
|
||||||
transformResponse: (response: OffsetPaginatedResults_ImageDTO_) => {
|
transformResponse: (response: OffsetPaginatedResults_ImageDTO_) => {
|
||||||
return response.total;
|
return { total: response.total };
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getBoardAssetsTotal: build.query<number, string | undefined>({
|
getBoardAssetsTotal: build.query<{ total: number }, string | undefined>({
|
||||||
query: (board_id) => ({
|
query: (board_id) => ({
|
||||||
url: getListImagesUrl({
|
url: getListImagesUrl({
|
||||||
board_id: board_id ?? 'none',
|
board_id: board_id ?? 'none',
|
||||||
@ -104,7 +104,7 @@ export const boardsApi = api.injectEndpoints({
|
|||||||
{ type: 'BoardAssetsTotal', id: arg ?? 'none' },
|
{ type: 'BoardAssetsTotal', id: arg ?? 'none' },
|
||||||
],
|
],
|
||||||
transformResponse: (response: OffsetPaginatedResults_ImageDTO_) => {
|
transformResponse: (response: OffsetPaginatedResults_ImageDTO_) => {
|
||||||
return response.total;
|
return { total: response.total };
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -103,6 +103,9 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
query: () => ({ url: getListImagesUrl({ is_intermediate: true }) }),
|
query: () => ({ url: getListImagesUrl({ is_intermediate: true }) }),
|
||||||
providesTags: ['IntermediatesCount'],
|
providesTags: ['IntermediatesCount'],
|
||||||
transformResponse: (response: OffsetPaginatedResults_ImageDTO_) => {
|
transformResponse: (response: OffsetPaginatedResults_ImageDTO_) => {
|
||||||
|
// TODO: This is storing a primitive value in the cache. `immer` cannot track state changes, so
|
||||||
|
// attempts to use manual cache updates on this value will fail. This should be changed into an
|
||||||
|
// object.
|
||||||
return response.total;
|
return response.total;
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -191,35 +194,51 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
url: `images/i/${image_name}`,
|
url: `images/i/${image_name}`,
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
}),
|
}),
|
||||||
invalidatesTags: (result, error, { board_id }) => [
|
|
||||||
{ type: 'BoardImagesTotal', id: board_id ?? 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: board_id ?? 'none' },
|
|
||||||
],
|
|
||||||
async onQueryStarted(imageDTO, { dispatch, queryFulfilled }) {
|
async onQueryStarted(imageDTO, { dispatch, queryFulfilled }) {
|
||||||
/**
|
/**
|
||||||
* Cache changes for `deleteImage`:
|
* Cache changes for `deleteImage`:
|
||||||
* - NOT POSSIBLE: *remove* from getImageDTO
|
* - NOT POSSIBLE: *remove* from getImageDTO
|
||||||
* - $cache = [board_id|no_board]/[images|assets]
|
* - $cache = [board_id|no_board]/[images|assets]
|
||||||
* - *remove* from $cache
|
* - *remove* from $cache
|
||||||
|
* - decrement the image's board's total
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { image_name, board_id } = imageDTO;
|
const { image_name, board_id } = imageDTO;
|
||||||
|
const isAsset = ASSETS_CATEGORIES.includes(imageDTO.image_category);
|
||||||
|
|
||||||
const queryArg = {
|
const queryArg = {
|
||||||
board_id: board_id ?? 'none',
|
board_id: board_id ?? 'none',
|
||||||
categories: getCategories(imageDTO),
|
categories: getCategories(imageDTO),
|
||||||
};
|
};
|
||||||
|
|
||||||
const patch = dispatch(
|
const patches: PatchCollection[] = [];
|
||||||
imagesApi.util.updateQueryData('listImages', queryArg, (draft) => {
|
|
||||||
imagesAdapter.removeOne(draft, image_name);
|
patches.push(
|
||||||
})
|
dispatch(
|
||||||
|
imagesApi.util.updateQueryData('listImages', queryArg, (draft) => {
|
||||||
|
imagesAdapter.removeOne(draft, image_name);
|
||||||
|
})
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
patches.push(
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
imageDTO.board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total = Math.max(draft.total - 1, 0);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
); // decrement the image board's total
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await queryFulfilled;
|
await queryFulfilled;
|
||||||
} catch {
|
} catch {
|
||||||
patch.undo();
|
patches.forEach((patch) => {
|
||||||
|
patch.undo();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -237,18 +256,11 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
invalidatesTags: (result, error, { imageDTOs }) => {
|
|
||||||
// for now, assume bulk delete is all on one board
|
|
||||||
const boardId = imageDTOs[0]?.board_id;
|
|
||||||
return [
|
|
||||||
{ type: 'BoardImagesTotal', id: boardId ?? 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: boardId ?? 'none' },
|
|
||||||
];
|
|
||||||
},
|
|
||||||
async onQueryStarted({ imageDTOs }, { dispatch, queryFulfilled }) {
|
async onQueryStarted({ imageDTOs }, { dispatch, queryFulfilled }) {
|
||||||
/**
|
/**
|
||||||
* Cache changes for `deleteImages`:
|
* Cache changes for `deleteImages`:
|
||||||
* - *remove* the deleted images from their boards
|
* - *remove* the deleted images from their boards
|
||||||
|
* - decrement the images' board's totals
|
||||||
*
|
*
|
||||||
* Unfortunately we cannot do an optimistic update here due to how immer handles patching
|
* Unfortunately we cannot do an optimistic update here due to how immer handles patching
|
||||||
* arrays. You have to undo *all* patches, else the entity adapter's `ids` array is borked.
|
* arrays. You have to undo *all* patches, else the entity adapter's `ids` array is borked.
|
||||||
@ -279,6 +291,21 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isAsset = ASSETS_CATEGORIES.includes(
|
||||||
|
imageDTO.image_category
|
||||||
|
);
|
||||||
|
|
||||||
|
// decrement the image board's total
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
imageDTO.board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total = Math.max(draft.total - 1, 0);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
@ -298,10 +325,6 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
body: { is_intermediate },
|
body: { is_intermediate },
|
||||||
}),
|
}),
|
||||||
invalidatesTags: (result, error, { imageDTO }) => [
|
|
||||||
{ type: 'BoardImagesTotal', id: imageDTO.board_id ?? 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: imageDTO.board_id ?? 'none' },
|
|
||||||
],
|
|
||||||
async onQueryStarted(
|
async onQueryStarted(
|
||||||
{ imageDTO, is_intermediate },
|
{ imageDTO, is_intermediate },
|
||||||
{ dispatch, queryFulfilled, getState }
|
{ dispatch, queryFulfilled, getState }
|
||||||
@ -312,9 +335,11 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
* - $cache = [board_id|no_board]/[images|assets]
|
* - $cache = [board_id|no_board]/[images|assets]
|
||||||
* - IF it is being changed to an intermediate:
|
* - IF it is being changed to an intermediate:
|
||||||
* - remove from $cache
|
* - remove from $cache
|
||||||
|
* - decrement the image's board's total
|
||||||
* - ELSE (it is being changed to a non-intermediate):
|
* - ELSE (it is being changed to a non-intermediate):
|
||||||
* - IF it eligible for insertion into existing $cache:
|
* - IF it eligible for insertion into existing $cache:
|
||||||
* - *upsert* to $cache
|
* - *upsert* to $cache
|
||||||
|
* - increment the image's board's total
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Store patches so we can undo if the query fails
|
// Store patches so we can undo if the query fails
|
||||||
@ -335,6 +360,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
|
|
||||||
// $cache = [board_id|no_board]/[images|assets]
|
// $cache = [board_id|no_board]/[images|assets]
|
||||||
const categories = getCategories(imageDTO);
|
const categories = getCategories(imageDTO);
|
||||||
|
const isAsset = ASSETS_CATEGORIES.includes(imageDTO.image_category);
|
||||||
|
|
||||||
if (is_intermediate) {
|
if (is_intermediate) {
|
||||||
// IF it is being changed to an intermediate:
|
// IF it is being changed to an intermediate:
|
||||||
@ -350,8 +376,35 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// decrement the image board's total
|
||||||
|
patches.push(
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
imageDTO.board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total = Math.max(draft.total - 1, 0);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// ELSE (it is being changed to a non-intermediate):
|
// ELSE (it is being changed to a non-intermediate):
|
||||||
|
|
||||||
|
// increment the image board's total
|
||||||
|
patches.push(
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
imageDTO.board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total += 1;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const queryArgs = {
|
const queryArgs = {
|
||||||
board_id: imageDTO.board_id ?? 'none',
|
board_id: imageDTO.board_id ?? 'none',
|
||||||
categories,
|
categories,
|
||||||
@ -361,9 +414,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
getState()
|
getState()
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: total } = IMAGE_CATEGORIES.includes(
|
const { data } = IMAGE_CATEGORIES.includes(imageDTO.image_category)
|
||||||
imageDTO.image_category
|
|
||||||
)
|
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
@ -378,7 +429,8 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
// - The image's `created_at` is within the range of the cached images
|
// - The image's `created_at` is within the range of the cached images
|
||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
currentCache.data &&
|
||||||
|
currentCache.data.ids.length >= (data?.total ?? 0);
|
||||||
|
|
||||||
const isInDateRange = getIsImageInDateRange(
|
const isInDateRange = getIsImageInDateRange(
|
||||||
currentCache.data,
|
currentCache.data,
|
||||||
@ -420,10 +472,6 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
body: { session_id },
|
body: { session_id },
|
||||||
}),
|
}),
|
||||||
invalidatesTags: (result, error, { imageDTO }) => [
|
|
||||||
{ type: 'BoardImagesTotal', id: imageDTO.board_id ?? 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: imageDTO.board_id ?? 'none' },
|
|
||||||
],
|
|
||||||
async onQueryStarted(
|
async onQueryStarted(
|
||||||
{ imageDTO, session_id },
|
{ imageDTO, session_id },
|
||||||
{ dispatch, queryFulfilled }
|
{ dispatch, queryFulfilled }
|
||||||
@ -535,9 +583,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
queryArgs
|
queryArgs
|
||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const { data: previousTotal } = IMAGE_CATEGORIES.includes(
|
const { data } = IMAGE_CATEGORIES.includes(imageDTO.image_category)
|
||||||
imageDTO.image_category
|
|
||||||
)
|
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
boardId ?? 'none'
|
boardId ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
@ -547,10 +593,10 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data &&
|
currentCache.data &&
|
||||||
currentCache.data.ids.length >= (previousTotal ?? 0);
|
currentCache.data.ids.length >= (data?.total ?? 0);
|
||||||
|
|
||||||
const isInDateRange =
|
const isInDateRange =
|
||||||
(previousTotal || 0) >= IMAGE_LIMIT
|
(data?.total ?? 0) >= IMAGE_LIMIT
|
||||||
? getIsImageInDateRange(currentCache.data, imageDTO)
|
? getIsImageInDateRange(currentCache.data, imageDTO)
|
||||||
: true;
|
: true;
|
||||||
|
|
||||||
@ -652,9 +698,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
queryArgs
|
queryArgs
|
||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const { data: previousTotal } = IMAGE_CATEGORIES.includes(
|
const { data } = IMAGE_CATEGORIES.includes(imageDTO.image_category)
|
||||||
imageDTO.image_category
|
|
||||||
)
|
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
boardId ?? 'none'
|
boardId ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
@ -664,10 +708,10 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data &&
|
currentCache.data &&
|
||||||
currentCache.data.ids.length >= (previousTotal ?? 0);
|
currentCache.data.ids.length >= (data?.total ?? 0);
|
||||||
|
|
||||||
const isInDateRange =
|
const isInDateRange =
|
||||||
(previousTotal || 0) >= IMAGE_LIMIT
|
(data?.total ?? 0) >= IMAGE_LIMIT
|
||||||
? getIsImageInDateRange(currentCache.data, imageDTO)
|
? getIsImageInDateRange(currentCache.data, imageDTO)
|
||||||
: true;
|
: true;
|
||||||
|
|
||||||
@ -736,6 +780,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
* - BAIL OUT
|
* - BAIL OUT
|
||||||
* - *add* to `getImageDTO`
|
* - *add* to `getImageDTO`
|
||||||
* - *add* to no_board/assets
|
* - *add* to no_board/assets
|
||||||
|
* - update the image's board's assets total
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { data: imageDTO } = await queryFulfilled;
|
const { data: imageDTO } = await queryFulfilled;
|
||||||
@ -770,11 +815,15 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// increment new board's total
|
||||||
dispatch(
|
dispatch(
|
||||||
imagesApi.util.invalidateTags([
|
boardsApi.util.updateQueryData(
|
||||||
{ type: 'BoardImagesTotal', id: imageDTO.board_id ?? 'none' },
|
'getBoardAssetsTotal',
|
||||||
{ type: 'BoardAssetsTotal', id: imageDTO.board_id ?? 'none' },
|
imageDTO.board_id ?? 'none',
|
||||||
])
|
(draft) => {
|
||||||
|
draft.total += 1;
|
||||||
|
}
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} catch {
|
} catch {
|
||||||
// query failed, no action needed
|
// query failed, no action needed
|
||||||
@ -801,8 +850,6 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
categories: ASSETS_CATEGORIES,
|
categories: ASSETS_CATEGORIES,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{ type: 'BoardImagesTotal', id: 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: 'none' },
|
|
||||||
],
|
],
|
||||||
async onQueryStarted(board_id, { dispatch, queryFulfilled }) {
|
async onQueryStarted(board_id, { dispatch, queryFulfilled }) {
|
||||||
/**
|
/**
|
||||||
@ -815,6 +862,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
* have access to the deleted images DTOs - only the names, and a network request
|
* have access to the deleted images DTOs - only the names, and a network request
|
||||||
* for all of a board's DTOs could be very large. Instead, we invalidate the 'No Board'
|
* for all of a board's DTOs could be very large. Instead, we invalidate the 'No Board'
|
||||||
* cache.
|
* cache.
|
||||||
|
* - set the board's totals to zero
|
||||||
*/
|
*/
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -834,6 +882,28 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// set the board's asset total to 0 (feels unnecessary since we are deleting it?)
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
'getBoardAssetsTotal',
|
||||||
|
board_id,
|
||||||
|
(draft) => {
|
||||||
|
draft.total = 0;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// set the board's images total to 0 (feels unnecessary since we are deleting it?)
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
'getBoardImagesTotal',
|
||||||
|
board_id,
|
||||||
|
(draft) => {
|
||||||
|
draft.total = 0;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// update 'All Images' & 'All Assets' caches
|
// update 'All Images' & 'All Assets' caches
|
||||||
const queryArgsToUpdate = [
|
const queryArgsToUpdate = [
|
||||||
{
|
{
|
||||||
@ -890,8 +960,6 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
categories: ASSETS_CATEGORIES,
|
categories: ASSETS_CATEGORIES,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{ type: 'BoardImagesTotal', id: 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: 'none' },
|
|
||||||
],
|
],
|
||||||
async onQueryStarted(board_id, { dispatch, queryFulfilled }) {
|
async onQueryStarted(board_id, { dispatch, queryFulfilled }) {
|
||||||
/**
|
/**
|
||||||
@ -901,6 +969,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
* Instead, we rely on the UI to remove all components that use the deleted images.
|
* Instead, we rely on the UI to remove all components that use the deleted images.
|
||||||
* - Remove every image in the 'All Images' cache that has the board_id
|
* - Remove every image in the 'All Images' cache that has the board_id
|
||||||
* - Remove every image in the 'All Assets' cache that has the board_id
|
* - Remove every image in the 'All Assets' cache that has the board_id
|
||||||
|
* - set the board's totals to zero
|
||||||
*/
|
*/
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -928,6 +997,28 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// set the board's asset total to 0 (feels unnecessary since we are deleting it?)
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
'getBoardAssetsTotal',
|
||||||
|
board_id,
|
||||||
|
(draft) => {
|
||||||
|
draft.total = 0;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// set the board's images total to 0 (feels unnecessary since we are deleting it?)
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
'getBoardImagesTotal',
|
||||||
|
board_id,
|
||||||
|
(draft) => {
|
||||||
|
draft.total = 0;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
//no-op
|
//no-op
|
||||||
}
|
}
|
||||||
@ -945,15 +1036,9 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
body: { board_id, image_name },
|
body: { board_id, image_name },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
invalidatesTags: (result, error, { board_id, imageDTO }) => [
|
invalidatesTags: (result, error, { board_id }) => [
|
||||||
// refresh the board itself
|
// refresh the board itself
|
||||||
{ type: 'Board', id: board_id },
|
{ type: 'Board', id: board_id },
|
||||||
// update old board totals
|
|
||||||
{ type: 'BoardImagesTotal', id: board_id },
|
|
||||||
{ type: 'BoardAssetsTotal', id: board_id },
|
|
||||||
// update new board totals
|
|
||||||
{ type: 'BoardImagesTotal', id: imageDTO.board_id ?? 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: imageDTO.board_id ?? 'none' },
|
|
||||||
],
|
],
|
||||||
async onQueryStarted(
|
async onQueryStarted(
|
||||||
{ board_id, imageDTO },
|
{ board_id, imageDTO },
|
||||||
@ -970,11 +1055,13 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
* - $cache = board_id/[images|assets]
|
* - $cache = board_id/[images|assets]
|
||||||
* - IF it eligible for insertion into existing $cache:
|
* - IF it eligible for insertion into existing $cache:
|
||||||
* - THEN *add* to $cache
|
* - THEN *add* to $cache
|
||||||
|
* - decrement both old board's total
|
||||||
|
* - increment the new board's total
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const patches: PatchCollection[] = [];
|
const patches: PatchCollection[] = [];
|
||||||
const categories = getCategories(imageDTO);
|
const categories = getCategories(imageDTO);
|
||||||
|
const isAsset = ASSETS_CATEGORIES.includes(imageDTO.image_category);
|
||||||
// *update* getImageDTO
|
// *update* getImageDTO
|
||||||
patches.push(
|
patches.push(
|
||||||
dispatch(
|
dispatch(
|
||||||
@ -1005,6 +1092,32 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// decrement old board's total
|
||||||
|
patches.push(
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
imageDTO.board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total = Math.max(draft.total - 1, 0);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// increment new board's total
|
||||||
|
patches.push(
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total += 1;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// $cache = board_id/[images|assets]
|
// $cache = board_id/[images|assets]
|
||||||
const queryArgs = { board_id: board_id ?? 'none', categories };
|
const queryArgs = { board_id: board_id ?? 'none', categories };
|
||||||
const currentCache = imagesApi.endpoints.listImages.select(queryArgs)(
|
const currentCache = imagesApi.endpoints.listImages.select(queryArgs)(
|
||||||
@ -1017,9 +1130,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
// OR
|
// OR
|
||||||
// - The image's `created_at` is within the range of the cached images
|
// - The image's `created_at` is within the range of the cached images
|
||||||
|
|
||||||
const { data: total } = IMAGE_CATEGORIES.includes(
|
const { data } = IMAGE_CATEGORIES.includes(imageDTO.image_category)
|
||||||
imageDTO.image_category
|
|
||||||
)
|
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
@ -1028,7 +1139,8 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
currentCache.data &&
|
||||||
|
currentCache.data.ids.length >= (data?.total ?? 0);
|
||||||
|
|
||||||
const isInDateRange = getIsImageInDateRange(
|
const isInDateRange = getIsImageInDateRange(
|
||||||
currentCache.data,
|
currentCache.data,
|
||||||
@ -1072,12 +1184,6 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
return [
|
return [
|
||||||
// invalidate the image's old board
|
// invalidate the image's old board
|
||||||
{ type: 'Board', id: board_id ?? 'none' },
|
{ type: 'Board', id: board_id ?? 'none' },
|
||||||
// update old board totals
|
|
||||||
{ type: 'BoardImagesTotal', id: board_id ?? 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: board_id ?? 'none' },
|
|
||||||
// update the no_board totals
|
|
||||||
{ type: 'BoardImagesTotal', id: 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: 'none' },
|
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
async onQueryStarted(
|
async onQueryStarted(
|
||||||
@ -1091,10 +1197,13 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
* - $cache = no_board/[images|assets]
|
* - $cache = no_board/[images|assets]
|
||||||
* - IF it eligible for insertion into existing $cache:
|
* - IF it eligible for insertion into existing $cache:
|
||||||
* - THEN *upsert* to $cache
|
* - THEN *upsert* to $cache
|
||||||
|
* - decrement old board's total
|
||||||
|
* - increment the new board's total (no board)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const categories = getCategories(imageDTO);
|
const categories = getCategories(imageDTO);
|
||||||
const patches: PatchCollection[] = [];
|
const patches: PatchCollection[] = [];
|
||||||
|
const isAsset = ASSETS_CATEGORIES.includes(imageDTO.image_category);
|
||||||
|
|
||||||
// *update* getImageDTO
|
// *update* getImageDTO
|
||||||
patches.push(
|
patches.push(
|
||||||
@ -1125,6 +1234,32 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// decrement old board's total
|
||||||
|
patches.push(
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
imageDTO.board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total = Math.max(draft.total - 1, 0);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// increment new board's total (no board)
|
||||||
|
patches.push(
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total += 1;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// $cache = no_board/[images|assets]
|
// $cache = no_board/[images|assets]
|
||||||
const queryArgs = { board_id: 'none', categories };
|
const queryArgs = { board_id: 'none', categories };
|
||||||
const currentCache = imagesApi.endpoints.listImages.select(queryArgs)(
|
const currentCache = imagesApi.endpoints.listImages.select(queryArgs)(
|
||||||
@ -1137,9 +1272,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
// OR
|
// OR
|
||||||
// - The image's `created_at` is within the range of the cached images
|
// - The image's `created_at` is within the range of the cached images
|
||||||
|
|
||||||
const { data: total } = IMAGE_CATEGORIES.includes(
|
const { data } = IMAGE_CATEGORIES.includes(imageDTO.image_category)
|
||||||
imageDTO.image_category
|
|
||||||
)
|
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
@ -1148,7 +1281,8 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
currentCache.data &&
|
||||||
|
currentCache.data.ids.length >= (data?.total ?? 0);
|
||||||
|
|
||||||
const isInDateRange = getIsImageInDateRange(
|
const isInDateRange = getIsImageInDateRange(
|
||||||
currentCache.data,
|
currentCache.data,
|
||||||
@ -1192,21 +1326,10 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
board_id,
|
board_id,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
invalidatesTags: (result, error, { imageDTOs, board_id }) => {
|
invalidatesTags: (result, error, { board_id }) => {
|
||||||
//assume all images are being moved from one board for now
|
|
||||||
const oldBoardId = imageDTOs[0]?.board_id;
|
|
||||||
return [
|
return [
|
||||||
// update the destination board
|
// update the destination board
|
||||||
{ type: 'Board', id: board_id ?? 'none' },
|
{ type: 'Board', id: board_id ?? 'none' },
|
||||||
// update new board totals
|
|
||||||
{ type: 'BoardImagesTotal', id: board_id ?? 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: board_id ?? 'none' },
|
|
||||||
// update old board totals
|
|
||||||
{ type: 'BoardImagesTotal', id: oldBoardId ?? 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: oldBoardId ?? 'none' },
|
|
||||||
// update the no_board totals
|
|
||||||
{ type: 'BoardImagesTotal', id: 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: 'none' },
|
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
async onQueryStarted(
|
async onQueryStarted(
|
||||||
@ -1222,6 +1345,8 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
* - *update* getImageDTO for each image
|
* - *update* getImageDTO for each image
|
||||||
* - *add* to board_id/[images|assets]
|
* - *add* to board_id/[images|assets]
|
||||||
* - *remove* from [old_board_id|no_board]/[images|assets]
|
* - *remove* from [old_board_id|no_board]/[images|assets]
|
||||||
|
* - decrement old board's totals for each image
|
||||||
|
* - increment new board's totals for each image
|
||||||
*/
|
*/
|
||||||
|
|
||||||
added_image_names.forEach((image_name) => {
|
added_image_names.forEach((image_name) => {
|
||||||
@ -1230,7 +1355,8 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
'getImageDTO',
|
'getImageDTO',
|
||||||
image_name,
|
image_name,
|
||||||
(draft) => {
|
(draft) => {
|
||||||
draft.board_id = new_board_id;
|
draft.board_id =
|
||||||
|
new_board_id === 'none' ? undefined : new_board_id;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -1243,6 +1369,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
|
|
||||||
const categories = getCategories(imageDTO);
|
const categories = getCategories(imageDTO);
|
||||||
const old_board_id = imageDTO.board_id;
|
const old_board_id = imageDTO.board_id;
|
||||||
|
const isAsset = ASSETS_CATEGORIES.includes(imageDTO.image_category);
|
||||||
|
|
||||||
// remove from the old board
|
// remove from the old board
|
||||||
dispatch(
|
dispatch(
|
||||||
@ -1255,6 +1382,28 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// decrement old board's total
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
old_board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total = Math.max(draft.total - 1, 0);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// increment new board's total
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
new_board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total += 1;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const queryArgs = {
|
const queryArgs = {
|
||||||
board_id: new_board_id,
|
board_id: new_board_id,
|
||||||
categories,
|
categories,
|
||||||
@ -1264,9 +1413,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
queryArgs
|
queryArgs
|
||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const { data: previousTotal } = IMAGE_CATEGORIES.includes(
|
const { data } = IMAGE_CATEGORIES.includes(imageDTO.image_category)
|
||||||
imageDTO.image_category
|
|
||||||
)
|
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
new_board_id ?? 'none'
|
new_board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
@ -1276,10 +1423,10 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data &&
|
currentCache.data &&
|
||||||
currentCache.data.ids.length >= (previousTotal ?? 0);
|
currentCache.data.ids.length >= (data?.total ?? 0);
|
||||||
|
|
||||||
const isInDateRange =
|
const isInDateRange =
|
||||||
(previousTotal || 0) >= IMAGE_LIMIT
|
(data?.total ?? 0) >= IMAGE_LIMIT
|
||||||
? getIsImageInDateRange(currentCache.data, imageDTO)
|
? getIsImageInDateRange(currentCache.data, imageDTO)
|
||||||
: true;
|
: true;
|
||||||
|
|
||||||
@ -1319,10 +1466,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
}),
|
}),
|
||||||
invalidatesTags: (result, error, { imageDTOs }) => {
|
invalidatesTags: (result, error, { imageDTOs }) => {
|
||||||
const touchedBoardIds: string[] = [];
|
const touchedBoardIds: string[] = [];
|
||||||
const tags: ApiTagDescription[] = [
|
const tags: ApiTagDescription[] = [];
|
||||||
{ type: 'BoardImagesTotal', id: 'none' },
|
|
||||||
{ type: 'BoardAssetsTotal', id: 'none' },
|
|
||||||
];
|
|
||||||
|
|
||||||
result?.removed_image_names.forEach((image_name) => {
|
result?.removed_image_names.forEach((image_name) => {
|
||||||
const board_id = imageDTOs.find((i) => i.image_name === image_name)
|
const board_id = imageDTOs.find((i) => i.image_name === image_name)
|
||||||
@ -1333,8 +1477,6 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
}
|
}
|
||||||
|
|
||||||
tags.push({ type: 'Board', id: board_id });
|
tags.push({ type: 'Board', id: board_id });
|
||||||
tags.push({ type: 'BoardImagesTotal', id: board_id });
|
|
||||||
tags.push({ type: 'BoardAssetsTotal', id: board_id });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return tags;
|
return tags;
|
||||||
@ -1352,6 +1494,8 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
* - *update* getImageDTO for each image
|
* - *update* getImageDTO for each image
|
||||||
* - *remove* from old_board_id/[images|assets]
|
* - *remove* from old_board_id/[images|assets]
|
||||||
* - *add* to no_board/[images|assets]
|
* - *add* to no_board/[images|assets]
|
||||||
|
* - decrement old board's totals for each image
|
||||||
|
* - increment new board's (no board) totals for each image
|
||||||
*/
|
*/
|
||||||
|
|
||||||
removed_image_names.forEach((image_name) => {
|
removed_image_names.forEach((image_name) => {
|
||||||
@ -1372,6 +1516,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const categories = getCategories(imageDTO);
|
const categories = getCategories(imageDTO);
|
||||||
|
const isAsset = ASSETS_CATEGORIES.includes(imageDTO.image_category);
|
||||||
|
|
||||||
// remove from the old board
|
// remove from the old board
|
||||||
dispatch(
|
dispatch(
|
||||||
@ -1384,6 +1529,28 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// decrement old board's total
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
imageDTO.board_id ?? 'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total = Math.max(draft.total - 1, 0);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// increment new board's total (no board)
|
||||||
|
dispatch(
|
||||||
|
boardsApi.util.updateQueryData(
|
||||||
|
isAsset ? 'getBoardAssetsTotal' : 'getBoardImagesTotal',
|
||||||
|
'none',
|
||||||
|
(draft) => {
|
||||||
|
draft.total += 1;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// add to `no_board`
|
// add to `no_board`
|
||||||
const queryArgs = {
|
const queryArgs = {
|
||||||
board_id: 'none',
|
board_id: 'none',
|
||||||
@ -1394,9 +1561,7 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
queryArgs
|
queryArgs
|
||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const { data: total } = IMAGE_CATEGORIES.includes(
|
const { data } = IMAGE_CATEGORIES.includes(imageDTO.image_category)
|
||||||
imageDTO.image_category
|
|
||||||
)
|
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
@ -1405,10 +1570,11 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
currentCache.data &&
|
||||||
|
currentCache.data.ids.length >= (data?.total ?? 0);
|
||||||
|
|
||||||
const isInDateRange =
|
const isInDateRange =
|
||||||
(total || 0) >= IMAGE_LIMIT
|
(data?.total ?? 0) >= IMAGE_LIMIT
|
||||||
? getIsImageInDateRange(currentCache.data, imageDTO)
|
? getIsImageInDateRange(currentCache.data, imageDTO)
|
||||||
: true;
|
: true;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ export const useBoardTotal = (board_id: BoardId) => {
|
|||||||
const { data: totalAssets } = useGetBoardAssetsTotalQuery(board_id);
|
const { data: totalAssets } = useGetBoardAssetsTotalQuery(board_id);
|
||||||
|
|
||||||
const currentViewTotal = useMemo(
|
const currentViewTotal = useMemo(
|
||||||
() => (galleryView === 'images' ? totalImages : totalAssets),
|
() => (galleryView === 'images' ? totalImages?.total : totalAssets?.total),
|
||||||
[galleryView, totalAssets, totalImages]
|
[galleryView, totalAssets, totalImages]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user