mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
(ui) hook up toggle pin mutation with context menu for single image
This commit is contained in:
parent
04a9894e77
commit
37be827e17
@ -29,10 +29,14 @@ import {
|
|||||||
FaShare,
|
FaShare,
|
||||||
FaTrash,
|
FaTrash,
|
||||||
} from 'react-icons/fa';
|
} 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 { 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';
|
||||||
|
|
||||||
type SingleSelectionMenuItemsProps = {
|
type SingleSelectionMenuItemsProps = {
|
||||||
imageDTO: ImageDTO;
|
imageDTO: ImageDTO;
|
||||||
@ -59,6 +63,8 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
|||||||
: debouncedMetadataQueryArg ?? skipToken
|
: debouncedMetadataQueryArg ?? skipToken
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [togglePin] = useChangeImagePinnedMutation();
|
||||||
|
|
||||||
const { isClipboardAPIAvailable, copyImageToClipboard } =
|
const { isClipboardAPIAvailable, copyImageToClipboard } =
|
||||||
useCopyImageToClipboard();
|
useCopyImageToClipboard();
|
||||||
|
|
||||||
@ -127,6 +133,14 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
|||||||
copyImageToClipboard(imageDTO.image_url);
|
copyImageToClipboard(imageDTO.image_url);
|
||||||
}, [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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
@ -196,6 +210,15 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
|||||||
<MenuItem icon={<FaFolder />} onClickCapture={handleChangeBoard}>
|
<MenuItem icon={<FaFolder />} onClickCapture={handleChangeBoard}>
|
||||||
Change Board
|
Change Board
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
{imageDTO.pinned ? (
|
||||||
|
<MenuItem icon={<BsPinAngle />} onClickCapture={handleUnpinImage}>
|
||||||
|
Unpin Image
|
||||||
|
</MenuItem>
|
||||||
|
) : (
|
||||||
|
<MenuItem icon={<BsPinAngleFill />} onClickCapture={handlePinImage}>
|
||||||
|
Pin Image
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
<MenuItem
|
<MenuItem
|
||||||
sx={{ color: 'error.600', _dark: { color: 'error.300' } }}
|
sx={{ color: 'error.600', _dark: { color: 'error.300' } }}
|
||||||
icon={<FaTrash />}
|
icon={<FaTrash />}
|
||||||
|
@ -296,11 +296,11 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
imageDTO.image_category
|
imageDTO.image_category
|
||||||
)
|
)
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
// IF it eligible for insertion into existing $cache
|
// IF it eligible for insertion into existing $cache
|
||||||
// "eligible" means either:
|
// "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<
|
uploadImage: build.mutation<
|
||||||
ImageDTO,
|
ImageDTO,
|
||||||
{
|
{
|
||||||
@ -726,11 +774,11 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
imageDTO.image_category
|
imageDTO.image_category
|
||||||
)
|
)
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
||||||
@ -846,11 +894,11 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
imageDTO.image_category
|
imageDTO.image_category
|
||||||
)
|
)
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
||||||
@ -973,11 +1021,11 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
imageDTO.image_category
|
imageDTO.image_category
|
||||||
)
|
)
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
new_board_id ?? 'none'
|
new_board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
||||||
new_board_id ?? 'none'
|
new_board_id ?? 'none'
|
||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data &&
|
currentCache.data &&
|
||||||
@ -1104,11 +1152,11 @@ export const imagesApi = api.injectEndpoints({
|
|||||||
imageDTO.image_category
|
imageDTO.image_category
|
||||||
)
|
)
|
||||||
? boardsApi.endpoints.getBoardImagesTotal.select(
|
? boardsApi.endpoints.getBoardImagesTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState())
|
)(getState())
|
||||||
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
: boardsApi.endpoints.getBoardAssetsTotal.select(
|
||||||
imageDTO.board_id ?? 'none'
|
imageDTO.board_id ?? 'none'
|
||||||
)(getState());
|
)(getState());
|
||||||
|
|
||||||
const isCacheFullyPopulated =
|
const isCacheFullyPopulated =
|
||||||
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
currentCache.data && currentCache.data.ids.length >= (total ?? 0);
|
||||||
@ -1158,6 +1206,7 @@ export const {
|
|||||||
useRemoveImageFromBoardMutation,
|
useRemoveImageFromBoardMutation,
|
||||||
useChangeImageIsIntermediateMutation,
|
useChangeImageIsIntermediateMutation,
|
||||||
useChangeImageSessionIdMutation,
|
useChangeImageSessionIdMutation,
|
||||||
|
useChangeImagePinnedMutation,
|
||||||
useDeleteBoardAndImagesMutation,
|
useDeleteBoardAndImagesMutation,
|
||||||
useDeleteBoardMutation,
|
useDeleteBoardMutation,
|
||||||
} = imagesApi;
|
} = imagesApi;
|
||||||
|
4857
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
4857
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user