Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions invokeai/frontend/web/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,8 @@
"isScheduled": "Canceling",
"setType": "Set cancel type"
},
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
"negativePrompts": "Negative Prompts",
"positivePromptPlaceholder": "Positive Prompt",
"negativePromptPlaceholder": "Negative Prompt",
"sendTo": "Send to",
"sendToImg2Img": "Send to Image to Image",
"sendToUnifiedCanvas": "Send To Unified Canvas",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
DragEndEvent,
DragOverlay,
DragStartEvent,
KeyboardSensor,
MouseSensor,
TouchSensor,
pointerWithin,
Expand All @@ -15,6 +14,7 @@ import OverlayDragImage from './OverlayDragImage';
import { ImageDTO } from 'services/api';
import { isImageDTO } from 'services/types/guards';
import { snapCenterToCursor } from '@dnd-kit/modifiers';
import { AnimatePresence, motion } from 'framer-motion';

type ImageDndContextProps = PropsWithChildren;

Expand All @@ -40,11 +40,11 @@ const ImageDndContext = (props: ImageDndContextProps) => {
);

const mouseSensor = useSensor(MouseSensor, {
activationConstraint: { distance: 15 },
activationConstraint: { delay: 250, tolerance: 5 },
});

const touchSensor = useSensor(TouchSensor, {
activationConstraint: { distance: 15 },
activationConstraint: { delay: 250, tolerance: 5 },
});
// TODO: Use KeyboardSensor - needs composition of multiple collisionDetection algos
// Alternatively, fix `rectIntersection` collection detection to work with the drag overlay
Expand All @@ -62,7 +62,25 @@ const ImageDndContext = (props: ImageDndContextProps) => {
>
{props.children}
<DragOverlay dropAnimation={null} modifiers={[snapCenterToCursor]}>
{draggedImage && <OverlayDragImage image={draggedImage} />}
<AnimatePresence>
{draggedImage && (
<motion.div
layout
key="overlay-drag-image"
initial={{
opacity: 0,
scale: 0.7,
}}
animate={{
opacity: 1,
scale: 1,
transition: { duration: 0.1 },
}}
>
<OverlayDragImage image={draggedImage} />
</motion.div>
)}
</AnimatePresence>
</DragOverlay>
</DndContext>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider';
import { getFullBaseLayerBlob } from 'features/canvas/util/getFullBaseLayerBlob';

const moduleLog = log.child({ namespace: 'canvasCopiedToClipboardListener' });
export const MERGED_CANVAS_FILENAME = 'mergedCanvas.png';

export const addCanvasMergedListener = () => {
startAppListening({
Expand Down Expand Up @@ -49,12 +48,15 @@ export const addCanvasMergedListener = () => {
const imageUploadedRequest = dispatch(
imageUploaded({
formData: {
file: new File([blob], MERGED_CANVAS_FILENAME, {
file: new File([blob], 'mergedCanvas.png', {
type: 'image/png',
}),
},
imageCategory: 'general',
isIntermediate: true,
postUploadAction: {
type: 'TOAST_CANVAS_MERGED',
},
})
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob';
import { addToast } from 'features/system/store/systemSlice';
import { imageUpserted } from 'features/gallery/store/imagesSlice';

export const SAVED_CANVAS_FILENAME = 'savedCanvas.png';

const moduleLog = log.child({ namespace: 'canvasSavedToGalleryListener' });

export const addCanvasSavedToGalleryListener = () => {
Expand All @@ -33,12 +31,15 @@ export const addCanvasSavedToGalleryListener = () => {
const imageUploadedRequest = dispatch(
imageUploaded({
formData: {
file: new File([blob], SAVED_CANVAS_FILENAME, {
file: new File([blob], 'savedCanvas.png', {
type: 'image/png',
}),
},
imageCategory: 'general',
isIntermediate: false,
postUploadAction: {
type: 'TOAST_CANVAS_SAVED_TO_GALLERY',
},
})
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
import { AnyAction } from '@reduxjs/toolkit';
import { AnyListenerPredicate } from '@reduxjs/toolkit';
import { startAppListening } from '..';
import { log } from 'app/logging/useLogger';
import { controlNetImageProcessed } from 'features/controlNet/store/actions';
import {
controlNetAutoConfigToggled,
controlNetImageChanged,
controlNetModelChanged,
controlNetProcessorParamsChanged,
controlNetProcessorTypeChanged,
} from 'features/controlNet/store/controlNetSlice';
import { RootState } from 'app/store/store';

const moduleLog = log.child({ namespace: 'controlNet' });

const predicate = (action: AnyAction, state: RootState) => {
const predicate: AnyListenerPredicate<RootState> = (action, state) => {
const isActionMatched =
controlNetProcessorParamsChanged.match(action) ||
controlNetModelChanged.match(action) ||
controlNetImageChanged.match(action) ||
controlNetProcessorTypeChanged.match(action);
controlNetProcessorTypeChanged.match(action) ||
controlNetAutoConfigToggled.match(action);

if (!isActionMatched) {
return false;
}

const { controlImage, processorType } =
const { controlImage, processorType, shouldAutoConfig } =
state.controlNet.controlNets[action.payload.controlNetId];

if (controlNetModelChanged.match(action) && !shouldAutoConfig) {
// do not process if the action is a model change but the processor settings are dirty
return false;
}

const isProcessorSelected = processorType !== 'none';

const isBusy = state.system.isProcessing;
Expand All @@ -49,7 +58,10 @@ export const addControlNetAutoProcessListener = () => {

// Cancel any in-progress instances of this listener
cancelActiveListeners();

moduleLog.trace(
{ data: action.payload },
'ControlNet auto-process triggered'
);
// Delay before starting actual work
await delay(300);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { imageUploaded } from 'services/thunks/image';
import { addToast } from 'features/system/store/systemSlice';
import { log } from 'app/logging/useLogger';
import { imageUpserted } from 'features/gallery/store/imagesSlice';
import { SAVED_CANVAS_FILENAME } from './canvasSavedToGallery';
import { MERGED_CANVAS_FILENAME } from './canvasMerged';
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice';
import { initialImageChanged } from 'features/parameters/store/generationSlice';
import { fieldValueChanged } from 'features/nodes/store/nodesSlice';

const moduleLog = log.child({ namespace: 'image' });

Expand All @@ -21,23 +23,48 @@ export const addImageUploadedFulfilledListener = () => {
return;
}

const originalFileName = action.meta.arg.formData.file.name;

dispatch(imageUpserted(image));

if (originalFileName === SAVED_CANVAS_FILENAME) {
const { postUploadAction } = action.meta.arg;

if (postUploadAction?.type === 'TOAST_CANVAS_SAVED_TO_GALLERY') {
dispatch(
addToast({ title: 'Canvas Saved to Gallery', status: 'success' })
);
return;
}

if (originalFileName === MERGED_CANVAS_FILENAME) {
if (postUploadAction?.type === 'TOAST_CANVAS_MERGED') {
dispatch(addToast({ title: 'Canvas Merged', status: 'success' }));
return;
}

dispatch(addToast({ title: 'Image Uploaded', status: 'success' }));
if (postUploadAction?.type === 'SET_CANVAS_INITIAL_IMAGE') {
dispatch(setInitialCanvasImage(image));
return;
}

if (postUploadAction?.type === 'SET_CONTROLNET_IMAGE') {
const { controlNetId } = postUploadAction;
dispatch(controlNetImageChanged({ controlNetId, controlImage: image }));
return;
}

if (postUploadAction?.type === 'SET_INITIAL_IMAGE') {
dispatch(initialImageChanged(image));
return;
}

if (postUploadAction?.type === 'SET_NODES_IMAGE') {
const { nodeId, fieldName } = postUploadAction;
dispatch(fieldValueChanged({ nodeId, fieldName, value: image }));
return;
}

if (postUploadAction?.type === 'TOAST_UPLOADED') {
dispatch(addToast({ title: 'Image Uploaded', status: 'success' }));
return;
}
},
});
};
Expand Down
Loading