mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): improve image upload handling
This commit is contained in:
parent
17164a37a8
commit
0d5f44b153
@ -8,7 +8,10 @@ import type { TypedStartListening, TypedAddListener } from '@reduxjs/toolkit';
|
||||
|
||||
import type { RootState, AppDispatch } from '../../store';
|
||||
import { addInitialImageSelectedListener } from './listeners/initialImageSelected';
|
||||
import { addImageUploadedListener } from './listeners/imageUploaded';
|
||||
import {
|
||||
addImageUploadedFulfilledListener,
|
||||
addImageUploadedRejectedListener,
|
||||
} from './listeners/imageUploaded';
|
||||
import { addRequestedImageDeletionListener } from './listeners/imageDeleted';
|
||||
import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas';
|
||||
import { addUserInvokedNodesListener } from './listeners/userInvokedNodes';
|
||||
@ -47,23 +50,28 @@ export type AppListenerEffect = ListenerEffect<
|
||||
AppDispatch
|
||||
>;
|
||||
|
||||
addImageUploadedListener();
|
||||
// Image uploads
|
||||
addImageUploadedFulfilledListener();
|
||||
addImageUploadedRejectedListener();
|
||||
|
||||
addInitialImageSelectedListener();
|
||||
|
||||
addRequestedImageDeletionListener();
|
||||
|
||||
// Invoking stuff
|
||||
addUserInvokedCanvasListener();
|
||||
addUserInvokedNodesListener();
|
||||
addUserInvokedTextToImageListener();
|
||||
addUserInvokedImageToImageListener();
|
||||
addSessionReadyToInvokeListener();
|
||||
|
||||
// Canvas actions
|
||||
addCanvasSavedToGalleryListener();
|
||||
addCanvasDownloadedAsImageListener();
|
||||
addCanvasCopiedToClipboardListener();
|
||||
addCanvasMergedListener();
|
||||
|
||||
// socketio
|
||||
|
||||
addGeneratorProgressListener();
|
||||
addGraphExecutionStateCompleteListener();
|
||||
addInvocationCompleteListener();
|
||||
|
@ -52,7 +52,6 @@ export const addCanvasMergedListener = () => {
|
||||
|
||||
dispatch(
|
||||
imageUploaded({
|
||||
imageType: 'intermediates',
|
||||
formData: {
|
||||
file: new File([blob], filename, { type: 'image/png' }),
|
||||
},
|
||||
@ -65,7 +64,7 @@ export const addCanvasMergedListener = () => {
|
||||
action.meta.arg.formData.file.name === filename
|
||||
);
|
||||
|
||||
const mergedCanvasImage = payload.response;
|
||||
const mergedCanvasImage = payload;
|
||||
|
||||
dispatch(
|
||||
setMergedCanvas({
|
||||
|
@ -29,7 +29,6 @@ export const addCanvasSavedToGalleryListener = () => {
|
||||
|
||||
dispatch(
|
||||
imageUploaded({
|
||||
imageType: 'results',
|
||||
formData: {
|
||||
file: new File([blob], 'mergedCanvas.png', { type: 'image/png' }),
|
||||
},
|
||||
|
@ -7,17 +7,23 @@ import { initialImageSelected } from 'features/parameters/store/actions';
|
||||
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
||||
import { resultAdded } from 'features/gallery/store/resultsSlice';
|
||||
import { isResultsImageDTO, isUploadsImageDTO } from 'services/types/guards';
|
||||
import { log } from 'app/logging/useLogger';
|
||||
|
||||
export const addImageUploadedListener = () => {
|
||||
const moduleLog = log.child({ namespace: 'image' });
|
||||
|
||||
export const addImageUploadedFulfilledListener = () => {
|
||||
startAppListening({
|
||||
predicate: (action): action is ReturnType<typeof imageUploaded.fulfilled> =>
|
||||
imageUploaded.fulfilled.match(action) &&
|
||||
action.payload.response.is_intermediate === false,
|
||||
action.payload.is_intermediate === false,
|
||||
effect: (action, { dispatch, getState }) => {
|
||||
const { response: image } = action.payload;
|
||||
const image = action.payload;
|
||||
|
||||
moduleLog.debug({ arg: '<Blob>', image }, 'Image uploaded');
|
||||
|
||||
const state = getState();
|
||||
|
||||
// Handle uploads
|
||||
if (isUploadsImageDTO(image)) {
|
||||
dispatch(uploadAdded(image));
|
||||
|
||||
@ -36,9 +42,26 @@ export const addImageUploadedListener = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle results
|
||||
// TODO: Can this ever happen? I don't think so...
|
||||
if (isResultsImageDTO(image)) {
|
||||
dispatch(resultAdded(image));
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addImageUploadedRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: imageUploaded.rejected,
|
||||
effect: (action, { dispatch }) => {
|
||||
dispatch(
|
||||
addToast({
|
||||
title: 'Image Upload Failed',
|
||||
description: action.error.message,
|
||||
status: 'error',
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -106,19 +106,16 @@ export const addUserInvokedCanvasListener = () => {
|
||||
);
|
||||
|
||||
// Wait for the image to be uploaded
|
||||
const [{ payload: basePayload }] = await take(
|
||||
const [{ payload: baseImageDTO }] = await take(
|
||||
(action): action is ReturnType<typeof imageUploaded.fulfilled> =>
|
||||
imageUploaded.fulfilled.match(action) &&
|
||||
action.meta.arg.formData.file.name === baseFilename
|
||||
);
|
||||
|
||||
// Update the base node with the image name and type
|
||||
const { image_name: baseName, image_type: baseType } =
|
||||
basePayload.response;
|
||||
|
||||
baseNode.image = {
|
||||
image_name: baseName,
|
||||
image_type: baseType,
|
||||
image_name: baseImageDTO.image_name,
|
||||
image_type: baseImageDTO.image_type,
|
||||
};
|
||||
}
|
||||
|
||||
@ -135,19 +132,16 @@ export const addUserInvokedCanvasListener = () => {
|
||||
);
|
||||
|
||||
// Wait for the mask to be uploaded
|
||||
const [{ payload: maskPayload }] = await take(
|
||||
const [{ payload: maskImageDTO }] = await take(
|
||||
(action): action is ReturnType<typeof imageUploaded.fulfilled> =>
|
||||
imageUploaded.fulfilled.match(action) &&
|
||||
action.meta.arg.formData.file.name === maskFilename
|
||||
);
|
||||
|
||||
// Update the base node with the image name and type
|
||||
const { image_name: maskName, image_type: maskType } =
|
||||
maskPayload.response;
|
||||
|
||||
baseNode.mask = {
|
||||
image_name: maskName,
|
||||
image_type: maskType,
|
||||
image_name: maskImageDTO.image_name,
|
||||
image_type: maskImageDTO.image_type,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,6 @@ const ImageUploader = (props: ImageUploaderProps) => {
|
||||
async (file: File) => {
|
||||
dispatch(
|
||||
imageUploaded({
|
||||
imageType: 'uploads',
|
||||
formData: { file },
|
||||
activeTabName,
|
||||
})
|
||||
|
@ -53,11 +53,8 @@ export const imageUploaded = createAppAsyncThunk(
|
||||
// strip out `activeTabName` from arg - the route does not need it
|
||||
const { activeTabName, ...rest } = arg;
|
||||
const response = await ImagesService.uploadImage(rest);
|
||||
const { location } = getHeaders(response);
|
||||
|
||||
imagesLog.debug({ arg: '<Blob>', response, location }, 'Image uploaded');
|
||||
|
||||
return { response, location };
|
||||
return response;
|
||||
}
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user