feat(gui): add cancel to API client
This commit is contained in:
parent
294c831d02
commit
900a95eb61
|
@ -141,6 +141,7 @@ export interface ImageResponse {
|
|||
* Status response from the ready endpoint.
|
||||
*/
|
||||
export interface ReadyResponse {
|
||||
progress: number;
|
||||
ready: boolean;
|
||||
}
|
||||
|
||||
|
@ -213,6 +214,8 @@ export interface ApiClient {
|
|||
* Check whether some pipeline's output is ready yet.
|
||||
*/
|
||||
ready(params: ImageResponse): Promise<ReadyResponse>;
|
||||
|
||||
cancel(params: ImageResponse): Promise<boolean>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -495,7 +498,14 @@ export function makeClient(root: string, f = fetch): ApiClient {
|
|||
|
||||
const res = await f(path);
|
||||
return await res.json() as ReadyResponse;
|
||||
}
|
||||
},
|
||||
async cancel(params: ImageResponse): Promise<boolean> {
|
||||
const path = makeApiUrl(root, 'cancel');
|
||||
path.searchParams.append('output', params.output.key);
|
||||
|
||||
const res = await f(path);
|
||||
return res.status === STATUS_SUCCESS;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -17,12 +17,12 @@ export function ImageHistory() {
|
|||
|
||||
const children = [];
|
||||
|
||||
if (doesExist(loading)) {
|
||||
children.push(<LoadingCard key='loading' loading={loading} />);
|
||||
if (loading.length > 0) {
|
||||
children.push(...loading.map((item) => <LoadingCard key={`loading-${item.image.output.key}`} loading={item.image} />));
|
||||
}
|
||||
|
||||
if (history.length > 0) {
|
||||
children.push(...history.map((item) => <ImageCard key={item.output.key} value={item} onDelete={removeHistory} />));
|
||||
children.push(...history.map((item) => <ImageCard key={`history-${item.output.key}`} value={item} onDelete={removeHistory} />));
|
||||
} else {
|
||||
if (doesExist(loading) === false) {
|
||||
children.push(<Typography>No results. Press Generate.</Typography>);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { doesExist, mustExist } from '@apextoaster/js-utils';
|
||||
import { Card, CardContent, CircularProgress } from '@mui/material';
|
||||
import { Button, Card, CardContent, CircularProgress } from '@mui/material';
|
||||
import * as React from 'react';
|
||||
import { useContext } from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
import { useStore } from 'zustand';
|
||||
|
||||
import { ImageResponse } from '../client.js';
|
||||
|
@ -17,15 +17,34 @@ export function LoadingCard(props: LoadingCardProps) {
|
|||
const client = mustExist(React.useContext(ClientContext));
|
||||
const { params } = mustExist(useContext(ConfigContext));
|
||||
|
||||
const state = mustExist(useContext(StateContext));
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const pushHistory = useStore(mustExist(useContext(StateContext)), (state) => state.pushHistory);
|
||||
const clearLoading = useStore(state, (s) => s.clearLoading);
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const pushHistory = useStore(state, (s) => s.pushHistory);
|
||||
|
||||
async function doCancel() {
|
||||
const cancelled = await client.cancel(props.loading);
|
||||
if (cancelled) {
|
||||
clearLoading();
|
||||
}
|
||||
}
|
||||
|
||||
const cancel = useMutation(doCancel);
|
||||
const query = useQuery('ready', () => client.ready(props.loading), {
|
||||
// data will always be ready without this, even if the API says its not
|
||||
cacheTime: 0,
|
||||
refetchInterval: POLL_TIME,
|
||||
});
|
||||
|
||||
function progress() {
|
||||
if (doesExist(query.data)) {
|
||||
return Math.ceil(query.data.progress / props.loading.params.steps);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function ready() {
|
||||
return doesExist(query.data) && query.data.ready;
|
||||
}
|
||||
|
@ -44,7 +63,8 @@ export function LoadingCard(props: LoadingCardProps) {
|
|||
justifyContent: 'center',
|
||||
minHeight: params.height.default,
|
||||
}}>
|
||||
<CircularProgress />
|
||||
<CircularProgress value={progress()} />
|
||||
<Button>Cancel</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable no-null/no-null */
|
||||
import { Maybe } from '@apextoaster/js-utils';
|
||||
import { doesExist, Maybe } from '@apextoaster/js-utils';
|
||||
import { createContext } from 'react';
|
||||
import { StateCreator, StoreApi } from 'zustand';
|
||||
|
||||
|
@ -12,6 +12,7 @@ import {
|
|||
InpaintParams,
|
||||
ModelParams,
|
||||
OutpaintPixels,
|
||||
ReadyResponse,
|
||||
Txt2ImgParams,
|
||||
UpscaleParams,
|
||||
UpscaleReqParams,
|
||||
|
@ -23,6 +24,11 @@ import { Config, ConfigFiles, ConfigState, ServerParams } from './config.js';
|
|||
*/
|
||||
type TabState<TabParams> = ConfigFiles<Required<TabParams>> & ConfigState<Required<TabParams>>;
|
||||
|
||||
interface LoadingItem {
|
||||
image: ImageResponse;
|
||||
ready: Maybe<ReadyResponse>;
|
||||
}
|
||||
|
||||
interface BrushSlice {
|
||||
brush: BrushParams;
|
||||
|
||||
|
@ -38,12 +44,14 @@ interface DefaultSlice {
|
|||
interface HistorySlice {
|
||||
history: Array<ImageResponse>;
|
||||
limit: number;
|
||||
loading: Maybe<ImageResponse>;
|
||||
loading: Array<LoadingItem>;
|
||||
|
||||
// TODO: hack until setLoading removes things
|
||||
clearLoading(): void;
|
||||
pushHistory(image: ImageResponse): void;
|
||||
removeHistory(image: ImageResponse): void;
|
||||
setLimit(limit: number): void;
|
||||
setLoading(image: Maybe<ImageResponse>): void;
|
||||
setLoading(image: ImageResponse, ready?: Maybe<ReadyResponse>): void;
|
||||
}
|
||||
|
||||
interface ModelSlice {
|
||||
|
@ -264,7 +272,13 @@ export function createStateSlices(server: ServerParams) {
|
|||
const createHistorySlice: Slice<HistorySlice> = (set) => ({
|
||||
history: [],
|
||||
limit: DEFAULT_HISTORY.limit,
|
||||
loading: null,
|
||||
loading: [],
|
||||
clearLoading() {
|
||||
set((prev) => ({
|
||||
...prev,
|
||||
loading: [],
|
||||
}));
|
||||
},
|
||||
pushHistory(image) {
|
||||
set((prev) => ({
|
||||
...prev,
|
||||
|
@ -272,9 +286,25 @@ export function createStateSlices(server: ServerParams) {
|
|||
image,
|
||||
...prev.history,
|
||||
].slice(0, prev.limit + DEFAULT_HISTORY.scrollback),
|
||||
loading: null,
|
||||
loading: [],
|
||||
}));
|
||||
},
|
||||
setLoading(image, ready) {
|
||||
set((prev) => {
|
||||
const loading = [...prev.loading];
|
||||
const idx = loading.findIndex((it) => it.image.output.key === image.output.key);
|
||||
if (idx >= 0) {
|
||||
loading[idx].ready = ready;
|
||||
} else {
|
||||
loading.push({ image, ready });
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
loading,
|
||||
};
|
||||
});
|
||||
},
|
||||
removeHistory(image) {
|
||||
set((prev) => ({
|
||||
...prev,
|
||||
|
@ -287,12 +317,6 @@ export function createStateSlices(server: ServerParams) {
|
|||
limit,
|
||||
}));
|
||||
},
|
||||
setLoading(loading) {
|
||||
set((prev) => ({
|
||||
...prev,
|
||||
loading,
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
const createOutpaintSlice: Slice<OutpaintSlice> = (set) => ({
|
||||
|
|
Loading…
Reference in New Issue