mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Refactors upload-related async thunks
- Now standard thunks instead of RTK createAsyncThunk() - Adds toasts for all canvas upload-related actions
This commit is contained in:
parent
d82a21cfb2
commit
bc46c46835
@ -25,7 +25,7 @@ import IAICanvasSettingsButtonPopover from './IAICanvasSettingsButtonPopover';
|
|||||||
import IAICanvasEraserButtonPopover from './IAICanvasEraserButtonPopover';
|
import IAICanvasEraserButtonPopover from './IAICanvasEraserButtonPopover';
|
||||||
import IAICanvasBrushButtonPopover from './IAICanvasBrushButtonPopover';
|
import IAICanvasBrushButtonPopover from './IAICanvasBrushButtonPopover';
|
||||||
import IAICanvasMaskButtonPopover from './IAICanvasMaskButtonPopover';
|
import IAICanvasMaskButtonPopover from './IAICanvasMaskButtonPopover';
|
||||||
import { mergeAndUploadCanvas } from 'features/canvas/util/mergeAndUploadCanvas';
|
import { mergeAndUploadCanvas } from 'features/canvas/store/thunks/mergeAndUploadCanvas';
|
||||||
import {
|
import {
|
||||||
canvasSelector,
|
canvasSelector,
|
||||||
isStagingSelector,
|
isStagingSelector,
|
||||||
@ -151,14 +151,19 @@ const IAICanvasOutpaintingControls = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleMergeVisible = () => {
|
const handleMergeVisible = () => {
|
||||||
dispatch(mergeAndUploadCanvas({}));
|
dispatch(
|
||||||
|
mergeAndUploadCanvas({
|
||||||
|
cropVisible: false,
|
||||||
|
shouldSetAsInitialImage: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveToGallery = () => {
|
const handleSaveToGallery = () => {
|
||||||
dispatch(
|
dispatch(
|
||||||
mergeAndUploadCanvas({
|
mergeAndUploadCanvas({
|
||||||
cropVisible: true,
|
cropVisible: true,
|
||||||
saveToGallery: true,
|
shouldSaveToGallery: true,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -167,7 +172,7 @@ const IAICanvasOutpaintingControls = () => {
|
|||||||
dispatch(
|
dispatch(
|
||||||
mergeAndUploadCanvas({
|
mergeAndUploadCanvas({
|
||||||
cropVisible: true,
|
cropVisible: true,
|
||||||
copyAfterSaving: true,
|
shouldCopy: true,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -176,7 +181,7 @@ const IAICanvasOutpaintingControls = () => {
|
|||||||
dispatch(
|
dispatch(
|
||||||
mergeAndUploadCanvas({
|
mergeAndUploadCanvas({
|
||||||
cropVisible: true,
|
cropVisible: true,
|
||||||
downloadAfterSaving: true,
|
shouldDownload: true,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -8,12 +8,11 @@ import {
|
|||||||
roundDownToMultiple,
|
roundDownToMultiple,
|
||||||
roundToMultiple,
|
roundToMultiple,
|
||||||
} from 'common/util/roundDownToMultiple';
|
} from 'common/util/roundDownToMultiple';
|
||||||
import { canvasExtraReducers } from './reducers/extraReducers';
|
|
||||||
import { setInitialCanvasImage as setInitialCanvasImage_reducer } from './reducers/setInitialCanvasImage';
|
|
||||||
import calculateScale from '../util/calculateScale';
|
import calculateScale from '../util/calculateScale';
|
||||||
import calculateCoordinates from '../util/calculateCoordinates';
|
import calculateCoordinates from '../util/calculateCoordinates';
|
||||||
import floorCoordinates from '../util/floorCoordinates';
|
import floorCoordinates from '../util/floorCoordinates';
|
||||||
import {
|
import {
|
||||||
|
CanvasImage,
|
||||||
CanvasLayer,
|
CanvasLayer,
|
||||||
CanvasLayerState,
|
CanvasLayerState,
|
||||||
CanvasState,
|
CanvasState,
|
||||||
@ -152,7 +151,45 @@ export const canvasSlice = createSlice({
|
|||||||
state.cursorPosition = action.payload;
|
state.cursorPosition = action.payload;
|
||||||
},
|
},
|
||||||
setInitialCanvasImage: (state, action: PayloadAction<InvokeAI.Image>) => {
|
setInitialCanvasImage: (state, action: PayloadAction<InvokeAI.Image>) => {
|
||||||
setInitialCanvasImage_reducer(state, action.payload);
|
const image = action.payload;
|
||||||
|
const newBoundingBoxDimensions = {
|
||||||
|
width: roundDownToMultiple(_.clamp(image.width, 64, 512), 64),
|
||||||
|
height: roundDownToMultiple(_.clamp(image.height, 64, 512), 64),
|
||||||
|
};
|
||||||
|
|
||||||
|
const newBoundingBoxCoordinates = {
|
||||||
|
x: roundToMultiple(
|
||||||
|
image.width / 2 - newBoundingBoxDimensions.width / 2,
|
||||||
|
64
|
||||||
|
),
|
||||||
|
y: roundToMultiple(
|
||||||
|
image.height / 2 - newBoundingBoxDimensions.height / 2,
|
||||||
|
64
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
state.boundingBoxDimensions = newBoundingBoxDimensions;
|
||||||
|
state.boundingBoxCoordinates = newBoundingBoxCoordinates;
|
||||||
|
|
||||||
|
state.pastLayerStates.push(state.layerState);
|
||||||
|
state.layerState = {
|
||||||
|
...initialLayerState,
|
||||||
|
objects: [
|
||||||
|
{
|
||||||
|
kind: 'image',
|
||||||
|
layer: 'base',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: image.width,
|
||||||
|
height: image.height,
|
||||||
|
image: image,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
state.futureLayerStates = [];
|
||||||
|
|
||||||
|
state.isCanvasInitialized = false;
|
||||||
|
state.doesCanvasNeedScaling = true;
|
||||||
},
|
},
|
||||||
setStageDimensions: (state, action: PayloadAction<Dimensions>) => {
|
setStageDimensions: (state, action: PayloadAction<Dimensions>) => {
|
||||||
state.stageDimensions = action.payload;
|
state.stageDimensions = action.payload;
|
||||||
@ -599,8 +636,16 @@ export const canvasSlice = createSlice({
|
|||||||
setShouldShowStagingImage: (state, action: PayloadAction<boolean>) => {
|
setShouldShowStagingImage: (state, action: PayloadAction<boolean>) => {
|
||||||
state.shouldShowStagingImage = action.payload;
|
state.shouldShowStagingImage = action.payload;
|
||||||
},
|
},
|
||||||
|
setMergedCanvas: (state, action: PayloadAction<CanvasImage>) => {
|
||||||
|
state.pastLayerStates.push({
|
||||||
|
...state.layerState,
|
||||||
|
});
|
||||||
|
|
||||||
|
state.futureLayerStates = [];
|
||||||
|
|
||||||
|
state.layerState.objects = [action.payload];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
extraReducers: canvasExtraReducers,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
@ -659,6 +704,7 @@ export const {
|
|||||||
setCanvasContainerDimensions,
|
setCanvasContainerDimensions,
|
||||||
fitBoundingBoxToStage,
|
fitBoundingBoxToStage,
|
||||||
setShouldShowStagingImage,
|
setShouldShowStagingImage,
|
||||||
|
setMergedCanvas,
|
||||||
} = canvasSlice.actions;
|
} = canvasSlice.actions;
|
||||||
|
|
||||||
export default canvasSlice.reducer;
|
export default canvasSlice.reducer;
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
import { CanvasState } from '../canvasTypes';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import { mergeAndUploadCanvas } from '../../util/mergeAndUploadCanvas';
|
|
||||||
import { uploadImage } from 'features/gallery/util/uploadImage';
|
|
||||||
import { ActionReducerMapBuilder } from '@reduxjs/toolkit';
|
|
||||||
import { setInitialCanvasImage } from './setInitialCanvasImage';
|
|
||||||
|
|
||||||
export const canvasExtraReducers = (
|
|
||||||
builder: ActionReducerMapBuilder<CanvasState>
|
|
||||||
) => {
|
|
||||||
builder.addCase(mergeAndUploadCanvas.fulfilled, (state, action) => {
|
|
||||||
if (!action.payload) return;
|
|
||||||
const { image, kind, originalBoundingBox } = action.payload;
|
|
||||||
|
|
||||||
if (kind === 'temp_merged_canvas') {
|
|
||||||
state.pastLayerStates.push({
|
|
||||||
...state.layerState,
|
|
||||||
});
|
|
||||||
|
|
||||||
state.futureLayerStates = [];
|
|
||||||
|
|
||||||
state.layerState.objects = [
|
|
||||||
{
|
|
||||||
kind: 'image',
|
|
||||||
layer: 'base',
|
|
||||||
...originalBoundingBox,
|
|
||||||
image,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.addCase(uploadImage.fulfilled, (state, action) => {
|
|
||||||
if (!action.payload) return;
|
|
||||||
const { image, kind, activeTabName } = action.payload;
|
|
||||||
|
|
||||||
if (kind !== 'init') return;
|
|
||||||
|
|
||||||
if (activeTabName === 'unifiedCanvas') {
|
|
||||||
setInitialCanvasImage(state, image);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,52 +0,0 @@
|
|||||||
import * as InvokeAI from 'app/invokeai';
|
|
||||||
import { initialLayerState } from '../canvasSlice';
|
|
||||||
import { CanvasState } from '../canvasTypes';
|
|
||||||
import {
|
|
||||||
roundDownToMultiple,
|
|
||||||
roundToMultiple,
|
|
||||||
} from 'common/util/roundDownToMultiple';
|
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
export const setInitialCanvasImage = (
|
|
||||||
state: CanvasState,
|
|
||||||
image: InvokeAI.Image
|
|
||||||
) => {
|
|
||||||
const newBoundingBoxDimensions = {
|
|
||||||
width: roundDownToMultiple(_.clamp(image.width, 64, 512), 64),
|
|
||||||
height: roundDownToMultiple(_.clamp(image.height, 64, 512), 64),
|
|
||||||
};
|
|
||||||
|
|
||||||
const newBoundingBoxCoordinates = {
|
|
||||||
x: roundToMultiple(
|
|
||||||
image.width / 2 - newBoundingBoxDimensions.width / 2,
|
|
||||||
64
|
|
||||||
),
|
|
||||||
y: roundToMultiple(
|
|
||||||
image.height / 2 - newBoundingBoxDimensions.height / 2,
|
|
||||||
64
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
state.boundingBoxDimensions = newBoundingBoxDimensions;
|
|
||||||
state.boundingBoxCoordinates = newBoundingBoxCoordinates;
|
|
||||||
|
|
||||||
state.pastLayerStates.push(state.layerState);
|
|
||||||
state.layerState = {
|
|
||||||
...initialLayerState,
|
|
||||||
objects: [
|
|
||||||
{
|
|
||||||
kind: 'image',
|
|
||||||
layer: 'base',
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: image.width,
|
|
||||||
height: image.height,
|
|
||||||
image: image,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
state.futureLayerStates = [];
|
|
||||||
|
|
||||||
state.isCanvasInitialized = false;
|
|
||||||
state.doesCanvasNeedScaling = true;
|
|
||||||
};
|
|
@ -0,0 +1,138 @@
|
|||||||
|
import { AnyAction, ThunkAction } from '@reduxjs/toolkit';
|
||||||
|
import { RootState } from 'app/store';
|
||||||
|
import * as InvokeAI from 'app/invokeai';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import layerToDataURL from '../../util/layerToDataURL';
|
||||||
|
import downloadFile from '../../util/downloadFile';
|
||||||
|
import copyImage from '../../util/copyImage';
|
||||||
|
import { getCanvasBaseLayer } from '../../util/konvaInstanceProvider';
|
||||||
|
import { addToast } from 'features/system/systemSlice';
|
||||||
|
import { addImage } from 'features/gallery/gallerySlice';
|
||||||
|
import { setMergedCanvas } from '../canvasSlice';
|
||||||
|
|
||||||
|
type MergeAndUploadCanvasConfig = {
|
||||||
|
cropVisible?: boolean;
|
||||||
|
shouldSaveToGallery?: boolean;
|
||||||
|
shouldDownload?: boolean;
|
||||||
|
shouldCopy?: boolean;
|
||||||
|
shouldSetAsInitialImage?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultConfig: MergeAndUploadCanvasConfig = {
|
||||||
|
cropVisible: false,
|
||||||
|
shouldSaveToGallery: false,
|
||||||
|
shouldDownload: false,
|
||||||
|
shouldCopy: false,
|
||||||
|
shouldSetAsInitialImage: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const mergeAndUploadCanvas =
|
||||||
|
(config = defaultConfig): ThunkAction<void, RootState, unknown, AnyAction> =>
|
||||||
|
async (dispatch, getState) => {
|
||||||
|
const {
|
||||||
|
cropVisible,
|
||||||
|
shouldSaveToGallery,
|
||||||
|
shouldDownload,
|
||||||
|
shouldCopy,
|
||||||
|
shouldSetAsInitialImage,
|
||||||
|
} = config;
|
||||||
|
|
||||||
|
const state = getState() as RootState;
|
||||||
|
|
||||||
|
const stageScale = state.canvas.stageScale;
|
||||||
|
|
||||||
|
const canvasBaseLayer = getCanvasBaseLayer();
|
||||||
|
|
||||||
|
if (!canvasBaseLayer) return;
|
||||||
|
|
||||||
|
const { dataURL, boundingBox: originalBoundingBox } = layerToDataURL(
|
||||||
|
canvasBaseLayer,
|
||||||
|
stageScale
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!dataURL) return;
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
formData.append(
|
||||||
|
'data',
|
||||||
|
JSON.stringify({
|
||||||
|
dataURL,
|
||||||
|
filename: 'merged_canvas.png',
|
||||||
|
kind: shouldSaveToGallery ? 'result' : 'temp',
|
||||||
|
cropVisible,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const response = await fetch(window.location.origin + '/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { url, mtime, width, height } =
|
||||||
|
(await response.json()) as InvokeAI.ImageUploadResponse;
|
||||||
|
|
||||||
|
const newImage: InvokeAI.Image = {
|
||||||
|
uuid: uuidv4(),
|
||||||
|
url,
|
||||||
|
mtime,
|
||||||
|
category: shouldSaveToGallery ? 'result' : 'user',
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (shouldDownload) {
|
||||||
|
downloadFile(url);
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: 'Image Download Started',
|
||||||
|
status: 'success',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldCopy) {
|
||||||
|
copyImage(url, width, height);
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: 'Image Copied',
|
||||||
|
status: 'success',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldSaveToGallery) {
|
||||||
|
dispatch(addImage({ image: newImage, category: 'result' }));
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: 'Image Saved to Gallery',
|
||||||
|
status: 'success',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldSetAsInitialImage) {
|
||||||
|
dispatch(
|
||||||
|
setMergedCanvas({
|
||||||
|
kind: 'image',
|
||||||
|
layer: 'base',
|
||||||
|
...originalBoundingBox,
|
||||||
|
image: newImage,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
dispatch(
|
||||||
|
addToast({
|
||||||
|
title: 'Canvas Merged',
|
||||||
|
status: 'success',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
@ -1,103 +0,0 @@
|
|||||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
|
||||||
import { RootState } from 'app/store';
|
|
||||||
import * as InvokeAI from 'app/invokeai';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
import layerToDataURL from './layerToDataURL';
|
|
||||||
import downloadFile from './downloadFile';
|
|
||||||
import copyImage from './copyImage';
|
|
||||||
import { getCanvasBaseLayer } from './konvaInstanceProvider';
|
|
||||||
import { addToast } from 'features/system/systemSlice';
|
|
||||||
|
|
||||||
export const mergeAndUploadCanvas = createAsyncThunk(
|
|
||||||
'canvas/mergeAndUploadCanvas',
|
|
||||||
async (
|
|
||||||
args: {
|
|
||||||
cropVisible?: boolean;
|
|
||||||
saveToGallery?: boolean;
|
|
||||||
downloadAfterSaving?: boolean;
|
|
||||||
copyAfterSaving?: boolean;
|
|
||||||
},
|
|
||||||
thunkAPI
|
|
||||||
) => {
|
|
||||||
const { saveToGallery, downloadAfterSaving, cropVisible, copyAfterSaving } =
|
|
||||||
args;
|
|
||||||
|
|
||||||
const { getState, dispatch } = thunkAPI;
|
|
||||||
|
|
||||||
const state = getState() as RootState;
|
|
||||||
|
|
||||||
const stageScale = state.canvas.stageScale;
|
|
||||||
|
|
||||||
const canvasBaseLayer = getCanvasBaseLayer();
|
|
||||||
|
|
||||||
if (!canvasBaseLayer) return;
|
|
||||||
|
|
||||||
const { dataURL, boundingBox: originalBoundingBox } = layerToDataURL(
|
|
||||||
canvasBaseLayer,
|
|
||||||
stageScale
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!dataURL) return;
|
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
|
|
||||||
formData.append(
|
|
||||||
'data',
|
|
||||||
JSON.stringify({
|
|
||||||
dataURL,
|
|
||||||
filename: 'merged_canvas.png',
|
|
||||||
kind: saveToGallery ? 'result' : 'temp',
|
|
||||||
cropVisible,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const response = await fetch(window.location.origin + '/upload', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { url, mtime, width, height } =
|
|
||||||
(await response.json()) as InvokeAI.ImageUploadResponse;
|
|
||||||
|
|
||||||
if (downloadAfterSaving) {
|
|
||||||
downloadFile(url);
|
|
||||||
dispatch(
|
|
||||||
addToast({
|
|
||||||
title: 'Image Download Started',
|
|
||||||
status: 'success',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copyAfterSaving) {
|
|
||||||
copyImage(url, width, height);
|
|
||||||
dispatch(
|
|
||||||
addToast({
|
|
||||||
title: 'Image Copied',
|
|
||||||
status: 'success',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newImage: InvokeAI.Image = {
|
|
||||||
uuid: uuidv4(),
|
|
||||||
url,
|
|
||||||
mtime,
|
|
||||||
category: saveToGallery ? 'result' : 'user',
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
image: newImage,
|
|
||||||
kind: saveToGallery ? 'merged_canvas' : 'temp_merged_canvas',
|
|
||||||
originalBoundingBox,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
@ -4,8 +4,6 @@ import _, { clamp } from 'lodash';
|
|||||||
import * as InvokeAI from 'app/invokeai';
|
import * as InvokeAI from 'app/invokeai';
|
||||||
import { IRect } from 'konva/lib/types';
|
import { IRect } from 'konva/lib/types';
|
||||||
import { InvokeTabName } from 'features/tabs/InvokeTabs';
|
import { InvokeTabName } from 'features/tabs/InvokeTabs';
|
||||||
import { mergeAndUploadCanvas } from 'features/canvas/util/mergeAndUploadCanvas';
|
|
||||||
import { uploadImage } from './util/uploadImage';
|
|
||||||
|
|
||||||
export type GalleryCategory = 'user' | 'result';
|
export type GalleryCategory = 'user' | 'result';
|
||||||
|
|
||||||
@ -266,46 +264,6 @@ export const gallerySlice = createSlice({
|
|||||||
state.galleryWidth = action.payload;
|
state.galleryWidth = action.payload;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extraReducers: (builder) => {
|
|
||||||
builder.addCase(mergeAndUploadCanvas.fulfilled, (state, action) => {
|
|
||||||
if (!action.payload) return;
|
|
||||||
const { image, kind, originalBoundingBox } = action.payload;
|
|
||||||
|
|
||||||
if (kind === 'merged_canvas') {
|
|
||||||
const { uuid, url, mtime } = image;
|
|
||||||
|
|
||||||
state.categories.result.images.unshift(image);
|
|
||||||
|
|
||||||
if (state.shouldAutoSwitchToNewImages) {
|
|
||||||
state.currentImageUuid = uuid;
|
|
||||||
state.currentImage = image;
|
|
||||||
state.currentCategory = 'result';
|
|
||||||
}
|
|
||||||
|
|
||||||
state.intermediateImage = undefined;
|
|
||||||
state.categories.result.latest_mtime = mtime;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.addCase(uploadImage.fulfilled, (state, action) => {
|
|
||||||
if (!action.payload) return;
|
|
||||||
const { image, kind } = action.payload;
|
|
||||||
|
|
||||||
if (kind === 'init') {
|
|
||||||
const { uuid, mtime } = image;
|
|
||||||
|
|
||||||
state.categories.result.images.unshift(image);
|
|
||||||
|
|
||||||
if (state.shouldAutoSwitchToNewImages) {
|
|
||||||
state.currentImageUuid = uuid;
|
|
||||||
state.currentImage = image;
|
|
||||||
state.currentCategory = 'user';
|
|
||||||
}
|
|
||||||
|
|
||||||
state.intermediateImage = undefined;
|
|
||||||
state.categories.result.latest_mtime = mtime;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
import { AnyAction, ThunkAction } from '@reduxjs/toolkit';
|
||||||
import { RootState } from 'app/store';
|
import { RootState } from 'app/store';
|
||||||
import * as InvokeAI from 'app/invokeai';
|
import * as InvokeAI from 'app/invokeai';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||||
|
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
||||||
|
import { setInitialImage } from 'features/options/optionsSlice';
|
||||||
|
import { addImage } from '../gallerySlice';
|
||||||
|
|
||||||
export const uploadImage = createAsyncThunk(
|
type UploadImageConfig = {
|
||||||
'gallery/uploadImage',
|
|
||||||
async (
|
|
||||||
args: {
|
|
||||||
imageFile: File;
|
imageFile: File;
|
||||||
},
|
};
|
||||||
thunkAPI
|
|
||||||
) => {
|
|
||||||
const { imageFile } = args;
|
|
||||||
|
|
||||||
const { getState } = thunkAPI;
|
export const uploadImage =
|
||||||
|
(
|
||||||
|
config: UploadImageConfig
|
||||||
|
): ThunkAction<void, RootState, unknown, AnyAction> =>
|
||||||
|
async (dispatch, getState) => {
|
||||||
|
const { imageFile } = config;
|
||||||
|
|
||||||
const state = getState() as RootState;
|
const state = getState() as RootState;
|
||||||
|
|
||||||
@ -47,10 +49,11 @@ export const uploadImage = createAsyncThunk(
|
|||||||
height: height,
|
height: height,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
dispatch(addImage({ image: newImage, category: 'user' }));
|
||||||
image: newImage,
|
|
||||||
kind: 'init',
|
if (activeTabName === 'unifiedCanvas') {
|
||||||
activeTabName,
|
dispatch(setInitialCanvasImage(newImage));
|
||||||
};
|
} else if (activeTabName === 'img2img') {
|
||||||
|
dispatch(setInitialImage(newImage));
|
||||||
}
|
}
|
||||||
);
|
};
|
||||||
|
@ -5,7 +5,6 @@ import promptToString from 'common/util/promptToString';
|
|||||||
import { seedWeightsToString } from 'common/util/seedWeightPairs';
|
import { seedWeightsToString } from 'common/util/seedWeightPairs';
|
||||||
import { FACETOOL_TYPES } from 'app/constants';
|
import { FACETOOL_TYPES } from 'app/constants';
|
||||||
import { InvokeTabName, tabMap } from 'features/tabs/InvokeTabs';
|
import { InvokeTabName, tabMap } from 'features/tabs/InvokeTabs';
|
||||||
import { uploadImage } from 'features/gallery/util/uploadImage';
|
|
||||||
|
|
||||||
export type UpscalingLevel = 2 | 4;
|
export type UpscalingLevel = 2 | 4;
|
||||||
|
|
||||||
@ -362,16 +361,6 @@ export const optionsSlice = createSlice({
|
|||||||
state.isLightBoxOpen = action.payload;
|
state.isLightBoxOpen = action.payload;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extraReducers: (builder) => {
|
|
||||||
builder.addCase(uploadImage.fulfilled, (state, action) => {
|
|
||||||
if (!action.payload) return;
|
|
||||||
const { image, kind, activeTabName } = action.payload;
|
|
||||||
|
|
||||||
if (kind === 'init' && activeTabName === 'img2img') {
|
|
||||||
state.initialImage = image;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user