mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Adds useToastWatcher hook
- Dispatch an `addToast` action with standard Chakra toast options object to add a toast to the toastQueue - The hook is called in App.tsx and just useEffect's w/ toastQueue as dependency to create the toasts - So now you can add toasts anywhere you have access to `dispatch`, which includes middleware and thunks - Adds first usage of this for the save image buttons in canvas
This commit is contained in:
parent
c69573e65d
commit
04cb2d39cb
@ -15,6 +15,7 @@ import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { SystemState } from 'features/system/systemSlice';
|
||||
import _ from 'lodash';
|
||||
import { Model } from './invokeai';
|
||||
import useToastWatcher from 'features/system/hooks/useToastWatcher';
|
||||
|
||||
keepGUIAlive();
|
||||
|
||||
@ -50,18 +51,13 @@ const appSelector = createSelector(
|
||||
|
||||
const shouldShowGalleryButton =
|
||||
!(shouldShowGallery || (shouldHoldGalleryOpen && !shouldPinGallery)) &&
|
||||
['txt2img', 'img2img', 'unifiedCanvas'].includes(
|
||||
activeTabName
|
||||
);
|
||||
['txt2img', 'img2img', 'unifiedCanvas'].includes(activeTabName);
|
||||
|
||||
const shouldShowOptionsPanelButton =
|
||||
!(
|
||||
shouldShowOptionsPanel ||
|
||||
(shouldHoldOptionsPanelOpen && !shouldPinOptionsPanel)
|
||||
) &&
|
||||
['txt2img', 'img2img', 'unifiedCanvas'].includes(
|
||||
activeTabName
|
||||
);
|
||||
) && ['txt2img', 'img2img', 'unifiedCanvas'].includes(activeTabName);
|
||||
|
||||
return {
|
||||
modelStatusText,
|
||||
@ -80,6 +76,8 @@ const App = () => {
|
||||
const { shouldShowGalleryButton, shouldShowOptionsPanelButton } =
|
||||
useAppSelector(appSelector);
|
||||
|
||||
useToastWatcher();
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<ImageUploader>
|
||||
|
@ -23,7 +23,6 @@ import {
|
||||
clearIntermediateImage,
|
||||
GalleryState,
|
||||
removeImage,
|
||||
setCurrentImage,
|
||||
setIntermediateImage,
|
||||
} from 'features/gallery/gallerySlice';
|
||||
|
||||
|
@ -43,8 +43,6 @@ export const socketioMiddleware = () => {
|
||||
onGalleryImages,
|
||||
onProcessingCanceled,
|
||||
onImageDeleted,
|
||||
// onImageUploaded,
|
||||
// onMaskImageUploaded,
|
||||
onSystemConfig,
|
||||
onModelChanged,
|
||||
onModelChangeFailed,
|
||||
@ -58,8 +56,6 @@ export const socketioMiddleware = () => {
|
||||
emitRequestImages,
|
||||
emitRequestNewImages,
|
||||
emitCancelProcessing,
|
||||
// emitUploadImage,
|
||||
// emitUploadMaskImage,
|
||||
emitRequestSystemConfig,
|
||||
emitRequestModelChange,
|
||||
} = makeSocketIOEmitters(store, socketio);
|
||||
@ -104,14 +100,6 @@ export const socketioMiddleware = () => {
|
||||
onImageDeleted(data);
|
||||
});
|
||||
|
||||
// socketio.on('imageUploaded', (data: InvokeAI.ImageUploadResponse) => {
|
||||
// onImageUploaded(data);
|
||||
// });
|
||||
|
||||
// socketio.on('maskImageUploaded', (data: InvokeAI.ImageUrlResponse) => {
|
||||
// onMaskImageUploaded(data);
|
||||
// });
|
||||
|
||||
socketio.on('systemConfig', (data: InvokeAI.SystemConfig) => {
|
||||
onSystemConfig(data);
|
||||
});
|
||||
@ -166,16 +154,6 @@ export const socketioMiddleware = () => {
|
||||
break;
|
||||
}
|
||||
|
||||
// case 'socketio/uploadImage': {
|
||||
// emitUploadImage(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
// case 'socketio/uploadMaskImage': {
|
||||
// emitUploadMaskImage(action.payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
case 'socketio/requestSystemConfig': {
|
||||
emitRequestSystemConfig();
|
||||
break;
|
||||
|
@ -6,6 +6,7 @@ import layerToDataURL from './layerToDataURL';
|
||||
import downloadFile from './downloadFile';
|
||||
import copyImage from './copyImage';
|
||||
import { getCanvasBaseLayer } from './konvaInstanceProvider';
|
||||
import { addToast } from 'features/system/systemSlice';
|
||||
|
||||
export const mergeAndUploadCanvas = createAsyncThunk(
|
||||
'canvas/mergeAndUploadCanvas',
|
||||
@ -21,7 +22,7 @@ export const mergeAndUploadCanvas = createAsyncThunk(
|
||||
const { saveToGallery, downloadAfterSaving, cropVisible, copyAfterSaving } =
|
||||
args;
|
||||
|
||||
const { getState } = thunkAPI;
|
||||
const { getState, dispatch } = thunkAPI;
|
||||
|
||||
const state = getState() as RootState;
|
||||
|
||||
@ -60,11 +61,27 @@ export const mergeAndUploadCanvas = createAsyncThunk(
|
||||
|
||||
if (downloadAfterSaving) {
|
||||
downloadFile(url);
|
||||
dispatch(
|
||||
addToast({
|
||||
title: 'Image Download Started',
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (copyAfterSaving) {
|
||||
copyImage(url, width, height);
|
||||
dispatch(
|
||||
addToast({
|
||||
title: 'Image Copied',
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -27,3 +27,6 @@ export const mayGenerateMultipleImagesSelector = createSelector(
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export const optionsSelector = (state: RootState): OptionsState =>
|
||||
state.options;
|
||||
|
19
frontend/src/features/system/hooks/useToastWatcher.ts
Normal file
19
frontend/src/features/system/hooks/useToastWatcher.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { useEffect } from 'react';
|
||||
import { toastQueueSelector } from '../systemSelectors';
|
||||
import { clearToastQueue } from '../systemSlice';
|
||||
|
||||
const useToastWatcher = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const toastQueue = useAppSelector(toastQueueSelector);
|
||||
const toast = useToast();
|
||||
useEffect(() => {
|
||||
toastQueue.forEach((t) => {
|
||||
toast(t);
|
||||
});
|
||||
toastQueue.length > 0 && dispatch(clearToastQueue());
|
||||
}, [dispatch, toast, toastQueue]);
|
||||
};
|
||||
|
||||
export default useToastWatcher;
|
6
frontend/src/features/system/systemSelectors.ts
Normal file
6
frontend/src/features/system/systemSelectors.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { RootState } from 'app/store';
|
||||
import { SystemState } from './systemSlice';
|
||||
|
||||
export const systemSelector = (state: RootState): SystemState => state.system;
|
||||
|
||||
export const toastQueueSelector = (state: RootState) => state.system.toastQueue;
|
@ -1,6 +1,6 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { ExpandedIndex } from '@chakra-ui/react';
|
||||
import { ExpandedIndex, UseToastOptions } from '@chakra-ui/react';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
|
||||
export type LogLevel = 'info' | 'warning' | 'error';
|
||||
@ -45,6 +45,7 @@ export interface SystemState
|
||||
isCancelable: boolean;
|
||||
saveIntermediatesInterval: number;
|
||||
enableImageDebugging: boolean;
|
||||
toastQueue: UseToastOptions[];
|
||||
}
|
||||
|
||||
const initialSystemState: SystemState = {
|
||||
@ -76,6 +77,7 @@ const initialSystemState: SystemState = {
|
||||
isCancelable: true,
|
||||
saveIntermediatesInterval: 5,
|
||||
enableImageDebugging: false,
|
||||
toastQueue: [],
|
||||
};
|
||||
|
||||
export const systemSlice = createSlice({
|
||||
@ -206,6 +208,12 @@ export const systemSlice = createSlice({
|
||||
setEnableImageDebugging: (state, action: PayloadAction<boolean>) => {
|
||||
state.enableImageDebugging = action.payload;
|
||||
},
|
||||
addToast: (state, action: PayloadAction<UseToastOptions>) => {
|
||||
state.toastQueue.push(action.payload);
|
||||
},
|
||||
clearToastQueue: (state) => {
|
||||
state.toastQueue = [];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -231,6 +239,8 @@ export const {
|
||||
setSaveIntermediatesInterval,
|
||||
setEnableImageDebugging,
|
||||
generationRequested,
|
||||
addToast,
|
||||
clearToastQueue,
|
||||
} = systemSlice.actions;
|
||||
|
||||
export default systemSlice.reducer;
|
||||
|
Loading…
Reference in New Issue
Block a user