mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
(ui) WIP trying to get all cache scenarios working smoothly, fix assets
This commit is contained in:
parent
0a71d6baa1
commit
767a612746
@ -36,7 +36,7 @@ import {
|
||||
import { ImageDTO } from 'services/api/types';
|
||||
import { useDebounce } from 'use-debounce';
|
||||
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
|
||||
import { BsPinAngle, BsPinAngleFill } from 'react-icons/bs';
|
||||
import { BsBookmarkStar, BsFillBookmarkStarFill } from 'react-icons/bs';
|
||||
|
||||
type SingleSelectionMenuItemsProps = {
|
||||
imageDTO: ImageDTO;
|
||||
@ -211,11 +211,14 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
||||
Change Board
|
||||
</MenuItem>
|
||||
{imageDTO.pinned ? (
|
||||
<MenuItem icon={<BsPinAngle />} onClickCapture={handleUnpinImage}>
|
||||
<MenuItem icon={<BsBookmarkStar />} onClickCapture={handleUnpinImage}>
|
||||
Unpin Image
|
||||
</MenuItem>
|
||||
) : (
|
||||
<MenuItem icon={<BsPinAngleFill />} onClickCapture={handlePinImage}>
|
||||
<MenuItem
|
||||
icon={<BsFillBookmarkStarFill />}
|
||||
onClickCapture={handlePinImage}
|
||||
>
|
||||
Pin Image
|
||||
</MenuItem>
|
||||
)}
|
||||
|
@ -2,16 +2,19 @@ import { Box, Flex } from '@chakra-ui/react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIDndImage from 'common/components/IAIDndImage';
|
||||
import IAIFillSkeleton from 'common/components/IAIFillSkeleton';
|
||||
import { useMultiselect } from 'features/gallery/hooks/useMultiselect.ts';
|
||||
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
||||
import { MouseEvent, memo, useCallback, useMemo } from 'react';
|
||||
import { FaTrash } from 'react-icons/fa';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import {
|
||||
ImageDTOsDraggableData,
|
||||
ImageDraggableData,
|
||||
TypesafeDraggableData,
|
||||
} from 'features/dnd/types';
|
||||
import { useMultiselect } from 'features/gallery/hooks/useMultiselect.ts';
|
||||
import { MouseEvent, memo, useCallback, useMemo } from 'react';
|
||||
import { BsBookmarkStar, BsFillBookmarkStarFill } from 'react-icons/bs';
|
||||
import {
|
||||
useChangeImagePinnedMutation,
|
||||
useGetImageDTOQuery,
|
||||
} from 'services/api/endpoints/images';
|
||||
|
||||
interface HoverableImageProps {
|
||||
imageName: string;
|
||||
@ -59,6 +62,14 @@ const GalleryImage = (props: HoverableImageProps) => {
|
||||
}
|
||||
}, [imageDTO, selection, selectionCount]);
|
||||
|
||||
const [togglePin] = useChangeImagePinnedMutation();
|
||||
|
||||
const togglePinnedState = useCallback(() => {
|
||||
if (imageDTO) {
|
||||
togglePin({ imageDTO, pinned: !imageDTO.pinned });
|
||||
}
|
||||
}, [togglePin, imageDTO]);
|
||||
|
||||
if (!imageDTO) {
|
||||
return <IAIFillSkeleton />;
|
||||
}
|
||||
@ -80,15 +91,17 @@ const GalleryImage = (props: HoverableImageProps) => {
|
||||
draggableData={draggableData}
|
||||
isSelected={isSelected}
|
||||
minSize={0}
|
||||
onClickReset={handleDelete}
|
||||
onClickReset={togglePinnedState}
|
||||
imageSx={{ w: 'full', h: 'full' }}
|
||||
isDropDisabled={true}
|
||||
isUploadDisabled={true}
|
||||
thumbnail={true}
|
||||
withHoverOverlay
|
||||
resetIcon={<FaTrash />}
|
||||
resetTooltip="Delete image"
|
||||
withResetIcon={shouldShowDeleteButton} // removed bc it's too easy to accidentally delete images
|
||||
resetIcon={
|
||||
imageDTO.pinned ? <BsFillBookmarkStarFill /> : <BsBookmarkStar />
|
||||
}
|
||||
resetTooltip="Pin image"
|
||||
withResetIcon={true}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
|
@ -399,15 +399,18 @@ export const imagesApi = api.injectEndpoints({
|
||||
method: 'PATCH',
|
||||
body: { pinned },
|
||||
}),
|
||||
invalidatesTags: (result, error, { imageDTO }) => [
|
||||
{
|
||||
type: 'ImageList',
|
||||
id: getListImagesUrl({
|
||||
board_id: imageDTO.board_id,
|
||||
categories: IMAGE_CATEGORIES,
|
||||
}),
|
||||
},
|
||||
],
|
||||
invalidatesTags: (result, error, { imageDTO }) => {
|
||||
const categories = getCategories(imageDTO);
|
||||
return [
|
||||
{
|
||||
type: 'ImageList',
|
||||
id: getListImagesUrl({
|
||||
board_id: imageDTO.board_id,
|
||||
categories,
|
||||
}),
|
||||
},
|
||||
]
|
||||
},
|
||||
async onQueryStarted(
|
||||
{ imageDTO, pinned },
|
||||
{ dispatch, queryFulfilled, getState }
|
||||
@ -465,27 +468,14 @@ export const imagesApi = api.injectEndpoints({
|
||||
const isCacheFullyPopulated =
|
||||
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
||||
|
||||
const isInDateRangeForPinnedState = getIsImageInDateRange(
|
||||
const isInDateRange = getIsImageInDateRange(
|
||||
currentCache.data,
|
||||
updatedImage
|
||||
);
|
||||
|
||||
if (!isInDateRangeForPinnedState) {
|
||||
// if newly pinned or unpinned image is not in date range for its new state, remove from cache
|
||||
patches.push(
|
||||
dispatch(
|
||||
imagesApi.util.updateQueryData(
|
||||
'listImages',
|
||||
queryArgs,
|
||||
(draft) => {
|
||||
imagesAdapter.removeOne(draft, updatedImage.image_name);
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
// should we remove images from cache if _not_ in date range? ie you are showing 100 of 101 pinned images and you unpin one. technically it should disappear from list.
|
||||
|
||||
if (isCacheFullyPopulated || isInDateRangeForPinnedState) {
|
||||
if (isCacheFullyPopulated || isInDateRange) {
|
||||
// *upsert* to $cache
|
||||
patches.push(
|
||||
dispatch(
|
||||
|
@ -21,21 +21,35 @@ export const getIsImageInDateRange = (
|
||||
return true;
|
||||
}
|
||||
|
||||
const cacheImageDTOSForPinnedState = totalCachedImageDtos.filter((image) => image.pinned === imageDTO.pinned);
|
||||
const cachedPinnedImages = [];
|
||||
const cachedUnpinnedImages = [];
|
||||
|
||||
if (cacheImageDTOSForPinnedState.length > 1) {
|
||||
// Images are sorted by `pinned` DESC and then `created_at` DESC
|
||||
// check if the image is newer than the oldest image in the cache for either the pinned group or unpinned group
|
||||
for (let index = 0; index < totalCachedImageDtos.length; index++) {
|
||||
const image = totalCachedImageDtos[index];
|
||||
if (image?.pinned) cachedPinnedImages.push(image)
|
||||
if (!image?.pinned) cachedUnpinnedImages.push(image)
|
||||
}
|
||||
|
||||
const lastPinnedImage = cachedPinnedImages[cachedPinnedImages.length - 1];
|
||||
const lastUnpinnedImage = cachedUnpinnedImages[cachedUnpinnedImages.length - 1];
|
||||
|
||||
if (!lastPinnedImage || !lastUnpinnedImage) {
|
||||
// satisfy TS gods, we already confirmed the array has more than one image
|
||||
return false;
|
||||
}
|
||||
|
||||
if (imageDTO.pinned) {
|
||||
// if pinning or already pinned, want to look in list of pinned images
|
||||
const createdDate = new Date(imageDTO.created_at);
|
||||
const oldestImage = cacheImageDTOSForPinnedState[cacheImageDTOSForPinnedState.length - 1];
|
||||
if (!oldestImage) {
|
||||
// satisfy TS gods, we already confirmed the array has more than one image
|
||||
return false;
|
||||
}
|
||||
const oldestDate = new Date(oldestImage.created_at);
|
||||
const oldestDate = new Date(lastPinnedImage.created_at);
|
||||
return createdDate >= oldestDate;
|
||||
} else {
|
||||
// if unpinning or already unpinned, want to look in list of unpinned images
|
||||
const createdDate = new Date(imageDTO.created_at);
|
||||
const oldestDate = new Date(lastUnpinnedImage.created_at);
|
||||
return createdDate >= oldestDate;
|
||||
}
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
export const getCategories = (imageDTO: ImageDTO) => {
|
||||
|
Loading…
Reference in New Issue
Block a user