mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): being dismantling old sio stuff, fix recall seed/prompt/init
- still need to fix up metadataviewer's recall features
This commit is contained in:
parent
2eb7c25bae
commit
258895bcc9
@ -1,7 +1,7 @@
|
||||
import React, { lazy, memo, PropsWithChildren, useEffect } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { PersistGate } from 'redux-persist/integration/react';
|
||||
import { buildMiddleware, store } from 'app/store/store';
|
||||
import { store } from 'app/store/store';
|
||||
import { persistor } from '../store/persistor';
|
||||
import { OpenAPI } from 'services/api';
|
||||
import '@fontsource/inter/100.css';
|
||||
@ -19,6 +19,7 @@ import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares';
|
||||
import { PartialAppConfig } from 'app/types/invokeai';
|
||||
|
||||
import '../../i18n';
|
||||
import { socketMiddleware } from 'services/events/middleware';
|
||||
|
||||
const App = lazy(() => import('./App'));
|
||||
const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider'));
|
||||
@ -50,7 +51,7 @@ const InvokeAIUI = ({ apiUrl, token, config, children }: Props) => {
|
||||
// the `apiUrl`/`token` dynamically.
|
||||
|
||||
// rebuild socket middleware with token and apiUrl
|
||||
addMiddleware(buildMiddleware());
|
||||
addMiddleware(socketMiddleware());
|
||||
}, [apiUrl, token]);
|
||||
|
||||
return (
|
||||
|
@ -1,7 +1,5 @@
|
||||
// TODO: use Enums?
|
||||
|
||||
import { InProgressImageType } from 'features/system/store/systemSlice';
|
||||
|
||||
export const DIFFUSERS_SCHEDULERS: Array<string> = [
|
||||
'ddim',
|
||||
'plms',
|
||||
@ -33,17 +31,8 @@ export const UPSCALING_LEVELS: Array<{ key: string; value: number }> = [
|
||||
|
||||
export const NUMPY_RAND_MIN = 0;
|
||||
|
||||
export const NUMPY_RAND_MAX = 4294967295;
|
||||
export const NUMPY_RAND_MAX = 2147483647;
|
||||
|
||||
export const FACETOOL_TYPES = ['gfpgan', 'codeformer'] as const;
|
||||
|
||||
export const IN_PROGRESS_IMAGE_TYPES: Array<{
|
||||
key: string;
|
||||
value: InProgressImageType;
|
||||
}> = [
|
||||
{ key: 'None', value: 'none' },
|
||||
{ key: 'Fast', value: 'latents' },
|
||||
{ key: 'Accurate', value: 'full-res' },
|
||||
];
|
||||
|
||||
export const NODE_MIN_WIDTH = 250;
|
||||
|
@ -1,65 +1,67 @@
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
import * as InvokeAI from 'app/types/invokeai';
|
||||
import { GalleryCategory } from 'features/gallery/store/gallerySlice';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
// import { createAction } from '@reduxjs/toolkit';
|
||||
// import * as InvokeAI from 'app/types/invokeai';
|
||||
// import { GalleryCategory } from 'features/gallery/store/gallerySlice';
|
||||
// import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
|
||||
/**
|
||||
* We can't use redux-toolkit's createSlice() to make these actions,
|
||||
* because they have no associated reducer. They only exist to dispatch
|
||||
* requests to the server via socketio. These actions will be handled
|
||||
* by the middleware.
|
||||
*/
|
||||
// /**
|
||||
// * We can't use redux-toolkit's createSlice() to make these actions,
|
||||
// * because they have no associated reducer. They only exist to dispatch
|
||||
// * requests to the server via socketio. These actions will be handled
|
||||
// * by the middleware.
|
||||
// */
|
||||
|
||||
export const generateImage = createAction<InvokeTabName>(
|
||||
'socketio/generateImage'
|
||||
);
|
||||
export const runESRGAN = createAction<InvokeAI._Image>('socketio/runESRGAN');
|
||||
export const runFacetool = createAction<InvokeAI._Image>(
|
||||
'socketio/runFacetool'
|
||||
);
|
||||
export const deleteImage = createAction<InvokeAI._Image>(
|
||||
'socketio/deleteImage'
|
||||
);
|
||||
export const requestImages = createAction<GalleryCategory>(
|
||||
'socketio/requestImages'
|
||||
);
|
||||
export const requestNewImages = createAction<GalleryCategory>(
|
||||
'socketio/requestNewImages'
|
||||
);
|
||||
export const cancelProcessing = createAction<undefined>(
|
||||
'socketio/cancelProcessing'
|
||||
);
|
||||
// export const generateImage = createAction<InvokeTabName>(
|
||||
// 'socketio/generateImage'
|
||||
// );
|
||||
// export const runESRGAN = createAction<InvokeAI._Image>('socketio/runESRGAN');
|
||||
// export const runFacetool = createAction<InvokeAI._Image>(
|
||||
// 'socketio/runFacetool'
|
||||
// );
|
||||
// export const deleteImage = createAction<InvokeAI._Image>(
|
||||
// 'socketio/deleteImage'
|
||||
// );
|
||||
// export const requestImages = createAction<GalleryCategory>(
|
||||
// 'socketio/requestImages'
|
||||
// );
|
||||
// export const requestNewImages = createAction<GalleryCategory>(
|
||||
// 'socketio/requestNewImages'
|
||||
// );
|
||||
// export const cancelProcessing = createAction<undefined>(
|
||||
// 'socketio/cancelProcessing'
|
||||
// );
|
||||
|
||||
export const requestSystemConfig = createAction<undefined>(
|
||||
'socketio/requestSystemConfig'
|
||||
);
|
||||
// export const requestSystemConfig = createAction<undefined>(
|
||||
// 'socketio/requestSystemConfig'
|
||||
// );
|
||||
|
||||
export const searchForModels = createAction<string>('socketio/searchForModels');
|
||||
// export const searchForModels = createAction<string>('socketio/searchForModels');
|
||||
|
||||
export const addNewModel = createAction<
|
||||
InvokeAI.InvokeModelConfigProps | InvokeAI.InvokeDiffusersModelConfigProps
|
||||
>('socketio/addNewModel');
|
||||
// export const addNewModel = createAction<
|
||||
// InvokeAI.InvokeModelConfigProps | InvokeAI.InvokeDiffusersModelConfigProps
|
||||
// >('socketio/addNewModel');
|
||||
|
||||
export const deleteModel = createAction<string>('socketio/deleteModel');
|
||||
// export const deleteModel = createAction<string>('socketio/deleteModel');
|
||||
|
||||
export const convertToDiffusers =
|
||||
createAction<InvokeAI.InvokeModelConversionProps>(
|
||||
'socketio/convertToDiffusers'
|
||||
);
|
||||
// export const convertToDiffusers =
|
||||
// createAction<InvokeAI.InvokeModelConversionProps>(
|
||||
// 'socketio/convertToDiffusers'
|
||||
// );
|
||||
|
||||
export const mergeDiffusersModels =
|
||||
createAction<InvokeAI.InvokeModelMergingProps>(
|
||||
'socketio/mergeDiffusersModels'
|
||||
);
|
||||
// export const mergeDiffusersModels =
|
||||
// createAction<InvokeAI.InvokeModelMergingProps>(
|
||||
// 'socketio/mergeDiffusersModels'
|
||||
// );
|
||||
|
||||
export const requestModelChange = createAction<string>(
|
||||
'socketio/requestModelChange'
|
||||
);
|
||||
// export const requestModelChange = createAction<string>(
|
||||
// 'socketio/requestModelChange'
|
||||
// );
|
||||
|
||||
export const saveStagingAreaImageToGallery = createAction<string>(
|
||||
'socketio/saveStagingAreaImageToGallery'
|
||||
);
|
||||
// export const saveStagingAreaImageToGallery = createAction<string>(
|
||||
// 'socketio/saveStagingAreaImageToGallery'
|
||||
// );
|
||||
|
||||
export const emptyTempFolder = createAction<undefined>(
|
||||
'socketio/requestEmptyTempFolder'
|
||||
);
|
||||
// export const emptyTempFolder = createAction<undefined>(
|
||||
// 'socketio/requestEmptyTempFolder'
|
||||
// );
|
||||
|
||||
export default {};
|
||||
|
@ -1,207 +1,209 @@
|
||||
import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit';
|
||||
import * as InvokeAI from 'app/types/invokeai';
|
||||
import type { RootState } from 'app/store/store';
|
||||
import {
|
||||
frontendToBackendParameters,
|
||||
FrontendToBackendParametersConfig,
|
||||
} from 'common/util/parameterTranslation';
|
||||
import dateFormat from 'dateformat';
|
||||
import {
|
||||
GalleryCategory,
|
||||
GalleryState,
|
||||
removeImage,
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
import {
|
||||
generationRequested,
|
||||
modelChangeRequested,
|
||||
modelConvertRequested,
|
||||
modelMergingRequested,
|
||||
setIsProcessing,
|
||||
} from 'features/system/store/systemSlice';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
import { Socket } from 'socket.io-client';
|
||||
// import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit';
|
||||
// import * as InvokeAI from 'app/types/invokeai';
|
||||
// import type { RootState } from 'app/store/store';
|
||||
// import {
|
||||
// frontendToBackendParameters,
|
||||
// FrontendToBackendParametersConfig,
|
||||
// } from 'common/util/parameterTranslation';
|
||||
// import dateFormat from 'dateformat';
|
||||
// import {
|
||||
// GalleryCategory,
|
||||
// GalleryState,
|
||||
// removeImage,
|
||||
// } from 'features/gallery/store/gallerySlice';
|
||||
// import {
|
||||
// generationRequested,
|
||||
// modelChangeRequested,
|
||||
// modelConvertRequested,
|
||||
// modelMergingRequested,
|
||||
// setIsProcessing,
|
||||
// } from 'features/system/store/systemSlice';
|
||||
// import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
// import { Socket } from 'socket.io-client';
|
||||
|
||||
/**
|
||||
* Returns an object containing all functions which use `socketio.emit()`.
|
||||
* i.e. those which make server requests.
|
||||
*/
|
||||
const makeSocketIOEmitters = (
|
||||
store: MiddlewareAPI<Dispatch<AnyAction>, RootState>,
|
||||
socketio: Socket
|
||||
) => {
|
||||
// We need to dispatch actions to redux and get pieces of state from the store.
|
||||
const { dispatch, getState } = store;
|
||||
// /**
|
||||
// * Returns an object containing all functions which use `socketio.emit()`.
|
||||
// * i.e. those which make server requests.
|
||||
// */
|
||||
// const makeSocketIOEmitters = (
|
||||
// store: MiddlewareAPI<Dispatch<AnyAction>, RootState>,
|
||||
// socketio: Socket
|
||||
// ) => {
|
||||
// // We need to dispatch actions to redux and get pieces of state from the store.
|
||||
// const { dispatch, getState } = store;
|
||||
|
||||
return {
|
||||
emitGenerateImage: (generationMode: InvokeTabName) => {
|
||||
dispatch(setIsProcessing(true));
|
||||
// return {
|
||||
// emitGenerateImage: (generationMode: InvokeTabName) => {
|
||||
// dispatch(setIsProcessing(true));
|
||||
|
||||
const state: RootState = getState();
|
||||
// const state: RootState = getState();
|
||||
|
||||
const {
|
||||
generation: generationState,
|
||||
postprocessing: postprocessingState,
|
||||
system: systemState,
|
||||
canvas: canvasState,
|
||||
} = state;
|
||||
// const {
|
||||
// generation: generationState,
|
||||
// postprocessing: postprocessingState,
|
||||
// system: systemState,
|
||||
// canvas: canvasState,
|
||||
// } = state;
|
||||
|
||||
const frontendToBackendParametersConfig: FrontendToBackendParametersConfig =
|
||||
{
|
||||
generationMode,
|
||||
generationState,
|
||||
postprocessingState,
|
||||
canvasState,
|
||||
systemState,
|
||||
};
|
||||
// const frontendToBackendParametersConfig: FrontendToBackendParametersConfig =
|
||||
// {
|
||||
// generationMode,
|
||||
// generationState,
|
||||
// postprocessingState,
|
||||
// canvasState,
|
||||
// systemState,
|
||||
// };
|
||||
|
||||
dispatch(generationRequested());
|
||||
// dispatch(generationRequested());
|
||||
|
||||
const { generationParameters, esrganParameters, facetoolParameters } =
|
||||
frontendToBackendParameters(frontendToBackendParametersConfig);
|
||||
// const { generationParameters, esrganParameters, facetoolParameters } =
|
||||
// frontendToBackendParameters(frontendToBackendParametersConfig);
|
||||
|
||||
socketio.emit(
|
||||
'generateImage',
|
||||
generationParameters,
|
||||
esrganParameters,
|
||||
facetoolParameters
|
||||
);
|
||||
// socketio.emit(
|
||||
// 'generateImage',
|
||||
// generationParameters,
|
||||
// esrganParameters,
|
||||
// facetoolParameters
|
||||
// );
|
||||
|
||||
// we need to truncate the init_mask base64 else it takes up the whole log
|
||||
// TODO: handle maintaining masks for reproducibility in future
|
||||
if (generationParameters.init_mask) {
|
||||
generationParameters.init_mask = generationParameters.init_mask
|
||||
.substr(0, 64)
|
||||
.concat('...');
|
||||
}
|
||||
if (generationParameters.init_img) {
|
||||
generationParameters.init_img = generationParameters.init_img
|
||||
.substr(0, 64)
|
||||
.concat('...');
|
||||
}
|
||||
// // we need to truncate the init_mask base64 else it takes up the whole log
|
||||
// // TODO: handle maintaining masks for reproducibility in future
|
||||
// if (generationParameters.init_mask) {
|
||||
// generationParameters.init_mask = generationParameters.init_mask
|
||||
// .substr(0, 64)
|
||||
// .concat('...');
|
||||
// }
|
||||
// if (generationParameters.init_img) {
|
||||
// generationParameters.init_img = generationParameters.init_img
|
||||
// .substr(0, 64)
|
||||
// .concat('...');
|
||||
// }
|
||||
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Image generation requested: ${JSON.stringify({
|
||||
...generationParameters,
|
||||
...esrganParameters,
|
||||
...facetoolParameters,
|
||||
})}`,
|
||||
})
|
||||
);
|
||||
},
|
||||
emitRunESRGAN: (imageToProcess: InvokeAI._Image) => {
|
||||
dispatch(setIsProcessing(true));
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Image generation requested: ${JSON.stringify({
|
||||
// ...generationParameters,
|
||||
// ...esrganParameters,
|
||||
// ...facetoolParameters,
|
||||
// })}`,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// emitRunESRGAN: (imageToProcess: InvokeAI._Image) => {
|
||||
// dispatch(setIsProcessing(true));
|
||||
|
||||
const {
|
||||
postprocessing: {
|
||||
upscalingLevel,
|
||||
upscalingDenoising,
|
||||
upscalingStrength,
|
||||
},
|
||||
} = getState();
|
||||
// const {
|
||||
// postprocessing: {
|
||||
// upscalingLevel,
|
||||
// upscalingDenoising,
|
||||
// upscalingStrength,
|
||||
// },
|
||||
// } = getState();
|
||||
|
||||
const esrganParameters = {
|
||||
upscale: [upscalingLevel, upscalingDenoising, upscalingStrength],
|
||||
};
|
||||
socketio.emit('runPostprocessing', imageToProcess, {
|
||||
type: 'esrgan',
|
||||
...esrganParameters,
|
||||
});
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `ESRGAN upscale requested: ${JSON.stringify({
|
||||
file: imageToProcess.url,
|
||||
...esrganParameters,
|
||||
})}`,
|
||||
})
|
||||
);
|
||||
},
|
||||
emitRunFacetool: (imageToProcess: InvokeAI._Image) => {
|
||||
dispatch(setIsProcessing(true));
|
||||
// const esrganParameters = {
|
||||
// upscale: [upscalingLevel, upscalingDenoising, upscalingStrength],
|
||||
// };
|
||||
// socketio.emit('runPostprocessing', imageToProcess, {
|
||||
// type: 'esrgan',
|
||||
// ...esrganParameters,
|
||||
// });
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `ESRGAN upscale requested: ${JSON.stringify({
|
||||
// file: imageToProcess.url,
|
||||
// ...esrganParameters,
|
||||
// })}`,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// emitRunFacetool: (imageToProcess: InvokeAI._Image) => {
|
||||
// dispatch(setIsProcessing(true));
|
||||
|
||||
const {
|
||||
postprocessing: { facetoolType, facetoolStrength, codeformerFidelity },
|
||||
} = getState();
|
||||
// const {
|
||||
// postprocessing: { facetoolType, facetoolStrength, codeformerFidelity },
|
||||
// } = getState();
|
||||
|
||||
const facetoolParameters: Record<string, unknown> = {
|
||||
facetool_strength: facetoolStrength,
|
||||
};
|
||||
// const facetoolParameters: Record<string, unknown> = {
|
||||
// facetool_strength: facetoolStrength,
|
||||
// };
|
||||
|
||||
if (facetoolType === 'codeformer') {
|
||||
facetoolParameters.codeformer_fidelity = codeformerFidelity;
|
||||
}
|
||||
// if (facetoolType === 'codeformer') {
|
||||
// facetoolParameters.codeformer_fidelity = codeformerFidelity;
|
||||
// }
|
||||
|
||||
socketio.emit('runPostprocessing', imageToProcess, {
|
||||
type: facetoolType,
|
||||
...facetoolParameters,
|
||||
});
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Face restoration (${facetoolType}) requested: ${JSON.stringify(
|
||||
{
|
||||
file: imageToProcess.url,
|
||||
...facetoolParameters,
|
||||
}
|
||||
)}`,
|
||||
})
|
||||
);
|
||||
},
|
||||
emitDeleteImage: (imageToDelete: InvokeAI._Image) => {
|
||||
const { url, uuid, category, thumbnail } = imageToDelete;
|
||||
dispatch(removeImage(imageToDelete));
|
||||
socketio.emit('deleteImage', url, thumbnail, uuid, category);
|
||||
},
|
||||
emitRequestImages: (category: GalleryCategory) => {
|
||||
const gallery: GalleryState = getState().gallery;
|
||||
const { earliest_mtime } = gallery.categories[category];
|
||||
socketio.emit('requestImages', category, earliest_mtime);
|
||||
},
|
||||
emitRequestNewImages: (category: GalleryCategory) => {
|
||||
const gallery: GalleryState = getState().gallery;
|
||||
const { latest_mtime } = gallery.categories[category];
|
||||
socketio.emit('requestLatestImages', category, latest_mtime);
|
||||
},
|
||||
emitCancelProcessing: () => {
|
||||
socketio.emit('cancel');
|
||||
},
|
||||
emitRequestSystemConfig: () => {
|
||||
socketio.emit('requestSystemConfig');
|
||||
},
|
||||
emitSearchForModels: (modelFolder: string) => {
|
||||
socketio.emit('searchForModels', modelFolder);
|
||||
},
|
||||
emitAddNewModel: (modelConfig: InvokeAI.InvokeModelConfigProps) => {
|
||||
socketio.emit('addNewModel', modelConfig);
|
||||
},
|
||||
emitDeleteModel: (modelName: string) => {
|
||||
socketio.emit('deleteModel', modelName);
|
||||
},
|
||||
emitConvertToDiffusers: (
|
||||
modelToConvert: InvokeAI.InvokeModelConversionProps
|
||||
) => {
|
||||
dispatch(modelConvertRequested());
|
||||
socketio.emit('convertToDiffusers', modelToConvert);
|
||||
},
|
||||
emitMergeDiffusersModels: (
|
||||
modelMergeInfo: InvokeAI.InvokeModelMergingProps
|
||||
) => {
|
||||
dispatch(modelMergingRequested());
|
||||
socketio.emit('mergeDiffusersModels', modelMergeInfo);
|
||||
},
|
||||
emitRequestModelChange: (modelName: string) => {
|
||||
dispatch(modelChangeRequested());
|
||||
socketio.emit('requestModelChange', modelName);
|
||||
},
|
||||
emitSaveStagingAreaImageToGallery: (url: string) => {
|
||||
socketio.emit('requestSaveStagingAreaImageToGallery', url);
|
||||
},
|
||||
emitRequestEmptyTempFolder: () => {
|
||||
socketio.emit('requestEmptyTempFolder');
|
||||
},
|
||||
};
|
||||
};
|
||||
// socketio.emit('runPostprocessing', imageToProcess, {
|
||||
// type: facetoolType,
|
||||
// ...facetoolParameters,
|
||||
// });
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Face restoration (${facetoolType}) requested: ${JSON.stringify(
|
||||
// {
|
||||
// file: imageToProcess.url,
|
||||
// ...facetoolParameters,
|
||||
// }
|
||||
// )}`,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// emitDeleteImage: (imageToDelete: InvokeAI._Image) => {
|
||||
// const { url, uuid, category, thumbnail } = imageToDelete;
|
||||
// dispatch(removeImage(imageToDelete));
|
||||
// socketio.emit('deleteImage', url, thumbnail, uuid, category);
|
||||
// },
|
||||
// emitRequestImages: (category: GalleryCategory) => {
|
||||
// const gallery: GalleryState = getState().gallery;
|
||||
// const { earliest_mtime } = gallery.categories[category];
|
||||
// socketio.emit('requestImages', category, earliest_mtime);
|
||||
// },
|
||||
// emitRequestNewImages: (category: GalleryCategory) => {
|
||||
// const gallery: GalleryState = getState().gallery;
|
||||
// const { latest_mtime } = gallery.categories[category];
|
||||
// socketio.emit('requestLatestImages', category, latest_mtime);
|
||||
// },
|
||||
// emitCancelProcessing: () => {
|
||||
// socketio.emit('cancel');
|
||||
// },
|
||||
// emitRequestSystemConfig: () => {
|
||||
// socketio.emit('requestSystemConfig');
|
||||
// },
|
||||
// emitSearchForModels: (modelFolder: string) => {
|
||||
// socketio.emit('searchForModels', modelFolder);
|
||||
// },
|
||||
// emitAddNewModel: (modelConfig: InvokeAI.InvokeModelConfigProps) => {
|
||||
// socketio.emit('addNewModel', modelConfig);
|
||||
// },
|
||||
// emitDeleteModel: (modelName: string) => {
|
||||
// socketio.emit('deleteModel', modelName);
|
||||
// },
|
||||
// emitConvertToDiffusers: (
|
||||
// modelToConvert: InvokeAI.InvokeModelConversionProps
|
||||
// ) => {
|
||||
// dispatch(modelConvertRequested());
|
||||
// socketio.emit('convertToDiffusers', modelToConvert);
|
||||
// },
|
||||
// emitMergeDiffusersModels: (
|
||||
// modelMergeInfo: InvokeAI.InvokeModelMergingProps
|
||||
// ) => {
|
||||
// dispatch(modelMergingRequested());
|
||||
// socketio.emit('mergeDiffusersModels', modelMergeInfo);
|
||||
// },
|
||||
// emitRequestModelChange: (modelName: string) => {
|
||||
// dispatch(modelChangeRequested());
|
||||
// socketio.emit('requestModelChange', modelName);
|
||||
// },
|
||||
// emitSaveStagingAreaImageToGallery: (url: string) => {
|
||||
// socketio.emit('requestSaveStagingAreaImageToGallery', url);
|
||||
// },
|
||||
// emitRequestEmptyTempFolder: () => {
|
||||
// socketio.emit('requestEmptyTempFolder');
|
||||
// },
|
||||
// };
|
||||
// };
|
||||
|
||||
export default makeSocketIOEmitters;
|
||||
// export default makeSocketIOEmitters;
|
||||
|
||||
export default {};
|
||||
|
@ -1,500 +1,502 @@
|
||||
import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit';
|
||||
import dateFormat from 'dateformat';
|
||||
import i18n from 'i18n';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
// import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit';
|
||||
// import dateFormat from 'dateformat';
|
||||
// import i18n from 'i18n';
|
||||
// import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import * as InvokeAI from 'app/types/invokeai';
|
||||
// import * as InvokeAI from 'app/types/invokeai';
|
||||
|
||||
import {
|
||||
addToast,
|
||||
errorOccurred,
|
||||
processingCanceled,
|
||||
setCurrentStatus,
|
||||
setFoundModels,
|
||||
setIsCancelable,
|
||||
setIsConnected,
|
||||
setIsProcessing,
|
||||
setModelList,
|
||||
setSearchFolder,
|
||||
setSystemConfig,
|
||||
setSystemStatus,
|
||||
} from 'features/system/store/systemSlice';
|
||||
// import {
|
||||
// addToast,
|
||||
// errorOccurred,
|
||||
// processingCanceled,
|
||||
// setCurrentStatus,
|
||||
// setFoundModels,
|
||||
// setIsCancelable,
|
||||
// setIsConnected,
|
||||
// setIsProcessing,
|
||||
// setModelList,
|
||||
// setSearchFolder,
|
||||
// setSystemConfig,
|
||||
// setSystemStatus,
|
||||
// } from 'features/system/store/systemSlice';
|
||||
|
||||
import {
|
||||
addGalleryImages,
|
||||
addImage,
|
||||
clearIntermediateImage,
|
||||
GalleryState,
|
||||
removeImage,
|
||||
setIntermediateImage,
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
// import {
|
||||
// addGalleryImages,
|
||||
// addImage,
|
||||
// clearIntermediateImage,
|
||||
// GalleryState,
|
||||
// removeImage,
|
||||
// setIntermediateImage,
|
||||
// } from 'features/gallery/store/gallerySlice';
|
||||
|
||||
import type { RootState } from 'app/store/store';
|
||||
import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
|
||||
import {
|
||||
clearInitialImage,
|
||||
initialImageSelected,
|
||||
setInfillMethod,
|
||||
// setInitialImage,
|
||||
setMaskPath,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { tabMap } from 'features/ui/store/tabMap';
|
||||
import {
|
||||
requestImages,
|
||||
requestNewImages,
|
||||
requestSystemConfig,
|
||||
} from './actions';
|
||||
// import type { RootState } from 'app/store/store';
|
||||
// import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
|
||||
// import {
|
||||
// clearInitialImage,
|
||||
// initialImageSelected,
|
||||
// setInfillMethod,
|
||||
// // setInitialImage,
|
||||
// setMaskPath,
|
||||
// } from 'features/parameters/store/generationSlice';
|
||||
// import { tabMap } from 'features/ui/store/tabMap';
|
||||
// import {
|
||||
// requestImages,
|
||||
// requestNewImages,
|
||||
// requestSystemConfig,
|
||||
// } from './actions';
|
||||
|
||||
/**
|
||||
* Returns an object containing listener callbacks for socketio events.
|
||||
* TODO: This file is large, but simple. Should it be split up further?
|
||||
*/
|
||||
const makeSocketIOListeners = (
|
||||
store: MiddlewareAPI<Dispatch<AnyAction>, RootState>
|
||||
) => {
|
||||
const { dispatch, getState } = store;
|
||||
// /**
|
||||
// * Returns an object containing listener callbacks for socketio events.
|
||||
// * TODO: This file is large, but simple. Should it be split up further?
|
||||
// */
|
||||
// const makeSocketIOListeners = (
|
||||
// store: MiddlewareAPI<Dispatch<AnyAction>, RootState>
|
||||
// ) => {
|
||||
// const { dispatch, getState } = store;
|
||||
|
||||
return {
|
||||
/**
|
||||
* Callback to run when we receive a 'connect' event.
|
||||
*/
|
||||
onConnect: () => {
|
||||
try {
|
||||
dispatch(setIsConnected(true));
|
||||
dispatch(setCurrentStatus(i18n.t('common.statusConnected')));
|
||||
dispatch(requestSystemConfig());
|
||||
const gallery: GalleryState = getState().gallery;
|
||||
// return {
|
||||
// /**
|
||||
// * Callback to run when we receive a 'connect' event.
|
||||
// */
|
||||
// onConnect: () => {
|
||||
// try {
|
||||
// dispatch(setIsConnected(true));
|
||||
// dispatch(setCurrentStatus(i18n.t('common.statusConnected')));
|
||||
// dispatch(requestSystemConfig());
|
||||
// const gallery: GalleryState = getState().gallery;
|
||||
|
||||
if (gallery.categories.result.latest_mtime) {
|
||||
dispatch(requestNewImages('result'));
|
||||
} else {
|
||||
dispatch(requestImages('result'));
|
||||
}
|
||||
// if (gallery.categories.result.latest_mtime) {
|
||||
// dispatch(requestNewImages('result'));
|
||||
// } else {
|
||||
// dispatch(requestImages('result'));
|
||||
// }
|
||||
|
||||
if (gallery.categories.user.latest_mtime) {
|
||||
dispatch(requestNewImages('user'));
|
||||
} else {
|
||||
dispatch(requestImages('user'));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Callback to run when we receive a 'disconnect' event.
|
||||
*/
|
||||
onDisconnect: () => {
|
||||
try {
|
||||
dispatch(setIsConnected(false));
|
||||
dispatch(setCurrentStatus(i18n.t('common.statusDisconnected')));
|
||||
// if (gallery.categories.user.latest_mtime) {
|
||||
// dispatch(requestNewImages('user'));
|
||||
// } else {
|
||||
// dispatch(requestImages('user'));
|
||||
// }
|
||||
// } catch (e) {
|
||||
// console.error(e);
|
||||
// }
|
||||
// },
|
||||
// /**
|
||||
// * Callback to run when we receive a 'disconnect' event.
|
||||
// */
|
||||
// onDisconnect: () => {
|
||||
// try {
|
||||
// dispatch(setIsConnected(false));
|
||||
// dispatch(setCurrentStatus(i18n.t('common.statusDisconnected')));
|
||||
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Disconnected from server`,
|
||||
level: 'warning',
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Callback to run when we receive a 'generationResult' event.
|
||||
*/
|
||||
onGenerationResult: (data: InvokeAI.ImageResultResponse) => {
|
||||
try {
|
||||
const state = getState();
|
||||
const { activeTab } = state.ui;
|
||||
const { shouldLoopback } = state.postprocessing;
|
||||
const { boundingBox: _, generationMode, ...rest } = data;
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Disconnected from server`,
|
||||
// level: 'warning',
|
||||
// })
|
||||
// );
|
||||
// } catch (e) {
|
||||
// console.error(e);
|
||||
// }
|
||||
// },
|
||||
// /**
|
||||
// * Callback to run when we receive a 'generationResult' event.
|
||||
// */
|
||||
// onGenerationResult: (data: InvokeAI.ImageResultResponse) => {
|
||||
// try {
|
||||
// const state = getState();
|
||||
// const { activeTab } = state.ui;
|
||||
// const { shouldLoopback } = state.postprocessing;
|
||||
// const { boundingBox: _, generationMode, ...rest } = data;
|
||||
|
||||
const newImage = {
|
||||
uuid: uuidv4(),
|
||||
...rest,
|
||||
};
|
||||
// const newImage = {
|
||||
// uuid: uuidv4(),
|
||||
// ...rest,
|
||||
// };
|
||||
|
||||
if (['txt2img', 'img2img'].includes(generationMode)) {
|
||||
dispatch(
|
||||
addImage({
|
||||
category: 'result',
|
||||
image: { ...newImage, category: 'result' },
|
||||
})
|
||||
);
|
||||
}
|
||||
// if (['txt2img', 'img2img'].includes(generationMode)) {
|
||||
// dispatch(
|
||||
// addImage({
|
||||
// category: 'result',
|
||||
// image: { ...newImage, category: 'result' },
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
|
||||
if (generationMode === 'unifiedCanvas' && data.boundingBox) {
|
||||
const { boundingBox } = data;
|
||||
dispatch(
|
||||
addImageToStagingArea({
|
||||
image: { ...newImage, category: 'temp' },
|
||||
boundingBox,
|
||||
})
|
||||
);
|
||||
// if (generationMode === 'unifiedCanvas' && data.boundingBox) {
|
||||
// const { boundingBox } = data;
|
||||
// dispatch(
|
||||
// addImageToStagingArea({
|
||||
// image: { ...newImage, category: 'temp' },
|
||||
// boundingBox,
|
||||
// })
|
||||
// );
|
||||
|
||||
if (state.canvas.shouldAutoSave) {
|
||||
dispatch(
|
||||
addImage({
|
||||
image: { ...newImage, category: 'result' },
|
||||
category: 'result',
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
// if (state.canvas.shouldAutoSave) {
|
||||
// dispatch(
|
||||
// addImage({
|
||||
// image: { ...newImage, category: 'result' },
|
||||
// category: 'result',
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: fix
|
||||
// if (shouldLoopback) {
|
||||
// const activeTabName = tabMap[activeTab];
|
||||
// switch (activeTabName) {
|
||||
// case 'img2img': {
|
||||
// dispatch(initialImageSelected(newImage.uuid));
|
||||
// // dispatch(setInitialImage(newImage));
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // TODO: fix
|
||||
// // if (shouldLoopback) {
|
||||
// // const activeTabName = tabMap[activeTab];
|
||||
// // switch (activeTabName) {
|
||||
// // case 'img2img': {
|
||||
// // dispatch(initialImageSelected(newImage.uuid));
|
||||
// // // dispatch(setInitialImage(newImage));
|
||||
// // break;
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
|
||||
dispatch(clearIntermediateImage());
|
||||
// dispatch(clearIntermediateImage());
|
||||
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Image generated: ${data.url}`,
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Callback to run when we receive a 'intermediateResult' event.
|
||||
*/
|
||||
onIntermediateResult: (data: InvokeAI.ImageResultResponse) => {
|
||||
try {
|
||||
dispatch(
|
||||
setIntermediateImage({
|
||||
uuid: uuidv4(),
|
||||
...data,
|
||||
category: 'result',
|
||||
})
|
||||
);
|
||||
if (!data.isBase64) {
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Intermediate image generated: ${data.url}`,
|
||||
})
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Callback to run when we receive an 'esrganResult' event.
|
||||
*/
|
||||
onPostprocessingResult: (data: InvokeAI.ImageResultResponse) => {
|
||||
try {
|
||||
dispatch(
|
||||
addImage({
|
||||
category: 'result',
|
||||
image: {
|
||||
uuid: uuidv4(),
|
||||
...data,
|
||||
category: 'result',
|
||||
},
|
||||
})
|
||||
);
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Image generated: ${data.url}`,
|
||||
// })
|
||||
// );
|
||||
// } catch (e) {
|
||||
// console.error(e);
|
||||
// }
|
||||
// },
|
||||
// /**
|
||||
// * Callback to run when we receive a 'intermediateResult' event.
|
||||
// */
|
||||
// onIntermediateResult: (data: InvokeAI.ImageResultResponse) => {
|
||||
// try {
|
||||
// dispatch(
|
||||
// setIntermediateImage({
|
||||
// uuid: uuidv4(),
|
||||
// ...data,
|
||||
// category: 'result',
|
||||
// })
|
||||
// );
|
||||
// if (!data.isBase64) {
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Intermediate image generated: ${data.url}`,
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
// } catch (e) {
|
||||
// console.error(e);
|
||||
// }
|
||||
// },
|
||||
// /**
|
||||
// * Callback to run when we receive an 'esrganResult' event.
|
||||
// */
|
||||
// onPostprocessingResult: (data: InvokeAI.ImageResultResponse) => {
|
||||
// try {
|
||||
// dispatch(
|
||||
// addImage({
|
||||
// category: 'result',
|
||||
// image: {
|
||||
// uuid: uuidv4(),
|
||||
// ...data,
|
||||
// category: 'result',
|
||||
// },
|
||||
// })
|
||||
// );
|
||||
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Postprocessed: ${data.url}`,
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Callback to run when we receive a 'progressUpdate' event.
|
||||
* TODO: Add additional progress phases
|
||||
*/
|
||||
onProgressUpdate: (data: InvokeAI.SystemStatus) => {
|
||||
try {
|
||||
dispatch(setIsProcessing(true));
|
||||
dispatch(setSystemStatus(data));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Callback to run when we receive a 'progressUpdate' event.
|
||||
*/
|
||||
onError: (data: InvokeAI.ErrorResponse) => {
|
||||
const { message, additionalData } = data;
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Postprocessed: ${data.url}`,
|
||||
// })
|
||||
// );
|
||||
// } catch (e) {
|
||||
// console.error(e);
|
||||
// }
|
||||
// },
|
||||
// /**
|
||||
// * Callback to run when we receive a 'progressUpdate' event.
|
||||
// * TODO: Add additional progress phases
|
||||
// */
|
||||
// onProgressUpdate: (data: InvokeAI.SystemStatus) => {
|
||||
// try {
|
||||
// dispatch(setIsProcessing(true));
|
||||
// dispatch(setSystemStatus(data));
|
||||
// } catch (e) {
|
||||
// console.error(e);
|
||||
// }
|
||||
// },
|
||||
// /**
|
||||
// * Callback to run when we receive a 'progressUpdate' event.
|
||||
// */
|
||||
// onError: (data: InvokeAI.ErrorResponse) => {
|
||||
// const { message, additionalData } = data;
|
||||
|
||||
if (additionalData) {
|
||||
// TODO: handle more data than short message
|
||||
}
|
||||
// if (additionalData) {
|
||||
// // TODO: handle more data than short message
|
||||
// }
|
||||
|
||||
try {
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Server error: ${message}`,
|
||||
level: 'error',
|
||||
})
|
||||
);
|
||||
dispatch(errorOccurred());
|
||||
dispatch(clearIntermediateImage());
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Callback to run when we receive a 'galleryImages' event.
|
||||
*/
|
||||
onGalleryImages: (data: InvokeAI.GalleryImagesResponse) => {
|
||||
const { images, areMoreImagesAvailable, category } = data;
|
||||
// try {
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Server error: ${message}`,
|
||||
// level: 'error',
|
||||
// })
|
||||
// );
|
||||
// dispatch(errorOccurred());
|
||||
// dispatch(clearIntermediateImage());
|
||||
// } catch (e) {
|
||||
// console.error(e);
|
||||
// }
|
||||
// },
|
||||
// /**
|
||||
// * Callback to run when we receive a 'galleryImages' event.
|
||||
// */
|
||||
// onGalleryImages: (data: InvokeAI.GalleryImagesResponse) => {
|
||||
// const { images, areMoreImagesAvailable, category } = data;
|
||||
|
||||
/**
|
||||
* the logic here ideally would be in the reducer but we have a side effect:
|
||||
* generating a uuid. so the logic needs to be here, outside redux.
|
||||
*/
|
||||
// /**
|
||||
// * the logic here ideally would be in the reducer but we have a side effect:
|
||||
// * generating a uuid. so the logic needs to be here, outside redux.
|
||||
// */
|
||||
|
||||
// Generate a UUID for each image
|
||||
const preparedImages = images.map((image): InvokeAI._Image => {
|
||||
return {
|
||||
uuid: uuidv4(),
|
||||
...image,
|
||||
};
|
||||
});
|
||||
// // Generate a UUID for each image
|
||||
// const preparedImages = images.map((image): InvokeAI._Image => {
|
||||
// return {
|
||||
// uuid: uuidv4(),
|
||||
// ...image,
|
||||
// };
|
||||
// });
|
||||
|
||||
dispatch(
|
||||
addGalleryImages({
|
||||
images: preparedImages,
|
||||
areMoreImagesAvailable,
|
||||
category,
|
||||
})
|
||||
);
|
||||
// dispatch(
|
||||
// addGalleryImages({
|
||||
// images: preparedImages,
|
||||
// areMoreImagesAvailable,
|
||||
// category,
|
||||
// })
|
||||
// );
|
||||
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Loaded ${images.length} images`,
|
||||
})
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Callback to run when we receive a 'processingCanceled' event.
|
||||
*/
|
||||
onProcessingCanceled: () => {
|
||||
dispatch(processingCanceled());
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Loaded ${images.length} images`,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// /**
|
||||
// * Callback to run when we receive a 'processingCanceled' event.
|
||||
// */
|
||||
// onProcessingCanceled: () => {
|
||||
// dispatch(processingCanceled());
|
||||
|
||||
const { intermediateImage } = getState().gallery;
|
||||
// const { intermediateImage } = getState().gallery;
|
||||
|
||||
if (intermediateImage) {
|
||||
if (!intermediateImage.isBase64) {
|
||||
dispatch(
|
||||
addImage({
|
||||
category: 'result',
|
||||
image: intermediateImage,
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Intermediate image saved: ${intermediateImage.url}`,
|
||||
})
|
||||
);
|
||||
}
|
||||
dispatch(clearIntermediateImage());
|
||||
}
|
||||
// if (intermediateImage) {
|
||||
// if (!intermediateImage.isBase64) {
|
||||
// dispatch(
|
||||
// addImage({
|
||||
// category: 'result',
|
||||
// image: intermediateImage,
|
||||
// })
|
||||
// );
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Intermediate image saved: ${intermediateImage.url}`,
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
// dispatch(clearIntermediateImage());
|
||||
// }
|
||||
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Processing canceled`,
|
||||
level: 'warning',
|
||||
})
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Callback to run when we receive a 'imageDeleted' event.
|
||||
*/
|
||||
onImageDeleted: (data: InvokeAI.ImageDeletedResponse) => {
|
||||
const { url } = data;
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Processing canceled`,
|
||||
// level: 'warning',
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// /**
|
||||
// * Callback to run when we receive a 'imageDeleted' event.
|
||||
// */
|
||||
// onImageDeleted: (data: InvokeAI.ImageDeletedResponse) => {
|
||||
// const { url } = data;
|
||||
|
||||
// remove image from gallery
|
||||
dispatch(removeImage(data));
|
||||
// // remove image from gallery
|
||||
// dispatch(removeImage(data));
|
||||
|
||||
// remove references to image in options
|
||||
const {
|
||||
generation: { initialImage, maskPath },
|
||||
} = getState();
|
||||
// // remove references to image in options
|
||||
// const {
|
||||
// generation: { initialImage, maskPath },
|
||||
// } = getState();
|
||||
|
||||
if (
|
||||
initialImage === url ||
|
||||
(initialImage as InvokeAI._Image)?.url === url
|
||||
) {
|
||||
dispatch(clearInitialImage());
|
||||
}
|
||||
// if (
|
||||
// initialImage === url ||
|
||||
// (initialImage as InvokeAI._Image)?.url === url
|
||||
// ) {
|
||||
// dispatch(clearInitialImage());
|
||||
// }
|
||||
|
||||
if (maskPath === url) {
|
||||
dispatch(setMaskPath(''));
|
||||
}
|
||||
// if (maskPath === url) {
|
||||
// dispatch(setMaskPath(''));
|
||||
// }
|
||||
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Image deleted: ${url}`,
|
||||
})
|
||||
);
|
||||
},
|
||||
onSystemConfig: (data: InvokeAI.SystemConfig) => {
|
||||
dispatch(setSystemConfig(data));
|
||||
if (!data.infill_methods.includes('patchmatch')) {
|
||||
dispatch(setInfillMethod(data.infill_methods[0]));
|
||||
}
|
||||
},
|
||||
onFoundModels: (data: InvokeAI.FoundModelResponse) => {
|
||||
const { search_folder, found_models } = data;
|
||||
dispatch(setSearchFolder(search_folder));
|
||||
dispatch(setFoundModels(found_models));
|
||||
},
|
||||
onNewModelAdded: (data: InvokeAI.ModelAddedResponse) => {
|
||||
const { new_model_name, model_list, update } = data;
|
||||
dispatch(setModelList(model_list));
|
||||
dispatch(setIsProcessing(false));
|
||||
dispatch(setCurrentStatus(i18n.t('modelManager.modelAdded')));
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Model Added: ${new_model_name}`,
|
||||
level: 'info',
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
addToast({
|
||||
title: !update
|
||||
? `${i18n.t('modelManager.modelAdded')}: ${new_model_name}`
|
||||
: `${i18n.t('modelManager.modelUpdated')}: ${new_model_name}`,
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
onModelDeleted: (data: InvokeAI.ModelDeletedResponse) => {
|
||||
const { deleted_model_name, model_list } = data;
|
||||
dispatch(setModelList(model_list));
|
||||
dispatch(setIsProcessing(false));
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `${i18n.t(
|
||||
'modelManager.modelAdded'
|
||||
)}: ${deleted_model_name}`,
|
||||
level: 'info',
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
addToast({
|
||||
title: `${i18n.t(
|
||||
'modelManager.modelEntryDeleted'
|
||||
)}: ${deleted_model_name}`,
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
onModelConverted: (data: InvokeAI.ModelConvertedResponse) => {
|
||||
const { converted_model_name, model_list } = data;
|
||||
dispatch(setModelList(model_list));
|
||||
dispatch(setCurrentStatus(i18n.t('common.statusModelConverted')));
|
||||
dispatch(setIsProcessing(false));
|
||||
dispatch(setIsCancelable(true));
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Model converted: ${converted_model_name}`,
|
||||
level: 'info',
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
addToast({
|
||||
title: `${i18n.t(
|
||||
'modelManager.modelConverted'
|
||||
)}: ${converted_model_name}`,
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
onModelsMerged: (data: InvokeAI.ModelsMergedResponse) => {
|
||||
const { merged_models, merged_model_name, model_list } = data;
|
||||
dispatch(setModelList(model_list));
|
||||
dispatch(setCurrentStatus(i18n.t('common.statusMergedModels')));
|
||||
dispatch(setIsProcessing(false));
|
||||
dispatch(setIsCancelable(true));
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Models merged: ${merged_models}`,
|
||||
level: 'info',
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
addToast({
|
||||
title: `${i18n.t('modelManager.modelsMerged')}: ${merged_model_name}`,
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
onModelChanged: (data: InvokeAI.ModelChangeResponse) => {
|
||||
const { model_name, model_list } = data;
|
||||
dispatch(setModelList(model_list));
|
||||
dispatch(setCurrentStatus(i18n.t('common.statusModelChanged')));
|
||||
dispatch(setIsProcessing(false));
|
||||
dispatch(setIsCancelable(true));
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Model changed: ${model_name}`,
|
||||
level: 'info',
|
||||
})
|
||||
);
|
||||
},
|
||||
onModelChangeFailed: (data: InvokeAI.ModelChangeResponse) => {
|
||||
const { model_name, model_list } = data;
|
||||
dispatch(setModelList(model_list));
|
||||
dispatch(setIsProcessing(false));
|
||||
dispatch(setIsCancelable(true));
|
||||
dispatch(errorOccurred());
|
||||
dispatch(
|
||||
addLogEntry({
|
||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
message: `Model change failed: ${model_name}`,
|
||||
level: 'error',
|
||||
})
|
||||
);
|
||||
},
|
||||
onTempFolderEmptied: () => {
|
||||
dispatch(
|
||||
addToast({
|
||||
title: i18n.t('toast.tempFoldersEmptied'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Image deleted: ${url}`,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// onSystemConfig: (data: InvokeAI.SystemConfig) => {
|
||||
// dispatch(setSystemConfig(data));
|
||||
// if (!data.infill_methods.includes('patchmatch')) {
|
||||
// dispatch(setInfillMethod(data.infill_methods[0]));
|
||||
// }
|
||||
// },
|
||||
// onFoundModels: (data: InvokeAI.FoundModelResponse) => {
|
||||
// const { search_folder, found_models } = data;
|
||||
// dispatch(setSearchFolder(search_folder));
|
||||
// dispatch(setFoundModels(found_models));
|
||||
// },
|
||||
// onNewModelAdded: (data: InvokeAI.ModelAddedResponse) => {
|
||||
// const { new_model_name, model_list, update } = data;
|
||||
// dispatch(setModelList(model_list));
|
||||
// dispatch(setIsProcessing(false));
|
||||
// dispatch(setCurrentStatus(i18n.t('modelManager.modelAdded')));
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Model Added: ${new_model_name}`,
|
||||
// level: 'info',
|
||||
// })
|
||||
// );
|
||||
// dispatch(
|
||||
// addToast({
|
||||
// title: !update
|
||||
// ? `${i18n.t('modelManager.modelAdded')}: ${new_model_name}`
|
||||
// : `${i18n.t('modelManager.modelUpdated')}: ${new_model_name}`,
|
||||
// status: 'success',
|
||||
// duration: 2500,
|
||||
// isClosable: true,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// onModelDeleted: (data: InvokeAI.ModelDeletedResponse) => {
|
||||
// const { deleted_model_name, model_list } = data;
|
||||
// dispatch(setModelList(model_list));
|
||||
// dispatch(setIsProcessing(false));
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `${i18n.t(
|
||||
// 'modelManager.modelAdded'
|
||||
// )}: ${deleted_model_name}`,
|
||||
// level: 'info',
|
||||
// })
|
||||
// );
|
||||
// dispatch(
|
||||
// addToast({
|
||||
// title: `${i18n.t(
|
||||
// 'modelManager.modelEntryDeleted'
|
||||
// )}: ${deleted_model_name}`,
|
||||
// status: 'success',
|
||||
// duration: 2500,
|
||||
// isClosable: true,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// onModelConverted: (data: InvokeAI.ModelConvertedResponse) => {
|
||||
// const { converted_model_name, model_list } = data;
|
||||
// dispatch(setModelList(model_list));
|
||||
// dispatch(setCurrentStatus(i18n.t('common.statusModelConverted')));
|
||||
// dispatch(setIsProcessing(false));
|
||||
// dispatch(setIsCancelable(true));
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Model converted: ${converted_model_name}`,
|
||||
// level: 'info',
|
||||
// })
|
||||
// );
|
||||
// dispatch(
|
||||
// addToast({
|
||||
// title: `${i18n.t(
|
||||
// 'modelManager.modelConverted'
|
||||
// )}: ${converted_model_name}`,
|
||||
// status: 'success',
|
||||
// duration: 2500,
|
||||
// isClosable: true,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// onModelsMerged: (data: InvokeAI.ModelsMergedResponse) => {
|
||||
// const { merged_models, merged_model_name, model_list } = data;
|
||||
// dispatch(setModelList(model_list));
|
||||
// dispatch(setCurrentStatus(i18n.t('common.statusMergedModels')));
|
||||
// dispatch(setIsProcessing(false));
|
||||
// dispatch(setIsCancelable(true));
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Models merged: ${merged_models}`,
|
||||
// level: 'info',
|
||||
// })
|
||||
// );
|
||||
// dispatch(
|
||||
// addToast({
|
||||
// title: `${i18n.t('modelManager.modelsMerged')}: ${merged_model_name}`,
|
||||
// status: 'success',
|
||||
// duration: 2500,
|
||||
// isClosable: true,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// onModelChanged: (data: InvokeAI.ModelChangeResponse) => {
|
||||
// const { model_name, model_list } = data;
|
||||
// dispatch(setModelList(model_list));
|
||||
// dispatch(setCurrentStatus(i18n.t('common.statusModelChanged')));
|
||||
// dispatch(setIsProcessing(false));
|
||||
// dispatch(setIsCancelable(true));
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Model changed: ${model_name}`,
|
||||
// level: 'info',
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// onModelChangeFailed: (data: InvokeAI.ModelChangeResponse) => {
|
||||
// const { model_name, model_list } = data;
|
||||
// dispatch(setModelList(model_list));
|
||||
// dispatch(setIsProcessing(false));
|
||||
// dispatch(setIsCancelable(true));
|
||||
// dispatch(errorOccurred());
|
||||
// dispatch(
|
||||
// addLogEntry({
|
||||
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||
// message: `Model change failed: ${model_name}`,
|
||||
// level: 'error',
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// onTempFolderEmptied: () => {
|
||||
// dispatch(
|
||||
// addToast({
|
||||
// title: i18n.t('toast.tempFoldersEmptied'),
|
||||
// status: 'success',
|
||||
// duration: 2500,
|
||||
// isClosable: true,
|
||||
// })
|
||||
// );
|
||||
// },
|
||||
// };
|
||||
// };
|
||||
|
||||
export default makeSocketIOListeners;
|
||||
// export default makeSocketIOListeners;
|
||||
|
||||
export default {};
|
||||
|
@ -1,246 +1,248 @@
|
||||
import { Middleware } from '@reduxjs/toolkit';
|
||||
import { io } from 'socket.io-client';
|
||||
// import { Middleware } from '@reduxjs/toolkit';
|
||||
// import { io } from 'socket.io-client';
|
||||
|
||||
import makeSocketIOEmitters from './emitters';
|
||||
import makeSocketIOListeners from './listeners';
|
||||
// import makeSocketIOEmitters from './emitters';
|
||||
// import makeSocketIOListeners from './listeners';
|
||||
|
||||
import * as InvokeAI from 'app/types/invokeai';
|
||||
// import * as InvokeAI from 'app/types/invokeai';
|
||||
|
||||
/**
|
||||
* Creates a socketio middleware to handle communication with server.
|
||||
*
|
||||
* Special `socketio/actionName` actions are created in actions.ts and
|
||||
* exported for use by the application, which treats them like any old
|
||||
* action, using `dispatch` to dispatch them.
|
||||
*
|
||||
* These actions are intercepted here, where `socketio.emit()` calls are
|
||||
* made on their behalf - see `emitters.ts`. The emitter functions
|
||||
* are the outbound communication to the server.
|
||||
*
|
||||
* Listeners are also established here - see `listeners.ts`. The listener
|
||||
* functions receive communication from the server and usually dispatch
|
||||
* some new action to handle whatever data was sent from the server.
|
||||
*/
|
||||
export const socketioMiddleware = () => {
|
||||
const { origin } = new URL(window.location.href);
|
||||
// /**
|
||||
// * Creates a socketio middleware to handle communication with server.
|
||||
// *
|
||||
// * Special `socketio/actionName` actions are created in actions.ts and
|
||||
// * exported for use by the application, which treats them like any old
|
||||
// * action, using `dispatch` to dispatch them.
|
||||
// *
|
||||
// * These actions are intercepted here, where `socketio.emit()` calls are
|
||||
// * made on their behalf - see `emitters.ts`. The emitter functions
|
||||
// * are the outbound communication to the server.
|
||||
// *
|
||||
// * Listeners are also established here - see `listeners.ts`. The listener
|
||||
// * functions receive communication from the server and usually dispatch
|
||||
// * some new action to handle whatever data was sent from the server.
|
||||
// */
|
||||
// export const socketioMiddleware = () => {
|
||||
// const { origin } = new URL(window.location.href);
|
||||
|
||||
const socketio = io(origin, {
|
||||
timeout: 60000,
|
||||
path: `${window.location.pathname}socket.io`,
|
||||
});
|
||||
// const socketio = io(origin, {
|
||||
// timeout: 60000,
|
||||
// path: `${window.location.pathname}socket.io`,
|
||||
// });
|
||||
|
||||
socketio.disconnect();
|
||||
// socketio.disconnect();
|
||||
|
||||
let areListenersSet = false;
|
||||
// let areListenersSet = false;
|
||||
|
||||
const middleware: Middleware = (store) => (next) => (action) => {
|
||||
const {
|
||||
onConnect,
|
||||
onDisconnect,
|
||||
onError,
|
||||
onPostprocessingResult,
|
||||
onGenerationResult,
|
||||
onIntermediateResult,
|
||||
onProgressUpdate,
|
||||
onGalleryImages,
|
||||
onProcessingCanceled,
|
||||
onImageDeleted,
|
||||
onSystemConfig,
|
||||
onModelChanged,
|
||||
onFoundModels,
|
||||
onNewModelAdded,
|
||||
onModelDeleted,
|
||||
onModelConverted,
|
||||
onModelsMerged,
|
||||
onModelChangeFailed,
|
||||
onTempFolderEmptied,
|
||||
} = makeSocketIOListeners(store);
|
||||
// const middleware: Middleware = (store) => (next) => (action) => {
|
||||
// const {
|
||||
// onConnect,
|
||||
// onDisconnect,
|
||||
// onError,
|
||||
// onPostprocessingResult,
|
||||
// onGenerationResult,
|
||||
// onIntermediateResult,
|
||||
// onProgressUpdate,
|
||||
// onGalleryImages,
|
||||
// onProcessingCanceled,
|
||||
// onImageDeleted,
|
||||
// onSystemConfig,
|
||||
// onModelChanged,
|
||||
// onFoundModels,
|
||||
// onNewModelAdded,
|
||||
// onModelDeleted,
|
||||
// onModelConverted,
|
||||
// onModelsMerged,
|
||||
// onModelChangeFailed,
|
||||
// onTempFolderEmptied,
|
||||
// } = makeSocketIOListeners(store);
|
||||
|
||||
const {
|
||||
emitGenerateImage,
|
||||
emitRunESRGAN,
|
||||
emitRunFacetool,
|
||||
emitDeleteImage,
|
||||
emitRequestImages,
|
||||
emitRequestNewImages,
|
||||
emitCancelProcessing,
|
||||
emitRequestSystemConfig,
|
||||
emitSearchForModels,
|
||||
emitAddNewModel,
|
||||
emitDeleteModel,
|
||||
emitConvertToDiffusers,
|
||||
emitMergeDiffusersModels,
|
||||
emitRequestModelChange,
|
||||
emitSaveStagingAreaImageToGallery,
|
||||
emitRequestEmptyTempFolder,
|
||||
} = makeSocketIOEmitters(store, socketio);
|
||||
// const {
|
||||
// emitGenerateImage,
|
||||
// emitRunESRGAN,
|
||||
// emitRunFacetool,
|
||||
// emitDeleteImage,
|
||||
// emitRequestImages,
|
||||
// emitRequestNewImages,
|
||||
// emitCancelProcessing,
|
||||
// emitRequestSystemConfig,
|
||||
// emitSearchForModels,
|
||||
// emitAddNewModel,
|
||||
// emitDeleteModel,
|
||||
// emitConvertToDiffusers,
|
||||
// emitMergeDiffusersModels,
|
||||
// emitRequestModelChange,
|
||||
// emitSaveStagingAreaImageToGallery,
|
||||
// emitRequestEmptyTempFolder,
|
||||
// } = makeSocketIOEmitters(store, socketio);
|
||||
|
||||
/**
|
||||
* If this is the first time the middleware has been called (e.g. during store setup),
|
||||
* initialize all our socket.io listeners.
|
||||
*/
|
||||
if (!areListenersSet) {
|
||||
socketio.on('connect', () => onConnect());
|
||||
// /**
|
||||
// * If this is the first time the middleware has been called (e.g. during store setup),
|
||||
// * initialize all our socket.io listeners.
|
||||
// */
|
||||
// if (!areListenersSet) {
|
||||
// socketio.on('connect', () => onConnect());
|
||||
|
||||
socketio.on('disconnect', () => onDisconnect());
|
||||
// socketio.on('disconnect', () => onDisconnect());
|
||||
|
||||
socketio.on('error', (data: InvokeAI.ErrorResponse) => onError(data));
|
||||
// socketio.on('error', (data: InvokeAI.ErrorResponse) => onError(data));
|
||||
|
||||
socketio.on('generationResult', (data: InvokeAI.ImageResultResponse) =>
|
||||
onGenerationResult(data)
|
||||
);
|
||||
// socketio.on('generationResult', (data: InvokeAI.ImageResultResponse) =>
|
||||
// onGenerationResult(data)
|
||||
// );
|
||||
|
||||
socketio.on(
|
||||
'postprocessingResult',
|
||||
(data: InvokeAI.ImageResultResponse) => onPostprocessingResult(data)
|
||||
);
|
||||
// socketio.on(
|
||||
// 'postprocessingResult',
|
||||
// (data: InvokeAI.ImageResultResponse) => onPostprocessingResult(data)
|
||||
// );
|
||||
|
||||
socketio.on('intermediateResult', (data: InvokeAI.ImageResultResponse) =>
|
||||
onIntermediateResult(data)
|
||||
);
|
||||
// socketio.on('intermediateResult', (data: InvokeAI.ImageResultResponse) =>
|
||||
// onIntermediateResult(data)
|
||||
// );
|
||||
|
||||
socketio.on('progressUpdate', (data: InvokeAI.SystemStatus) =>
|
||||
onProgressUpdate(data)
|
||||
);
|
||||
// socketio.on('progressUpdate', (data: InvokeAI.SystemStatus) =>
|
||||
// onProgressUpdate(data)
|
||||
// );
|
||||
|
||||
socketio.on('galleryImages', (data: InvokeAI.GalleryImagesResponse) =>
|
||||
onGalleryImages(data)
|
||||
);
|
||||
// socketio.on('galleryImages', (data: InvokeAI.GalleryImagesResponse) =>
|
||||
// onGalleryImages(data)
|
||||
// );
|
||||
|
||||
socketio.on('processingCanceled', () => {
|
||||
onProcessingCanceled();
|
||||
});
|
||||
// socketio.on('processingCanceled', () => {
|
||||
// onProcessingCanceled();
|
||||
// });
|
||||
|
||||
socketio.on('imageDeleted', (data: InvokeAI.ImageDeletedResponse) => {
|
||||
onImageDeleted(data);
|
||||
});
|
||||
// socketio.on('imageDeleted', (data: InvokeAI.ImageDeletedResponse) => {
|
||||
// onImageDeleted(data);
|
||||
// });
|
||||
|
||||
socketio.on('systemConfig', (data: InvokeAI.SystemConfig) => {
|
||||
onSystemConfig(data);
|
||||
});
|
||||
// socketio.on('systemConfig', (data: InvokeAI.SystemConfig) => {
|
||||
// onSystemConfig(data);
|
||||
// });
|
||||
|
||||
socketio.on('foundModels', (data: InvokeAI.FoundModelResponse) => {
|
||||
onFoundModels(data);
|
||||
});
|
||||
// socketio.on('foundModels', (data: InvokeAI.FoundModelResponse) => {
|
||||
// onFoundModels(data);
|
||||
// });
|
||||
|
||||
socketio.on('newModelAdded', (data: InvokeAI.ModelAddedResponse) => {
|
||||
onNewModelAdded(data);
|
||||
});
|
||||
// socketio.on('newModelAdded', (data: InvokeAI.ModelAddedResponse) => {
|
||||
// onNewModelAdded(data);
|
||||
// });
|
||||
|
||||
socketio.on('modelDeleted', (data: InvokeAI.ModelDeletedResponse) => {
|
||||
onModelDeleted(data);
|
||||
});
|
||||
// socketio.on('modelDeleted', (data: InvokeAI.ModelDeletedResponse) => {
|
||||
// onModelDeleted(data);
|
||||
// });
|
||||
|
||||
socketio.on('modelConverted', (data: InvokeAI.ModelConvertedResponse) => {
|
||||
onModelConverted(data);
|
||||
});
|
||||
// socketio.on('modelConverted', (data: InvokeAI.ModelConvertedResponse) => {
|
||||
// onModelConverted(data);
|
||||
// });
|
||||
|
||||
socketio.on('modelsMerged', (data: InvokeAI.ModelsMergedResponse) => {
|
||||
onModelsMerged(data);
|
||||
});
|
||||
// socketio.on('modelsMerged', (data: InvokeAI.ModelsMergedResponse) => {
|
||||
// onModelsMerged(data);
|
||||
// });
|
||||
|
||||
socketio.on('modelChanged', (data: InvokeAI.ModelChangeResponse) => {
|
||||
onModelChanged(data);
|
||||
});
|
||||
// socketio.on('modelChanged', (data: InvokeAI.ModelChangeResponse) => {
|
||||
// onModelChanged(data);
|
||||
// });
|
||||
|
||||
socketio.on('modelChangeFailed', (data: InvokeAI.ModelChangeResponse) => {
|
||||
onModelChangeFailed(data);
|
||||
});
|
||||
// socketio.on('modelChangeFailed', (data: InvokeAI.ModelChangeResponse) => {
|
||||
// onModelChangeFailed(data);
|
||||
// });
|
||||
|
||||
socketio.on('tempFolderEmptied', () => {
|
||||
onTempFolderEmptied();
|
||||
});
|
||||
// socketio.on('tempFolderEmptied', () => {
|
||||
// onTempFolderEmptied();
|
||||
// });
|
||||
|
||||
areListenersSet = true;
|
||||
}
|
||||
// areListenersSet = true;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Handle redux actions caught by middleware.
|
||||
*/
|
||||
switch (action.type) {
|
||||
case 'socketio/generateImage': {
|
||||
emitGenerateImage(action.payload);
|
||||
break;
|
||||
}
|
||||
// /**
|
||||
// * Handle redux actions caught by middleware.
|
||||
// */
|
||||
// switch (action.type) {
|
||||
// case 'socketio/generateImage': {
|
||||
// emitGenerateImage(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/runESRGAN': {
|
||||
emitRunESRGAN(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/runESRGAN': {
|
||||
// emitRunESRGAN(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/runFacetool': {
|
||||
emitRunFacetool(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/runFacetool': {
|
||||
// emitRunFacetool(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/deleteImage': {
|
||||
emitDeleteImage(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/deleteImage': {
|
||||
// emitDeleteImage(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/requestImages': {
|
||||
emitRequestImages(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/requestImages': {
|
||||
// emitRequestImages(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/requestNewImages': {
|
||||
emitRequestNewImages(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/requestNewImages': {
|
||||
// emitRequestNewImages(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/cancelProcessing': {
|
||||
emitCancelProcessing();
|
||||
break;
|
||||
}
|
||||
// case 'socketio/cancelProcessing': {
|
||||
// emitCancelProcessing();
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/requestSystemConfig': {
|
||||
emitRequestSystemConfig();
|
||||
break;
|
||||
}
|
||||
// case 'socketio/requestSystemConfig': {
|
||||
// emitRequestSystemConfig();
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/searchForModels': {
|
||||
emitSearchForModels(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/searchForModels': {
|
||||
// emitSearchForModels(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/addNewModel': {
|
||||
emitAddNewModel(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/addNewModel': {
|
||||
// emitAddNewModel(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/deleteModel': {
|
||||
emitDeleteModel(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/deleteModel': {
|
||||
// emitDeleteModel(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/convertToDiffusers': {
|
||||
emitConvertToDiffusers(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/convertToDiffusers': {
|
||||
// emitConvertToDiffusers(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/mergeDiffusersModels': {
|
||||
emitMergeDiffusersModels(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/mergeDiffusersModels': {
|
||||
// emitMergeDiffusersModels(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/requestModelChange': {
|
||||
emitRequestModelChange(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/requestModelChange': {
|
||||
// emitRequestModelChange(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/saveStagingAreaImageToGallery': {
|
||||
emitSaveStagingAreaImageToGallery(action.payload);
|
||||
break;
|
||||
}
|
||||
// case 'socketio/saveStagingAreaImageToGallery': {
|
||||
// emitSaveStagingAreaImageToGallery(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/requestEmptyTempFolder': {
|
||||
emitRequestEmptyTempFolder();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// case 'socketio/requestEmptyTempFolder': {
|
||||
// emitRequestEmptyTempFolder();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
next(action);
|
||||
};
|
||||
// next(action);
|
||||
// };
|
||||
|
||||
return middleware;
|
||||
};
|
||||
// return middleware;
|
||||
// };
|
||||
|
||||
export default {};
|
||||
|
@ -19,7 +19,6 @@ import hotkeysReducer from 'features/ui/store/hotkeysSlice';
|
||||
import modelsReducer from 'features/system/store/modelSlice';
|
||||
import nodesReducer from 'features/nodes/store/nodesSlice';
|
||||
|
||||
import { socketioMiddleware } from '../socketio/middleware';
|
||||
import { socketMiddleware } from 'services/events/middleware';
|
||||
import { canvasDenylist } from 'features/canvas/store/canvasPersistDenylist';
|
||||
import { galleryDenylist } from 'features/gallery/store/galleryPersistDenylist';
|
||||
@ -87,13 +86,13 @@ const rootPersistConfig = getPersistConfig({
|
||||
const persistedReducer = persistReducer(rootPersistConfig, rootReducer);
|
||||
|
||||
// TODO: rip the old middleware out when nodes is complete
|
||||
export function buildMiddleware() {
|
||||
if (import.meta.env.MODE === 'nodes' || import.meta.env.MODE === 'package') {
|
||||
return socketMiddleware();
|
||||
} else {
|
||||
return socketioMiddleware();
|
||||
}
|
||||
}
|
||||
// export function buildMiddleware() {
|
||||
// if (import.meta.env.MODE === 'nodes' || import.meta.env.MODE === 'package') {
|
||||
// return socketMiddleware();
|
||||
// } else {
|
||||
// return socketioMiddleware();
|
||||
// }
|
||||
// }
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: persistedReducer,
|
||||
|
@ -111,9 +111,9 @@ export type FacetoolMetadata = CommonPostProcessedImageMetadata & {
|
||||
export type PostProcessedImageMetadata = ESRGANMetadata | FacetoolMetadata;
|
||||
|
||||
// Metadata includes the system config and image metadata.
|
||||
export type Metadata = SystemGenerationMetadata & {
|
||||
image: GeneratedImageMetadata | PostProcessedImageMetadata;
|
||||
};
|
||||
// export type Metadata = SystemGenerationMetadata & {
|
||||
// image: GeneratedImageMetadata | PostProcessedImageMetadata;
|
||||
// };
|
||||
|
||||
// An Image has a UUID, url, modified timestamp, width, height and maybe metadata
|
||||
export type _Image = {
|
||||
@ -150,31 +150,31 @@ export type GalleryImages = {
|
||||
* Types related to the system status.
|
||||
*/
|
||||
|
||||
// This represents the processing status of the backend.
|
||||
export type SystemStatus = {
|
||||
isProcessing: boolean;
|
||||
currentStep: number;
|
||||
totalSteps: number;
|
||||
currentIteration: number;
|
||||
totalIterations: number;
|
||||
currentStatus: string;
|
||||
currentStatusHasSteps: boolean;
|
||||
hasError: boolean;
|
||||
};
|
||||
// // This represents the processing status of the backend.
|
||||
// export type SystemStatus = {
|
||||
// isProcessing: boolean;
|
||||
// currentStep: number;
|
||||
// totalSteps: number;
|
||||
// currentIteration: number;
|
||||
// totalIterations: number;
|
||||
// currentStatus: string;
|
||||
// currentStatusHasSteps: boolean;
|
||||
// hasError: boolean;
|
||||
// };
|
||||
|
||||
export type SystemGenerationMetadata = {
|
||||
model: string;
|
||||
model_weights?: string;
|
||||
model_id?: string;
|
||||
model_hash: string;
|
||||
app_id: string;
|
||||
app_version: string;
|
||||
};
|
||||
// export type SystemGenerationMetadata = {
|
||||
// model: string;
|
||||
// model_weights?: string;
|
||||
// model_id?: string;
|
||||
// model_hash: string;
|
||||
// app_id: string;
|
||||
// app_version: string;
|
||||
// };
|
||||
|
||||
export type SystemConfig = SystemGenerationMetadata & {
|
||||
model_list: ModelList;
|
||||
infill_methods: string[];
|
||||
};
|
||||
// export type SystemConfig = SystemGenerationMetadata & {
|
||||
// model_list: ModelList;
|
||||
// infill_methods: string[];
|
||||
// };
|
||||
|
||||
export type ModelStatus = 'active' | 'cached' | 'not loaded';
|
||||
|
||||
@ -286,9 +286,9 @@ export type FoundModelResponse = {
|
||||
found_models: FoundModel[];
|
||||
};
|
||||
|
||||
export type SystemStatusResponse = SystemStatus;
|
||||
// export type SystemStatusResponse = SystemStatus;
|
||||
|
||||
export type SystemConfigResponse = SystemConfig;
|
||||
// export type SystemConfigResponse = SystemConfig;
|
||||
|
||||
export type ImageResultResponse = Omit<_Image, 'uuid'> & {
|
||||
boundingBox?: IRect;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ButtonGroup, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { saveStagingAreaImageToGallery } from 'app/socketio/actions';
|
||||
// import { saveStagingAreaImageToGallery } from 'app/socketio/actions';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { get, isEqual, isNumber, isString } from 'lodash-es';
|
||||
|
||||
import {
|
||||
ButtonGroup,
|
||||
@ -10,7 +10,7 @@ import {
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import { runESRGAN, runFacetool } from 'app/socketio/actions';
|
||||
// import { runESRGAN, runFacetool } from 'app/socketio/actions';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
@ -68,6 +68,7 @@ import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvas
|
||||
import { useGetUrl } from 'common/util/getUrl';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { imageDeleted } from 'services/thunks/image';
|
||||
import { useParameters } from 'features/parameters/hooks/useParameters';
|
||||
|
||||
const currentImageButtonsSelector = createSelector(
|
||||
[
|
||||
@ -112,6 +113,8 @@ const currentImageButtonsSelector = createSelector(
|
||||
isLightboxOpen,
|
||||
shouldHidePreview,
|
||||
image,
|
||||
seed: image?.metadata?.invokeai?.node?.seed,
|
||||
prompt: image?.metadata?.invokeai?.node?.prompt,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -161,16 +164,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
|
||||
const toast = useToast();
|
||||
const { t } = useTranslation();
|
||||
const setBothPrompts = useSetBothPrompts();
|
||||
|
||||
const handleClickUseAsInitialImage = useCallback(() => {
|
||||
if (!image) return;
|
||||
if (isLightboxOpen) dispatch(setIsLightboxOpen(false));
|
||||
dispatch(initialImageSelected({ name: image.name, type: image.type }));
|
||||
// dispatch(setInitialImage(currentImage));
|
||||
|
||||
// dispatch(setActiveTab('img2img'));
|
||||
}, [dispatch, image, isLightboxOpen]);
|
||||
const { recallPrompt, recallSeed, sendToImageToImage } = useParameters();
|
||||
|
||||
const handleCopyImage = useCallback(async () => {
|
||||
if (!image?.url) {
|
||||
@ -217,30 +212,6 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
});
|
||||
}, [toast, shouldTransformUrls, getUrl, t, image]);
|
||||
|
||||
useHotkeys(
|
||||
'shift+i',
|
||||
() => {
|
||||
if (image) {
|
||||
handleClickUseAsInitialImage();
|
||||
toast({
|
||||
title: t('toast.sentToImageToImage'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
title: t('toast.imageNotLoaded'),
|
||||
description: t('toast.imageNotLoadedDesc'),
|
||||
status: 'error',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
[image]
|
||||
);
|
||||
|
||||
const handlePreviewVisibility = useCallback(() => {
|
||||
dispatch(setShouldHidePreview(!shouldHidePreview));
|
||||
}, [dispatch, shouldHidePreview]);
|
||||
@ -259,7 +230,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
useHotkeys(
|
||||
'a',
|
||||
() => {
|
||||
if (['txt2img', 'img2img'].includes(image?.metadata?.sd_metadata?.type)) {
|
||||
const type = image?.metadata?.invokeai?.node?.types;
|
||||
if (isString(type) && ['txt2img', 'img2img'].includes(type)) {
|
||||
handleClickUseAllParameters();
|
||||
toast({
|
||||
title: t('toast.parametersSet'),
|
||||
@ -280,63 +252,23 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
[image]
|
||||
);
|
||||
|
||||
const handleClickUseSeed = () => {
|
||||
image?.metadata && dispatch(setSeed(image.metadata.sd_metadata.seed));
|
||||
};
|
||||
const handleUseSeed = useCallback(() => {
|
||||
recallSeed(image?.metadata?.invokeai?.node?.seed);
|
||||
}, [image, recallSeed]);
|
||||
|
||||
useHotkeys(
|
||||
's',
|
||||
() => {
|
||||
if (image?.metadata?.sd_metadata?.seed) {
|
||||
handleClickUseSeed();
|
||||
toast({
|
||||
title: t('toast.seedSet'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
title: t('toast.seedNotSet'),
|
||||
description: t('toast.seedNotSetDesc'),
|
||||
status: 'error',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
[image]
|
||||
);
|
||||
useHotkeys('s', handleUseSeed, [image]);
|
||||
|
||||
const handleClickUsePrompt = useCallback(() => {
|
||||
if (image?.metadata?.sd_metadata?.prompt) {
|
||||
setBothPrompts(image?.metadata?.sd_metadata?.prompt);
|
||||
}
|
||||
}, [image?.metadata?.sd_metadata?.prompt, setBothPrompts]);
|
||||
const handleUsePrompt = useCallback(() => {
|
||||
recallPrompt(image?.metadata?.invokeai?.node?.prompt);
|
||||
}, [image, recallPrompt]);
|
||||
|
||||
useHotkeys(
|
||||
'p',
|
||||
() => {
|
||||
if (image?.metadata?.sd_metadata?.prompt) {
|
||||
handleClickUsePrompt();
|
||||
toast({
|
||||
title: t('toast.promptSet'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
title: t('toast.promptNotSet'),
|
||||
description: t('toast.promptNotSetDesc'),
|
||||
status: 'error',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
[image]
|
||||
);
|
||||
useHotkeys('p', handleUsePrompt, [image]);
|
||||
|
||||
const handleSendToImageToImage = useCallback(() => {
|
||||
sendToImageToImage(image);
|
||||
}, [image, sendToImageToImage]);
|
||||
|
||||
useHotkeys('shift+i', handleSendToImageToImage, [image]);
|
||||
|
||||
const handleClickUpscale = useCallback(() => {
|
||||
// selectedImage && dispatch(runESRGAN(selectedImage));
|
||||
@ -496,7 +428,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
>
|
||||
<IAIButton
|
||||
size="sm"
|
||||
onClick={handleClickUseAsInitialImage}
|
||||
onClick={handleSendToImageToImage}
|
||||
leftIcon={<FaShare />}
|
||||
>
|
||||
{t('parameters.sendToImg2Img')}
|
||||
@ -570,8 +502,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
icon={<FaQuoteRight />}
|
||||
tooltip={`${t('parameters.usePrompt')} (P)`}
|
||||
aria-label={`${t('parameters.usePrompt')} (P)`}
|
||||
isDisabled={!image?.metadata?.sd_metadata?.prompt}
|
||||
onClick={handleClickUsePrompt}
|
||||
isDisabled={!image?.metadata?.invokeai?.node?.prompt}
|
||||
onClick={handleUsePrompt}
|
||||
/>
|
||||
|
||||
<IAIIconButton
|
||||
@ -579,7 +511,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
||||
tooltip={`${t('parameters.useSeed')} (S)`}
|
||||
aria-label={`${t('parameters.useSeed')} (S)`}
|
||||
isDisabled={!image?.metadata?.sd_metadata?.seed}
|
||||
onClick={handleClickUseSeed}
|
||||
onClick={handleUseSeed}
|
||||
/>
|
||||
|
||||
<IAIIconButton
|
||||
|
@ -5,65 +5,37 @@ import {
|
||||
Image,
|
||||
MenuItem,
|
||||
MenuList,
|
||||
Text,
|
||||
useDisclosure,
|
||||
useTheme,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
imageSelected,
|
||||
setCurrentImage,
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
import {
|
||||
initialImageSelected,
|
||||
setAllImageToImageParameters,
|
||||
setAllParameters,
|
||||
setSeed,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { DragEvent, memo, useState } from 'react';
|
||||
import {
|
||||
FaCheck,
|
||||
FaExpand,
|
||||
FaLink,
|
||||
FaShare,
|
||||
FaTrash,
|
||||
FaTrashAlt,
|
||||
} from 'react-icons/fa';
|
||||
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
||||
import { DragEvent, memo, useCallback, useState } from 'react';
|
||||
import { FaCheck, FaExpand, FaShare, FaTrash } from 'react-icons/fa';
|
||||
import DeleteImageModal from './DeleteImageModal';
|
||||
import { ContextMenu } from 'chakra-ui-contextmenu';
|
||||
import * as InvokeAI from 'app/types/invokeai';
|
||||
import {
|
||||
resizeAndScaleCanvas,
|
||||
setInitialCanvasImage,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { resizeAndScaleCanvas } from 'features/canvas/store/canvasSlice';
|
||||
import { gallerySelector } from 'features/gallery/store/gallerySelectors';
|
||||
import { setActiveTab } from 'features/ui/store/uiSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import useSetBothPrompts from 'features/parameters/hooks/usePrompt';
|
||||
import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { useGetUrl } from 'common/util/getUrl';
|
||||
import { ExternalLinkIcon } from '@chakra-ui/icons';
|
||||
import { BiZoomIn } from 'react-icons/bi';
|
||||
import { IoArrowUndoCircleOutline } from 'react-icons/io5';
|
||||
import { imageDeleted } from 'services/thunks/image';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import { configSelector } from 'features/system/store/configSelectors';
|
||||
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { useParameters } from 'features/parameters/hooks/useParameters';
|
||||
|
||||
export const selector = createSelector(
|
||||
[
|
||||
gallerySelector,
|
||||
systemSelector,
|
||||
configSelector,
|
||||
lightboxSelector,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(gallery, system, config, lightbox, activeTabName) => {
|
||||
[gallerySelector, systemSelector, lightboxSelector, activeTabNameSelector],
|
||||
(gallery, system, lightbox, activeTabName) => {
|
||||
const {
|
||||
galleryImageObjectFit,
|
||||
galleryImageMinimumWidth,
|
||||
@ -71,7 +43,6 @@ export const selector = createSelector(
|
||||
} = gallery;
|
||||
|
||||
const { isLightboxOpen } = lightbox;
|
||||
const { disabledFeatures } = config;
|
||||
const { isConnected, isProcessing, shouldConfirmOnDelete } = system;
|
||||
|
||||
return {
|
||||
@ -82,7 +53,6 @@ export const selector = createSelector(
|
||||
shouldUseSingleGalleryColumn,
|
||||
activeTabName,
|
||||
isLightboxOpen,
|
||||
disabledFeatures,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -113,14 +83,15 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
galleryImageMinimumWidth,
|
||||
canDeleteImage,
|
||||
shouldUseSingleGalleryColumn,
|
||||
disabledFeatures,
|
||||
shouldConfirmOnDelete,
|
||||
} = useAppSelector(selector);
|
||||
|
||||
const {
|
||||
isOpen: isDeleteDialogOpen,
|
||||
onOpen: onDeleteDialogOpen,
|
||||
onClose: onDeleteDialogClose,
|
||||
} = useDisclosure();
|
||||
|
||||
const { image, isSelected } = props;
|
||||
const { url, thumbnail, name, metadata } = image;
|
||||
const { getUrl } = useGetUrl();
|
||||
@ -130,53 +101,62 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
const toast = useToast();
|
||||
const { direction } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const setBothPrompts = useSetBothPrompts();
|
||||
const { isFeatureEnabled: isLightboxEnabled } = useFeatureStatus('lightbox');
|
||||
const { recallSeed, recallPrompt, sendToImageToImage, recallInitialImage } =
|
||||
useParameters();
|
||||
|
||||
const handleMouseOver = () => setIsHovered(true);
|
||||
|
||||
const handleMouseOut = () => setIsHovered(false);
|
||||
|
||||
const handleInitiateDelete = () => {
|
||||
// Immediately deletes an image
|
||||
const handleDelete = useCallback(() => {
|
||||
if (canDeleteImage && image) {
|
||||
dispatch(imageDeleted({ imageType: image.type, imageName: image.name }));
|
||||
}
|
||||
}, [dispatch, image, canDeleteImage]);
|
||||
|
||||
// Opens the alert dialog to check if user is sure they want to delete
|
||||
const handleInitiateDelete = useCallback(() => {
|
||||
if (shouldConfirmOnDelete) {
|
||||
onDeleteDialogOpen();
|
||||
} else {
|
||||
handleDelete();
|
||||
}
|
||||
};
|
||||
}, [handleDelete, onDeleteDialogOpen, shouldConfirmOnDelete]);
|
||||
|
||||
const handleDelete = () => {
|
||||
if (canDeleteImage && image) {
|
||||
dispatch(imageDeleted({ imageType: image.type, imageName: image.name }));
|
||||
}
|
||||
};
|
||||
const handleSelectImage = useCallback(() => {
|
||||
dispatch(imageSelected(image.name));
|
||||
}, [image, dispatch]);
|
||||
|
||||
const handleUsePrompt = () => {
|
||||
if (typeof image.metadata?.invokeai?.node?.prompt === 'string') {
|
||||
setBothPrompts(image.metadata?.invokeai?.node?.prompt);
|
||||
}
|
||||
toast({
|
||||
title: t('toast.promptSet'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
};
|
||||
const handleDragStart = useCallback(
|
||||
(e: DragEvent<HTMLDivElement>) => {
|
||||
e.dataTransfer.setData('invokeai/imageName', image.name);
|
||||
e.dataTransfer.setData('invokeai/imageType', image.type);
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
},
|
||||
[image]
|
||||
);
|
||||
|
||||
const handleUseSeed = () => {
|
||||
typeof image.metadata.invokeai?.node?.seed === 'number' &&
|
||||
dispatch(setSeed(image.metadata.invokeai?.node?.seed));
|
||||
toast({
|
||||
title: t('toast.seedSet'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
};
|
||||
// Recall parameters handlers
|
||||
const handleRecallPrompt = useCallback(() => {
|
||||
recallPrompt(image.metadata?.invokeai?.node?.prompt);
|
||||
}, [image, recallPrompt]);
|
||||
|
||||
const handleSendToImageToImage = () => {
|
||||
dispatch(initialImageSelected(image.name));
|
||||
};
|
||||
const handleRecallSeed = useCallback(() => {
|
||||
recallSeed(image.metadata.invokeai?.node?.seed);
|
||||
}, [image, recallSeed]);
|
||||
|
||||
const handleSendToImageToImage = useCallback(() => {
|
||||
sendToImageToImage(image);
|
||||
}, [image, sendToImageToImage]);
|
||||
|
||||
const handleRecallInitialImage = useCallback(() => {
|
||||
recallInitialImage(image.metadata.invokeai?.node?.image);
|
||||
}, [image, recallInitialImage]);
|
||||
|
||||
/**
|
||||
* TODO: the rest of these
|
||||
*/
|
||||
const handleSendToCanvas = () => {
|
||||
// dispatch(setInitialCanvasImage(image));
|
||||
|
||||
@ -205,41 +185,6 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
// });
|
||||
};
|
||||
|
||||
const handleUseInitialImage = async () => {
|
||||
// if (metadata.invokeai?.node?.image?.init_image_path) {
|
||||
// const response = await fetch(
|
||||
// metadata.invokeai?.node?.image?.init_image_path
|
||||
// );
|
||||
// if (response.ok) {
|
||||
// dispatch(setAllImageToImageParameters(metadata?.invokeai?.node));
|
||||
// toast({
|
||||
// title: t('toast.initialImageSet'),
|
||||
// status: 'success',
|
||||
// duration: 2500,
|
||||
// isClosable: true,
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// toast({
|
||||
// title: t('toast.initialImageNotSet'),
|
||||
// description: t('toast.initialImageNotSetDesc'),
|
||||
// status: 'error',
|
||||
// duration: 2500,
|
||||
// isClosable: true,
|
||||
// });
|
||||
};
|
||||
|
||||
const handleSelectImage = () => {
|
||||
dispatch(imageSelected(image.name));
|
||||
};
|
||||
|
||||
const handleDragStart = (e: DragEvent<HTMLDivElement>) => {
|
||||
e.dataTransfer.setData('invokeai/imageName', image.name);
|
||||
e.dataTransfer.setData('invokeai/imageType', image.type);
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
};
|
||||
|
||||
const handleLightBox = () => {
|
||||
// dispatch(setCurrentImage(image));
|
||||
// dispatch(setIsLightboxOpen(true));
|
||||
@ -254,21 +199,21 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
<ContextMenu<HTMLDivElement>
|
||||
menuProps={{ size: 'sm', isLazy: true }}
|
||||
renderMenu={() => (
|
||||
<MenuList>
|
||||
<MenuList sx={{ visibility: 'visible !important' }}>
|
||||
<MenuItem
|
||||
icon={<ExternalLinkIcon />}
|
||||
onClickCapture={handleOpenInNewTab}
|
||||
>
|
||||
{t('common.openInNewTab')}
|
||||
</MenuItem>
|
||||
{!disabledFeatures.includes('lightbox') && (
|
||||
{isLightboxEnabled && (
|
||||
<MenuItem icon={<FaExpand />} onClickCapture={handleLightBox}>
|
||||
{t('parameters.openInViewer')}
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem
|
||||
icon={<IoArrowUndoCircleOutline />}
|
||||
onClickCapture={handleUsePrompt}
|
||||
onClickCapture={handleRecallPrompt}
|
||||
isDisabled={image?.metadata?.invokeai?.node?.prompt === undefined}
|
||||
>
|
||||
{t('parameters.usePrompt')}
|
||||
@ -276,14 +221,14 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
|
||||
<MenuItem
|
||||
icon={<IoArrowUndoCircleOutline />}
|
||||
onClickCapture={handleUseSeed}
|
||||
onClickCapture={handleRecallSeed}
|
||||
isDisabled={image?.metadata?.invokeai?.node?.seed === undefined}
|
||||
>
|
||||
{t('parameters.useSeed')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={<IoArrowUndoCircleOutline />}
|
||||
onClickCapture={handleUseInitialImage}
|
||||
onClickCapture={handleRecallInitialImage}
|
||||
isDisabled={image?.metadata?.invokeai?.node?.type !== 'img2img'}
|
||||
>
|
||||
{t('parameters.useInitImg')}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ButtonGroup, Flex, Grid, Icon, Image, Text } from '@chakra-ui/react';
|
||||
import { requestImages } from 'app/socketio/actions';
|
||||
// import { requestImages } from 'app/socketio/actions';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAICheckbox from 'common/components/IAICheckbox';
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { readinessSelector } from 'app/selectors/readinessSelector';
|
||||
import { generateImage } from 'app/socketio/actions';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton, { IAIButtonProps } from 'common/components/IAIButton';
|
||||
import IAIIconButton, {
|
||||
@ -8,10 +7,11 @@ import IAIIconButton, {
|
||||
} from 'common/components/IAIIconButton';
|
||||
import { clampSymmetrySteps } from 'features/parameters/store/generationSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { useCallback } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaPlay } from 'react-icons/fa';
|
||||
import { generateGraphBuilt, sessionCreated } from 'services/thunks/session';
|
||||
import { generateGraphBuilt } from 'services/thunks/session';
|
||||
|
||||
interface InvokeButton
|
||||
extends Omit<IAIButtonProps | IAIIconButtonProps, 'aria-label'> {
|
||||
@ -24,19 +24,16 @@ export default function InvokeButton(props: InvokeButton) {
|
||||
const { isReady } = useAppSelector(readinessSelector);
|
||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||
|
||||
const handleClickGenerate = () => {
|
||||
// dispatch(generateImage(activeTabName));
|
||||
const handleInvoke = useCallback(() => {
|
||||
dispatch(clampSymmetrySteps());
|
||||
dispatch(generateGraphBuilt());
|
||||
};
|
||||
}, [dispatch]);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
useHotkeys(
|
||||
['ctrl+enter', 'meta+enter'],
|
||||
() => {
|
||||
dispatch(clampSymmetrySteps());
|
||||
dispatch(generateImage(activeTabName));
|
||||
},
|
||||
handleInvoke,
|
||||
{
|
||||
enabled: () => isReady,
|
||||
preventDefault: true,
|
||||
@ -53,7 +50,7 @@ export default function InvokeButton(props: InvokeButton) {
|
||||
type="submit"
|
||||
icon={<FaPlay />}
|
||||
isDisabled={!isReady}
|
||||
onClick={handleClickGenerate}
|
||||
onClick={handleInvoke}
|
||||
flexGrow={1}
|
||||
w="100%"
|
||||
tooltip={t('parameters.invoke')}
|
||||
@ -66,7 +63,7 @@ export default function InvokeButton(props: InvokeButton) {
|
||||
aria-label={t('parameters.invoke')}
|
||||
type="submit"
|
||||
isDisabled={!isReady}
|
||||
onClick={handleClickGenerate}
|
||||
onClick={handleInvoke}
|
||||
flexGrow={1}
|
||||
w="100%"
|
||||
colorScheme="accent"
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Box, FormControl, Textarea } from '@chakra-ui/react';
|
||||
import { generateImage } from 'app/socketio/actions';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { ChangeEvent, KeyboardEvent, useRef } from 'react';
|
||||
@ -8,6 +7,7 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import { readinessSelector } from 'app/selectors/readinessSelector';
|
||||
import {
|
||||
GenerationState,
|
||||
clampSymmetrySteps,
|
||||
setPrompt,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
@ -15,6 +15,7 @@ import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { generateGraphBuilt } from 'services/thunks/session';
|
||||
|
||||
const promptInputSelector = createSelector(
|
||||
[(state: RootState) => state.generation, activeTabNameSelector],
|
||||
@ -36,7 +37,7 @@ const promptInputSelector = createSelector(
|
||||
*/
|
||||
const PromptInput = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { prompt, activeTabName } = useAppSelector(promptInputSelector);
|
||||
const { prompt } = useAppSelector(promptInputSelector);
|
||||
const { isReady } = useAppSelector(readinessSelector);
|
||||
|
||||
const promptRef = useRef<HTMLTextAreaElement>(null);
|
||||
@ -58,7 +59,8 @@ const PromptInput = () => {
|
||||
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === 'Enter' && e.shiftKey === false && isReady) {
|
||||
e.preventDefault();
|
||||
dispatch(generateImage(activeTabName));
|
||||
dispatch(clampSymmetrySteps());
|
||||
dispatch(generateGraphBuilt());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,130 @@
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { isFinite, isString } from 'lodash-es';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import useSetBothPrompts from './usePrompt';
|
||||
import { initialImageSelected, setSeed } from '../store/generationSlice';
|
||||
import { isImage, isImageField } from 'services/types/guards';
|
||||
import { NUMPY_RAND_MAX } from 'app/constants';
|
||||
|
||||
export const useParameters = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const toast = useToast();
|
||||
const { t } = useTranslation();
|
||||
const setBothPrompts = useSetBothPrompts();
|
||||
|
||||
/**
|
||||
* Sets prompt with toast
|
||||
*/
|
||||
const recallPrompt = useCallback(
|
||||
(prompt: unknown) => {
|
||||
if (!isString(prompt)) {
|
||||
toast({
|
||||
title: t('toast.promptNotSet'),
|
||||
description: t('toast.promptNotSetDesc'),
|
||||
status: 'warning',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setBothPrompts(prompt);
|
||||
toast({
|
||||
title: t('toast.promptSet'),
|
||||
status: 'info',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
},
|
||||
[t, toast, setBothPrompts]
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets seed with toast
|
||||
*/
|
||||
const recallSeed = useCallback(
|
||||
(seed: unknown) => {
|
||||
const s = Number(seed);
|
||||
if (!isFinite(s) || (isFinite(s) && !(s >= 0 && s <= NUMPY_RAND_MAX))) {
|
||||
toast({
|
||||
title: t('toast.seedNotSet'),
|
||||
description: t('toast.seedNotSetDesc'),
|
||||
status: 'error',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(setSeed(s));
|
||||
toast({
|
||||
title: t('toast.seedSet'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
},
|
||||
[t, toast, dispatch]
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets initial image with toast
|
||||
*/
|
||||
const recallInitialImage = useCallback(
|
||||
async (image: unknown) => {
|
||||
if (!isImageField(image)) {
|
||||
toast({
|
||||
title: t('toast.initialImageNotSet'),
|
||||
description: t('toast.initialImageNotSetDesc'),
|
||||
status: 'error',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
initialImageSelected({ name: image.image_name, type: image.image_type })
|
||||
);
|
||||
toast({
|
||||
title: t('toast.initialImageSet'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
},
|
||||
[t, toast, dispatch]
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets image as initial image with toast
|
||||
*/
|
||||
const sendToImageToImage = useCallback(
|
||||
(image: unknown) => {
|
||||
if (!isImage(image)) {
|
||||
toast({
|
||||
title: t('toast.imageNotLoaded'),
|
||||
description: t('toast.imageNotLoadedDesc'),
|
||||
status: 'error',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(initialImageSelected({ name: image.name, type: image.type }));
|
||||
|
||||
toast({
|
||||
title: t('toast.sentToImageToImage'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
},
|
||||
[t, toast, dispatch]
|
||||
);
|
||||
|
||||
return { recallPrompt, recallSeed, recallInitialImage, sendToImageToImage };
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import { emptyTempFolder } from 'app/socketio/actions';
|
||||
// import { emptyTempFolder } from 'app/socketio/actions';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
|
@ -17,7 +17,7 @@ import React from 'react';
|
||||
|
||||
import SearchModels from './SearchModels';
|
||||
|
||||
import { addNewModel } from 'app/socketio/actions';
|
||||
// import { addNewModel } from 'app/socketio/actions';
|
||||
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
VStack,
|
||||
} from '@chakra-ui/react';
|
||||
import { InvokeDiffusersModelConfigProps } from 'app/types/invokeai';
|
||||
import { addNewModel } from 'app/socketio/actions';
|
||||
// import { addNewModel } from 'app/socketio/actions';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIInput from 'common/components/IAIInput';
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
VStack,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { addNewModel } from 'app/socketio/actions';
|
||||
// import { addNewModel } from 'app/socketio/actions';
|
||||
import { Field, Formik } from 'formik';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
|
@ -9,7 +9,7 @@ import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
|
||||
import { Flex, FormControl, FormLabel, Text, VStack } from '@chakra-ui/react';
|
||||
|
||||
import { addNewModel } from 'app/socketio/actions';
|
||||
// import { addNewModel } from 'app/socketio/actions';
|
||||
import { Field, Formik } from 'formik';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
Tooltip,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { mergeDiffusersModels } from 'app/socketio/actions';
|
||||
// import { mergeDiffusersModels } from 'app/socketio/actions';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
UnorderedList,
|
||||
Tooltip,
|
||||
} from '@chakra-ui/react';
|
||||
import { convertToDiffusers } from 'app/socketio/actions';
|
||||
// import { convertToDiffusers } from 'app/socketio/actions';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { DeleteIcon, EditIcon } from '@chakra-ui/icons';
|
||||
import { Box, Button, Flex, Spacer, Text, Tooltip } from '@chakra-ui/react';
|
||||
import { ModelStatus } from 'app/types/invokeai';
|
||||
import { deleteModel, requestModelChange } from 'app/socketio/actions';
|
||||
// import { deleteModel, requestModelChange } from 'app/socketio/actions';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
||||
|
@ -20,7 +20,7 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { FaSearch, FaTrash } from 'react-icons/fa';
|
||||
|
||||
import { addNewModel, searchForModels } from 'app/socketio/actions';
|
||||
// import { addNewModel, searchForModels } from 'app/socketio/actions';
|
||||
import {
|
||||
setFoundModels,
|
||||
setSearchFolder,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import {
|
||||
ChakraProps,
|
||||
Flex,
|
||||
Grid,
|
||||
Heading,
|
||||
Modal,
|
||||
ModalBody,
|
||||
@ -14,22 +13,16 @@ import {
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { IN_PROGRESS_IMAGE_TYPES } from 'app/constants';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import IAISelect from 'common/components/IAISelect';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import {
|
||||
consoleLogLevelChanged,
|
||||
InProgressImageType,
|
||||
setEnableImageDebugging,
|
||||
setSaveIntermediatesInterval,
|
||||
setShouldConfirmOnDelete,
|
||||
setShouldDisplayGuides,
|
||||
setShouldDisplayInProgressType,
|
||||
shouldLogToConsoleChanged,
|
||||
SystemState,
|
||||
} from 'features/system/store/systemSlice';
|
||||
@ -39,23 +32,19 @@ import {
|
||||
setShouldUseSliders,
|
||||
} from 'features/ui/store/uiSlice';
|
||||
import { UIState } from 'features/ui/store/uiTypes';
|
||||
import { isEqual, map } from 'lodash-es';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { persistor } from 'app/store/persistor';
|
||||
import { ChangeEvent, cloneElement, ReactElement, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger';
|
||||
import { VALID_LOG_LEVELS } from 'app/logging/useLogger';
|
||||
import { LogLevelName } from 'roarr';
|
||||
import { F } from 'ts-toolbelt';
|
||||
|
||||
const selector = createSelector(
|
||||
[systemSelector, uiSelector],
|
||||
(system: SystemState, ui: UIState) => {
|
||||
const {
|
||||
shouldDisplayInProgressType,
|
||||
shouldConfirmOnDelete,
|
||||
shouldDisplayGuides,
|
||||
model_list,
|
||||
saveIntermediatesInterval,
|
||||
enableImageDebugging,
|
||||
consoleLogLevel,
|
||||
shouldLogToConsole,
|
||||
@ -64,11 +53,8 @@ const selector = createSelector(
|
||||
const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui;
|
||||
|
||||
return {
|
||||
shouldDisplayInProgressType,
|
||||
shouldConfirmOnDelete,
|
||||
shouldDisplayGuides,
|
||||
models: map(model_list, (_model, key) => key),
|
||||
saveIntermediatesInterval,
|
||||
enableImageDebugging,
|
||||
shouldUseCanvasBetaLayout,
|
||||
shouldUseSliders,
|
||||
@ -104,8 +90,6 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const steps = useAppSelector((state: RootState) => state.generation.steps);
|
||||
|
||||
const {
|
||||
isOpen: isSettingsModalOpen,
|
||||
onOpen: onSettingsModalOpen,
|
||||
@ -119,10 +103,8 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
||||
} = useDisclosure();
|
||||
|
||||
const {
|
||||
shouldDisplayInProgressType,
|
||||
shouldConfirmOnDelete,
|
||||
shouldDisplayGuides,
|
||||
saveIntermediatesInterval,
|
||||
enableImageDebugging,
|
||||
shouldUseCanvasBetaLayout,
|
||||
shouldUseSliders,
|
||||
@ -134,18 +116,12 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
||||
* Resets localstorage, then opens a secondary modal informing user to
|
||||
* refresh their browser.
|
||||
* */
|
||||
const handleClickResetWebUI = () => {
|
||||
const handleClickResetWebUI = useCallback(() => {
|
||||
persistor.purge().then(() => {
|
||||
onSettingsModalClose();
|
||||
onRefreshModalOpen();
|
||||
});
|
||||
};
|
||||
|
||||
const handleChangeIntermediateSteps = (value: number) => {
|
||||
if (value > steps) value = steps;
|
||||
if (value < 1) value = 1;
|
||||
dispatch(setSaveIntermediatesInterval(value));
|
||||
};
|
||||
}, [onSettingsModalClose, onRefreshModalOpen]);
|
||||
|
||||
const handleLogLevelChanged = useCallback(
|
||||
(e: ChangeEvent<HTMLSelectElement>) => {
|
||||
@ -182,32 +158,6 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
||||
<Flex sx={modalSectionStyles}>
|
||||
<Heading size="sm">{t('settings.general')}</Heading>
|
||||
|
||||
<IAISelect
|
||||
horizontal
|
||||
spaceEvenly
|
||||
label={t('settings.displayInProgress')}
|
||||
validValues={IN_PROGRESS_IMAGE_TYPES}
|
||||
value={shouldDisplayInProgressType}
|
||||
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
|
||||
dispatch(
|
||||
setShouldDisplayInProgressType(
|
||||
e.target.value as InProgressImageType
|
||||
)
|
||||
)
|
||||
}
|
||||
/>
|
||||
{shouldDisplayInProgressType === 'full-res' && (
|
||||
<IAINumberInput
|
||||
label={t('settings.saveSteps')}
|
||||
min={1}
|
||||
max={steps}
|
||||
step={1}
|
||||
onChange={handleChangeIntermediateSteps}
|
||||
value={saveIntermediatesInterval}
|
||||
width="auto"
|
||||
textAlign="center"
|
||||
/>
|
||||
)}
|
||||
<IAISwitch
|
||||
label={t('settings.confirmOnDelete')}
|
||||
isChecked={shouldConfirmOnDelete}
|
||||
|
@ -1,22 +1,19 @@
|
||||
import { Text, Tooltip } from '@chakra-ui/react';
|
||||
import { Text } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { errorSeen, SystemState } from 'features/system/store/systemSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { systemSelector } from '../store/systemSelectors';
|
||||
|
||||
const statusIndicatorSelector = createSelector(
|
||||
systemSelector,
|
||||
(system: SystemState) => {
|
||||
(system) => {
|
||||
return {
|
||||
isConnected: system.isConnected,
|
||||
isProcessing: system.isProcessing,
|
||||
currentIteration: system.currentIteration,
|
||||
totalIterations: system.totalIterations,
|
||||
currentStatus: system.currentStatus,
|
||||
hasError: system.hasError,
|
||||
wasErrorSeen: system.wasErrorSeen,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -31,15 +28,12 @@ const StatusIndicator = () => {
|
||||
currentIteration,
|
||||
totalIterations,
|
||||
currentStatus,
|
||||
hasError,
|
||||
wasErrorSeen,
|
||||
} = useAppSelector(statusIndicatorSelector);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
let statusIdentifier;
|
||||
|
||||
if (isConnected && !hasError) {
|
||||
if (isConnected) {
|
||||
statusIdentifier = 'ok';
|
||||
} else {
|
||||
statusIdentifier = 'error';
|
||||
@ -60,25 +54,8 @@ const StatusIndicator = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const tooltipLabel =
|
||||
hasError && !wasErrorSeen
|
||||
? 'Click to clear, check logs for details'
|
||||
: undefined;
|
||||
|
||||
const statusIndicatorCursor =
|
||||
hasError && !wasErrorSeen ? 'pointer' : 'initial';
|
||||
|
||||
const handleClickStatusIndicator = () => {
|
||||
if (hasError || !wasErrorSeen) {
|
||||
dispatch(errorSeen());
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Tooltip label={tooltipLabel}>
|
||||
<Text
|
||||
cursor={statusIndicatorCursor}
|
||||
onClick={handleClickStatusIndicator}
|
||||
sx={{
|
||||
fontSize: 'sm',
|
||||
fontWeight: '600',
|
||||
@ -87,7 +64,6 @@ const StatusIndicator = () => {
|
||||
>
|
||||
{t(statusMessage as keyof typeof t)}
|
||||
</Text>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -23,33 +23,14 @@ import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
|
||||
import { LogLevelName } from 'roarr';
|
||||
import { InvokeLogLevel } from 'app/logging/useLogger';
|
||||
|
||||
export type LogLevel = 'info' | 'warning' | 'error';
|
||||
|
||||
export interface LogEntry {
|
||||
timestamp: string;
|
||||
level: LogLevel;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface Log {
|
||||
[index: number]: LogEntry;
|
||||
}
|
||||
|
||||
export type InProgressImageType = 'none' | 'full-res' | 'latents';
|
||||
|
||||
export type CancelType = 'immediate' | 'scheduled';
|
||||
|
||||
export interface SystemState
|
||||
extends InvokeAI.SystemStatus,
|
||||
InvokeAI.SystemConfig {
|
||||
shouldDisplayInProgressType: InProgressImageType;
|
||||
shouldShowLogViewer: boolean;
|
||||
export interface SystemState {
|
||||
isGFPGANAvailable: boolean;
|
||||
isESRGANAvailable: boolean;
|
||||
isConnected: boolean;
|
||||
socketId: string;
|
||||
isProcessing: boolean;
|
||||
shouldConfirmOnDelete: boolean;
|
||||
openAccordions: ExpandedIndex;
|
||||
currentStep: number;
|
||||
totalSteps: number;
|
||||
currentIteration: number;
|
||||
@ -57,18 +38,12 @@ export interface SystemState
|
||||
currentStatus: string;
|
||||
currentStatusHasSteps: boolean;
|
||||
shouldDisplayGuides: boolean;
|
||||
wasErrorSeen: boolean;
|
||||
isCancelable: boolean;
|
||||
saveIntermediatesInterval: number;
|
||||
enableImageDebugging: boolean;
|
||||
toastQueue: UseToastOptions[];
|
||||
searchFolder: string | null;
|
||||
foundModels: InvokeAI.FoundModel[] | null;
|
||||
openModel: string | null;
|
||||
cancelOptions: {
|
||||
cancelType: CancelType;
|
||||
cancelAfter: number | null;
|
||||
};
|
||||
/**
|
||||
* The current progress image
|
||||
*/
|
||||
@ -107,14 +82,10 @@ export interface SystemState
|
||||
const initialSystemState: SystemState = {
|
||||
isConnected: false,
|
||||
isProcessing: false,
|
||||
shouldShowLogViewer: false,
|
||||
shouldDisplayInProgressType: 'latents',
|
||||
shouldDisplayGuides: true,
|
||||
isGFPGANAvailable: true,
|
||||
isESRGANAvailable: true,
|
||||
socketId: '',
|
||||
shouldConfirmOnDelete: true,
|
||||
openAccordions: [0],
|
||||
currentStep: 0,
|
||||
totalSteps: 0,
|
||||
currentIteration: 0,
|
||||
@ -123,26 +94,12 @@ const initialSystemState: SystemState = {
|
||||
? i18n.t('common.statusDisconnected')
|
||||
: 'Disconnected',
|
||||
currentStatusHasSteps: false,
|
||||
model: '',
|
||||
model_id: '',
|
||||
model_hash: '',
|
||||
app_id: '',
|
||||
app_version: '',
|
||||
model_list: {},
|
||||
infill_methods: [],
|
||||
hasError: false,
|
||||
wasErrorSeen: true,
|
||||
isCancelable: true,
|
||||
saveIntermediatesInterval: 5,
|
||||
enableImageDebugging: false,
|
||||
toastQueue: [],
|
||||
searchFolder: null,
|
||||
foundModels: null,
|
||||
openModel: null,
|
||||
cancelOptions: {
|
||||
cancelType: 'immediate',
|
||||
cancelAfter: null,
|
||||
},
|
||||
progressImage: null,
|
||||
sessionId: null,
|
||||
cancelType: 'immediate',
|
||||
@ -158,23 +115,13 @@ export const systemSlice = createSlice({
|
||||
name: 'system',
|
||||
initialState: initialSystemState,
|
||||
reducers: {
|
||||
setShouldDisplayInProgressType: (
|
||||
state,
|
||||
action: PayloadAction<InProgressImageType>
|
||||
) => {
|
||||
state.shouldDisplayInProgressType = action.payload;
|
||||
},
|
||||
setIsProcessing: (state, action: PayloadAction<boolean>) => {
|
||||
state.isProcessing = action.payload;
|
||||
},
|
||||
setCurrentStatus: (state, action: PayloadAction<string>) => {
|
||||
state.currentStatus = action.payload;
|
||||
},
|
||||
setSystemStatus: (state, action: PayloadAction<InvokeAI.SystemStatus>) => {
|
||||
return { ...state, ...action.payload };
|
||||
},
|
||||
errorOccurred: (state) => {
|
||||
state.hasError = true;
|
||||
state.isProcessing = false;
|
||||
state.isCancelable = true;
|
||||
state.currentStep = 0;
|
||||
@ -183,17 +130,6 @@ export const systemSlice = createSlice({
|
||||
state.totalIterations = 0;
|
||||
state.currentStatusHasSteps = false;
|
||||
state.currentStatus = i18n.t('common.statusError');
|
||||
state.wasErrorSeen = false;
|
||||
},
|
||||
errorSeen: (state) => {
|
||||
state.hasError = false;
|
||||
state.wasErrorSeen = true;
|
||||
state.currentStatus = state.isConnected
|
||||
? i18n.t('common.statusConnected')
|
||||
: i18n.t('common.statusDisconnected');
|
||||
},
|
||||
setShouldShowLogViewer: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowLogViewer = action.payload;
|
||||
},
|
||||
setIsConnected: (state, action: PayloadAction<boolean>) => {
|
||||
state.isConnected = action.payload;
|
||||
@ -204,23 +140,10 @@ export const systemSlice = createSlice({
|
||||
state.currentIteration = 0;
|
||||
state.totalIterations = 0;
|
||||
state.currentStatusHasSteps = false;
|
||||
state.hasError = false;
|
||||
},
|
||||
setSocketId: (state, action: PayloadAction<string>) => {
|
||||
state.socketId = action.payload;
|
||||
},
|
||||
setShouldConfirmOnDelete: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldConfirmOnDelete = action.payload;
|
||||
},
|
||||
setOpenAccordions: (state, action: PayloadAction<ExpandedIndex>) => {
|
||||
state.openAccordions = action.payload;
|
||||
},
|
||||
setSystemConfig: (state, action: PayloadAction<InvokeAI.SystemConfig>) => {
|
||||
return {
|
||||
...state,
|
||||
...action.payload,
|
||||
};
|
||||
},
|
||||
setShouldDisplayGuides: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldDisplayGuides = action.payload;
|
||||
},
|
||||
@ -244,12 +167,6 @@ export const systemSlice = createSlice({
|
||||
state.currentStatusHasSteps = false;
|
||||
state.currentStatus = i18n.t('common.statusPreparing');
|
||||
},
|
||||
setModelList: (
|
||||
state,
|
||||
action: PayloadAction<InvokeAI.ModelList | Record<string, never>>
|
||||
) => {
|
||||
state.model_list = action.payload;
|
||||
},
|
||||
setIsCancelable: (state, action: PayloadAction<boolean>) => {
|
||||
state.isCancelable = action.payload;
|
||||
},
|
||||
@ -271,9 +188,6 @@ export const systemSlice = createSlice({
|
||||
state.isProcessing = true;
|
||||
state.currentStatusHasSteps = false;
|
||||
},
|
||||
setSaveIntermediatesInterval: (state, action: PayloadAction<number>) => {
|
||||
state.saveIntermediatesInterval = action.payload;
|
||||
},
|
||||
setEnableImageDebugging: (state, action: PayloadAction<boolean>) => {
|
||||
state.enableImageDebugging = action.payload;
|
||||
},
|
||||
@ -300,12 +214,6 @@ export const systemSlice = createSlice({
|
||||
setOpenModel: (state, action: PayloadAction<string | null>) => {
|
||||
state.openModel = action.payload;
|
||||
},
|
||||
setCancelType: (state, action: PayloadAction<CancelType>) => {
|
||||
state.cancelOptions.cancelType = action.payload;
|
||||
},
|
||||
setCancelAfter: (state, action: PayloadAction<number | null>) => {
|
||||
state.cancelOptions.cancelAfter = action.payload;
|
||||
},
|
||||
/**
|
||||
* A cancel was scheduled
|
||||
*/
|
||||
@ -420,7 +328,6 @@ export const systemSlice = createSlice({
|
||||
builder.addCase(invocationError, (state, action) => {
|
||||
const { data, timestamp } = action.payload;
|
||||
|
||||
state.wasErrorSeen = true;
|
||||
state.progressImage = null;
|
||||
state.isProcessing = false;
|
||||
|
||||
@ -479,26 +386,17 @@ export const systemSlice = createSlice({
|
||||
});
|
||||
|
||||
export const {
|
||||
setShouldDisplayInProgressType,
|
||||
setIsProcessing,
|
||||
setShouldShowLogViewer,
|
||||
setIsConnected,
|
||||
setSocketId,
|
||||
setShouldConfirmOnDelete,
|
||||
setOpenAccordions,
|
||||
setSystemStatus,
|
||||
setCurrentStatus,
|
||||
setSystemConfig,
|
||||
setShouldDisplayGuides,
|
||||
processingCanceled,
|
||||
errorOccurred,
|
||||
errorSeen,
|
||||
setModelList,
|
||||
setIsCancelable,
|
||||
modelChangeRequested,
|
||||
modelConvertRequested,
|
||||
modelMergingRequested,
|
||||
setSaveIntermediatesInterval,
|
||||
setEnableImageDebugging,
|
||||
generationRequested,
|
||||
addToast,
|
||||
@ -507,8 +405,6 @@ export const {
|
||||
setSearchFolder,
|
||||
setFoundModels,
|
||||
setOpenModel,
|
||||
setCancelType,
|
||||
setCancelAfter,
|
||||
cancelScheduled,
|
||||
scheduledCancelAborted,
|
||||
cancelTypeChanged,
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Image } from 'app/types/invokeai';
|
||||
import { get, isObject, isString } from 'lodash-es';
|
||||
import {
|
||||
GraphExecutionState,
|
||||
GraphInvocationOutput,
|
||||
@ -6,6 +8,8 @@ import {
|
||||
PromptOutput,
|
||||
IterateInvocationOutput,
|
||||
CollectInvocationOutput,
|
||||
ImageType,
|
||||
ImageField,
|
||||
} from 'services/api';
|
||||
|
||||
export const isImageOutput = (
|
||||
@ -31,3 +35,16 @@ export const isIterateOutput = (
|
||||
export const isCollectOutput = (
|
||||
output: GraphExecutionState['results'][string]
|
||||
): output is CollectInvocationOutput => output.type === 'collect_output';
|
||||
|
||||
export const isImageType = (t: unknown): t is ImageType =>
|
||||
isString(t) && ['results', 'uploads', 'intermediates'].includes(t);
|
||||
|
||||
export const isImage = (image: unknown): image is Image =>
|
||||
isObject(image) &&
|
||||
isString(get(image, 'name')) &&
|
||||
isImageType(get(image, 'type'));
|
||||
|
||||
export const isImageField = (imageField: unknown): imageField is ImageField =>
|
||||
isObject(imageField) &&
|
||||
isString(get(imageField, 'image_name')) &&
|
||||
isImageType(get(imageField, 'image_type'));
|
||||
|
Loading…
Reference in New Issue
Block a user