(ui) WIP trying to get all cache scenarios working smoothly, fix assets

This commit is contained in:
Mary Hipp 2023-08-11 16:14:47 -04:00 committed by psychedelicious
parent 0a71d6baa1
commit 767a612746
4 changed files with 67 additions and 47 deletions

View File

@ -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>
)}

View File

@ -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>

View File

@ -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(

View File

@ -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) => {