Merge branch 'development' into development

This commit is contained in:
Peter Baylies
2022-10-03 23:53:19 -04:00
committed by GitHub
167 changed files with 5162 additions and 1963 deletions

17
frontend/src/app/App.scss Normal file
View File

@@ -0,0 +1,17 @@
@use '../styles/Mixins/' as *;
.App {
display: grid;
}
.app-content {
display: grid;
row-gap: 1rem;
margin: 0.6rem;
padding: 1rem;
border-radius: 0.5rem;
background-color: var(--background-color);
grid-auto-rows: max-content;
width: $app-width;
height: $app-height;
}

View File

@@ -1,16 +1,14 @@
import { Grid, GridItem } from '@chakra-ui/react';
import { useEffect, useState } from 'react';
import CurrentImageDisplay from '../features/gallery/CurrentImageDisplay';
import ImageGallery from '../features/gallery/ImageGallery';
import ProgressBar from '../features/system/ProgressBar';
import SiteHeader from '../features/system/SiteHeader';
import OptionsAccordion from '../features/options/OptionsAccordion';
import ProcessButtons from '../features/options/ProcessButtons';
import PromptInput from '../features/options/PromptInput';
import LogViewer from '../features/system/LogViewer';
import Console from '../features/system/Console';
import Loading from '../Loading';
import { useAppDispatch } from './store';
import { requestSystemConfig } from './socketio/actions';
import { keepGUIAlive } from './utils';
import InvokeTabs from '../features/tabs/InvokeTabs';
keepGUIAlive();
const App = () => {
const dispatch = useAppDispatch();
@@ -22,43 +20,14 @@ const App = () => {
}, [dispatch]);
return isReady ? (
<>
<Grid
width="100vw"
height="100vh"
templateAreas={`
"header header header header"
"progressBar progressBar progressBar progressBar"
"menu prompt processButtons imageRoll"
"menu currentImage currentImage imageRoll"`}
gridTemplateRows={'36px 10px 100px auto'}
gridTemplateColumns={'350px auto 100px 388px'}
gap={2}
>
<GridItem area={'header'} pt={1}>
<SiteHeader />
</GridItem>
<GridItem area={'progressBar'}>
<ProgressBar />
</GridItem>
<GridItem pl="2" area={'menu'} overflowY="scroll">
<OptionsAccordion />
</GridItem>
<GridItem area={'prompt'}>
<PromptInput />
</GridItem>
<GridItem area={'processButtons'}>
<ProcessButtons />
</GridItem>
<GridItem area={'currentImage'}>
<CurrentImageDisplay />
</GridItem>
<GridItem pr="2" area={'imageRoll'} overflowY="scroll">
<ImageGallery />
</GridItem>
</Grid>
<LogViewer />
</>
<div className="App">
<ProgressBar />
<div className="app-content">
<SiteHeader />
<InvokeTabs />
</div>
<Console />
</div>
) : (
<Loading />
);

View File

@@ -17,13 +17,15 @@ export const SAMPLERS: Array<string> = [
// Valid image widths
export const WIDTHS: Array<number> = [
64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960,
1024,
1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792,
1856, 1920, 1984, 2048,
];
// Valid image heights
export const HEIGHTS: Array<number> = [
64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960,
1024,
1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792,
1856, 1920, 1984, 2048,
];
// Valid upscaling levels

View File

@@ -7,12 +7,12 @@ type FeatureHelpInfo = {
export enum Feature {
PROMPT,
GALLERY,
OUTPUT,
SEED_AND_VARIATION,
ESRGAN,
OTHER,
SEED,
VARIATIONS,
UPSCALE,
FACE_CORRECTION,
IMAGE_TO_IMAGE,
SAMPLER,
}
export const FEATURES: Record<Feature, FeatureHelpInfo> = {
@@ -26,18 +26,23 @@ export const FEATURES: Record<Feature, FeatureHelpInfo> = {
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.OUTPUT]: {
text: 'The Height and Width of generations can be controlled here. If you experience errors, you may be generating an image too large for your system. The seamless option will more often result in repeating patterns in outputs.',
[Feature.OTHER]: {
text: 'Additional Options',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.SEED_AND_VARIATION]: {
text: 'Seed values provide an initial set of noise which guide the denoising process. Try a variation with an amount of between 0 and 1 to change the output image for that seed.',
[Feature.SEED]: {
text: 'Seed values provide an initial set of noise which guide the denoising process.',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.ESRGAN]: {
text: 'The ESRGAN setting can be used to increase the output resolution without requiring a higher width/height in the initial generation.',
[Feature.VARIATIONS]: {
text: 'Try a variation with an amount of between 0 and 1 to change the output image for the set seed.',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.UPSCALE]: {
text: 'Using ESRGAN you can increase the output resolution without requiring a higher width/height in the initial generation.',
href: 'link/to/docs/feature1.html',
guideImage: 'asset/path.gif',
},
@@ -51,9 +56,4 @@ export const FEATURES: Record<Feature, FeatureHelpInfo> = {
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.SAMPLER]: {
text: 'This setting allows for different denoising samplers to be used, as well as the number of denoising steps used, which will change the resulting output.',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
};

View File

@@ -129,6 +129,7 @@ export declare type SystemStatus = {
totalIterations: number;
currentStatus: string;
currentStatusHasSteps: boolean;
hasError: boolean;
};
export declare type SystemConfig = {
@@ -159,10 +160,8 @@ export declare type ErrorResponse = {
};
export declare type GalleryImagesResponse = {
images: Array<Omit<Image, 'uuid'>>;
nextPage: number;
offset: number;
onlyNewImages: boolean;
images: Array<Omit<Image, 'uuid'>>;
areMoreImagesAvailable: boolean;
};
export declare type ImageUrlAndUuidResponse = {

View File

@@ -50,7 +50,10 @@ const makeSocketIOEmitters = (
const esrganParameters = {
upscale: [upscalingLevel, upscalingStrength],
};
socketio.emit('runESRGAN', imageToProcess, esrganParameters);
socketio.emit('runPostprocessing', imageToProcess, {
type: 'esrgan',
...esrganParameters,
});
dispatch(
addLogEntry({
timestamp: dateFormat(new Date(), 'isoDateTime'),
@@ -68,7 +71,10 @@ const makeSocketIOEmitters = (
const gfpganParameters = {
gfpgan_strength: gfpganStrength,
};
socketio.emit('runGFPGAN', imageToProcess, gfpganParameters);
socketio.emit('runPostprocessing', imageToProcess, {
type: 'gfpgan',
...gfpganParameters,
});
dispatch(
addLogEntry({
timestamp: dateFormat(new Date(), 'isoDateTime'),
@@ -84,16 +90,12 @@ const makeSocketIOEmitters = (
socketio.emit('deleteImage', url, uuid);
},
emitRequestImages: () => {
const { nextPage, offset } = getState().gallery;
socketio.emit('requestImages', nextPage, offset);
const { earliest_mtime } = getState().gallery;
socketio.emit('requestImages', earliest_mtime);
},
emitRequestNewImages: () => {
const { nextPage, offset, images } = getState().gallery;
if (images.length > 0) {
socketio.emit('requestImages', nextPage, offset, images[0].mtime);
} else {
socketio.emit('requestImages', nextPage, offset);
}
const { latest_mtime } = getState().gallery;
socketio.emit('requestLatestImages', latest_mtime);
},
emitCancelProcessing: () => {
socketio.emit('cancel');

View File

@@ -11,6 +11,8 @@ import {
setSystemStatus,
setCurrentStatus,
setSystemConfig,
processingCanceled,
errorOccurred,
} from '../../features/system/systemSlice';
import {
@@ -25,7 +27,7 @@ import {
setInitialImagePath,
setMaskPath,
} from '../../features/options/optionsSlice';
import { requestNewImages } from './actions';
import { requestImages, requestNewImages } from './actions';
/**
* Returns an object containing listener callbacks for socketio events.
@@ -44,7 +46,11 @@ const makeSocketIOListeners = (
try {
dispatch(setIsConnected(true));
dispatch(setCurrentStatus('Connected'));
dispatch(requestNewImages());
if (getState().gallery.latest_mtime) {
dispatch(requestNewImages());
} else {
dispatch(requestImages());
}
} catch (e) {
console.error(e);
}
@@ -90,7 +96,6 @@ const makeSocketIOListeners = (
message: `Image generated: ${url}`,
})
);
dispatch(setIsProcessing(false));
} catch (e) {
console.error(e);
}
@@ -116,7 +121,6 @@ const makeSocketIOListeners = (
message: `Intermediate image generated: ${url}`,
})
);
dispatch(setIsProcessing(false));
} catch (e) {
console.error(e);
}
@@ -124,7 +128,7 @@ const makeSocketIOListeners = (
/**
* Callback to run when we receive an 'esrganResult' event.
*/
onESRGANResult: (data: InvokeAI.ImageResultResponse) => {
onPostprocessingResult: (data: InvokeAI.ImageResultResponse) => {
try {
const { url, metadata, mtime } = data;
@@ -140,10 +144,9 @@ const makeSocketIOListeners = (
dispatch(
addLogEntry({
timestamp: dateFormat(new Date(), 'isoDateTime'),
message: `Upscaled: ${url}`,
message: `Postprocessed: ${url}`,
})
);
dispatch(setIsProcessing(false));
} catch (e) {
console.error(e);
}
@@ -204,7 +207,7 @@ const makeSocketIOListeners = (
level: 'error',
})
);
dispatch(setIsProcessing(false));
dispatch(errorOccurred());
dispatch(clearIntermediateImage());
} catch (e) {
console.error(e);
@@ -214,7 +217,7 @@ const makeSocketIOListeners = (
* Callback to run when we receive a 'galleryImages' event.
*/
onGalleryImages: (data: InvokeAI.GalleryImagesResponse) => {
const { images, nextPage, offset } = data;
const { images, areMoreImagesAvailable } = data;
/**
* the logic here ideally would be in the reducer but we have a side effect:
@@ -232,7 +235,9 @@ const makeSocketIOListeners = (
};
});
dispatch(addGalleryImages({ images: preparedImages, nextPage, offset }));
dispatch(
addGalleryImages({ images: preparedImages, areMoreImagesAvailable })
);
dispatch(
addLogEntry({
@@ -245,7 +250,7 @@ const makeSocketIOListeners = (
* Callback to run when we receive a 'processingCanceled' event.
*/
onProcessingCanceled: () => {
dispatch(setIsProcessing(false));
dispatch(processingCanceled());
const { intermediateImage } = getState().gallery;
@@ -259,6 +264,7 @@ const makeSocketIOListeners = (
);
dispatch(clearIntermediateImage());
}
dispatch(
addLogEntry({
timestamp: dateFormat(new Date(), 'isoDateTime'),
@@ -273,6 +279,17 @@ const makeSocketIOListeners = (
onImageDeleted: (data: InvokeAI.ImageUrlAndUuidResponse) => {
const { url, uuid } = data;
dispatch(removeImage(uuid));
const { initialImagePath, maskPath } = getState().options;
if (initialImagePath === url) {
dispatch(setInitialImagePath(''));
}
if (maskPath === url) {
dispatch(setMaskPath(''));
}
dispatch(
addLogEntry({
timestamp: dateFormat(new Date(), 'isoDateTime'),

View File

@@ -35,8 +35,7 @@ export const socketioMiddleware = () => {
onConnect,
onDisconnect,
onError,
onESRGANResult,
onGFPGANResult,
onPostprocessingResult,
onGenerationResult,
onIntermediateResult,
onProgressUpdate,
@@ -76,12 +75,9 @@ export const socketioMiddleware = () => {
onGenerationResult(data)
);
socketio.on('esrganResult', (data: InvokeAI.ImageResultResponse) =>
onESRGANResult(data)
);
socketio.on('gfpganResult', (data: InvokeAI.ImageResultResponse) =>
onGFPGANResult(data)
socketio.on(
'postprocessingResult',
(data: InvokeAI.ImageResultResponse) => onPostprocessingResult(data)
);
socketio.on('intermediateResult', (data: InvokeAI.ImageResultResponse) =>
@@ -153,7 +149,6 @@ export const socketioMiddleware = () => {
break;
}
case 'socketio/cancelProcessing': {
emitCancelProcessing();
break;

View File

@@ -7,6 +7,7 @@ import storage from 'redux-persist/lib/storage'; // defaults to localStorage for
import optionsReducer from '../features/options/optionsSlice';
import galleryReducer from '../features/gallery/gallerySlice';
import systemReducer from '../features/system/systemSlice';
import { socketioMiddleware } from './socketio/middleware';

25
frontend/src/app/utils.ts Normal file
View File

@@ -0,0 +1,25 @@
export function keepGUIAlive() {
async function getRequest(url = '') {
const response = await fetch(url, {
method: 'GET',
cache: 'no-cache',
});
return response;
}
const keepAliveServer = () => {
const url = document.location;
const route = '/flaskwebgui-keep-server-alive';
getRequest(url + route).then((data) => {
return data;
});
};
if (!import.meta.env.NODE_ENV || import.meta.env.NODE_ENV === 'production') {
document.addEventListener('DOMContentLoaded', () => {
const intervalRequest = 3 * 1000;
keepAliveServer();
setInterval(keepAliveServer, intervalRequest);
});
}
}