feat(ui): wip again sry lol

This commit is contained in:
psychedelicious 2023-07-10 21:42:47 +10:00
parent 2ef5919475
commit 58cb5fefd0
12 changed files with 157 additions and 189 deletions

View File

@ -82,7 +82,7 @@ const DragPreview = (props: OverlayDragImageProps) => {
);
}
if (props.dragData.payloadType === 'BATCH_SELECTION') {
if (props.dragData.payloadType === 'IMAGE_NAMES') {
return (
<Flex
sx={{
@ -95,26 +95,7 @@ const DragPreview = (props: OverlayDragImageProps) => {
...STYLES,
}}
>
<Heading>{batchSelectionCount}</Heading>
<Heading size="sm">Images</Heading>
</Flex>
);
}
if (props.dragData.payloadType === 'GALLERY_SELECTION') {
return (
<Flex
sx={{
cursor: 'none',
userSelect: 'none',
position: 'relative',
alignItems: 'center',
justifyContent: 'center',
flexDir: 'column',
...STYLES,
}}
>
<Heading>{gallerySelectionCount}</Heading>
<Heading>{props.dragData.payload.image_names.length}</Heading>
<Heading size="sm">Images</Heading>
</Flex>
);

View File

@ -7,7 +7,7 @@ import {
useSensors,
} from '@dnd-kit/core';
import { snapCenterToCursor } from '@dnd-kit/modifiers';
import { imageDropped } from 'app/store/middleware/listenerMiddleware/listeners/imageDropped';
import { dndDropped } from 'app/store/middleware/listenerMiddleware/listeners/imageDropped';
import { useAppDispatch } from 'app/store/storeHooks';
import { AnimatePresence, motion } from 'framer-motion';
import { PropsWithChildren, memo, useCallback, useState } from 'react';
@ -42,7 +42,7 @@ const ImageDndContext = (props: ImageDndContextProps) => {
if (!activeData || !overData) {
return;
}
dispatch(imageDropped({ overData, activeData }));
dispatch(dndDropped({ overData, activeData }));
setActiveDragData(null);
},
[dispatch]

View File

@ -77,18 +77,14 @@ export type ImageDraggableData = BaseDragData & {
payload: { imageDTO: ImageDTO };
};
export type GallerySelectionDraggableData = BaseDragData & {
payloadType: 'GALLERY_SELECTION';
};
export type BatchSelectionDraggableData = BaseDragData & {
payloadType: 'BATCH_SELECTION';
export type ImageNamesDraggableData = BaseDragData & {
payloadType: 'IMAGE_NAMES';
payload: { image_names: string[] };
};
export type TypesafeDraggableData =
| ImageDraggableData
| GallerySelectionDraggableData
| BatchSelectionDraggableData;
| ImageNamesDraggableData;
interface UseDroppableTypesafeArguments
extends Omit<UseDroppableArguments, 'data'> {
@ -159,13 +155,11 @@ export const isValidDrop = (
case 'SET_NODES_IMAGE':
return payloadType === 'IMAGE_DTO';
case 'SET_MULTI_NODES_IMAGE':
return payloadType === 'IMAGE_DTO' || 'GALLERY_SELECTION';
return payloadType === 'IMAGE_DTO' || 'IMAGE_NAMES';
case 'ADD_TO_BATCH':
return payloadType === 'IMAGE_DTO' || 'GALLERY_SELECTION';
return payloadType === 'IMAGE_DTO' || 'IMAGE_NAMES';
case 'MOVE_BOARD':
return (
payloadType === 'IMAGE_DTO' || 'GALLERY_SELECTION' || 'BATCH_SELECTION'
);
return payloadType === 'IMAGE_DTO' || 'IMAGE_NAMES';
default:
return false;
}

View File

@ -1,9 +1,7 @@
import { createAction } from '@reduxjs/toolkit';
import { log } from 'app/logging/useLogger';
import { imagesAddedToBatch } from 'features/batch/store/batchSlice';
import { imagesApi } from 'services/api/endpoints/images';
import { boardImageNamesReceived } from 'services/api/thunks/boardImages';
import { receivedListOfImages } from 'services/api/thunks/image';
import { startAppListening } from '..';
const moduleLog = log.child({ namespace: 'batch' });
@ -27,26 +25,7 @@ export const addAddBoardToBatchListener = () => {
action.meta.requestId === requestId
);
moduleLog.debug({ data: { payload } }, 'boardImageNamesReceived');
const { requestId: requestId2 } = dispatch(
receivedListOfImages(payload.image_names)
);
const [{ payload: payload2 }] = await take(
(action): action is ReturnType<typeof receivedListOfImages.fulfilled> =>
action.meta.requestId === requestId2
);
moduleLog.debug({ data: { payload2 } }, 'receivedListOfImages');
dispatch(imagesAddedToBatch(payload2.image_dtos));
payload2.image_dtos.forEach((image) => {
dispatch(
imagesApi.util.upsertQueryData('getImageDTO', image.image_name, image)
);
});
dispatch(imagesAddedToBatch(payload.image_names));
},
});
};

View File

@ -10,7 +10,6 @@ import {
} from 'features/batch/store/batchSlice';
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice';
import { selectSelectedImages } from 'features/gallery/store/gallerySelectors';
import { imageSelected } from 'features/gallery/store/gallerySlice';
import {
fieldValueChanged,
@ -22,15 +21,15 @@ import { startAppListening } from '../';
const moduleLog = log.child({ namespace: 'dnd' });
export const imageDropped = createAction<{
export const dndDropped = createAction<{
overData: TypesafeDroppableData;
activeData: TypesafeDraggableData;
}>('dnd/imageDropped');
}>('dnd/dndDropped');
export const addImageDroppedListener = () => {
startAppListening({
actionCreator: imageDropped,
effect: (action, { dispatch, getState }) => {
actionCreator: dndDropped,
effect: async (action, { dispatch, getState, take }) => {
const { activeData, overData } = action.payload;
const state = getState();
@ -46,6 +45,7 @@ export const addImageDroppedListener = () => {
activeData.payload.imageDTO
) {
dispatch(imageSelected(activeData.payload.imageDTO.image_name));
return;
}
// set initial image
@ -55,6 +55,7 @@ export const addImageDroppedListener = () => {
activeData.payload.imageDTO
) {
dispatch(initialImageChanged(activeData.payload.imageDTO));
return;
}
// add image to batch
@ -63,16 +64,18 @@ export const addImageDroppedListener = () => {
activeData.payloadType === 'IMAGE_DTO' &&
activeData.payload.imageDTO
) {
dispatch(imageAddedToBatch(activeData.payload.imageDTO));
dispatch(imageAddedToBatch(activeData.payload.imageDTO.image_name));
return;
}
// add multiple images to batch
if (
overData.actionType === 'ADD_TO_BATCH' &&
activeData.payloadType === 'GALLERY_SELECTION'
activeData.payloadType === 'IMAGE_NAMES'
) {
const images = selectSelectedImages(state);
dispatch(imagesAddedToBatch(images));
dispatch(imagesAddedToBatch(activeData.payload.image_names));
return;
}
// set control image
@ -88,6 +91,7 @@ export const addImageDroppedListener = () => {
controlNetId,
})
);
return;
}
// set canvas image
@ -97,6 +101,7 @@ export const addImageDroppedListener = () => {
activeData.payload.imageDTO
) {
dispatch(setInitialCanvasImage(activeData.payload.imageDTO));
return;
}
// set nodes image
@ -113,6 +118,7 @@ export const addImageDroppedListener = () => {
value: activeData.payload.imageDTO,
})
);
return;
}
// set multiple nodes images (single image handler)
@ -129,23 +135,25 @@ export const addImageDroppedListener = () => {
value: [activeData.payload.imageDTO],
})
);
return;
}
// set multiple nodes images (multiple images handler)
if (
overData.actionType === 'SET_MULTI_NODES_IMAGE' &&
activeData.payloadType === 'GALLERY_SELECTION'
activeData.payloadType === 'IMAGE_NAMES'
) {
const { fieldName, nodeId } = overData.context;
dispatch(
imageCollectionFieldValueChanged({
nodeId,
fieldName,
value: state.gallery.selection.map((image_name) => ({
value: activeData.payload.image_names.map((image_name) => ({
image_name,
})),
})
);
return;
}
// add image to board
@ -163,6 +171,7 @@ export const addImageDroppedListener = () => {
board_id: boardId,
})
);
return;
}
// remove image from board
@ -176,68 +185,69 @@ export const addImageDroppedListener = () => {
dispatch(
boardImagesApi.endpoints.deleteBoardImage.initiate({ image_name })
);
return;
}
// add gallery selection to board
if (
overData.actionType === 'MOVE_BOARD' &&
activeData.payloadType === 'GALLERY_SELECTION' &&
activeData.payloadType === 'IMAGE_NAMES' &&
overData.context.boardId
) {
console.log('adding gallery selection to board');
const board_id = overData.context.boardId;
const image_names = state.gallery.selection;
dispatch(
boardImagesApi.endpoints.addManyBoardImages.initiate({
board_id,
image_names,
image_names: activeData.payload.image_names,
})
);
return;
}
// remove gallery selection from board
if (
overData.actionType === 'MOVE_BOARD' &&
activeData.payloadType === 'GALLERY_SELECTION' &&
activeData.payloadType === 'IMAGE_NAMES' &&
overData.context.boardId === null
) {
console.log('removing gallery selection to board');
const image_names = state.gallery.selection;
dispatch(
boardImagesApi.endpoints.deleteManyBoardImages.initiate({
image_names,
image_names: activeData.payload.image_names,
})
);
return;
}
// add batch selection to board
if (
overData.actionType === 'MOVE_BOARD' &&
activeData.payloadType === 'BATCH_SELECTION' &&
activeData.payloadType === 'IMAGE_NAMES' &&
overData.context.boardId
) {
const board_id = overData.context.boardId;
const image_names = state.batch.selection;
dispatch(
boardImagesApi.endpoints.addManyBoardImages.initiate({
board_id,
image_names,
image_names: activeData.payload.image_names,
})
);
return;
}
// remove batch selection from board
if (
overData.actionType === 'MOVE_BOARD' &&
activeData.payloadType === 'BATCH_SELECTION' &&
activeData.payloadType === 'IMAGE_NAMES' &&
overData.context.boardId === null
) {
const image_names = state.batch.selection;
dispatch(
boardImagesApi.endpoints.deleteManyBoardImages.initiate({
image_names,
image_names: activeData.payload.image_names,
})
);
return;
}
},
});

View File

@ -1,4 +1,4 @@
import { Box } from '@chakra-ui/react';
import { Box, Spinner } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { TypesafeDraggableData } from 'app/components/ImageDnd/typesafeDnd';
import { stateSelector } from 'app/store/store';
@ -13,54 +13,57 @@ import {
} from 'features/batch/store/batchSlice';
import ImageContextMenu from 'features/gallery/components/ImageContextMenu';
import { MouseEvent, memo, useCallback, useMemo } from 'react';
import { ImageDTO } from 'services/api/types';
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
const makeSelector = (image_name: string) =>
createSelector(
[stateSelector],
(state) => ({
selectionCount: state.batch.selection.length,
selection: state.batch.selection,
isSelected: state.batch.selection.includes(image_name),
}),
defaultSelectorOptions
);
type BatchImageProps = {
imageDTO: ImageDTO;
imageName: string;
};
const BatchImage = (props: BatchImageProps) => {
const dispatch = useAppDispatch();
const { imageDTO } = props;
const { image_name } = imageDTO;
const { imageName } = props;
const selector = useMemo(() => makeSelector(image_name), [image_name]);
const { currentData: imageDTO } = useGetImageDTOQuery(imageName);
const { isSelected, selectionCount } = useAppSelector(selector);
const selector = useMemo(() => makeSelector(imageName), [imageName]);
const { isSelected, selectionCount, selection } = useAppSelector(selector);
const handleClickRemove = useCallback(() => {
dispatch(imageRemovedFromBatch(image_name));
}, [dispatch, image_name]);
dispatch(imageRemovedFromBatch(imageName));
}, [dispatch, imageName]);
const handleClick = useCallback(
(e: MouseEvent<HTMLDivElement>) => {
if (e.shiftKey) {
dispatch(batchImageRangeEndSelected(image_name));
dispatch(batchImageRangeEndSelected(imageName));
} else if (e.ctrlKey || e.metaKey) {
dispatch(batchImageSelectionToggled(image_name));
dispatch(batchImageSelectionToggled(imageName));
} else {
dispatch(batchImageSelected(image_name));
dispatch(batchImageSelected(imageName));
}
},
[dispatch, image_name]
[dispatch, imageName]
);
const draggableData = useMemo<TypesafeDraggableData | undefined>(() => {
if (selectionCount > 1) {
return {
id: 'batch',
payloadType: 'BATCH_SELECTION',
payloadType: 'IMAGE_NAMES',
payload: { image_names: selection },
};
}
@ -71,15 +74,19 @@ const BatchImage = (props: BatchImageProps) => {
payload: { imageDTO },
};
}
}, [imageDTO, selectionCount]);
}, [imageDTO, selection, selectionCount]);
if (!imageDTO) {
return <Spinner />;
}
return (
<Box sx={{ w: 'full', h: 'full', touchAction: 'none' }}>
<ImageContextMenu image={imageDTO}>
<ImageContextMenu imageDTO={imageDTO}>
{(ref) => (
<Box
position="relative"
key={image_name}
key={imageName}
userSelect="none"
ref={ref}
sx={{

View File

@ -1,32 +1,22 @@
import {
PayloadAction,
createEntityAdapter,
createSlice,
} from '@reduxjs/toolkit';
import { dateComparator } from 'common/util/dateComparator';
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
import { uniq } from 'lodash-es';
import { imageDeleted } from 'services/api/thunks/image';
import { ImageDTO } from 'services/api/types';
export const batchImagesAdapter = createEntityAdapter<ImageDTO>({
selectId: (image) => image.image_name,
sortComparer: (a, b) => dateComparator(b.updated_at, a.updated_at),
});
type AdditionalBatchState = {
type BatchState = {
isEnabled: boolean;
imageNames: string[];
asInitialImage: boolean;
controlNets: string[];
selection: string[];
};
export const initialBatchState =
batchImagesAdapter.getInitialState<AdditionalBatchState>({
isEnabled: false,
asInitialImage: false,
controlNets: [],
selection: [],
});
export const initialBatchState: BatchState = {
isEnabled: false,
imageNames: [],
asInitialImage: false,
controlNets: [],
selection: [],
};
const batch = createSlice({
name: 'batch',
@ -35,20 +25,24 @@ const batch = createSlice({
isEnabledChanged: (state, action: PayloadAction<boolean>) => {
state.isEnabled = action.payload;
},
imageAddedToBatch: (state, action: PayloadAction<ImageDTO>) => {
batchImagesAdapter.addOne(state, action.payload);
imageAddedToBatch: (state, action: PayloadAction<string>) => {
state.imageNames.push(action.payload);
},
imagesAddedToBatch: (state, action: PayloadAction<ImageDTO[]>) => {
batchImagesAdapter.addMany(state, action.payload);
imagesAddedToBatch: (state, action: PayloadAction<string[]>) => {
state.imageNames = state.imageNames.concat(action.payload);
},
imageRemovedFromBatch: (state, action: PayloadAction<string>) => {
batchImagesAdapter.removeOne(state, action.payload);
state.imageNames = state.imageNames.filter(
(imageName) => action.payload !== imageName
);
state.selection = state.selection.filter(
(imageName) => action.payload !== imageName
);
},
imagesRemovedFromBatch: (state, action: PayloadAction<string[]>) => {
batchImagesAdapter.removeMany(state, action.payload);
state.imageNames = state.imageNames.filter(
(imageName) => !action.payload.includes(imageName)
);
state.selection = state.selection.filter(
(imageName) => !action.payload.includes(imageName)
);
@ -57,21 +51,20 @@ const batch = createSlice({
const rangeEndImageName = action.payload;
const lastSelectedImage = state.selection[state.selection.length - 1];
const images = batchImagesAdapter.getSelectors().selectAll(state);
const lastClickedIndex = images.findIndex(
(n) => n.image_name === lastSelectedImage
const { imageNames } = state;
const lastClickedIndex = imageNames.findIndex(
(n) => n === lastSelectedImage
);
const currentClickedIndex = images.findIndex(
(n) => n.image_name === rangeEndImageName
const currentClickedIndex = imageNames.findIndex(
(n) => n === rangeEndImageName
);
if (lastClickedIndex > -1 && currentClickedIndex > -1) {
// We have a valid range!
const start = Math.min(lastClickedIndex, currentClickedIndex);
const end = Math.max(lastClickedIndex, currentClickedIndex);
const imagesToSelect = images
.slice(start, end + 1)
.map((i) => i.image_name);
const imagesToSelect = imageNames.slice(start, end + 1);
state.selection = uniq(state.selection.concat(imagesToSelect));
}
@ -91,10 +84,10 @@ const batch = createSlice({
batchImageSelected: (state, action: PayloadAction<string | null>) => {
state.selection = action.payload
? [action.payload]
: [String(state.ids[0])];
: [String(state.imageNames[0])];
},
batchReset: (state) => {
batchImagesAdapter.removeAll(state);
state.imageNames = [];
state.selection = [];
},
asInitialImageToggled: (state) => {
@ -120,7 +113,9 @@ const batch = createSlice({
},
extraReducers: (builder) => {
builder.addCase(imageDeleted.fulfilled, (state, action) => {
batchImagesAdapter.removeOne(state, action.meta.arg.image_name);
state.imageNames = state.imageNames.filter(
(imageName) => imageName !== action.meta.arg.image_name
);
state.selection = state.selection.filter(
(imageName) => imageName !== action.meta.arg.image_name
);

View File

@ -11,7 +11,6 @@ import { stateSelector } from 'app/store/store';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
import BatchImage from 'features/batch/components/BatchImage';
import { batchImagesAdapter } from 'features/batch/store/batchSlice';
import { VirtuosoGrid } from 'react-virtuoso';
import ItemContainer from './ItemContainer';
import ListContainer from './ListContainer';
@ -19,9 +18,8 @@ import ListContainer from './ListContainer';
const selector = createSelector(
[stateSelector],
(state) => {
const images = batchImagesAdapter.getSelectors().selectAll(state.batch);
return {
images,
imageNames: state.batch.imageNames,
};
},
defaultSelectorOptions
@ -45,7 +43,7 @@ const BatchGrid = () => {
},
});
const { images } = useAppSelector(selector);
const { imageNames } = useAppSelector(selector);
useEffect(() => {
const { current: root } = rootRef;
@ -60,22 +58,19 @@ const BatchGrid = () => {
return () => osInstance()?.destroy();
}, [scroller, initialize, osInstance]);
if (images.length) {
if (imageNames.length) {
return (
<Box ref={rootRef} data-overlayscrollbars="" h="100%">
<VirtuosoGrid
style={{ height: '100%' }}
data={images}
data={imageNames}
components={{
Item: ItemContainer,
List: ListContainer,
}}
scrollerRef={setScroller}
itemContent={(index, item) => (
<BatchImage
key={`${item.image_name}-${item.thumbnail_url}`}
imageDTO={item}
/>
itemContent={(index, imageName) => (
<BatchImage key={imageName} imageName={imageName} />
)}
/>
</Box>

View File

@ -10,7 +10,7 @@ import GenericBoard from './GenericBoard';
const selector = createSelector(stateSelector, (state) => {
return {
count: state.batch.ids.length,
count: state.batch.imageNames.length,
};
});

View File

@ -17,6 +17,7 @@ export const makeSelector = (image_name: string) =>
({ gallery }) => ({
isSelected: gallery.selection.includes(image_name),
selectionCount: gallery.selection.length,
selection: gallery.selection,
}),
defaultSelectorOptions
);
@ -33,7 +34,8 @@ const GalleryImage = (props: HoverableImageProps) => {
const localSelector = useMemo(() => makeSelector(image_name), [image_name]);
const { isSelected, selectionCount } = useAppSelector(localSelector);
const { isSelected, selectionCount, selection } =
useAppSelector(localSelector);
const handleClick = useCallback(
(e: MouseEvent<HTMLDivElement>) => {
@ -65,7 +67,8 @@ const GalleryImage = (props: HoverableImageProps) => {
if (selectionCount > 1) {
return {
id: 'gallery-image',
payloadType: 'GALLERY_SELECTION',
payloadType: 'IMAGE_NAMES',
payload: { image_names: selection },
};
}
@ -76,11 +79,11 @@ const GalleryImage = (props: HoverableImageProps) => {
payload: { imageDTO },
};
}
}, [imageDTO, selectionCount]);
}, [imageDTO, selection, selectionCount]);
return (
<Box sx={{ w: 'full', h: 'full', touchAction: 'none' }}>
<ImageContextMenu image={imageDTO}>
<ImageContextMenu imageDTO={imageDTO}>
{(ref) => (
<Box
position="relative"

View File

@ -40,11 +40,11 @@ import { AddImageToBoardContext } from '../../../app/contexts/AddImageToBoardCon
import { sentImageToCanvas, sentImageToImg2Img } from '../store/actions';
type Props = {
image: ImageDTO;
imageDTO: ImageDTO;
children: ContextMenuProps<HTMLDivElement>['children'];
};
const ImageContextMenu = ({ image, children }: Props) => {
const ImageContextMenu = ({ imageDTO, children }: Props) => {
const selector = useMemo(
() =>
createSelector(
@ -53,13 +53,13 @@ const ImageContextMenu = ({ image, children }: Props) => {
const isBatch = gallery.selectedBoardId === 'batch';
const selection = isBatch ? batch.selection : gallery.selection;
const isInBatch = batch.ids.includes(image.image_name);
const isInBatch = batch.imageNames.includes(imageDTO.image_name);
return { selection, isInBatch };
},
defaultSelectorOptions
),
[image.image_name]
[imageDTO.image_name]
);
const { selection, isInBatch } = useAppSelector(selector);
const dispatch = useAppDispatch();
@ -73,11 +73,11 @@ const ImageContextMenu = ({ image, children }: Props) => {
const { onClickAddToBoard } = useContext(AddImageToBoardContext);
const handleDelete = useCallback(() => {
if (!image) {
if (!imageDTO) {
return;
}
dispatch(imageToDeleteSelected(image));
}, [dispatch, image]);
dispatch(imageToDeleteSelected(imageDTO));
}, [dispatch, imageDTO]);
const { recallBothPrompts, recallSeed, recallAllParameters } =
useRecallParameters();
@ -89,23 +89,23 @@ const ImageContextMenu = ({ image, children }: Props) => {
// Recall parameters handlers
const handleRecallPrompt = useCallback(() => {
recallBothPrompts(
image.metadata?.positive_conditioning,
image.metadata?.negative_conditioning
imageDTO.metadata?.positive_conditioning,
imageDTO.metadata?.negative_conditioning
);
}, [
image.metadata?.negative_conditioning,
image.metadata?.positive_conditioning,
imageDTO.metadata?.negative_conditioning,
imageDTO.metadata?.positive_conditioning,
recallBothPrompts,
]);
const handleRecallSeed = useCallback(() => {
recallSeed(image.metadata?.seed);
}, [image, recallSeed]);
recallSeed(imageDTO.metadata?.seed);
}, [imageDTO, recallSeed]);
const handleSendToImageToImage = useCallback(() => {
dispatch(sentImageToImg2Img());
dispatch(initialImageSelected(image));
}, [dispatch, image]);
dispatch(initialImageSelected(imageDTO));
}, [dispatch, imageDTO]);
// const handleRecallInitialImage = useCallback(() => {
// recallInitialImage(image.metadata.invokeai?.node?.image);
@ -113,7 +113,7 @@ const ImageContextMenu = ({ image, children }: Props) => {
const handleSendToCanvas = () => {
dispatch(sentImageToCanvas());
dispatch(setInitialCanvasImage(image));
dispatch(setInitialCanvasImage(imageDTO));
dispatch(resizeAndScaleCanvas());
dispatch(setActiveTab('unifiedCanvas'));
@ -126,8 +126,8 @@ const ImageContextMenu = ({ image, children }: Props) => {
};
const handleUseAllParameters = useCallback(() => {
recallAllParameters(image);
}, [image, recallAllParameters]);
recallAllParameters(imageDTO);
}, [imageDTO, recallAllParameters]);
const handleLightBox = () => {
// dispatch(setCurrentImage(image));
@ -135,39 +135,43 @@ const ImageContextMenu = ({ image, children }: Props) => {
};
const handleAddToBoard = useCallback(() => {
onClickAddToBoard(image);
}, [image, onClickAddToBoard]);
onClickAddToBoard(imageDTO);
}, [imageDTO, onClickAddToBoard]);
const handleRemoveFromBoard = useCallback(() => {
if (!image.board_id) {
if (!imageDTO.board_id) {
return;
}
deleteBoardImage({ image_name: image.image_name });
}, [deleteBoardImage, image.board_id, image.image_name]);
deleteBoardImage({ image_name: imageDTO.image_name });
}, [deleteBoardImage, imageDTO.board_id, imageDTO.image_name]);
const handleAddSelectionToBoard = useCallback(() => {
addManyBoardImages({ board_id, image_names: selection });
}, [addManyBoardImages, selection]);
// addManyBoardImages({ board_id, image_names: selection });
}, []);
const handleRemoveSelectionFromBoard = useCallback(() => {
deleteManyBoardImages({ image_names: selection });
}, [deleteManyBoardImages, selection]);
const handleOpenInNewTab = useCallback(() => {
window.open(image.image_url, '_blank');
}, [image.image_url]);
window.open(imageDTO.image_url, '_blank');
}, [imageDTO.image_url]);
const handleAddSelectionToBatch = useCallback(() => {
dispatch(selectionAddedToBatch({ images_names: selection }));
}, [dispatch, selection]);
const handleAddToBatch = useCallback(() => {
dispatch(imageAddedToBatch(image));
}, [dispatch, image]);
dispatch(imageAddedToBatch(imageDTO.image_name));
}, [dispatch, imageDTO]);
const handleRemoveFromBatch = useCallback(() => {
dispatch(imageRemovedFromBatch(image.image_name));
}, [dispatch, image]);
dispatch(imageRemovedFromBatch(imageDTO.image_name));
}, [dispatch, imageDTO]);
if (!imageDTO) {
return null;
}
return (
<ContextMenu<HTMLDivElement>
@ -191,7 +195,7 @@ const ImageContextMenu = ({ image, children }: Props) => {
icon={<IoArrowUndoCircleOutline />}
onClickCapture={handleRecallPrompt}
isDisabled={
image?.metadata?.positive_conditioning === undefined
imageDTO?.metadata?.positive_conditioning === undefined
}
>
{t('parameters.usePrompt')}
@ -200,7 +204,7 @@ const ImageContextMenu = ({ image, children }: Props) => {
<MenuItem
icon={<IoArrowUndoCircleOutline />}
onClickCapture={handleRecallSeed}
isDisabled={image?.metadata?.seed === undefined}
isDisabled={imageDTO?.metadata?.seed === undefined}
>
{t('parameters.useSeed')}
</MenuItem>
@ -210,7 +214,7 @@ const ImageContextMenu = ({ image, children }: Props) => {
isDisabled={
// what should these be
!['t2l', 'l2l', 'inpaint'].includes(
String(image?.metadata?.type)
String(imageDTO?.metadata?.type)
)
}
>
@ -241,9 +245,9 @@ const ImageContextMenu = ({ image, children }: Props) => {
{isInBatch ? 'Remove from Batch' : 'Add to Batch'}
</MenuItem>
<MenuItem icon={<FaFolder />} onClickCapture={handleAddToBoard}>
{image.board_id ? 'Change Board' : 'Add to Board'}
{imageDTO.board_id ? 'Change Board' : 'Add to Board'}
</MenuItem>
{image.board_id && (
{imageDTO.board_id && (
<MenuItem
icon={<FaFolder />}
onClickCapture={handleRemoveFromBoard}

View File

@ -27,7 +27,7 @@ export const ASSETS_CATEGORIES: ImageCategory[] = [
export const INITIAL_IMAGE_LIMIT = 100;
export const IMAGE_LIMIT = 20;
type AdditionaGalleryState = {
type AdditionalGalleryState = {
offset: number;
limit: number;
total: number;
@ -43,7 +43,7 @@ type AdditionaGalleryState = {
};
export const initialGalleryState =
galleryImagesAdapter.getInitialState<AdditionaGalleryState>({
galleryImagesAdapter.getInitialState<AdditionalGalleryState>({
offset: 0,
limit: 0,
total: 0,