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 { ImageDTO } from 'services/api/types';
|
||||||
import { useDebounce } from 'use-debounce';
|
import { useDebounce } from 'use-debounce';
|
||||||
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
|
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
|
||||||
import { BsPinAngle, BsPinAngleFill } from 'react-icons/bs';
|
import { BsBookmarkStar, BsFillBookmarkStarFill } from 'react-icons/bs';
|
||||||
|
|
||||||
type SingleSelectionMenuItemsProps = {
|
type SingleSelectionMenuItemsProps = {
|
||||||
imageDTO: ImageDTO;
|
imageDTO: ImageDTO;
|
||||||
@ -211,11 +211,14 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
|||||||
Change Board
|
Change Board
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{imageDTO.pinned ? (
|
{imageDTO.pinned ? (
|
||||||
<MenuItem icon={<BsPinAngle />} onClickCapture={handleUnpinImage}>
|
<MenuItem icon={<BsBookmarkStar />} onClickCapture={handleUnpinImage}>
|
||||||
Unpin Image
|
Unpin Image
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
) : (
|
) : (
|
||||||
<MenuItem icon={<BsPinAngleFill />} onClickCapture={handlePinImage}>
|
<MenuItem
|
||||||
|
icon={<BsFillBookmarkStarFill />}
|
||||||
|
onClickCapture={handlePinImage}
|
||||||
|
>
|
||||||
Pin Image
|
Pin Image
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
|
@ -2,16 +2,19 @@ import { Box, Flex } from '@chakra-ui/react';
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIDndImage from 'common/components/IAIDndImage';
|
import IAIDndImage from 'common/components/IAIDndImage';
|
||||||
import IAIFillSkeleton from 'common/components/IAIFillSkeleton';
|
import IAIFillSkeleton from 'common/components/IAIFillSkeleton';
|
||||||
import { useMultiselect } from 'features/gallery/hooks/useMultiselect.ts';
|
|
||||||
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
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 {
|
import {
|
||||||
ImageDTOsDraggableData,
|
ImageDTOsDraggableData,
|
||||||
ImageDraggableData,
|
ImageDraggableData,
|
||||||
TypesafeDraggableData,
|
TypesafeDraggableData,
|
||||||
} from 'features/dnd/types';
|
} 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 {
|
interface HoverableImageProps {
|
||||||
imageName: string;
|
imageName: string;
|
||||||
@ -59,6 +62,14 @@ const GalleryImage = (props: HoverableImageProps) => {
|
|||||||
}
|
}
|
||||||
}, [imageDTO, selection, selectionCount]);
|
}, [imageDTO, selection, selectionCount]);
|
||||||
|
|
||||||
|
const [togglePin] = useChangeImagePinnedMutation();
|
||||||
|
|
||||||
|
const togglePinnedState = useCallback(() => {
|
||||||
|
if (imageDTO) {
|
||||||
|
togglePin({ imageDTO, pinned: !imageDTO.pinned });
|
||||||
|
}
|
||||||
|
}, [togglePin, imageDTO]);
|
||||||
|
|
||||||
if (!imageDTO) {
|
if (!imageDTO) {
|
||||||
return <IAIFillSkeleton />;
|
return <IAIFillSkeleton />;
|
||||||
}
|
}
|
||||||
@ -80,15 +91,17 @@ const GalleryImage = (props: HoverableImageProps) => {
|
|||||||
draggableData={draggableData}
|
draggableData={draggableData}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
minSize={0}
|
minSize={0}
|
||||||
onClickReset={handleDelete}
|
onClickReset={togglePinnedState}
|
||||||
imageSx={{ w: 'full', h: 'full' }}
|
imageSx={{ w: 'full', h: 'full' }}
|
||||||
isDropDisabled={true}
|
isDropDisabled={true}
|
||||||
isUploadDisabled={true}
|
isUploadDisabled={true}
|
||||||
thumbnail={true}
|
thumbnail={true}
|
||||||
withHoverOverlay
|
withHoverOverlay
|
||||||
resetIcon={<FaTrash />}
|
resetIcon={
|
||||||
resetTooltip="Delete image"
|
imageDTO.pinned ? <BsFillBookmarkStarFill /> : <BsBookmarkStar />
|
||||||
withResetIcon={shouldShowDeleteButton} // removed bc it's too easy to accidentally delete images
|
}
|
||||||
|
resetTooltip="Pin image"
|
||||||
|
withResetIcon={true}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -399,15 +399,18 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
body: { pinned },
|
body: { pinned },
|
||||||
}),
|
}),
|
||||||
invalidatesTags: (result, error, { imageDTO }) => [
|
invalidatesTags: (result, error, { imageDTO }) => {
|
||||||
|
const categories = getCategories(imageDTO);
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
type: 'ImageList',
|
type: 'ImageList',
|
||||||
id: getListImagesUrl({
|
id: getListImagesUrl({
|
||||||
board_id: imageDTO.board_id,
|
board_id: imageDTO.board_id,
|
||||||
categories: IMAGE_CATEGORIES,
|
categories,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
|
},
|
||||||
async onQueryStarted(
|
async onQueryStarted(
|
||||||
{ imageDTO, pinned },
|
{ imageDTO, pinned },
|
||||||
{ dispatch, queryFulfilled, getState }
|
{ dispatch, queryFulfilled, getState }
|
||||||
@ -465,27 +468,14 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
||||||
|
|
||||||
const isInDateRangeForPinnedState = getIsImageInDateRange(
|
const isInDateRange = getIsImageInDateRange(
|
||||||
currentCache.data,
|
currentCache.data,
|
||||||
updatedImage
|
updatedImage
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isInDateRangeForPinnedState) {
|
// 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 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);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCacheFullyPopulated || isInDateRangeForPinnedState) {
|
if (isCacheFullyPopulated || isInDateRange) {
|
||||||
// *upsert* to $cache
|
// *upsert* to $cache
|
||||||
patches.push(
|
patches.push(
|
||||||
dispatch(
|
dispatch(
|
||||||
|
@ -21,21 +21,35 @@ export const getIsImageInDateRange = (
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cacheImageDTOSForPinnedState = totalCachedImageDtos.filter((image) => image.pinned === imageDTO.pinned);
|
const cachedPinnedImages = [];
|
||||||
|
const cachedUnpinnedImages = [];
|
||||||
|
|
||||||
if (cacheImageDTOSForPinnedState.length > 1) {
|
for (let index = 0; index < totalCachedImageDtos.length; index++) {
|
||||||
// Images are sorted by `pinned` DESC and then `created_at` DESC
|
const image = totalCachedImageDtos[index];
|
||||||
// check if the image is newer than the oldest image in the cache for either the pinned group or unpinned group
|
if (image?.pinned) cachedPinnedImages.push(image)
|
||||||
const createdDate = new Date(imageDTO.created_at);
|
if (!image?.pinned) cachedUnpinnedImages.push(image)
|
||||||
const oldestImage = cacheImageDTOSForPinnedState[cacheImageDTOSForPinnedState.length - 1];
|
}
|
||||||
if (!oldestImage) {
|
|
||||||
|
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
|
// satisfy TS gods, we already confirmed the array has more than one image
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const oldestDate = new Date(oldestImage.created_at);
|
|
||||||
|
if (imageDTO.pinned) {
|
||||||
|
// if pinning or already pinned, want to look in list of pinned images
|
||||||
|
const createdDate = new Date(imageDTO.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 createdDate >= oldestDate;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCategories = (imageDTO: ImageDTO) => {
|
export const getCategories = (imageDTO: ImageDTO) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user