feat(gui): add retry function to error card
This commit is contained in:
parent
6226778cfb
commit
89790645cb
|
@ -1,5 +1,5 @@
|
||||||
/* eslint-disable max-lines */
|
/* eslint-disable max-lines */
|
||||||
import { doesExist } from '@apextoaster/js-utils';
|
import { doesExist, InvalidArgumentError } from '@apextoaster/js-utils';
|
||||||
|
|
||||||
import { ServerParams } from '../config.js';
|
import { ServerParams } from '../config.js';
|
||||||
import { range } from '../utils.js';
|
import { range } from '../utils.js';
|
||||||
|
@ -191,6 +191,43 @@ export interface ModelsResponse {
|
||||||
upscaling: Array<string>;
|
upscaling: Array<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type RetryParams = {
|
||||||
|
type: 'txt2img';
|
||||||
|
model: ModelParams;
|
||||||
|
params: Txt2ImgParams;
|
||||||
|
upscale?: UpscaleParams;
|
||||||
|
} | {
|
||||||
|
type: 'img2img';
|
||||||
|
model: ModelParams;
|
||||||
|
params: Img2ImgParams;
|
||||||
|
upscale?: UpscaleParams;
|
||||||
|
} | {
|
||||||
|
type: 'inpaint';
|
||||||
|
model: ModelParams;
|
||||||
|
params: InpaintParams;
|
||||||
|
upscale?: UpscaleParams;
|
||||||
|
} | {
|
||||||
|
type: 'outpaint';
|
||||||
|
model: ModelParams;
|
||||||
|
params: OutpaintParams;
|
||||||
|
upscale?: UpscaleParams;
|
||||||
|
} | {
|
||||||
|
type: 'upscale';
|
||||||
|
model: ModelParams;
|
||||||
|
params: UpscaleReqParams;
|
||||||
|
upscale?: UpscaleParams;
|
||||||
|
} | {
|
||||||
|
type: 'blend';
|
||||||
|
model: ModelParams;
|
||||||
|
params: BlendParams;
|
||||||
|
upscale?: UpscaleParams;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ImageResponseWithRetry {
|
||||||
|
image: ImageResponse;
|
||||||
|
retry: RetryParams;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ApiClient {
|
export interface ApiClient {
|
||||||
/**
|
/**
|
||||||
* List the available filter masks for inpaint.
|
* List the available filter masks for inpaint.
|
||||||
|
@ -232,32 +269,32 @@ export interface ApiClient {
|
||||||
/**
|
/**
|
||||||
* Start a txt2img pipeline.
|
* Start a txt2img pipeline.
|
||||||
*/
|
*/
|
||||||
txt2img(model: ModelParams, params: Txt2ImgParams, upscale?: UpscaleParams): Promise<ImageResponse>;
|
txt2img(model: ModelParams, params: Txt2ImgParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an im2img pipeline.
|
* Start an im2img pipeline.
|
||||||
*/
|
*/
|
||||||
img2img(model: ModelParams, params: Img2ImgParams, upscale?: UpscaleParams): Promise<ImageResponse>;
|
img2img(model: ModelParams, params: Img2ImgParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an inpaint pipeline.
|
* Start an inpaint pipeline.
|
||||||
*/
|
*/
|
||||||
inpaint(model: ModelParams, params: InpaintParams, upscale?: UpscaleParams): Promise<ImageResponse>;
|
inpaint(model: ModelParams, params: InpaintParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an outpaint pipeline.
|
* Start an outpaint pipeline.
|
||||||
*/
|
*/
|
||||||
outpaint(model: ModelParams, params: OutpaintParams, upscale?: UpscaleParams): Promise<ImageResponse>;
|
outpaint(model: ModelParams, params: OutpaintParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an upscale pipeline.
|
* Start an upscale pipeline.
|
||||||
*/
|
*/
|
||||||
upscale(model: ModelParams, params: UpscaleReqParams, upscale?: UpscaleParams): Promise<ImageResponse>;
|
upscale(model: ModelParams, params: UpscaleReqParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a blending pipeline.
|
* Start a blending pipeline.
|
||||||
*/
|
*/
|
||||||
blend(model: ModelParams, params: BlendParams, upscale?: UpscaleParams): Promise<ImageResponse>;
|
blend(model: ModelParams, params: BlendParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether some pipeline's output is ready yet.
|
* Check whether some pipeline's output is ready yet.
|
||||||
|
@ -265,6 +302,8 @@ export interface ApiClient {
|
||||||
ready(key: string): Promise<ReadyResponse>;
|
ready(key: string): Promise<ReadyResponse>;
|
||||||
|
|
||||||
cancel(key: string): Promise<boolean>;
|
cancel(key: string): Promise<boolean>;
|
||||||
|
|
||||||
|
retry(params: RetryParams): Promise<ImageResponseWithRetry>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -363,7 +402,7 @@ export function appendUpscaleToURL(url: URL, upscale: UpscaleParams) {
|
||||||
* Make an API client using the given API root and fetch client.
|
* Make an API client using the given API root and fetch client.
|
||||||
*/
|
*/
|
||||||
export function makeClient(root: string, f = fetch): ApiClient {
|
export function makeClient(root: string, f = fetch): ApiClient {
|
||||||
function throttleRequest(url: URL, options: RequestInit): Promise<ImageResponse> {
|
function parseRequest(url: URL, options: RequestInit): Promise<ImageResponse> {
|
||||||
return f(url, options).then((res) => parseApiResponse(root, res));
|
return f(url, options).then((res) => parseApiResponse(root, res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,7 +446,7 @@ export function makeClient(root: string, f = fetch): ApiClient {
|
||||||
translation: Record<string, string>;
|
translation: Record<string, string>;
|
||||||
}>;
|
}>;
|
||||||
},
|
},
|
||||||
async img2img(model: ModelParams, params: Img2ImgParams, upscale?: UpscaleParams): Promise<ImageResponse> {
|
async img2img(model: ModelParams, params: Img2ImgParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry> {
|
||||||
const url = makeImageURL(root, 'img2img', params);
|
const url = makeImageURL(root, 'img2img', params);
|
||||||
appendModelToURL(url, model);
|
appendModelToURL(url, model);
|
||||||
|
|
||||||
|
@ -420,13 +459,21 @@ export function makeClient(root: string, f = fetch): ApiClient {
|
||||||
const body = new FormData();
|
const body = new FormData();
|
||||||
body.append('source', params.source, 'source');
|
body.append('source', params.source, 'source');
|
||||||
|
|
||||||
// eslint-disable-next-line no-return-await
|
const image = await parseRequest(url, {
|
||||||
return await throttleRequest(url, {
|
|
||||||
body,
|
body,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
});
|
});
|
||||||
|
return {
|
||||||
|
image,
|
||||||
|
retry: {
|
||||||
|
type: 'img2img',
|
||||||
|
model,
|
||||||
|
params,
|
||||||
|
upscale,
|
||||||
},
|
},
|
||||||
async txt2img(model: ModelParams, params: Txt2ImgParams, upscale?: UpscaleParams): Promise<ImageResponse> {
|
};
|
||||||
|
},
|
||||||
|
async txt2img(model: ModelParams, params: Txt2ImgParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry> {
|
||||||
const url = makeImageURL(root, 'txt2img', params);
|
const url = makeImageURL(root, 'txt2img', params);
|
||||||
appendModelToURL(url, model);
|
appendModelToURL(url, model);
|
||||||
|
|
||||||
|
@ -442,12 +489,20 @@ export function makeClient(root: string, f = fetch): ApiClient {
|
||||||
appendUpscaleToURL(url, upscale);
|
appendUpscaleToURL(url, upscale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-return-await
|
const image = await parseRequest(url, {
|
||||||
return await throttleRequest(url, {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
});
|
});
|
||||||
|
return {
|
||||||
|
image,
|
||||||
|
retry: {
|
||||||
|
type: 'txt2img',
|
||||||
|
model,
|
||||||
|
params,
|
||||||
|
upscale,
|
||||||
},
|
},
|
||||||
async inpaint(model: ModelParams, params: InpaintParams, upscale?: UpscaleParams) {
|
};
|
||||||
|
},
|
||||||
|
async inpaint(model: ModelParams, params: InpaintParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry> {
|
||||||
const url = makeImageURL(root, 'inpaint', params);
|
const url = makeImageURL(root, 'inpaint', params);
|
||||||
appendModelToURL(url, model);
|
appendModelToURL(url, model);
|
||||||
|
|
||||||
|
@ -464,13 +519,21 @@ export function makeClient(root: string, f = fetch): ApiClient {
|
||||||
body.append('mask', params.mask, 'mask');
|
body.append('mask', params.mask, 'mask');
|
||||||
body.append('source', params.source, 'source');
|
body.append('source', params.source, 'source');
|
||||||
|
|
||||||
// eslint-disable-next-line no-return-await
|
const image = await parseRequest(url, {
|
||||||
return await throttleRequest(url, {
|
|
||||||
body,
|
body,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
});
|
});
|
||||||
|
return {
|
||||||
|
image,
|
||||||
|
retry: {
|
||||||
|
type: 'inpaint',
|
||||||
|
model,
|
||||||
|
params,
|
||||||
|
upscale,
|
||||||
},
|
},
|
||||||
async outpaint(model: ModelParams, params: OutpaintParams, upscale?: UpscaleParams) {
|
};
|
||||||
|
},
|
||||||
|
async outpaint(model: ModelParams, params: OutpaintParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry> {
|
||||||
const url = makeImageURL(root, 'inpaint', params);
|
const url = makeImageURL(root, 'inpaint', params);
|
||||||
appendModelToURL(url, model);
|
appendModelToURL(url, model);
|
||||||
|
|
||||||
|
@ -504,13 +567,21 @@ export function makeClient(root: string, f = fetch): ApiClient {
|
||||||
body.append('mask', params.mask, 'mask');
|
body.append('mask', params.mask, 'mask');
|
||||||
body.append('source', params.source, 'source');
|
body.append('source', params.source, 'source');
|
||||||
|
|
||||||
// eslint-disable-next-line no-return-await
|
const image = await parseRequest(url, {
|
||||||
return await throttleRequest(url, {
|
|
||||||
body,
|
body,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
});
|
});
|
||||||
|
return {
|
||||||
|
image,
|
||||||
|
retry: {
|
||||||
|
type: 'outpaint',
|
||||||
|
model,
|
||||||
|
params,
|
||||||
|
upscale,
|
||||||
},
|
},
|
||||||
async upscale(model: ModelParams, params: UpscaleReqParams, upscale: UpscaleParams): Promise<ImageResponse> {
|
};
|
||||||
|
},
|
||||||
|
async upscale(model: ModelParams, params: UpscaleReqParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry> {
|
||||||
const url = makeApiUrl(root, 'upscale');
|
const url = makeApiUrl(root, 'upscale');
|
||||||
appendModelToURL(url, model);
|
appendModelToURL(url, model);
|
||||||
|
|
||||||
|
@ -527,13 +598,21 @@ export function makeClient(root: string, f = fetch): ApiClient {
|
||||||
const body = new FormData();
|
const body = new FormData();
|
||||||
body.append('source', params.source, 'source');
|
body.append('source', params.source, 'source');
|
||||||
|
|
||||||
// eslint-disable-next-line no-return-await
|
const image = await parseRequest(url, {
|
||||||
return await throttleRequest(url, {
|
|
||||||
body,
|
body,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
});
|
});
|
||||||
|
return {
|
||||||
|
image,
|
||||||
|
retry: {
|
||||||
|
type: 'upscale',
|
||||||
|
model,
|
||||||
|
params,
|
||||||
|
upscale,
|
||||||
},
|
},
|
||||||
async blend(model: ModelParams, params: BlendParams, upscale: UpscaleParams): Promise<ImageResponse> {
|
};
|
||||||
|
},
|
||||||
|
async blend(model: ModelParams, params: BlendParams, upscale?: UpscaleParams): Promise<ImageResponseWithRetry> {
|
||||||
const url = makeApiUrl(root, 'blend');
|
const url = makeApiUrl(root, 'blend');
|
||||||
appendModelToURL(url, model);
|
appendModelToURL(url, model);
|
||||||
|
|
||||||
|
@ -549,11 +628,19 @@ export function makeClient(root: string, f = fetch): ApiClient {
|
||||||
body.append(name, params.sources[i], name);
|
body.append(name, params.sources[i], name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-return-await
|
const image = await parseRequest(url, {
|
||||||
return await throttleRequest(url, {
|
|
||||||
body,
|
body,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
});
|
});
|
||||||
|
return {
|
||||||
|
image,
|
||||||
|
retry: {
|
||||||
|
type: 'blend',
|
||||||
|
model,
|
||||||
|
params,
|
||||||
|
upscale,
|
||||||
|
}
|
||||||
|
};
|
||||||
},
|
},
|
||||||
async ready(key: string): Promise<ReadyResponse> {
|
async ready(key: string): Promise<ReadyResponse> {
|
||||||
const path = makeApiUrl(root, 'ready');
|
const path = makeApiUrl(root, 'ready');
|
||||||
|
@ -571,6 +658,24 @@ export function makeClient(root: string, f = fetch): ApiClient {
|
||||||
});
|
});
|
||||||
return res.status === STATUS_SUCCESS;
|
return res.status === STATUS_SUCCESS;
|
||||||
},
|
},
|
||||||
|
async retry(retry: RetryParams): Promise<ImageResponseWithRetry> {
|
||||||
|
switch (retry.type) {
|
||||||
|
case 'blend':
|
||||||
|
return this.blend(retry.model, retry.params, retry.upscale);
|
||||||
|
case 'img2img':
|
||||||
|
return this.img2img(retry.model, retry.params, retry.upscale);
|
||||||
|
case 'inpaint':
|
||||||
|
return this.inpaint(retry.model, retry.params, retry.upscale);
|
||||||
|
case 'outpaint':
|
||||||
|
return this.outpaint(retry.model, retry.params, retry.upscale);
|
||||||
|
case 'txt2img':
|
||||||
|
return this.txt2img(retry.model, retry.params, retry.upscale);
|
||||||
|
case 'upscale':
|
||||||
|
return this.upscale(retry.model, retry.params, retry.upscale);
|
||||||
|
default:
|
||||||
|
throw new InvalidArgumentError('unknown request type');
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,9 @@ export const LOCAL_CLIENT = {
|
||||||
async cancel(key) {
|
async cancel(key) {
|
||||||
throw new NoServerError();
|
throw new NoServerError();
|
||||||
},
|
},
|
||||||
|
async retry(params) {
|
||||||
|
throw new NoServerError();
|
||||||
|
},
|
||||||
async models() {
|
async models() {
|
||||||
throw new NoServerError();
|
throw new NoServerError();
|
||||||
},
|
},
|
||||||
|
|
|
@ -30,7 +30,7 @@ export function ImageHistory() {
|
||||||
|
|
||||||
if (doesExist(item.ready) && item.ready.ready) {
|
if (doesExist(item.ready) && item.ready.ready) {
|
||||||
if (item.ready.cancelled || item.ready.failed) {
|
if (item.ready.cancelled || item.ready.failed) {
|
||||||
children.push([key, <ErrorCard key={`history-${key}`} image={item.image} ready={item.ready} />]);
|
children.push([key, <ErrorCard key={`history-${key}`} image={item.image} ready={item.ready} retry={item.retry} />]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { mustExist } from '@apextoaster/js-utils';
|
import { mustExist } from '@apextoaster/js-utils';
|
||||||
import { Box, Button, Card, CardContent, Typography } from '@mui/material';
|
import { Delete, Replay } from '@mui/icons-material';
|
||||||
|
import { Box, Card, CardContent, IconButton, Tooltip, Typography } from '@mui/material';
|
||||||
import { Stack } from '@mui/system';
|
import { Stack } from '@mui/system';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
|
@ -7,31 +8,35 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useMutation } from 'react-query';
|
import { useMutation } from 'react-query';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
import { ImageResponse, ReadyResponse } from '../../client/api.js';
|
import { ImageResponse, ReadyResponse, RetryParams } from '../../client/api.js';
|
||||||
import { ClientContext, ConfigContext, StateContext } from '../../state.js';
|
import { ClientContext, ConfigContext, StateContext } from '../../state.js';
|
||||||
|
|
||||||
export interface ErrorCardProps {
|
export interface ErrorCardProps {
|
||||||
image: ImageResponse;
|
image: ImageResponse;
|
||||||
ready: ReadyResponse;
|
ready: ReadyResponse;
|
||||||
|
retry: RetryParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ErrorCard(props: ErrorCardProps) {
|
export function ErrorCard(props: ErrorCardProps) {
|
||||||
const { image, ready } = props;
|
const { image, ready, retry: retryParams } = props;
|
||||||
|
|
||||||
const client = mustExist(React.useContext(ClientContext));
|
const client = mustExist(React.useContext(ClientContext));
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const pushHistory = useStore(state, (s) => s.pushHistory);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const removeHistory = useStore(state, (s) => s.removeHistory);
|
const removeHistory = useStore(state, (s) => s.removeHistory);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
// TODO: actually retry
|
async function retryImage() {
|
||||||
const retry = useMutation(() => {
|
removeHistory(image);
|
||||||
// eslint-disable-next-line no-console
|
const { image: nextImage, retry: nextRetry } = await client.retry(retryParams);
|
||||||
console.log('retry', image);
|
pushHistory(nextImage, nextRetry);
|
||||||
return Promise.resolve(true);
|
}
|
||||||
});
|
|
||||||
|
const retry = useMutation(retryImage);
|
||||||
|
|
||||||
return <Card sx={{ maxWidth: params.width.default }}>
|
return <Card sx={{ maxWidth: params.width.default }}>
|
||||||
<CardContent sx={{ height: params.height.default }}>
|
<CardContent sx={{ height: params.height.default }}>
|
||||||
|
@ -50,8 +55,18 @@ export function ErrorCard(props: ErrorCardProps) {
|
||||||
current: ready.progress,
|
current: ready.progress,
|
||||||
total: image.params.steps,
|
total: image.params.steps,
|
||||||
})}</Typography>
|
})}</Typography>
|
||||||
<Button onClick={() => retry.mutate()}>{t('loading.retry')}</Button>
|
<Stack direction='row' spacing={2}>
|
||||||
<Button onClick={() => removeHistory(image)}>{t('loading.remove')}</Button>
|
<Tooltip title={t('tooltip.retry')}>
|
||||||
|
<IconButton onClick={() => retry.mutate()}>
|
||||||
|
<Replay />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title={t('tooltip.delete')}>
|
||||||
|
<IconButton onClick={() => removeHistory(image)}>
|
||||||
|
<Delete />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
|
@ -16,14 +16,13 @@ import { MaskCanvas } from '../input/MaskCanvas.js';
|
||||||
export function Blend() {
|
export function Blend() {
|
||||||
async function uploadSource() {
|
async function uploadSource() {
|
||||||
const { model, blend, upscale } = state.getState();
|
const { model, blend, upscale } = state.getState();
|
||||||
|
const { image, retry } = await client.blend(model, {
|
||||||
const output = await client.blend(model, {
|
|
||||||
...blend,
|
...blend,
|
||||||
mask: mustExist(blend.mask),
|
mask: mustExist(blend.mask),
|
||||||
sources: mustExist(blend.sources), // TODO: show an error if this doesn't exist
|
sources: mustExist(blend.sources), // TODO: show an error if this doesn't exist
|
||||||
}, upscale);
|
}, upscale);
|
||||||
|
|
||||||
pushHistory(output);
|
pushHistory(image, retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = mustExist(useContext(ClientContext));
|
const client = mustExist(useContext(ClientContext));
|
||||||
|
|
|
@ -18,13 +18,12 @@ export function Img2Img() {
|
||||||
|
|
||||||
async function uploadSource() {
|
async function uploadSource() {
|
||||||
const { model, img2img, upscale } = state.getState();
|
const { model, img2img, upscale } = state.getState();
|
||||||
|
const { image, retry } = await client.img2img(model, {
|
||||||
const output = await client.img2img(model, {
|
|
||||||
...img2img,
|
...img2img,
|
||||||
source: mustExist(img2img.source), // TODO: show an error if this doesn't exist
|
source: mustExist(img2img.source), // TODO: show an error if this doesn't exist
|
||||||
}, upscale);
|
}, upscale);
|
||||||
|
|
||||||
pushHistory(output);
|
pushHistory(image, retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = mustExist(useContext(ClientContext));
|
const client = mustExist(useContext(ClientContext));
|
||||||
|
|
|
@ -32,22 +32,22 @@ export function Inpaint() {
|
||||||
const { model, inpaint, outpaint, upscale } = state.getState();
|
const { model, inpaint, outpaint, upscale } = state.getState();
|
||||||
|
|
||||||
if (outpaint.enabled) {
|
if (outpaint.enabled) {
|
||||||
const output = await client.outpaint(model, {
|
const { image, retry } = await client.outpaint(model, {
|
||||||
...inpaint,
|
...inpaint,
|
||||||
...outpaint,
|
...outpaint,
|
||||||
mask: mustExist(mask),
|
mask: mustExist(mask),
|
||||||
source: mustExist(source),
|
source: mustExist(source),
|
||||||
}, upscale);
|
}, upscale);
|
||||||
|
|
||||||
pushHistory(output);
|
pushHistory(image, retry);
|
||||||
} else {
|
} else {
|
||||||
const output = await client.inpaint(model, {
|
const { image, retry } = await client.inpaint(model, {
|
||||||
...inpaint,
|
...inpaint,
|
||||||
mask: mustExist(mask),
|
mask: mustExist(mask),
|
||||||
source: mustExist(source),
|
source: mustExist(source),
|
||||||
}, upscale);
|
}, upscale);
|
||||||
|
|
||||||
pushHistory(output);
|
pushHistory(image, retry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@ export function Txt2Img() {
|
||||||
|
|
||||||
async function generateImage() {
|
async function generateImage() {
|
||||||
const { model, txt2img, upscale } = state.getState();
|
const { model, txt2img, upscale } = state.getState();
|
||||||
const output = await client.txt2img(model, txt2img, upscale);
|
const { image, retry } = await client.txt2img(model, txt2img, upscale);
|
||||||
|
|
||||||
pushHistory(output);
|
pushHistory(image, retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = mustExist(useContext(ClientContext));
|
const client = mustExist(useContext(ClientContext));
|
||||||
|
|
|
@ -15,13 +15,12 @@ import { PromptInput } from '../input/PromptInput.js';
|
||||||
export function Upscale() {
|
export function Upscale() {
|
||||||
async function uploadSource() {
|
async function uploadSource() {
|
||||||
const { model, upscale } = state.getState();
|
const { model, upscale } = state.getState();
|
||||||
|
const { image, retry } = await client.upscale(model, {
|
||||||
const output = await client.upscale(model, {
|
|
||||||
...params,
|
...params,
|
||||||
source: mustExist(params.source), // TODO: show an error if this doesn't exist
|
source: mustExist(params.source), // TODO: show an error if this doesn't exist
|
||||||
}, upscale);
|
}, upscale);
|
||||||
|
|
||||||
pushHistory(output);
|
pushHistory(image, retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = mustExist(useContext(ClientContext));
|
const client = mustExist(useContext(ClientContext));
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
ModelParams,
|
ModelParams,
|
||||||
OutpaintPixels,
|
OutpaintPixels,
|
||||||
ReadyResponse,
|
ReadyResponse,
|
||||||
|
RetryParams,
|
||||||
Txt2ImgParams,
|
Txt2ImgParams,
|
||||||
UpscaleParams,
|
UpscaleParams,
|
||||||
UpscaleReqParams,
|
UpscaleReqParams,
|
||||||
|
@ -30,6 +31,7 @@ type TabState<TabParams> = ConfigFiles<Required<TabParams>> & ConfigState<Requir
|
||||||
interface HistoryItem {
|
interface HistoryItem {
|
||||||
image: ImageResponse;
|
image: ImageResponse;
|
||||||
ready: Maybe<ReadyResponse>;
|
ready: Maybe<ReadyResponse>;
|
||||||
|
retry: RetryParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BrushSlice {
|
interface BrushSlice {
|
||||||
|
@ -48,7 +50,7 @@ interface HistorySlice {
|
||||||
history: Array<HistoryItem>;
|
history: Array<HistoryItem>;
|
||||||
limit: number;
|
limit: number;
|
||||||
|
|
||||||
pushHistory(image: ImageResponse): void;
|
pushHistory(image: ImageResponse, retry: RetryParams): void;
|
||||||
removeHistory(image: ImageResponse): void;
|
removeHistory(image: ImageResponse): void;
|
||||||
setLimit(limit: number): void;
|
setLimit(limit: number): void;
|
||||||
setReady(image: ImageResponse, ready: ReadyResponse): void;
|
setReady(image: ImageResponse, ready: ReadyResponse): void;
|
||||||
|
@ -301,7 +303,7 @@ export function createStateSlices(server: ServerParams) {
|
||||||
const createHistorySlice: Slice<HistorySlice> = (set) => ({
|
const createHistorySlice: Slice<HistorySlice> = (set) => ({
|
||||||
history: [],
|
history: [],
|
||||||
limit: DEFAULT_HISTORY.limit,
|
limit: DEFAULT_HISTORY.limit,
|
||||||
pushHistory(image) {
|
pushHistory(image, retry) {
|
||||||
set((prev) => ({
|
set((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
history: [
|
history: [
|
||||||
|
@ -313,6 +315,7 @@ export function createStateSlices(server: ServerParams) {
|
||||||
progress: 0,
|
progress: 0,
|
||||||
ready: false,
|
ready: false,
|
||||||
},
|
},
|
||||||
|
retry,
|
||||||
},
|
},
|
||||||
...prev.history,
|
...prev.history,
|
||||||
],
|
],
|
||||||
|
|
|
@ -154,6 +154,7 @@ export const I18N_STRINGS_DE = {
|
||||||
delete: 'Löschen',
|
delete: 'Löschen',
|
||||||
next: 'Nächste',
|
next: 'Nächste',
|
||||||
previous: 'Vorherige',
|
previous: 'Vorherige',
|
||||||
|
retry: '',
|
||||||
save: 'Speichern',
|
save: 'Speichern',
|
||||||
},
|
},
|
||||||
upscaleOrder: {
|
upscaleOrder: {
|
||||||
|
|
|
@ -217,6 +217,7 @@ export const I18N_STRINGS_EN = {
|
||||||
delete: 'Delete',
|
delete: 'Delete',
|
||||||
next: 'Next',
|
next: 'Next',
|
||||||
previous: 'Previous',
|
previous: 'Previous',
|
||||||
|
retry: 'Retry',
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
},
|
},
|
||||||
upscaleOrder: {
|
upscaleOrder: {
|
||||||
|
|
|
@ -154,6 +154,7 @@ export const I18N_STRINGS_ES = {
|
||||||
delete: 'Borrar',
|
delete: 'Borrar',
|
||||||
next: 'Próximo',
|
next: 'Próximo',
|
||||||
previous: 'Anterior',
|
previous: 'Anterior',
|
||||||
|
retry: '',
|
||||||
save: 'Ahorrar',
|
save: 'Ahorrar',
|
||||||
},
|
},
|
||||||
upscaleOrder: {
|
upscaleOrder: {
|
||||||
|
|
|
@ -154,6 +154,7 @@ export const I18N_STRINGS_FR = {
|
||||||
delete: '',
|
delete: '',
|
||||||
next: '',
|
next: '',
|
||||||
previous: '',
|
previous: '',
|
||||||
|
retry: '',
|
||||||
save: '',
|
save: '',
|
||||||
},
|
},
|
||||||
upscaleOrder: {
|
upscaleOrder: {
|
||||||
|
|
Loading…
Reference in New Issue