(ui) hook up toggle pin mutation with context menu for single image

This commit is contained in:
Mary Hipp 2023-08-11 11:50:54 -04:00 committed by psychedelicious
parent 04a9894e77
commit 37be827e17
3 changed files with 2829 additions and 2142 deletions

View File

@ -29,10 +29,14 @@ import {
FaShare,
FaTrash,
} from 'react-icons/fa';
import { useGetImageMetadataQuery } from 'services/api/endpoints/images';
import {
useChangeImagePinnedMutation,
useGetImageMetadataQuery,
} from 'services/api/endpoints/images';
import { ImageDTO } from 'services/api/types';
import { useDebounce } from 'use-debounce';
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
import { BsPinAngle, BsPinAngleFill } from 'react-icons/bs';
type SingleSelectionMenuItemsProps = {
imageDTO: ImageDTO;
@ -59,6 +63,8 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
: debouncedMetadataQueryArg ?? skipToken
);
const [togglePin] = useChangeImagePinnedMutation();
const { isClipboardAPIAvailable, copyImageToClipboard } =
useCopyImageToClipboard();
@ -127,6 +133,14 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
copyImageToClipboard(imageDTO.image_url);
}, [copyImageToClipboard, imageDTO.image_url]);
const handlePinImage = useCallback(() => {
togglePin({ imageName: imageDTO.image_name, pinned: true });
}, [togglePin, imageDTO.image_name]);
const handleUnpinImage = useCallback(() => {
togglePin({ imageName: imageDTO.image_name, pinned: false });
}, [togglePin, imageDTO.image_name]);
return (
<>
<MenuItem
@ -196,6 +210,15 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
<MenuItem icon={<FaFolder />} onClickCapture={handleChangeBoard}>
Change Board
</MenuItem>
{imageDTO.pinned ? (
<MenuItem icon={<BsPinAngle />} onClickCapture={handleUnpinImage}>
Unpin Image
</MenuItem>
) : (
<MenuItem icon={<BsPinAngleFill />} onClickCapture={handlePinImage}>
Pin Image
</MenuItem>
)}
<MenuItem
sx={{ color: 'error.600', _dark: { color: 'error.300' } }}
icon={<FaTrash />}

View File

@ -296,11 +296,11 @@ export const imagesApi = api.injectEndpoints({
imageDTO.image_category
)
? boardsApi.endpoints.getBoardImagesTotal.select(
imageDTO.board_id ?? 'none'
)(getState())
imageDTO.board_id ?? 'none'
)(getState())
: boardsApi.endpoints.getBoardAssetsTotal.select(
imageDTO.board_id ?? 'none'
)(getState());
imageDTO.board_id ?? 'none'
)(getState());
// IF it eligible for insertion into existing $cache
// "eligible" means either:
@ -387,6 +387,54 @@ export const imagesApi = api.injectEndpoints({
}
},
}),
/**
* Change an image's `pinned` state.
*/
changeImagePinned: build.mutation<
ImageDTO,
{ imageName: string; pinned: boolean }
>({
query: ({ imageName, pinned }) => ({
url: `images/i/${imageName}`,
method: 'PATCH',
body: { pinned },
}),
// invalidatesTags: (result, error, { imageDTO }) => [
// { type: 'BoardImagesTotal', id: imageDTO.board_id ?? 'none' },
// { type: 'BoardAssetsTotal', id: imageDTO.board_id ?? 'none' },
// ],
async onQueryStarted(
{ imageName, pinned },
{ dispatch, queryFulfilled, getState }
) {
/**
* Cache changes for `changeImageSessionId`:
* - *update* getImageDTO
*/
// Store patches so we can undo if the query fails
const patches: PatchCollection[] = [];
// *update* getImageDTO
patches.push(
dispatch(
imagesApi.util.updateQueryData(
'getImageDTO',
imageName,
(draft) => {
Object.assign(draft, { pinned });
}
)
)
);
try {
await queryFulfilled;
} catch {
patches.forEach((patchResult) => patchResult.undo());
}
},
}),
uploadImage: build.mutation<
ImageDTO,
{
@ -726,11 +774,11 @@ export const imagesApi = api.injectEndpoints({
imageDTO.image_category
)
? boardsApi.endpoints.getBoardImagesTotal.select(
imageDTO.board_id ?? 'none'
)(getState())
imageDTO.board_id ?? 'none'
)(getState())
: boardsApi.endpoints.getBoardAssetsTotal.select(
imageDTO.board_id ?? 'none'
)(getState());
imageDTO.board_id ?? 'none'
)(getState());
const isCacheFullyPopulated =
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
@ -846,11 +894,11 @@ export const imagesApi = api.injectEndpoints({
imageDTO.image_category
)
? boardsApi.endpoints.getBoardImagesTotal.select(
imageDTO.board_id ?? 'none'
)(getState())
imageDTO.board_id ?? 'none'
)(getState())
: boardsApi.endpoints.getBoardAssetsTotal.select(
imageDTO.board_id ?? 'none'
)(getState());
imageDTO.board_id ?? 'none'
)(getState());
const isCacheFullyPopulated =
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
@ -973,11 +1021,11 @@ export const imagesApi = api.injectEndpoints({
imageDTO.image_category
)
? boardsApi.endpoints.getBoardImagesTotal.select(
new_board_id ?? 'none'
)(getState())
new_board_id ?? 'none'
)(getState())
: boardsApi.endpoints.getBoardAssetsTotal.select(
new_board_id ?? 'none'
)(getState());
new_board_id ?? 'none'
)(getState());
const isCacheFullyPopulated =
currentCache.data &&
@ -1104,11 +1152,11 @@ export const imagesApi = api.injectEndpoints({
imageDTO.image_category
)
? boardsApi.endpoints.getBoardImagesTotal.select(
imageDTO.board_id ?? 'none'
)(getState())
imageDTO.board_id ?? 'none'
)(getState())
: boardsApi.endpoints.getBoardAssetsTotal.select(
imageDTO.board_id ?? 'none'
)(getState());
imageDTO.board_id ?? 'none'
)(getState());
const isCacheFullyPopulated =
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
@ -1158,6 +1206,7 @@ export const {
useRemoveImageFromBoardMutation,
useChangeImageIsIntermediateMutation,
useChangeImageSessionIdMutation,
useChangeImagePinnedMutation,
useDeleteBoardAndImagesMutation,
useDeleteBoardMutation,
} = imagesApi;

File diff suppressed because it is too large Load Diff