clean up horizontal layout styles, use constants for spacing
This commit is contained in:
parent
f5506b17f0
commit
f30c5f2d31
|
@ -2,6 +2,8 @@
|
||||||
import { doesExist, InvalidArgumentError, Maybe } from '@apextoaster/js-utils';
|
import { doesExist, InvalidArgumentError, Maybe } from '@apextoaster/js-utils';
|
||||||
|
|
||||||
import { ServerParams } from '../config.js';
|
import { ServerParams } from '../config.js';
|
||||||
|
import { FIXED_FLOAT, FIXED_INTEGER, STATUS_SUCCESS } from '../constants.js';
|
||||||
|
import { JobResponse, JobResponseWithRetry, SuccessJobResponse } from '../types/api-v2.js';
|
||||||
import {
|
import {
|
||||||
FilterResponse,
|
FilterResponse,
|
||||||
ModelResponse,
|
ModelResponse,
|
||||||
|
@ -24,22 +26,6 @@ import {
|
||||||
} from '../types/params.js';
|
} from '../types/params.js';
|
||||||
import { range } from '../utils.js';
|
import { range } from '../utils.js';
|
||||||
import { ApiClient } from './base.js';
|
import { ApiClient } from './base.js';
|
||||||
import { JobResponse, JobResponseWithRetry, SuccessJobResponse } from '../types/api-v2.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixed precision for integer parameters.
|
|
||||||
*/
|
|
||||||
export const FIXED_INTEGER = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixed precision for float parameters.
|
|
||||||
*
|
|
||||||
* The GUI limits the input steps based on the server parameters, but this does limit
|
|
||||||
* the maximum precision that can be sent back to the server, and may have to be
|
|
||||||
* increased in the future.
|
|
||||||
*/
|
|
||||||
export const FIXED_FLOAT = 2;
|
|
||||||
export const STATUS_SUCCESS = 200;
|
|
||||||
|
|
||||||
export function equalResponse(a: JobResponse, b: JobResponse): boolean {
|
export function equalResponse(a: JobResponse, b: JobResponse): boolean {
|
||||||
return a.name === b.name;
|
return a.name === b.name;
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import { mustExist } from '@apextoaster/js-utils';
|
import { mustExist } from '@apextoaster/js-utils';
|
||||||
import { Grid, Typography } from '@mui/material';
|
import { Grid, Typography } from '@mui/material';
|
||||||
import { ReactNode, useContext } from 'react';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { ReactNode, useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../constants.js';
|
||||||
import { OnnxState, StateContext } from '../state/full.js';
|
import { OnnxState, StateContext } from '../state/full.js';
|
||||||
|
import { JobStatus } from '../types/api-v2.js';
|
||||||
import { ErrorCard } from './card/ErrorCard.js';
|
import { ErrorCard } from './card/ErrorCard.js';
|
||||||
import { ImageCard } from './card/ImageCard.js';
|
import { ImageCard } from './card/ImageCard.js';
|
||||||
import { LoadingCard } from './card/LoadingCard.js';
|
import { LoadingCard } from './card/LoadingCard.js';
|
||||||
import { JobStatus } from '../types/api-v2.js';
|
|
||||||
|
|
||||||
export interface ImageHistoryProps {
|
export interface ImageHistoryProps {
|
||||||
width: number;
|
width: number;
|
||||||
|
@ -50,7 +51,7 @@ export function ImageHistory(props: ImageHistoryProps) {
|
||||||
|
|
||||||
return <Grid
|
return <Grid
|
||||||
container
|
container
|
||||||
spacing={2}
|
spacing={STANDARD_SPACING}
|
||||||
>{
|
>{
|
||||||
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
||||||
children.map(([key, child]) => <Grid item key={key} xs={12 / width}>{child}</Grid>)
|
children.map(([key, child]) => <Grid item key={key} xs={12 / width}>{child}</Grid>)
|
||||||
|
|
|
@ -2,6 +2,8 @@ import { Box, CircularProgress, Stack, Typography } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../constants';
|
||||||
|
|
||||||
export function LoadingScreen() {
|
export function LoadingScreen() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
@ -13,7 +15,7 @@ export function LoadingScreen() {
|
||||||
}}>
|
}}>
|
||||||
<Stack
|
<Stack
|
||||||
direction='column'
|
direction='column'
|
||||||
spacing={2}
|
spacing={STANDARD_SPACING}
|
||||||
sx={{ alignItems: 'center' }}
|
sx={{ alignItems: 'center' }}
|
||||||
>
|
>
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Box, Button, Container, Stack, Typography } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
import { STANDARD_MARGIN, STANDARD_SPACING } from '../constants.js';
|
||||||
import { STATE_KEY } from '../state/full.js';
|
import { STATE_KEY } from '../state/full.js';
|
||||||
import { Logo } from './Logo.js';
|
import { Logo } from './Logo.js';
|
||||||
|
|
||||||
|
@ -20,11 +21,11 @@ export function OnnxError(props: OnnxErrorProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Box sx={{ my: 4 }}>
|
<Box sx={{ my: STANDARD_MARGIN }}>
|
||||||
<Logo />
|
<Logo />
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ my: 4 }}>
|
<Box sx={{ my: STANDARD_MARGIN }}>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={STANDARD_SPACING}>
|
||||||
{props.children}
|
{props.children}
|
||||||
<Typography variant='body1'>
|
<Typography variant='body1'>
|
||||||
This is a web UI for running ONNX models with GPU acceleration or in software, running locally or on a
|
This is a web UI for running ONNX models with GPU acceleration or in software, running locally or on a
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
/* eslint-disable @typescript-eslint/no-magic-numbers */
|
|
||||||
import { mustExist } from '@apextoaster/js-utils';
|
import { mustExist } from '@apextoaster/js-utils';
|
||||||
import { TabContext, TabList, TabPanel } from '@mui/lab';
|
import { TabContext, TabList, TabPanel } from '@mui/lab';
|
||||||
import { Box, Container, CssBaseline, Divider, Stack, Tab, useMediaQuery } from '@mui/material';
|
import { Box, Container, CssBaseline, Divider, Stack, Tab, useMediaQuery } from '@mui/material';
|
||||||
import { Breakpoint, SxProps, Theme, ThemeProvider, createTheme } from '@mui/material/styles';
|
import { SxProps, Theme, ThemeProvider, createTheme } from '@mui/material/styles';
|
||||||
import { Allotment } from 'allotment';
|
import { Allotment } from 'allotment';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useContext, useMemo } from 'react';
|
import { useContext, useMemo } from 'react';
|
||||||
import { useHash } from 'react-use/lib/useHash';
|
import { useHash } from 'react-use/lib/useHash';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
|
||||||
|
|
||||||
|
import { LAYOUT_MIN, LAYOUT_PROPORTIONS, LAYOUT_STYLES, STANDARD_MARGIN, STANDARD_SPACING } from '../constants.js';
|
||||||
import { Motd } from '../Motd.js';
|
import { Motd } from '../Motd.js';
|
||||||
import { OnnxState, StateContext } from '../state/full.js';
|
import { OnnxState, StateContext } from '../state/full.js';
|
||||||
import { Layout } from '../state/settings.js';
|
import { Layout } from '../state/settings.js';
|
||||||
|
@ -36,7 +35,10 @@ export function OnnxWeb(props: OnnxWebProps) {
|
||||||
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
||||||
const store = mustExist(useContext(StateContext));
|
const store = mustExist(useContext(StateContext));
|
||||||
const stateTheme = useStore(store, selectTheme);
|
const stateTheme = useStore(store, selectTheme);
|
||||||
const layout = useStore(store, selectLayout, shallow);
|
const historyWidth = useStore(store, selectHistoryWidth);
|
||||||
|
const direction = useStore(store, selectDirection);
|
||||||
|
|
||||||
|
const layout = LAYOUT_STYLES[direction];
|
||||||
|
|
||||||
const theme = useMemo(
|
const theme = useMemo(
|
||||||
() => createTheme({
|
() => createTheme({
|
||||||
|
@ -47,17 +49,17 @@ export function OnnxWeb(props: OnnxWebProps) {
|
||||||
[prefersDarkMode, stateTheme],
|
[prefersDarkMode, stateTheme],
|
||||||
);
|
);
|
||||||
|
|
||||||
const historyStyle: SxProps<Theme> = LAYOUT_STYLES[layout.direction].history.style;
|
const historyStyle: SxProps<Theme> = layout.history.style;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Container maxWidth={LAYOUT_STYLES[layout.direction].container}>
|
<Container maxWidth={layout.container}>
|
||||||
<Box sx={{ my: 4 }}>
|
<Box sx={{ my: STANDARD_MARGIN }}>
|
||||||
<Logo />
|
<Logo />
|
||||||
</Box>
|
</Box>
|
||||||
{props.motd && <Motd />}
|
{props.motd && <Motd />}
|
||||||
{renderBody(layout, historyStyle)}
|
{renderBody(direction, historyStyle, historyWidth)}
|
||||||
</Container>
|
</Container>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
|
@ -67,52 +69,19 @@ export function selectTheme(state: OnnxState) {
|
||||||
return state.theme;
|
return state.theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectLayout(state: OnnxState) {
|
export function selectDirection(state: OnnxState) {
|
||||||
return {
|
return state.layout;
|
||||||
direction: state.layout,
|
|
||||||
width: state.historyWidth,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LAYOUT_STYLES = {
|
export function selectHistoryWidth(state: OnnxState) {
|
||||||
horizontal: {
|
return state.historyWidth;
|
||||||
container: false,
|
}
|
||||||
control: {
|
|
||||||
width: '30%',
|
|
||||||
},
|
|
||||||
direction: 'row',
|
|
||||||
divider: 'vertical',
|
|
||||||
history: {
|
|
||||||
style: {
|
|
||||||
marginLeft: 4,
|
|
||||||
maxHeight: '85vb',
|
|
||||||
overflowY: 'auto',
|
|
||||||
},
|
|
||||||
width: 4,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
vertical: {
|
|
||||||
container: 'lg' as Breakpoint,
|
|
||||||
control: {
|
|
||||||
width: undefined,
|
|
||||||
},
|
|
||||||
direction: 'column',
|
|
||||||
divider: 'horizontal',
|
|
||||||
history: {
|
|
||||||
style: {
|
|
||||||
mx: 4,
|
|
||||||
my: 4,
|
|
||||||
},
|
|
||||||
width: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
function renderBody(layout: ReturnType<typeof selectLayout>, historyStyle: SxProps<Theme>) {
|
function renderBody(direction: Layout, historyStyle: SxProps<Theme>, historyWidth: number) {
|
||||||
if (layout.direction === 'vertical') {
|
if (direction === 'vertical') {
|
||||||
return <VerticalBody {...layout} style={historyStyle} />;
|
return <VerticalBody direction={direction} style={historyStyle} width={historyWidth} />;
|
||||||
} else {
|
} else {
|
||||||
return <HorizontalBody {...layout} style={historyStyle} />;
|
return <HorizontalBody direction={direction} style={historyStyle} width={historyWidth} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,9 +95,9 @@ export interface BodyProps {
|
||||||
export function HorizontalBody(props: BodyProps) {
|
export function HorizontalBody(props: BodyProps) {
|
||||||
const layout = LAYOUT_STYLES[props.direction];
|
const layout = LAYOUT_STYLES[props.direction];
|
||||||
|
|
||||||
return <Allotment separator className='body-allotment' minSize={300}>
|
return <Allotment separator className='body-allotment' minSize={LAYOUT_MIN} defaultSizes={LAYOUT_PROPORTIONS} snap>
|
||||||
<TabGroup direction={props.direction} />
|
<TabGroup direction={props.direction} />
|
||||||
<Box sx={layout.history.style}>
|
<Box className='box-history' sx={layout.history.style}>
|
||||||
<ImageHistory width={props.width} />
|
<ImageHistory width={props.width} />
|
||||||
</Box>
|
</Box>
|
||||||
</Allotment>;
|
</Allotment>;
|
||||||
|
@ -137,10 +106,10 @@ export function HorizontalBody(props: BodyProps) {
|
||||||
export function VerticalBody(props: BodyProps) {
|
export function VerticalBody(props: BodyProps) {
|
||||||
const layout = LAYOUT_STYLES[props.direction];
|
const layout = LAYOUT_STYLES[props.direction];
|
||||||
|
|
||||||
return <Stack direction={layout.direction} spacing={2}>
|
return <Stack direction={layout.direction} spacing={STANDARD_SPACING}>
|
||||||
<TabGroup direction={props.direction} />
|
<TabGroup direction={props.direction} />
|
||||||
<Divider flexItem variant='middle' orientation={layout.divider} />
|
<Divider flexItem variant='middle' orientation={layout.divider} />
|
||||||
<Box sx={layout.history.style}>
|
<Box className='box-history' sx={layout.history.style}>
|
||||||
<ImageHistory width={props.width} />
|
<ImageHistory width={props.width} />
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>;
|
</Stack>;
|
||||||
|
@ -155,7 +124,7 @@ export function TabGroup(props: TabGroupProps) {
|
||||||
|
|
||||||
const [hash, setHash] = useHash();
|
const [hash, setHash] = useHash();
|
||||||
|
|
||||||
return <Stack direction='column' minWidth={layout.control.width} sx={{ mx: 4 }}>
|
return <Stack direction='column' minWidth={layout.control.width} sx={{ mx: STANDARD_MARGIN }}>
|
||||||
<TabContext value={getTab(hash)}>
|
<TabContext value={getTab(hash)}>
|
||||||
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
||||||
<TabList onChange={(_e, idx) => {
|
<TabList onChange={(_e, idx) => {
|
||||||
|
|
|
@ -21,12 +21,15 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../constants.js';
|
||||||
import { OnnxState, StateContext } from '../state/full.js';
|
import { OnnxState, StateContext } from '../state/full.js';
|
||||||
import { ImageMetadata } from '../types/api.js';
|
import { AnyImageMetadata } from '../types/api-v2.js';
|
||||||
import { DeepPartial } from '../types/model.js';
|
import { DeepPartial } from '../types/model.js';
|
||||||
import { BaseImgParams, HighresParams, ModelParams, Txt2ImgParams, UpscaleParams } from '../types/params.js';
|
import { BaseImgParams, HighresParams, ModelParams, Txt2ImgParams, UpscaleParams } from '../types/params.js';
|
||||||
import { downloadAsJson } from '../utils.js';
|
import { downloadAsJson } from '../utils.js';
|
||||||
|
|
||||||
|
export type PartialImageMetadata = DeepPartial<AnyImageMetadata>;
|
||||||
|
|
||||||
export const ALLOWED_EXTENSIONS = ['.json','.jpg','.jpeg','.png','.txt','.webp'];
|
export const ALLOWED_EXTENSIONS = ['.json','.jpg','.jpeg','.png','.txt','.webp'];
|
||||||
export const EXTENSION_FILTER = ALLOWED_EXTENSIONS.join(',');
|
export const EXTENSION_FILTER = ALLOWED_EXTENSIONS.join(',');
|
||||||
|
|
||||||
|
@ -51,7 +54,7 @@ export function Profiles(props: ProfilesProps) {
|
||||||
const [profileName, setProfileName] = useState('');
|
const [profileName, setProfileName] = useState('');
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack direction='row' spacing={2}>
|
return <Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
id='profile-select'
|
id='profile-select'
|
||||||
options={profiles}
|
options={profiles}
|
||||||
|
@ -193,7 +196,7 @@ export function selectProfiles(state: OnnxState) {
|
||||||
return state.profiles;
|
return state.profiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadParamsFromFile(file: File): Promise<DeepPartial<ImageMetadata>> {
|
export async function loadParamsFromFile(file: File): Promise<PartialImageMetadata> {
|
||||||
const parts = file.name.toLocaleLowerCase().split('.');
|
const parts = file.name.toLocaleLowerCase().split('.');
|
||||||
const ext = parts[parts.length - 1];
|
const ext = parts[parts.length - 1];
|
||||||
|
|
||||||
|
@ -211,7 +214,7 @@ export async function loadParamsFromFile(file: File): Promise<DeepPartial<ImageM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseImageParams(file: File): Promise<DeepPartial<ImageMetadata>> {
|
export async function parseImageParams(file: File): Promise<PartialImageMetadata> {
|
||||||
const tags = await ExifReader.load(file);
|
const tags = await ExifReader.load(file);
|
||||||
|
|
||||||
// some parsers expect uppercase, some use lowercase, read both
|
// some parsers expect uppercase, some use lowercase, read both
|
||||||
|
@ -251,8 +254,8 @@ export function decodeTag(tag: Maybe<ExifReader.XmpTag | (ExifReader.NumberTag &
|
||||||
throw new InvalidArgumentError('tag value cannot be decoded');
|
throw new InvalidArgumentError('tag value cannot be decoded');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseJSONParams(json: string): Promise<DeepPartial<ImageMetadata>> {
|
export async function parseJSONParams(json: string): Promise<PartialImageMetadata> {
|
||||||
const data = JSON.parse(json) as DeepPartial<ImageMetadata>;
|
const data = JSON.parse(json) as PartialImageMetadata;
|
||||||
const params: Partial<Txt2ImgParams> = {
|
const params: Partial<Txt2ImgParams> = {
|
||||||
...data.params,
|
...data.params,
|
||||||
};
|
};
|
||||||
|
@ -276,7 +279,7 @@ export function isProbablyJSON(maybeJSON: unknown): boolean {
|
||||||
|
|
||||||
export const NEGATIVE_PROMPT_TAG = 'Negative prompt:';
|
export const NEGATIVE_PROMPT_TAG = 'Negative prompt:';
|
||||||
|
|
||||||
export async function parseAutoComment(comment: string): Promise<DeepPartial<ImageMetadata>> {
|
export async function parseAutoComment(comment: string): Promise<PartialImageMetadata> {
|
||||||
if (isProbablyJSON(comment)) {
|
if (isProbablyJSON(comment)) {
|
||||||
return parseJSONParams(comment);
|
return parseJSONParams(comment);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { FailedJobResponse, JobStatus, RetryParams, UnknownJobResponse } from '../../types/api-v2.js';
|
import { FailedJobResponse, JobStatus, RetryParams, UnknownJobResponse } from '../../types/api-v2.js';
|
||||||
|
import { STANDARD_SPACING } from '../../constants.js';
|
||||||
|
|
||||||
export interface ErrorCardProps {
|
export interface ErrorCardProps {
|
||||||
image: FailedJobResponse | UnknownJobResponse;
|
image: FailedJobResponse | UnknownJobResponse;
|
||||||
|
@ -48,7 +49,7 @@ export function ErrorCard(props: ErrorCardProps) {
|
||||||
}}>
|
}}>
|
||||||
<Stack
|
<Stack
|
||||||
direction='column'
|
direction='column'
|
||||||
spacing={2}
|
spacing={STANDARD_SPACING}
|
||||||
sx={{ alignItems: 'center' }}
|
sx={{ alignItems: 'center' }}
|
||||||
>
|
>
|
||||||
<Alert severity='error'>
|
<Alert severity='error'>
|
||||||
|
@ -56,7 +57,7 @@ export function ErrorCard(props: ErrorCardProps) {
|
||||||
<br />
|
<br />
|
||||||
{t(getImageErrorReason(image))}
|
{t(getImageErrorReason(image))}
|
||||||
</Alert>
|
</Alert>
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<Tooltip title={t('tooltip.retry')}>
|
<Tooltip title={t('tooltip.retry')}>
|
||||||
<IconButton onClick={() => retry.mutate()}>
|
<IconButton onClick={() => retry.mutate()}>
|
||||||
<Replay />
|
<Replay />
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { range, visibleIndex } from '../../utils.js';
|
import { range, visibleIndex } from '../../utils.js';
|
||||||
import { BLEND_SOURCES } from '../../constants.js';
|
import { BLEND_SOURCES, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { JobResponse, SuccessJobResponse } from '../../types/api-v2.js';
|
import { JobResponse, SuccessJobResponse } from '../../types/api-v2.js';
|
||||||
|
|
||||||
export interface ImageCardProps {
|
export interface ImageCardProps {
|
||||||
|
@ -120,7 +120,7 @@ export function ImageCard(props: ImageCardProps) {
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box textAlign='center'>
|
<Box textAlign='center'>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={STANDARD_SPACING}>
|
||||||
<GridItem xs={4}>
|
<GridItem xs={4}>
|
||||||
<Tooltip title={t('tooltip.previous')}>
|
<Tooltip title={t('tooltip.previous')}>
|
||||||
<IconButton onClick={() => {
|
<IconButton onClick={() => {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { POLL_TIME } from '../../config.js';
|
import { POLL_TIME, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { JobResponse, JobStatus } from '../../types/api-v2.js';
|
import { JobResponse, JobStatus } from '../../types/api-v2.js';
|
||||||
import { visibleIndex } from '../../utils.js';
|
import { visibleIndex } from '../../utils.js';
|
||||||
|
@ -71,7 +71,7 @@ export function LoadingCard(props: LoadingCardProps) {
|
||||||
}}>
|
}}>
|
||||||
<Stack
|
<Stack
|
||||||
direction='column'
|
direction='column'
|
||||||
spacing={2}
|
spacing={STANDARD_SPACING}
|
||||||
sx={{ alignItems: 'center' }}
|
sx={{ alignItems: 'center' }}
|
||||||
>
|
>
|
||||||
{renderProgress()}
|
{renderProgress()}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { STALE_TIME } from '../../config.js';
|
import { STALE_TIME, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { BaseImgParams } from '../../types/params.js';
|
import { BaseImgParams } from '../../types/params.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
|
@ -46,7 +46,7 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
staleTime: STALE_TIME,
|
staleTime: STALE_TIME,
|
||||||
});
|
});
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={STANDARD_SPACING}>
|
||||||
<Stack direction='row' spacing={4}>
|
<Stack direction='row' spacing={4}>
|
||||||
<QueryList
|
<QueryList
|
||||||
id='schedulers'
|
id='schedulers'
|
||||||
|
|
|
@ -5,11 +5,11 @@ import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { STALE_TIME } from '../../config.js';
|
import { STALE_TIME, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ClientContext } from '../../state/full.js';
|
import { ClientContext } from '../../state/full.js';
|
||||||
|
import { JobType } from '../../types/api-v2.js';
|
||||||
import { ModelParams } from '../../types/params.js';
|
import { ModelParams } from '../../types/params.js';
|
||||||
import { QueryList } from '../input/QueryList.js';
|
import { QueryList } from '../input/QueryList.js';
|
||||||
import { JobType } from '../../types/api-v2.js';
|
|
||||||
|
|
||||||
export interface ModelControlProps {
|
export interface ModelControlProps {
|
||||||
model: ModelParams;
|
model: ModelParams;
|
||||||
|
@ -35,7 +35,7 @@ export function ModelControl(props: ModelControlProps) {
|
||||||
staleTime: STALE_TIME,
|
staleTime: STALE_TIME,
|
||||||
});
|
});
|
||||||
|
|
||||||
return <Stack direction='row' spacing={2}>
|
return <Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<QueryList
|
<QueryList
|
||||||
id='platforms'
|
id='platforms'
|
||||||
labelKey='platform'
|
labelKey='platform'
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { useStore } from 'zustand';
|
||||||
import { PipelineGrid } from '../../client/utils.js';
|
import { PipelineGrid } from '../../client/utils.js';
|
||||||
import { OnnxState, StateContext } from '../../state/full.js';
|
import { OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { VARIABLE_PARAMETERS } from '../../types/chain.js';
|
import { VARIABLE_PARAMETERS } from '../../types/chain.js';
|
||||||
|
import { STANDARD_SPACING } from '../../constants.js';
|
||||||
|
|
||||||
export interface VariableControlProps {
|
export interface VariableControlProps {
|
||||||
selectGrid: (state: OnnxState) => PipelineGrid;
|
selectGrid: (state: OnnxState) => PipelineGrid;
|
||||||
|
@ -20,7 +21,7 @@ export function VariableControl(props: VariableControlProps) {
|
||||||
const grid = useStore(store, props.selectGrid);
|
const grid = useStore(store, props.selectGrid);
|
||||||
|
|
||||||
const stack = [
|
const stack = [
|
||||||
<Stack direction='row' spacing={2} key='variable-enable'>
|
<Stack direction='row' spacing={STANDARD_SPACING} key='variable-enable'>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
label='Grid Mode'
|
label='Grid Mode'
|
||||||
|
@ -37,7 +38,7 @@ export function VariableControl(props: VariableControlProps) {
|
||||||
|
|
||||||
if (grid.enabled) {
|
if (grid.enabled) {
|
||||||
stack.push(
|
stack.push(
|
||||||
<Stack direction='row' spacing={2} key='variable-row'>
|
<Stack direction='row' spacing={STANDARD_SPACING} key='variable-row'>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<InputLabel id='TODO'>Columns</InputLabel>
|
<InputLabel id='TODO'>Columns</InputLabel>
|
||||||
<Select onChange={(event) => props.setGrid({
|
<Select onChange={(event) => props.setGrid({
|
||||||
|
@ -56,7 +57,7 @@ export function VariableControl(props: VariableControlProps) {
|
||||||
},
|
},
|
||||||
})} />
|
})} />
|
||||||
</Stack>,
|
</Stack>,
|
||||||
<Stack direction='row' spacing={2} key='variable-column'>
|
<Stack direction='row' spacing={STANDARD_SPACING} key='variable-column'>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<InputLabel id='TODO'>Rows</InputLabel>
|
<InputLabel id='TODO'>Rows</InputLabel>
|
||||||
<Select onChange={(event) => props.setGrid({
|
<Select onChange={(event) => props.setGrid({
|
||||||
|
@ -78,7 +79,7 @@ export function VariableControl(props: VariableControlProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Stack direction='column' spacing={2}>{...stack}</Stack>;
|
return <Stack direction='column' spacing={STANDARD_SPACING}>{...stack}</Stack>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parameterList(exclude?: Array<string>) {
|
export function parameterList(exclude?: Array<string>) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Alert, AlertTitle, Typography } from '@mui/material';
|
import { Alert, AlertTitle, Typography } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { PARAM_VERSION } from '../../config.js';
|
import { PARAM_VERSION } from '../../constants';
|
||||||
|
|
||||||
export interface ParamsVersionErrorProps {
|
export interface ParamsVersionErrorProps {
|
||||||
root: string;
|
root: string;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { memo, useContext, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../../constants.js';
|
||||||
import { OnnxState, StateContext } from '../../state/full.js';
|
import { OnnxState, StateContext } from '../../state/full.js';
|
||||||
|
|
||||||
export interface EditableListProps<T> {
|
export interface EditableListProps<T> {
|
||||||
|
@ -30,7 +31,7 @@ export function EditableList<T>(props: EditableListProps<T>) {
|
||||||
const [nextSource, setNextSource] = useState('');
|
const [nextSource, setNextSource] = useState('');
|
||||||
const RenderMemo = useMemo(() => memo(renderItem), [renderItem]);
|
const RenderMemo = useMemo(() => memo(renderItem), [renderItem]);
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={STANDARD_SPACING}>
|
||||||
{items.map((model, idx) =>
|
{items.map((model, idx) =>
|
||||||
<RenderMemo
|
<RenderMemo
|
||||||
key={idx}
|
key={idx}
|
||||||
|
@ -39,7 +40,7 @@ export function EditableList<T>(props: EditableListProps<T>) {
|
||||||
onRemove={removeItem}
|
onRemove={removeItem}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('extras.label')}
|
label={t('extras.label')}
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { Button, Stack, Typography } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../../constants';
|
||||||
|
|
||||||
export interface ImageInputProps {
|
export interface ImageInputProps {
|
||||||
filter: string;
|
filter: string;
|
||||||
image?: Maybe<Blob>;
|
image?: Maybe<Blob>;
|
||||||
|
@ -35,7 +37,7 @@ export function ImageInput(props: ImageInputProps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Stack direction='row' spacing={2}>
|
return <Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Button component='label' startIcon={<PhotoCamera />} variant='outlined'>
|
<Button component='label' startIcon={<PhotoCamera />} variant='outlined'>
|
||||||
{props.label}
|
{props.label}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { throttle } from 'lodash';
|
||||||
import React, { RefObject, useContext, useEffect, useMemo, useRef } from 'react';
|
import React, { RefObject, useContext, useEffect, useMemo, useRef } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { SAVE_TIME } from '../../config.js';
|
import { SAVE_TIME, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ConfigContext, LoggerContext, StateContext } from '../../state/full.js';
|
import { ConfigContext, LoggerContext, StateContext } from '../../state/full.js';
|
||||||
import { BrushParams } from '../../types/params.js';
|
import { BrushParams } from '../../types/params.js';
|
||||||
import { imageFromBlob } from '../../utils.js';
|
import { imageFromBlob } from '../../utils.js';
|
||||||
|
@ -255,8 +255,8 @@ export function MaskCanvas(props: MaskCanvasProps) {
|
||||||
display: 'none',
|
display: 'none',
|
||||||
};
|
};
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={STANDARD_SPACING}>
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<Button
|
<Button
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
startIcon={<Download />}
|
startIcon={<Download />}
|
||||||
|
@ -348,7 +348,7 @@ export function MaskCanvas(props: MaskCanvasProps) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<Button
|
<Button
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
startIcon={<FormatColorFill />}
|
startIcon={<FormatColorFill />}
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { Slider, Stack, TextField } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../../constants';
|
||||||
|
|
||||||
export function parseNumber(num: string, decimal = false): number {
|
export function parseNumber(num: string, decimal = false): number {
|
||||||
if (decimal) {
|
if (decimal) {
|
||||||
return parseFloat(num);
|
return parseFloat(num);
|
||||||
|
@ -29,7 +31,7 @@ export function NumericField(props: ImageControlProps) {
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={STANDARD_SPACING}>
|
||||||
<TextField
|
<TextField
|
||||||
error={error}
|
error={error}
|
||||||
label={label}
|
label={label}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { STALE_TIME } from '../../config.js';
|
import { STALE_TIME, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ClientContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { ModelResponse, NetworkModel } from '../../types/api.js';
|
import { ModelResponse, NetworkModel } from '../../types/api.js';
|
||||||
import { QueryMenu, QueryMenuComplete, QueryMenuFilter } from '../input/QueryMenu.js';
|
import { QueryMenu, QueryMenuComplete, QueryMenuFilter } from '../input/QueryMenu.js';
|
||||||
|
@ -55,7 +55,7 @@ export function PromptTextBlock(props: PromptTextBlockProps) {
|
||||||
return [];
|
return [];
|
||||||
}, [models, prompt]);
|
}, [models, prompt]);
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={STANDARD_SPACING}>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('parameter.prompt')}
|
label={t('parameter.prompt')}
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
|
@ -67,7 +67,7 @@ export function PromptTextBlock(props: PromptTextBlockProps) {
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
{tokens.map((token) => <Chip
|
{tokens.map((token) => <Chip
|
||||||
color={prompt.includes(token) ? 'primary' : 'default'}
|
color={prompt.includes(token) ? 'primary' : 'default'}
|
||||||
label={token}
|
label={token}
|
||||||
|
@ -139,13 +139,13 @@ export function PromptInput(props: PromptInputProps) {
|
||||||
result: wildcards,
|
result: wildcards,
|
||||||
}), [wildcards.status]);
|
}), [wildcards.status]);
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={STANDARD_SPACING}>
|
||||||
<PromptTextBlock
|
<PromptTextBlock
|
||||||
models={models.data}
|
models={models.data}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
selector={selector}
|
selector={selector}
|
||||||
/>
|
/>
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<ModelMenu
|
<ModelMenu
|
||||||
id='inversion'
|
id='inversion'
|
||||||
labelKey='model.inversion'
|
labelKey='model.inversion'
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Button, MenuItem, Select, Stack, TextField } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../../../constants.js';
|
||||||
import { CorrectionArch, CorrectionModel, ModelFormat } from '../../../types/model.js';
|
import { CorrectionArch, CorrectionModel, ModelFormat } from '../../../types/model.js';
|
||||||
|
|
||||||
export interface CorrectionModelInputProps {
|
export interface CorrectionModelInputProps {
|
||||||
|
@ -16,7 +17,7 @@ export function CorrectionModelInput(props: CorrectionModelInputProps) {
|
||||||
const { key, model, onChange, onRemove } = props;
|
const { key, model, onChange, onRemove } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack direction='row' spacing={2} key={key}>
|
return <Stack direction='row' spacing={STANDARD_SPACING} key={key}>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('extras.label')}
|
label={t('extras.label')}
|
||||||
value={model.label}
|
value={model.label}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Button, MenuItem, Select, Stack, TextField } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../../../constants.js';
|
||||||
import { DiffusionModel, ModelFormat } from '../../../types/model.js';
|
import { DiffusionModel, ModelFormat } from '../../../types/model.js';
|
||||||
|
|
||||||
export interface DiffusionModelInputProps {
|
export interface DiffusionModelInputProps {
|
||||||
|
@ -16,7 +17,7 @@ export function DiffusionModelInput(props: DiffusionModelInputProps) {
|
||||||
const { key, model, onChange, onRemove } = props;
|
const { key, model, onChange, onRemove } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack direction='row' spacing={2} key={key}>
|
return <Stack direction='row' spacing={STANDARD_SPACING} key={key}>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('extras.label')}
|
label={t('extras.label')}
|
||||||
value={model.label}
|
value={model.label}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Button, MenuItem, Select, Stack, TextField } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../../../constants.js';
|
||||||
import { ExtraNetwork, ModelFormat, NetworkModel, NetworkType } from '../../../types/model.js';
|
import { ExtraNetwork, ModelFormat, NetworkModel, NetworkType } from '../../../types/model.js';
|
||||||
|
|
||||||
export interface ExtraNetworkInputProps {
|
export interface ExtraNetworkInputProps {
|
||||||
|
@ -16,7 +17,7 @@ export function ExtraNetworkInput(props: ExtraNetworkInputProps) {
|
||||||
const { key, model, onChange, onRemove } = props;
|
const { key, model, onChange, onRemove } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack direction='row' spacing={2} key={key}>
|
return <Stack direction='row' spacing={STANDARD_SPACING} key={key}>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('extras.label')}
|
label={t('extras.label')}
|
||||||
value={model.label}
|
value={model.label}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Button, MenuItem, Select, Stack, TextField } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../../../constants.js';
|
||||||
import { AnyFormat, ExtraSource } from '../../../types/model.js';
|
import { AnyFormat, ExtraSource } from '../../../types/model.js';
|
||||||
|
|
||||||
export interface ExtraSourceInputProps {
|
export interface ExtraSourceInputProps {
|
||||||
|
@ -16,7 +17,7 @@ export function ExtraSourceInput(props: ExtraSourceInputProps) {
|
||||||
const { key, model, onChange, onRemove } = props;
|
const { key, model, onChange, onRemove } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack direction='row' spacing={2} key={key}>
|
return <Stack direction='row' spacing={STANDARD_SPACING} key={key}>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('extras.name')}
|
label={t('extras.name')}
|
||||||
value={model.name}
|
value={model.name}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Button, MenuItem, Select, Stack, TextField } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { STANDARD_SPACING } from '../../../constants.js';
|
||||||
import { ModelFormat, UpscalingArch, UpscalingModel } from '../../../types/model.js';
|
import { ModelFormat, UpscalingArch, UpscalingModel } from '../../../types/model.js';
|
||||||
import { NumericField } from '../NumericField.js';
|
import { NumericField } from '../NumericField.js';
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ export function UpscalingModelInput(props: UpscalingModelInputProps) {
|
||||||
const { key, model, onChange, onRemove } = props;
|
const { key, model, onChange, onRemove } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack direction='row' spacing={2} key={key}>
|
return <Stack direction='row' spacing={STANDARD_SPACING} key={key}>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('extras.label')}
|
label={t('extras.label')}
|
||||||
value={model.label}
|
value={model.label}
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
.body-allotment {
|
.body-allotment {
|
||||||
height: 85vb;
|
height: 90vb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.box-history {
|
||||||
|
max-height: 90vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
|
@ -7,8 +7,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { IMAGE_FILTER } from '../../config.js';
|
import { BLEND_SOURCES, IMAGE_FILTER, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { BLEND_SOURCES } from '../../constants.js';
|
|
||||||
import { ClientContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { TabState } from '../../state/types.js';
|
import { TabState } from '../../state/types.js';
|
||||||
import { BlendParams, BrushParams, ModelParams, UpscaleParams } from '../../types/params.js';
|
import { BlendParams, BrushParams, ModelParams, UpscaleParams } from '../../types/params.js';
|
||||||
|
@ -44,7 +43,7 @@ export function Blend() {
|
||||||
const sources = mustDefault(blend.sources, []);
|
const sources = mustDefault(blend.sources, []);
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={STANDARD_SPACING}>
|
||||||
{range(BLEND_SOURCES).map((idx) =>
|
{range(BLEND_SOURCES).map((idx) =>
|
||||||
<ImageInput
|
<ImageInput
|
||||||
key={`source-${idx.toFixed(0)}`}
|
key={`source-${idx.toFixed(0)}`}
|
||||||
|
|
|
@ -7,9 +7,10 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { IMAGE_FILTER, STALE_TIME } from '../../config.js';
|
import { IMAGE_FILTER, STALE_TIME, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { TabState } from '../../state/types.js';
|
import { TabState } from '../../state/types.js';
|
||||||
|
import { JobType } from '../../types/api-v2.js';
|
||||||
import { HighresParams, Img2ImgParams, ModelParams, UpscaleParams } from '../../types/params.js';
|
import { HighresParams, Img2ImgParams, ModelParams, UpscaleParams } from '../../types/params.js';
|
||||||
import { Profiles } from '../Profiles.js';
|
import { Profiles } from '../Profiles.js';
|
||||||
import { HighresControl } from '../control/HighresControl.js';
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
|
@ -19,7 +20,6 @@ import { UpscaleControl } from '../control/UpscaleControl.js';
|
||||||
import { ImageInput } from '../input/ImageInput.js';
|
import { ImageInput } from '../input/ImageInput.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
import { QueryList } from '../input/QueryList.js';
|
import { QueryList } from '../input/QueryList.js';
|
||||||
import { JobType } from '../../types/api-v2.js';
|
|
||||||
|
|
||||||
export function Img2Img() {
|
export function Img2Img() {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
|
@ -57,7 +57,7 @@ export function Img2Img() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={STANDARD_SPACING}>
|
||||||
<Profiles
|
<Profiles
|
||||||
selectHighres={selectHighres}
|
selectHighres={selectHighres}
|
||||||
selectModel={selectModel}
|
selectModel={selectModel}
|
||||||
|
@ -80,7 +80,7 @@ export function Img2Img() {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ImageControl selector={selectParams} onChange={setImg2Img} />
|
<ImageControl selector={selectParams} onChange={setImg2Img} />
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<QueryList
|
<QueryList
|
||||||
id='control'
|
id='control'
|
||||||
labelKey='model.control'
|
labelKey='model.control'
|
||||||
|
|
|
@ -7,9 +7,10 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { IMAGE_FILTER, STALE_TIME } from '../../config.js';
|
import { IMAGE_FILTER, STALE_TIME, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { TabState } from '../../state/types.js';
|
import { TabState } from '../../state/types.js';
|
||||||
|
import { JobType } from '../../types/api-v2.js';
|
||||||
import { BrushParams, HighresParams, InpaintParams, ModelParams, UpscaleParams } from '../../types/params.js';
|
import { BrushParams, HighresParams, InpaintParams, ModelParams, UpscaleParams } from '../../types/params.js';
|
||||||
import { Profiles } from '../Profiles.js';
|
import { Profiles } from '../Profiles.js';
|
||||||
import { HighresControl } from '../control/HighresControl.js';
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
|
@ -21,7 +22,6 @@ import { ImageInput } from '../input/ImageInput.js';
|
||||||
import { MaskCanvas } from '../input/MaskCanvas.js';
|
import { MaskCanvas } from '../input/MaskCanvas.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
import { QueryList } from '../input/QueryList.js';
|
import { QueryList } from '../input/QueryList.js';
|
||||||
import { JobType } from '../../types/api-v2.js';
|
|
||||||
|
|
||||||
export function Inpaint() {
|
export function Inpaint() {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
|
@ -89,7 +89,7 @@ export function Inpaint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={STANDARD_SPACING}>
|
||||||
<Profiles
|
<Profiles
|
||||||
selectHighres={selectHighres}
|
selectHighres={selectHighres}
|
||||||
selectModel={selectModel}
|
selectModel={selectModel}
|
||||||
|
@ -153,7 +153,7 @@ export function Inpaint() {
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<QueryList
|
<QueryList
|
||||||
id='masks'
|
id='masks'
|
||||||
labelKey={'maskFilter'}
|
labelKey={'maskFilter'}
|
||||||
|
@ -200,7 +200,7 @@ export function Inpaint() {
|
||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
label={t('parameter.fillColor')}
|
label={t('parameter.fillColor')}
|
||||||
sx={{ mx: 1 }}
|
sx={{ mx: 1 }}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { STALE_TIME } from '../../config.js';
|
import { STALE_TIME, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ClientContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import {
|
import {
|
||||||
CorrectionModel,
|
CorrectionModel,
|
||||||
|
@ -111,13 +111,13 @@ export function Models() {
|
||||||
}, [result.status]);
|
}, [result.status]);
|
||||||
|
|
||||||
if (result.status === 'error') {
|
if (result.status === 'error') {
|
||||||
return <Stack spacing={2} direction='row' sx={{ alignItems: 'center' }}>
|
return <Stack spacing={STANDARD_SPACING} direction='row' sx={{ alignItems: 'center' }}>
|
||||||
<Alert severity='error'>Error</Alert>
|
<Alert severity='error'>Error</Alert>
|
||||||
</Stack>;
|
</Stack>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.status === 'loading') {
|
if (result.status === 'loading') {
|
||||||
return <Stack spacing={2} direction='row' sx={{ alignItems: 'center' }}>
|
return <Stack spacing={STANDARD_SPACING} direction='row' sx={{ alignItems: 'center' }}>
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
</Stack>;
|
</Stack>;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ export function Models() {
|
||||||
// TODO: do something with resp
|
// TODO: do something with resp
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={STANDARD_SPACING}>
|
||||||
<Accordion>
|
<Accordion>
|
||||||
<AccordionSummary>
|
<AccordionSummary>
|
||||||
{t('modelType.diffusion', { count: 10 })}
|
{t('modelType.diffusion', { count: 10 })}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { ConfigContext, StateContext, STATE_KEY } from '../../state/full.js';
|
||||||
import { getTheme } from '../utils.js';
|
import { getTheme } from '../utils.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
import { downloadAsJson } from '../../utils.js';
|
import { downloadAsJson } from '../../utils.js';
|
||||||
|
import { STANDARD_SPACING } from '../../constants.js';
|
||||||
|
|
||||||
function removeBlobs(key: string, value: unknown): unknown {
|
function removeBlobs(key: string, value: unknown): unknown {
|
||||||
if (value instanceof Blob || value instanceof File) {
|
if (value instanceof Blob || value instanceof File) {
|
||||||
|
@ -39,7 +40,7 @@ export function Settings() {
|
||||||
const [root, setRoot] = useState(getApiRoot(config));
|
const [root, setRoot] = useState(getApiRoot(config));
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={STANDARD_SPACING}>
|
||||||
<NumericField
|
<NumericField
|
||||||
label={t('setting.history.limit')}
|
label={t('setting.history.limit')}
|
||||||
min={2}
|
min={2}
|
||||||
|
@ -67,7 +68,7 @@ export function Settings() {
|
||||||
scheduler: event.target.value,
|
scheduler: event.target.value,
|
||||||
});
|
});
|
||||||
}} />
|
}} />
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<TextField variant='outlined' label={t('setting.server')} value={root} onChange={(event) => {
|
<TextField variant='outlined' label={t('setting.server')} value={root} onChange={(event) => {
|
||||||
setRoot(event.target.value);
|
setRoot(event.target.value);
|
||||||
}} />
|
}} />
|
||||||
|
@ -82,7 +83,7 @@ export function Settings() {
|
||||||
{config.params.version}
|
{config.params.version}
|
||||||
</Alert>
|
</Alert>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<TextField variant='outlined' label={t('setting.state.label')} value={json} onChange={(event) => {
|
<TextField variant='outlined' label={t('setting.state.label')} value={json} onChange={(event) => {
|
||||||
setJson(event.target.value);
|
setJson(event.target.value);
|
||||||
}} />
|
}} />
|
||||||
|
@ -109,7 +110,7 @@ export function Settings() {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
} label={t('setting.darkMode')} />
|
} label={t('setting.darkMode')} />
|
||||||
<Stack direction='row' spacing={2}>
|
<Stack direction='row' spacing={STANDARD_SPACING}>
|
||||||
<Button onClick={() => state.resetTxt2Img()} color='warning'>{t('setting.reset.txt2img')}</Button>
|
<Button onClick={() => state.resetTxt2Img()} color='warning'>{t('setting.reset.txt2img')}</Button>
|
||||||
<Button onClick={() => state.resetImg2Img()} color='warning'>{t('setting.reset.img2img')}</Button>
|
<Button onClick={() => state.resetImg2Img()} color='warning'>{t('setting.reset.img2img')}</Button>
|
||||||
<Button onClick={() => state.resetInpaint()} color='warning'>{t('setting.reset.inpaint')}</Button>
|
<Button onClick={() => state.resetInpaint()} color='warning'>{t('setting.reset.inpaint')}</Button>
|
||||||
|
|
|
@ -8,8 +8,10 @@ import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { PipelineGrid, makeTxt2ImgGridPipeline } from '../../client/utils.js';
|
import { PipelineGrid, makeTxt2ImgGridPipeline } from '../../client/utils.js';
|
||||||
|
import { STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { TabState } from '../../state/types.js';
|
import { TabState } from '../../state/types.js';
|
||||||
|
import { JobType } from '../../types/api-v2.js';
|
||||||
import { HighresParams, ModelParams, Txt2ImgParams, UpscaleParams } from '../../types/params.js';
|
import { HighresParams, ModelParams, Txt2ImgParams, UpscaleParams } from '../../types/params.js';
|
||||||
import { Profiles } from '../Profiles.js';
|
import { Profiles } from '../Profiles.js';
|
||||||
import { HighresControl } from '../control/HighresControl.js';
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
|
@ -18,7 +20,6 @@ import { ModelControl } from '../control/ModelControl.js';
|
||||||
import { UpscaleControl } from '../control/UpscaleControl.js';
|
import { UpscaleControl } from '../control/UpscaleControl.js';
|
||||||
import { VariableControl } from '../control/VariableControl.js';
|
import { VariableControl } from '../control/VariableControl.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
import { JobType } from '../../types/api-v2.js';
|
|
||||||
|
|
||||||
export function SizeControl() {
|
export function SizeControl() {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
|
@ -88,7 +89,7 @@ export function Txt2Img() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={STANDARD_SPACING}>
|
||||||
<Profiles
|
<Profiles
|
||||||
selectHighres={selectHighres}
|
selectHighres={selectHighres}
|
||||||
selectModel={selectModel}
|
selectModel={selectModel}
|
||||||
|
|
|
@ -7,9 +7,10 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
|
|
||||||
import { IMAGE_FILTER } from '../../config.js';
|
import { IMAGE_FILTER, STANDARD_SPACING } from '../../constants.js';
|
||||||
import { ClientContext, OnnxState, StateContext } from '../../state/full.js';
|
import { ClientContext, OnnxState, StateContext } from '../../state/full.js';
|
||||||
import { TabState } from '../../state/types.js';
|
import { TabState } from '../../state/types.js';
|
||||||
|
import { JobType } from '../../types/api-v2.js';
|
||||||
import { HighresParams, ModelParams, UpscaleParams, UpscaleReqParams } from '../../types/params.js';
|
import { HighresParams, ModelParams, UpscaleParams, UpscaleReqParams } from '../../types/params.js';
|
||||||
import { Profiles } from '../Profiles.js';
|
import { Profiles } from '../Profiles.js';
|
||||||
import { HighresControl } from '../control/HighresControl.js';
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
|
@ -17,7 +18,6 @@ import { ModelControl } from '../control/ModelControl.js';
|
||||||
import { UpscaleControl } from '../control/UpscaleControl.js';
|
import { UpscaleControl } from '../control/UpscaleControl.js';
|
||||||
import { ImageInput } from '../input/ImageInput.js';
|
import { ImageInput } from '../input/ImageInput.js';
|
||||||
import { PromptInput } from '../input/PromptInput.js';
|
import { PromptInput } from '../input/PromptInput.js';
|
||||||
import { JobType } from '../../types/api-v2.js';
|
|
||||||
|
|
||||||
export function Upscale() {
|
export function Upscale() {
|
||||||
async function uploadSource() {
|
async function uploadSource() {
|
||||||
|
@ -43,7 +43,7 @@ export function Upscale() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={STANDARD_SPACING}>
|
||||||
<Profiles
|
<Profiles
|
||||||
selectHighres={selectHighres}
|
selectHighres={selectHighres}
|
||||||
selectModel={selectModel}
|
selectModel={selectModel}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { doesExist, Maybe } from '@apextoaster/js-utils';
|
import { doesExist, Maybe } from '@apextoaster/js-utils';
|
||||||
import { merge } from 'lodash';
|
import { merge } from 'lodash';
|
||||||
|
|
||||||
import { STATUS_SUCCESS } from './client/api.js';
|
|
||||||
import {
|
import {
|
||||||
HighresParams,
|
HighresParams,
|
||||||
Img2ImgParams,
|
Img2ImgParams,
|
||||||
|
@ -11,6 +10,7 @@ import {
|
||||||
Txt2ImgParams,
|
Txt2ImgParams,
|
||||||
UpscaleParams,
|
UpscaleParams,
|
||||||
} from './types/params.js';
|
} from './types/params.js';
|
||||||
|
import { STATUS_SUCCESS } from './constants.js';
|
||||||
|
|
||||||
export interface ConfigBoolean {
|
export interface ConfigBoolean {
|
||||||
default: boolean;
|
default: boolean;
|
||||||
|
@ -93,13 +93,6 @@ export interface Config<T = ClientParams> {
|
||||||
params: T;
|
params: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IMAGE_FILTER = '.bmp, .jpg, .jpeg, .png';
|
|
||||||
export const PARAM_VERSION = '>=0.10.0';
|
|
||||||
|
|
||||||
export const STALE_TIME = 300_000; // 5 minutes
|
|
||||||
export const POLL_TIME = 5_000; // 5 seconds
|
|
||||||
export const SAVE_TIME = 5_000; // 5 seconds
|
|
||||||
|
|
||||||
export async function loadConfig(): Promise<Config> {
|
export async function loadConfig(): Promise<Config> {
|
||||||
const configPath = new URL('./config.json', window.location.href);
|
const configPath = new URL('./config.json', window.location.href);
|
||||||
const configReq = await fetch(configPath);
|
const configReq = await fetch(configPath);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Breakpoint } from '@mui/material/styles';
|
||||||
|
|
||||||
export const BLEND_SOURCES = 2;
|
export const BLEND_SOURCES = 2;
|
||||||
|
|
||||||
|
@ -29,3 +30,66 @@ export const DEFAULT_HISTORY = {
|
||||||
*/
|
*/
|
||||||
scrollback: 4,
|
scrollback: 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const STANDARD_MARGIN = 4; // translated into 32px by mui
|
||||||
|
export const STANDARD_SPACING = 2;
|
||||||
|
|
||||||
|
export const LAYOUT_MIN = 300;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
||||||
|
export const LAYOUT_PROPORTIONS = [100, 200];
|
||||||
|
|
||||||
|
export const LAYOUT_STYLES = {
|
||||||
|
horizontal: {
|
||||||
|
container: false,
|
||||||
|
control: {
|
||||||
|
width: '30%',
|
||||||
|
},
|
||||||
|
direction: 'row',
|
||||||
|
divider: 'vertical',
|
||||||
|
history: {
|
||||||
|
style: {
|
||||||
|
ml: STANDARD_MARGIN,
|
||||||
|
},
|
||||||
|
width: 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
vertical: {
|
||||||
|
container: 'lg' as Breakpoint,
|
||||||
|
control: {
|
||||||
|
width: undefined,
|
||||||
|
},
|
||||||
|
direction: 'column',
|
||||||
|
divider: 'horizontal',
|
||||||
|
history: {
|
||||||
|
style: {
|
||||||
|
mx: STANDARD_MARGIN,
|
||||||
|
my: STANDARD_MARGIN,
|
||||||
|
},
|
||||||
|
width: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const INITIAL_LOAD_TIMEOUT = 5_000;
|
||||||
|
|
||||||
|
export const STALE_TIME = 300_000; // 5 minutes
|
||||||
|
export const POLL_TIME = 5_000; // 5 seconds
|
||||||
|
export const SAVE_TIME = 5_000; // 5 seconds
|
||||||
|
|
||||||
|
export const IMAGE_FILTER = '.bmp, .jpg, .jpeg, .png';
|
||||||
|
export const PARAM_VERSION = '>=0.10.0';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed precision for integer parameters.
|
||||||
|
*/
|
||||||
|
export const FIXED_INTEGER = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed precision for float parameters.
|
||||||
|
*
|
||||||
|
* The GUI limits the input steps based on the server parameters, but this does limit
|
||||||
|
* the maximum precision that can be sent back to the server, and may have to be
|
||||||
|
* increased in the future.
|
||||||
|
*/
|
||||||
|
export const FIXED_FLOAT = 2;
|
||||||
|
export const STATUS_SUCCESS = 200;
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { ServerParamsError } from './components/error/ServerParams.js';
|
||||||
import { LoadingScreen } from './components/LoadingScreen.js';
|
import { LoadingScreen } from './components/LoadingScreen.js';
|
||||||
import { OnnxError } from './components/OnnxError.js';
|
import { OnnxError } from './components/OnnxError.js';
|
||||||
import { OnnxWeb } from './components/OnnxWeb.js';
|
import { OnnxWeb } from './components/OnnxWeb.js';
|
||||||
import { Config, getApiRoot, isDebug, loadConfig, mergeConfig, PARAM_VERSION, ServerParams } from './config.js';
|
import { Config, getApiRoot, isDebug, loadConfig, mergeConfig, ServerParams } from './config.js';
|
||||||
import {
|
import {
|
||||||
ClientContext,
|
ClientContext,
|
||||||
ConfigContext,
|
ConfigContext,
|
||||||
|
@ -31,8 +31,7 @@ import {
|
||||||
} from './state/full.js';
|
} from './state/full.js';
|
||||||
import { I18N_STRINGS } from './strings/all.js';
|
import { I18N_STRINGS } from './strings/all.js';
|
||||||
import { applyStateMigrations, UnknownState } from './state/migration/default.js';
|
import { applyStateMigrations, UnknownState } from './state/migration/default.js';
|
||||||
|
import { INITIAL_LOAD_TIMEOUT, PARAM_VERSION } from './constants.js';
|
||||||
export const INITIAL_LOAD_TIMEOUT = 5_000;
|
|
||||||
|
|
||||||
export async function renderApp(config: Config, params: ServerParams, logger: Logger, client: ApiClient) {
|
export async function renderApp(config: Config, params: ServerParams, logger: Logger, client: ApiClient) {
|
||||||
const completeConfig = mergeConfig(config, params);
|
const completeConfig = mergeConfig(config, params);
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
import { Maybe } from '@apextoaster/js-utils';
|
import { Maybe } from '@apextoaster/js-utils';
|
||||||
import { ImageResponse, ReadyResponse, RetryParams } from '../types/api.js';
|
import { RetryParams } from '../types/api.js';
|
||||||
import { Slice } from './types.js';
|
import { Slice } from './types.js';
|
||||||
import { DEFAULT_HISTORY } from '../constants.js';
|
import { DEFAULT_HISTORY } from '../constants.js';
|
||||||
import { JobResponse } from '../types/api-v2.js';
|
import { JobResponse } from '../types/api-v2.js';
|
||||||
|
|
||||||
export interface HistoryItem {
|
|
||||||
image: ImageResponse;
|
|
||||||
ready: Maybe<ReadyResponse>;
|
|
||||||
retry: Maybe<RetryParams>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HistoryItemV2 {
|
export interface HistoryItemV2 {
|
||||||
image: JobResponse;
|
image: JobResponse;
|
||||||
retry: Maybe<RetryParams>;
|
retry: Maybe<RetryParams>;
|
||||||
|
|
|
@ -34,6 +34,13 @@ export interface ImageMetadata<TParams extends BaseImgParams, TType extends JobT
|
||||||
type: TType;
|
type: TType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AnyImageMetadata
|
||||||
|
= ImageMetadata<Txt2ImgParams, JobType.TXT2IMG>
|
||||||
|
| ImageMetadata<Img2ImgParams, JobType.IMG2IMG>
|
||||||
|
| ImageMetadata<InpaintParams, JobType.INPAINT>
|
||||||
|
| ImageMetadata<BaseImgParams, JobType.UPSCALE>
|
||||||
|
| ImageMetadata<BaseImgParams, JobType.BLEND>;
|
||||||
|
|
||||||
export enum JobStatus {
|
export enum JobStatus {
|
||||||
PENDING = 'pending',
|
PENDING = 'pending',
|
||||||
RUNNING = 'running',
|
RUNNING = 'running',
|
||||||
|
@ -143,13 +150,7 @@ export interface SuccessBlendJobResponse extends BaseJobResponse {
|
||||||
export interface SuccessChainJobResponse extends BaseJobResponse {
|
export interface SuccessChainJobResponse extends BaseJobResponse {
|
||||||
status: JobStatus.SUCCESS;
|
status: JobStatus.SUCCESS;
|
||||||
outputs: Array<string>;
|
outputs: Array<string>;
|
||||||
metadata: Array<
|
metadata: Array<AnyImageMetadata>;
|
||||||
ImageMetadata<Txt2ImgParams, JobType.TXT2IMG>
|
|
||||||
| ImageMetadata<Img2ImgParams, JobType.IMG2IMG>
|
|
||||||
| ImageMetadata<InpaintParams, JobType.INPAINT>
|
|
||||||
| ImageMetadata<BaseImgParams, JobType.UPSCALE>
|
|
||||||
| ImageMetadata<BaseImgParams, JobType.BLEND>
|
|
||||||
>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,38 +1,15 @@
|
||||||
import {
|
import {
|
||||||
BaseImgParams,
|
BlendParams,
|
||||||
ModelParams,
|
|
||||||
Txt2ImgParams,
|
|
||||||
UpscaleParams,
|
|
||||||
HighresParams,
|
HighresParams,
|
||||||
Img2ImgParams,
|
Img2ImgParams,
|
||||||
InpaintParams,
|
InpaintParams,
|
||||||
|
ModelParams,
|
||||||
OutpaintParams,
|
OutpaintParams,
|
||||||
|
Txt2ImgParams,
|
||||||
|
UpscaleParams,
|
||||||
UpscaleReqParams,
|
UpscaleReqParams,
|
||||||
BlendParams,
|
|
||||||
ImageSize,
|
|
||||||
} from './params.js';
|
} from './params.js';
|
||||||
|
|
||||||
/**
|
|
||||||
* Output image data within the response.
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export interface ImageOutput {
|
|
||||||
key: string;
|
|
||||||
url: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* General response for most image requests.
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export interface ImageResponse {
|
|
||||||
outputs: Array<ImageOutput>;
|
|
||||||
params: Required<BaseImgParams> & Required<ModelParams>;
|
|
||||||
size: ImageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status response from the ready endpoint.
|
* Status response from the ready endpoint.
|
||||||
*/
|
*/
|
||||||
|
@ -122,26 +99,3 @@ export type RetryParams = {
|
||||||
params: BlendParams;
|
params: BlendParams;
|
||||||
upscale?: UpscaleParams;
|
upscale?: UpscaleParams;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Status response from the image endpoint, with parameters to retry the job if it fails.
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export interface ImageResponseWithRetry {
|
|
||||||
image: ImageResponse;
|
|
||||||
retry: RetryParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export interface ImageMetadata {
|
|
||||||
highres: HighresParams;
|
|
||||||
outputs: string | Array<string>;
|
|
||||||
params: Txt2ImgParams | Img2ImgParams | InpaintParams;
|
|
||||||
upscale: UpscaleParams;
|
|
||||||
|
|
||||||
input_size: ImageSize;
|
|
||||||
size: ImageSize;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue