feat(gui): move model controls into each tab
This commit is contained in:
parent
27a21dfa62
commit
f14f197264
|
@ -140,9 +140,7 @@ export interface UpscaleParams {
|
||||||
/**
|
/**
|
||||||
* Parameters for upscale requests.
|
* Parameters for upscale requests.
|
||||||
*/
|
*/
|
||||||
export interface UpscaleReqParams {
|
export interface UpscaleReqParams extends BaseImgParams {
|
||||||
prompt: string;
|
|
||||||
negativePrompt?: string;
|
|
||||||
source: Blob;
|
source: Blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { useHash } from 'react-use/lib/useHash';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
import { StateContext } from '../state.js';
|
import { StateContext } from '../state.js';
|
||||||
import { ModelControl } from './control/ModelControl.js';
|
|
||||||
import { ImageHistory } from './ImageHistory.js';
|
import { ImageHistory } from './ImageHistory.js';
|
||||||
import { Logo } from './Logo.js';
|
import { Logo } from './Logo.js';
|
||||||
import { Blend } from './tab/Blend.js';
|
import { Blend } from './tab/Blend.js';
|
||||||
|
@ -43,9 +42,6 @@ export function OnnxWeb() {
|
||||||
<Box sx={{ my: 4 }}>
|
<Box sx={{ my: 4 }}>
|
||||||
<Logo />
|
<Logo />
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ mx: 4, my: 4 }}>
|
|
||||||
<ModelControl />
|
|
||||||
</Box>
|
|
||||||
<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) => {
|
||||||
|
|
|
@ -20,29 +20,35 @@ import { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
import { BaseImgParams, Txt2ImgParams } from '../client/types.js';
|
import { BaseImgParams, HighresParams, Txt2ImgParams, UpscaleParams } from '../client/types.js';
|
||||||
import { StateContext } from '../state.js';
|
import { StateContext } from '../state.js';
|
||||||
|
|
||||||
|
const { useState, Fragment } = React;
|
||||||
|
|
||||||
export interface ProfilesProps {
|
export interface ProfilesProps {
|
||||||
|
highres: HighresParams;
|
||||||
params: BaseImgParams;
|
params: BaseImgParams;
|
||||||
setParams: ((params: BaseImgParams) => void) | undefined;
|
upscale: UpscaleParams;
|
||||||
|
|
||||||
|
setHighres(params: HighresParams): void;
|
||||||
|
setParams(params: BaseImgParams): void;
|
||||||
|
setUpscale(params: UpscaleParams): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Profiles(props: ProfilesProps) {
|
export function Profiles(props: ProfilesProps) {
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
|
const profiles = useStore(state, (s) => s.profiles);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const saveProfile = useStore(state, (s) => s.saveProfile);
|
const saveProfile = useStore(state, (s) => s.saveProfile);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const removeProfile = useStore(state, (s) => s.removeProfile);
|
const removeProfile = useStore(state, (s) => s.removeProfile);
|
||||||
const profiles = useStore(state, (s) => s.profiles);
|
|
||||||
const highres = useStore(state, (s) => s.highres);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
const upscale = useStore(state, (s) => s.upscale);
|
const [profileName, setProfileName] = useState('');
|
||||||
const [dialogOpen, setDialogOpen] = React.useState(false);
|
|
||||||
const [profileName, setProfileName] = React.useState('');
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <>
|
return <Stack direction='row' spacing={2}>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
id="profile-select"
|
id="profile-select"
|
||||||
options={profiles}
|
options={profiles}
|
||||||
|
@ -77,36 +83,10 @@ export function Profiles(props: ProfilesProps) {
|
||||||
<Button type="button" variant="contained" onClick={() => setDialogOpen(true)}>
|
<Button type="button" variant="contained" onClick={() => setDialogOpen(true)}>
|
||||||
<SaveIcon />
|
<SaveIcon />
|
||||||
</Button>
|
</Button>
|
||||||
<Button component='label' variant="contained">
|
|
||||||
<ImageSearch />
|
|
||||||
<input
|
|
||||||
hidden
|
|
||||||
accept={'.json,.jpg,.jpeg,.png,.txt,.webp'}
|
|
||||||
type='file'
|
|
||||||
onChange={(event) => {
|
|
||||||
const { files } = event.target;
|
|
||||||
if (doesExist(files) && files.length > 0) {
|
|
||||||
const file = mustExist(files[0]);
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
loadParamsFromFile(file).then((newParams) => {
|
|
||||||
if (doesExist(props.setParams) && doesExist(newParams)) {
|
|
||||||
props.setParams({
|
|
||||||
...props.params,
|
|
||||||
...newParams,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onClick={(event) => {
|
|
||||||
event.currentTarget.value = '';
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
onChange={(event, value) => {
|
onChange={(event, value) => {
|
||||||
if (doesExist(value) && doesExist(props.setParams)) {
|
if (doesExist(value)) {
|
||||||
props.setParams({
|
props.setParams({
|
||||||
...value.params
|
...value.params
|
||||||
});
|
});
|
||||||
|
@ -138,8 +118,8 @@ export function Profiles(props: ProfilesProps) {
|
||||||
saveProfile({
|
saveProfile({
|
||||||
params: props.params,
|
params: props.params,
|
||||||
name: profileName,
|
name: profileName,
|
||||||
highResParams: highres,
|
highResParams: props.highres,
|
||||||
upscaleParams: upscale,
|
upscaleParams: props.upscale,
|
||||||
});
|
});
|
||||||
setDialogOpen(false);
|
setDialogOpen(false);
|
||||||
setProfileName('');
|
setProfileName('');
|
||||||
|
@ -147,7 +127,33 @@ export function Profiles(props: ProfilesProps) {
|
||||||
>{t('profile.save')}</Button>
|
>{t('profile.save')}</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</>;
|
<Button component='label' variant="contained">
|
||||||
|
<ImageSearch />
|
||||||
|
<input
|
||||||
|
hidden
|
||||||
|
accept={'.json,.jpg,.jpeg,.png,.txt,.webp'}
|
||||||
|
type='file'
|
||||||
|
onChange={(event) => {
|
||||||
|
const { files } = event.target;
|
||||||
|
if (doesExist(files) && files.length > 0) {
|
||||||
|
const file = mustExist(files[0]);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
loadParamsFromFile(file).then((newParams) => {
|
||||||
|
if (doesExist(newParams)) {
|
||||||
|
props.setParams({
|
||||||
|
...props.params,
|
||||||
|
...newParams,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onClick={(event) => {
|
||||||
|
event.currentTarget.value = '';
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</Stack>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadParamsFromFile(file: File): Promise<Partial<Txt2ImgParams>> {
|
export async function loadParamsFromFile(file: File): Promise<Partial<Txt2ImgParams>> {
|
||||||
|
@ -276,7 +282,7 @@ export async function parseAutoComment(comment: string): Promise<Partial<Txt2Img
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// unknown param
|
// unknown param
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ export function ImageCard(props: ImageCardProps) {
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setInpaint = useStore(state, (s) => s.setInpaint);
|
const setInpaint = useStore(state, (s) => s.setInpaint);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setUpscale = useStore(state, (s) => s.setUpscaleTab);
|
const setUpscale = useStore(state, (s) => s.setUpscale);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setBlend = useStore(state, (s) => s.setBlend);
|
const setBlend = useStore(state, (s) => s.setBlend);
|
||||||
|
|
||||||
|
|
|
@ -3,17 +3,21 @@ import { Checkbox, FormControl, FormControlLabel, InputLabel, MenuItem, Select,
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
|
||||||
|
|
||||||
import { ConfigContext, StateContext } from '../../state.js';
|
import { HighresParams } from '../../client/types.js';
|
||||||
|
import { ConfigContext } from '../../state.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
|
|
||||||
export function HighresControl() {
|
export interface HighresControlProps {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
highres: HighresParams;
|
||||||
const state = mustExist(useContext(StateContext));
|
setHighres(params: Partial<HighresParams>): void;
|
||||||
const highres = useStore(state, (s) => s.highres);
|
}
|
||||||
|
|
||||||
|
export function HighresControl(props: HighresControlProps) {
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setHighres = useStore(state, (s) => s.setHighres);
|
const { highres, setHighres } = props;
|
||||||
|
|
||||||
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack direction='row' spacing={4}>
|
return <Stack direction='row' spacing={4}>
|
||||||
|
@ -22,7 +26,7 @@ export function HighresControl() {
|
||||||
control={<Checkbox
|
control={<Checkbox
|
||||||
checked={highres.enabled}
|
checked={highres.enabled}
|
||||||
value='check'
|
value='check'
|
||||||
onChange={(event) => {
|
onChange={(_event) => {
|
||||||
setHighres({
|
setHighres({
|
||||||
enabled: highres.enabled === false,
|
enabled: highres.enabled === false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,21 +13,21 @@ import { ClientContext, ConfigContext, OnnxState, StateContext } from '../../sta
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
import { PromptInput } from '../input/PromptInput.js';
|
import { PromptInput } from '../input/PromptInput.js';
|
||||||
import { QueryList } from '../input/QueryList.js';
|
import { QueryList } from '../input/QueryList.js';
|
||||||
import { Profiles } from '../Profiles.js';
|
|
||||||
|
|
||||||
export interface ImageControlProps {
|
export interface ImageControlProps {
|
||||||
selector: (state: OnnxState) => BaseImgParams;
|
onChange(params: BaseImgParams): void;
|
||||||
|
selector(state: OnnxState): BaseImgParams;
|
||||||
onChange?: (params: BaseImgParams) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Doesn't need to use state directly, the parent component knows which params to pass
|
* Doesn't need to use state directly, the parent component knows which params to pass
|
||||||
*/
|
*/
|
||||||
export function ImageControl(props: ImageControlProps) {
|
export function ImageControl(props: ImageControlProps) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const { onChange, selector } = props;
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const controlState = useStore(state, props.selector);
|
const controlState = useStore(state, selector);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const client = mustExist(useContext(ClientContext));
|
const client = mustExist(useContext(ClientContext));
|
||||||
|
@ -40,7 +40,6 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={2}>
|
||||||
<Stack direction='row' spacing={4}>
|
<Stack direction='row' spacing={4}>
|
||||||
<Profiles params={controlState} setParams={props.onChange} />
|
|
||||||
<QueryList
|
<QueryList
|
||||||
id='schedulers'
|
id='schedulers'
|
||||||
labelKey='scheduler'
|
labelKey='scheduler'
|
||||||
|
@ -50,8 +49,8 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
}}
|
}}
|
||||||
value={mustDefault(controlState.scheduler, '')}
|
value={mustDefault(controlState.scheduler, '')}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
if (doesExist(props.onChange)) {
|
if (doesExist(onChange)) {
|
||||||
props.onChange({
|
onChange({
|
||||||
...controlState,
|
...controlState,
|
||||||
scheduler: value,
|
scheduler: value,
|
||||||
});
|
});
|
||||||
|
@ -66,8 +65,8 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
step={params.eta.step}
|
step={params.eta.step}
|
||||||
value={controlState.eta}
|
value={controlState.eta}
|
||||||
onChange={(eta) => {
|
onChange={(eta) => {
|
||||||
if (doesExist(props.onChange)) {
|
if (doesExist(onChange)) {
|
||||||
props.onChange({
|
onChange({
|
||||||
...controlState,
|
...controlState,
|
||||||
eta,
|
eta,
|
||||||
});
|
});
|
||||||
|
@ -82,8 +81,8 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
step={params.cfg.step}
|
step={params.cfg.step}
|
||||||
value={controlState.cfg}
|
value={controlState.cfg}
|
||||||
onChange={(cfg) => {
|
onChange={(cfg) => {
|
||||||
if (doesExist(props.onChange)) {
|
if (doesExist(onChange)) {
|
||||||
props.onChange({
|
onChange({
|
||||||
...controlState,
|
...controlState,
|
||||||
cfg,
|
cfg,
|
||||||
});
|
});
|
||||||
|
@ -97,12 +96,10 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
step={params.steps.step}
|
step={params.steps.step}
|
||||||
value={controlState.steps}
|
value={controlState.steps}
|
||||||
onChange={(steps) => {
|
onChange={(steps) => {
|
||||||
if (doesExist(props.onChange)) {
|
onChange({
|
||||||
props.onChange({
|
...controlState,
|
||||||
...controlState,
|
steps,
|
||||||
steps,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<NumericField
|
<NumericField
|
||||||
|
@ -112,12 +109,10 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
step={params.seed.step}
|
step={params.seed.step}
|
||||||
value={controlState.seed}
|
value={controlState.seed}
|
||||||
onChange={(seed) => {
|
onChange={(seed) => {
|
||||||
if (doesExist(props.onChange)) {
|
onChange({
|
||||||
props.onChange({
|
...controlState,
|
||||||
...controlState,
|
seed,
|
||||||
seed,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
|
@ -125,12 +120,10 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
startIcon={<Casino />}
|
startIcon={<Casino />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const seed = Math.floor(Math.random() * params.seed.max);
|
const seed = Math.floor(Math.random() * params.seed.max);
|
||||||
if (doesExist(props.onChange)) {
|
props.onChange({
|
||||||
props.onChange({
|
...controlState,
|
||||||
...controlState,
|
seed,
|
||||||
seed,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('parameter.newSeed')}
|
{t('parameter.newSeed')}
|
||||||
|
@ -144,12 +137,10 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
step={params.batch.step}
|
step={params.batch.step}
|
||||||
value={controlState.batch}
|
value={controlState.batch}
|
||||||
onChange={(batch) => {
|
onChange={(batch) => {
|
||||||
if (doesExist(props.onChange)) {
|
props.onChange({
|
||||||
props.onChange({
|
...controlState,
|
||||||
...controlState,
|
batch,
|
||||||
batch,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<NumericField
|
<NumericField
|
||||||
|
@ -159,12 +150,10 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
step={params.tiles.step}
|
step={params.tiles.step}
|
||||||
value={controlState.tiles}
|
value={controlState.tiles}
|
||||||
onChange={(tiles) => {
|
onChange={(tiles) => {
|
||||||
if (doesExist(props.onChange)) {
|
props.onChange({
|
||||||
props.onChange({
|
...controlState,
|
||||||
...controlState,
|
tiles,
|
||||||
tiles,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<NumericField
|
<NumericField
|
||||||
|
@ -175,12 +164,10 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
step={params.overlap.step}
|
step={params.overlap.step}
|
||||||
value={controlState.overlap}
|
value={controlState.overlap}
|
||||||
onChange={(overlap) => {
|
onChange={(overlap) => {
|
||||||
if (doesExist(props.onChange)) {
|
props.onChange({
|
||||||
props.onChange({
|
...controlState,
|
||||||
...controlState,
|
overlap,
|
||||||
overlap,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<NumericField
|
<NumericField
|
||||||
|
@ -190,12 +177,10 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
step={params.stride.step}
|
step={params.stride.step}
|
||||||
value={controlState.stride}
|
value={controlState.stride}
|
||||||
onChange={(stride) => {
|
onChange={(stride) => {
|
||||||
if (doesExist(props.onChange)) {
|
props.onChange({
|
||||||
props.onChange({
|
...controlState,
|
||||||
...controlState,
|
stride,
|
||||||
stride,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
|
@ -204,12 +189,10 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
checked={controlState.tiledVAE}
|
checked={controlState.tiledVAE}
|
||||||
value='check'
|
value='check'
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
if (doesExist(props.onChange)) {
|
props.onChange({
|
||||||
props.onChange({
|
...controlState,
|
||||||
...controlState,
|
tiledVAE: controlState.tiledVAE === false,
|
||||||
tiledVAE: controlState.tiledVAE === false,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>}
|
/>}
|
||||||
/>
|
/>
|
||||||
|
@ -218,12 +201,10 @@ export function ImageControl(props: ImageControlProps) {
|
||||||
prompt={controlState.prompt}
|
prompt={controlState.prompt}
|
||||||
negativePrompt={controlState.negativePrompt}
|
negativePrompt={controlState.negativePrompt}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
if (doesExist(props.onChange)) {
|
props.onChange({
|
||||||
props.onChange({
|
...controlState,
|
||||||
...controlState,
|
...value,
|
||||||
...value,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Stack>;
|
</Stack>;
|
||||||
|
|
|
@ -4,25 +4,25 @@ import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHash } from 'react-use/lib/useHash';
|
|
||||||
import { useStore } from 'zustand';
|
|
||||||
|
|
||||||
|
import { ModelParams } from '../../client/types.js';
|
||||||
import { STALE_TIME } from '../../config.js';
|
import { STALE_TIME } from '../../config.js';
|
||||||
import { ClientContext, StateContext } from '../../state.js';
|
import { ClientContext, StateContext } from '../../state.js';
|
||||||
import { QueryList } from '../input/QueryList.js';
|
import { QueryList } from '../input/QueryList.js';
|
||||||
import { QueryMenu } from '../input/QueryMenu.js';
|
|
||||||
import { getTab } from '../utils.js';
|
|
||||||
|
|
||||||
export function ModelControl() {
|
export interface ModelControlProps {
|
||||||
|
model: ModelParams;
|
||||||
|
setModel(params: Partial<ModelParams>): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ModelControl(props: ModelControlProps) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const { model, setModel } = props;
|
||||||
|
|
||||||
const client = mustExist(useContext(ClientContext));
|
const client = mustExist(useContext(ClientContext));
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const params = useStore(state, (s) => s.model);
|
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
||||||
const setModel = useStore(state, (s) => s.setModel);
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [hash, _setHash] = useHash();
|
|
||||||
|
|
||||||
const restart = useMutation(['restart'], async () => client.restart());
|
const restart = useMutation(['restart'], async () => client.restart());
|
||||||
const models = useQuery(['models'], async () => client.models(), {
|
const models = useQuery(['models'], async () => client.models(), {
|
||||||
staleTime: STALE_TIME,
|
staleTime: STALE_TIME,
|
||||||
|
@ -34,135 +34,83 @@ export function ModelControl() {
|
||||||
staleTime: STALE_TIME,
|
staleTime: STALE_TIME,
|
||||||
});
|
});
|
||||||
|
|
||||||
function addToken(type: string, name: string, weight = 1.0) {
|
return <Stack direction='row' spacing={2}>
|
||||||
const tab = getTab(hash);
|
<QueryList
|
||||||
const current = state.getState();
|
id='platforms'
|
||||||
|
labelKey='platform'
|
||||||
switch (tab) {
|
name={t('parameter.platform')}
|
||||||
case 'txt2img': {
|
query={{
|
||||||
const { prompt } = current.txt2img;
|
result: platforms,
|
||||||
current.setTxt2Img({
|
}}
|
||||||
prompt: `<${type}:${name}:1.0> ${prompt}`,
|
value={model.platform}
|
||||||
|
onChange={(platform) => {
|
||||||
|
setModel({
|
||||||
|
platform,
|
||||||
});
|
});
|
||||||
break;
|
}}
|
||||||
}
|
/>
|
||||||
case 'img2img': {
|
<QueryList
|
||||||
const { prompt } = current.img2img;
|
id='pipeline'
|
||||||
current.setImg2Img({
|
labelKey='pipeline'
|
||||||
prompt: `<${type}:${name}:1.0> ${prompt}`,
|
name={t('parameter.pipeline')}
|
||||||
|
query={{
|
||||||
|
result: pipelines,
|
||||||
|
}}
|
||||||
|
value={model.pipeline}
|
||||||
|
onChange={(pipeline) => {
|
||||||
|
setModel({
|
||||||
|
pipeline,
|
||||||
});
|
});
|
||||||
break;
|
}}
|
||||||
}
|
/>
|
||||||
default:
|
<QueryList
|
||||||
// not supported yet
|
id='diffusion'
|
||||||
}
|
labelKey='model'
|
||||||
}
|
name={t('modelType.diffusion', { count: 1 })}
|
||||||
|
query={{
|
||||||
return <Stack direction='column' spacing={2}>
|
result: models,
|
||||||
<Stack direction='row' spacing={2}>
|
selector: (result) => result.diffusion,
|
||||||
<QueryList
|
}}
|
||||||
id='platforms'
|
value={model.model}
|
||||||
labelKey='platform'
|
onChange={(newModel) => {
|
||||||
name={t('parameter.platform')}
|
setModel({
|
||||||
query={{
|
model: newModel,
|
||||||
result: platforms,
|
});
|
||||||
}}
|
}}
|
||||||
value={params.platform}
|
/>
|
||||||
onChange={(platform) => {
|
<QueryList
|
||||||
setModel({
|
id='upscaling'
|
||||||
platform,
|
labelKey='model'
|
||||||
});
|
name={t('modelType.upscaling', { count: 1 })}
|
||||||
}}
|
query={{
|
||||||
/>
|
result: models,
|
||||||
<QueryList
|
selector: (result) => result.upscaling,
|
||||||
id='pipeline'
|
}}
|
||||||
labelKey='pipeline'
|
value={model.upscaling}
|
||||||
name={t('parameter.pipeline')}
|
onChange={(upscaling) => {
|
||||||
query={{
|
setModel({
|
||||||
result: pipelines,
|
upscaling,
|
||||||
}}
|
});
|
||||||
value={params.pipeline}
|
}}
|
||||||
onChange={(pipeline) => {
|
/>
|
||||||
setModel({
|
<QueryList
|
||||||
pipeline,
|
id='correction'
|
||||||
});
|
labelKey='model'
|
||||||
}}
|
name={t('modelType.correction', { count: 1 })}
|
||||||
/>
|
query={{
|
||||||
<QueryList
|
result: models,
|
||||||
id='diffusion'
|
selector: (result) => result.correction,
|
||||||
labelKey='model'
|
}}
|
||||||
name={t('modelType.diffusion', {count: 1})}
|
value={model.correction}
|
||||||
query={{
|
onChange={(correction) => {
|
||||||
result: models,
|
setModel({
|
||||||
selector: (result) => result.diffusion,
|
correction,
|
||||||
}}
|
});
|
||||||
value={params.model}
|
}}
|
||||||
onChange={(model) => {
|
/>
|
||||||
setModel({
|
<Button
|
||||||
model,
|
variant='outlined'
|
||||||
});
|
onClick={() => restart.mutate()}
|
||||||
}}
|
>{t('admin.restart')}</Button>
|
||||||
/>
|
|
||||||
<QueryList
|
|
||||||
id='upscaling'
|
|
||||||
labelKey='model'
|
|
||||||
name={t('modelType.upscaling', {count: 1})}
|
|
||||||
query={{
|
|
||||||
result: models,
|
|
||||||
selector: (result) => result.upscaling,
|
|
||||||
}}
|
|
||||||
value={params.upscaling}
|
|
||||||
onChange={(upscaling) => {
|
|
||||||
setModel({
|
|
||||||
upscaling,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<QueryList
|
|
||||||
id='correction'
|
|
||||||
labelKey='model'
|
|
||||||
name={t('modelType.correction', {count: 1})}
|
|
||||||
query={{
|
|
||||||
result: models,
|
|
||||||
selector: (result) => result.correction,
|
|
||||||
}}
|
|
||||||
value={params.correction}
|
|
||||||
onChange={(correction) => {
|
|
||||||
setModel({
|
|
||||||
correction,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
<Stack direction='row' spacing={2}>
|
|
||||||
<QueryMenu
|
|
||||||
id='inversion'
|
|
||||||
labelKey='model.inversion'
|
|
||||||
name={t('modelType.inversion')}
|
|
||||||
query={{
|
|
||||||
result: models,
|
|
||||||
selector: (result) => result.networks.filter((network) => network.type === 'inversion').map((network) => network.name),
|
|
||||||
}}
|
|
||||||
onSelect={(name) => {
|
|
||||||
addToken('inversion', name);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<QueryMenu
|
|
||||||
id='lora'
|
|
||||||
labelKey='model.lora'
|
|
||||||
name={t('modelType.lora')}
|
|
||||||
query={{
|
|
||||||
result: models,
|
|
||||||
selector: (result) => result.networks.filter((network) => network.type === 'lora').map((network) => network.name),
|
|
||||||
}}
|
|
||||||
onSelect={(name) => {
|
|
||||||
addToken('lora', name);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
variant='outlined'
|
|
||||||
onClick={() => restart.mutate()}
|
|
||||||
>{t('admin.restart')}</Button>
|
|
||||||
</Stack>
|
|
||||||
</Stack>;
|
</Stack>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,21 @@ import { Checkbox, FormControl, FormControlLabel, InputLabel, MenuItem, Select,
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
|
||||||
|
|
||||||
import { ConfigContext, StateContext } from '../../state.js';
|
import { UpscaleParams } from '../../client/types.js';
|
||||||
|
import { ConfigContext } from '../../state.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
|
|
||||||
export function UpscaleControl() {
|
export interface UpscaleControlProps {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
upscale: UpscaleParams;
|
||||||
const state = mustExist(useContext(StateContext));
|
setUpscale(params: Partial<UpscaleParams>): void;
|
||||||
const upscale = useStore(state, (s) => s.upscale);
|
}
|
||||||
|
|
||||||
|
export function UpscaleControl(props: UpscaleControlProps) {
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setUpscale = useStore(state, (s) => s.setUpscale);
|
const { upscale, setUpscale } = props;
|
||||||
|
|
||||||
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Stack direction='row' spacing={4}>
|
return <Stack direction='row' spacing={4}>
|
||||||
|
@ -22,7 +26,7 @@ export function UpscaleControl() {
|
||||||
control={<Checkbox
|
control={<Checkbox
|
||||||
checked={upscale.enabled}
|
checked={upscale.enabled}
|
||||||
value='check'
|
value='check'
|
||||||
onChange={(event) => {
|
onChange={(_event) => {
|
||||||
setUpscale({
|
setUpscale({
|
||||||
enabled: upscale.enabled === false,
|
enabled: upscale.enabled === false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { Button, Stack, Typography } from '@mui/material';
|
||||||
import { throttle } from 'lodash';
|
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 { useStore } from 'zustand';
|
|
||||||
|
|
||||||
|
import { BrushParams } from '../../client/types.js';
|
||||||
import { SAVE_TIME } from '../../config.js';
|
import { SAVE_TIME } from '../../config.js';
|
||||||
import { ConfigContext, LoggerContext, StateContext } from '../../state.js';
|
import { ConfigContext, LoggerContext, StateContext } from '../../state.js';
|
||||||
import { imageFromBlob } from '../../utils.js';
|
import { imageFromBlob } from '../../utils.js';
|
||||||
|
@ -36,14 +36,17 @@ export interface Point {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MaskCanvasProps {
|
export interface MaskCanvasProps {
|
||||||
|
brush: BrushParams;
|
||||||
source?: Maybe<Blob>;
|
source?: Maybe<Blob>;
|
||||||
mask?: Maybe<Blob>;
|
mask?: Maybe<Blob>;
|
||||||
|
|
||||||
onSave: (blob: Blob) => void;
|
onSave(blob: Blob): void;
|
||||||
|
setBrush(brush: Partial<BrushParams>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MaskCanvas(props: MaskCanvasProps) {
|
export function MaskCanvas(props: MaskCanvasProps) {
|
||||||
const { source, mask } = props;
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const { source, mask, brush, setBrush } = props;
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
const logger = mustExist(useContext(LoggerContext));
|
const logger = mustExist(useContext(LoggerContext));
|
||||||
|
|
||||||
|
@ -202,9 +205,6 @@ export function MaskCanvas(props: MaskCanvasProps) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const brush = useStore(state, (s) => s.brush);
|
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
||||||
const setBrush = useStore(state, (s) => s.setBrush);
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -1,16 +1,23 @@
|
||||||
import { doesExist, Maybe } from '@apextoaster/js-utils';
|
import { doesExist, mustExist } from '@apextoaster/js-utils';
|
||||||
import { TextField } from '@mui/material';
|
import { TextField } from '@mui/material';
|
||||||
import { Stack } from '@mui/system';
|
import { Stack } from '@mui/system';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { QueryMenu } from '../input/QueryMenu.js';
|
||||||
|
import { STALE_TIME } from '../../config.js';
|
||||||
|
import { ClientContext } from '../../state.js';
|
||||||
|
|
||||||
|
const { useContext } = React;
|
||||||
|
|
||||||
export interface PromptValue {
|
export interface PromptValue {
|
||||||
prompt: string;
|
prompt: string;
|
||||||
negativePrompt?: string;
|
negativePrompt?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PromptInputProps extends PromptValue {
|
export interface PromptInputProps extends PromptValue {
|
||||||
onChange?: Maybe<(value: PromptValue) => void>;
|
onChange: (value: PromptValue) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PROMPT_GROUP = 75;
|
export const PROMPT_GROUP = 75;
|
||||||
|
@ -29,12 +36,24 @@ export function PromptInput(props: PromptInputProps) {
|
||||||
const tokens = splitPrompt(prompt);
|
const tokens = splitPrompt(prompt);
|
||||||
const groups = Math.ceil(tokens.length / PROMPT_GROUP);
|
const groups = Math.ceil(tokens.length / PROMPT_GROUP);
|
||||||
|
|
||||||
|
const client = mustExist(useContext(ClientContext));
|
||||||
|
const models = useQuery(['models'], async () => client.models(), {
|
||||||
|
staleTime: STALE_TIME,
|
||||||
|
});
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const helper = t('input.prompt.tokens', {
|
const helper = t('input.prompt.tokens', {
|
||||||
groups,
|
groups,
|
||||||
tokens: tokens.length,
|
tokens: tokens.length,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function addToken(type: string, name: string, weight = 1.0) {
|
||||||
|
props.onChange({
|
||||||
|
prompt: `<${type}:${name}:1.0> ${prompt}`,
|
||||||
|
negativePrompt,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return <Stack spacing={2}>
|
return <Stack spacing={2}>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('parameter.prompt')}
|
label={t('parameter.prompt')}
|
||||||
|
@ -63,5 +82,31 @@ export function PromptInput(props: PromptInputProps) {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Stack direction='row' spacing={2}>
|
||||||
|
<QueryMenu
|
||||||
|
id='inversion'
|
||||||
|
labelKey='model.inversion'
|
||||||
|
name={t('modelType.inversion')}
|
||||||
|
query={{
|
||||||
|
result: models,
|
||||||
|
selector: (result) => result.networks.filter((network) => network.type === 'inversion').map((network) => network.name),
|
||||||
|
}}
|
||||||
|
onSelect={(name) => {
|
||||||
|
addToken('inversion', name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<QueryMenu
|
||||||
|
id='lora'
|
||||||
|
labelKey='model.lora'
|
||||||
|
name={t('modelType.lora')}
|
||||||
|
query={{
|
||||||
|
result: models,
|
||||||
|
selector: (result) => result.networks.filter((network) => network.type === 'lora').map((network) => network.name),
|
||||||
|
}}
|
||||||
|
onSelect={(name) => {
|
||||||
|
addToken('lora', name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
</Stack>;
|
</Stack>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,12 @@ 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 { blend, blendModel, blendUpscale } = state.getState();
|
||||||
const { image, retry } = await client.blend(model, {
|
const { image, retry } = await client.blend(blendModel, {
|
||||||
...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);
|
}, blendUpscale);
|
||||||
|
|
||||||
pushHistory(image, retry);
|
pushHistory(image, retry);
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,16 @@ export function Blend() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
|
const brush = useStore(state, (s) => s.blendBrush);
|
||||||
const blend = useStore(state, (s) => s.blend);
|
const blend = useStore(state, (s) => s.blend);
|
||||||
|
const upscale = useStore(state, (s) => s.blendUpscale);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setBlend = useStore(state, (s) => s.setBlend);
|
const setBlend = useStore(state, (s) => s.setBlend);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setBrush = useStore(state, (s) => s.setBlendBrush);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setUpscale = useStore(state, (s) => s.setBlendUpscale);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const pushHistory = useStore(state, (s) => s.pushHistory);
|
const pushHistory = useStore(state, (s) => s.pushHistory);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
@ -61,6 +67,7 @@ export function Blend() {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<MaskCanvas
|
<MaskCanvas
|
||||||
|
brush={brush}
|
||||||
source={sources[0]}
|
source={sources[0]}
|
||||||
mask={blend.mask}
|
mask={blend.mask}
|
||||||
onSave={(mask) => {
|
onSave={(mask) => {
|
||||||
|
@ -68,8 +75,9 @@ export function Blend() {
|
||||||
mask,
|
mask,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
setBrush={setBrush}
|
||||||
/>
|
/>
|
||||||
<UpscaleControl />
|
<UpscaleControl upscale={upscale} setUpscale={setUpscale} />
|
||||||
<Button
|
<Button
|
||||||
disabled={sources.length < 2}
|
disabled={sources.length < 2}
|
||||||
variant='contained'
|
variant='contained'
|
||||||
|
|
|
@ -14,12 +14,13 @@ 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 { HighresControl } from '../control/HighresControl.js';
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
|
import { ModelControl } from '../control/ModelControl.js';
|
||||||
|
import { Profiles } from '../Profiles.js';
|
||||||
|
|
||||||
export function Img2Img() {
|
export function Img2Img() {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
|
|
||||||
async function uploadSource() {
|
async function uploadSource() {
|
||||||
const { model, img2img, upscale, highres } = state.getState();
|
|
||||||
const { image, retry } = await client.img2img(model, {
|
const { image, retry } = 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
|
||||||
|
@ -42,21 +43,27 @@ export function Img2Img() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const control = useStore(state, (s) => s.model.control);
|
const model = useStore(state, (s) => s.img2imgModel);
|
||||||
const source = useStore(state, (s) => s.img2img.source);
|
const source = useStore(state, (s) => s.img2img.source);
|
||||||
const sourceFilter = useStore(state, (s) => s.img2img.sourceFilter);
|
const img2img = useStore(state, (s) => s.img2img);
|
||||||
const strength = useStore(state, (s) => s.img2img.strength);
|
const highres = useStore(state, (s) => s.img2imgHighres);
|
||||||
const loopback = useStore(state, (s) => s.img2img.loopback);
|
const upscale = useStore(state, (s) => s.img2imgUpscale);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setImg2Img = useStore(state, (s) => s.setImg2Img);
|
const setImg2Img = useStore(state, (s) => s.setImg2Img);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setModel = useStore(state, (s) => s.setModel);
|
const setHighres = useStore(state, (s) => s.setImg2ImgHighres);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setUpscale = useStore(state, (s) => s.setImg2ImgUpscale);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setModel = useStore(state, (s) => s.setImg2ImgModel);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const pushHistory = useStore(state, (s) => s.pushHistory);
|
const pushHistory = useStore(state, (s) => s.pushHistory);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
|
<Profiles params={img2img} setParams={setImg2Img} highres={highres} setHighres={setHighres} upscale={upscale} setUpscale={setUpscale} />
|
||||||
|
<ModelControl model={model} setModel={setModel} />
|
||||||
<ImageInput
|
<ImageInput
|
||||||
filter={IMAGE_FILTER}
|
filter={IMAGE_FILTER}
|
||||||
image={source}
|
image={source}
|
||||||
|
@ -77,7 +84,7 @@ export function Img2Img() {
|
||||||
result: models,
|
result: models,
|
||||||
selector: (result) => result.networks.filter((network) => network.type === 'control').map((network) => network.name),
|
selector: (result) => result.networks.filter((network) => network.type === 'control').map((network) => network.name),
|
||||||
}}
|
}}
|
||||||
value={control}
|
value={model.control}
|
||||||
onChange={(newControl) => {
|
onChange={(newControl) => {
|
||||||
setModel({
|
setModel({
|
||||||
control: newControl,
|
control: newControl,
|
||||||
|
@ -93,7 +100,7 @@ export function Img2Img() {
|
||||||
selector: (f) => f.source,
|
selector: (f) => f.source,
|
||||||
}}
|
}}
|
||||||
showNone
|
showNone
|
||||||
value={sourceFilter}
|
value={img2img.sourceFilter}
|
||||||
onChange={(newFilter) => {
|
onChange={(newFilter) => {
|
||||||
setImg2Img({
|
setImg2Img({
|
||||||
sourceFilter: newFilter,
|
sourceFilter: newFilter,
|
||||||
|
@ -106,7 +113,7 @@ export function Img2Img() {
|
||||||
min={params.strength.min}
|
min={params.strength.min}
|
||||||
max={params.strength.max}
|
max={params.strength.max}
|
||||||
step={params.strength.step}
|
step={params.strength.step}
|
||||||
value={strength}
|
value={img2img.strength}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setImg2Img({
|
setImg2Img({
|
||||||
strength: value,
|
strength: value,
|
||||||
|
@ -118,7 +125,7 @@ export function Img2Img() {
|
||||||
min={params.loopback.min}
|
min={params.loopback.min}
|
||||||
max={params.loopback.max}
|
max={params.loopback.max}
|
||||||
step={params.loopback.step}
|
step={params.loopback.step}
|
||||||
value={loopback}
|
value={img2img.loopback}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setImg2Img({
|
setImg2Img({
|
||||||
loopback: value,
|
loopback: value,
|
||||||
|
@ -126,8 +133,8 @@ export function Img2Img() {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<HighresControl />
|
<HighresControl highres={highres} setHighres={setHighres} />
|
||||||
<UpscaleControl />
|
<UpscaleControl upscale={upscale} setUpscale={setUpscale} />
|
||||||
<Button
|
<Button
|
||||||
disabled={doesExist(source) === false}
|
disabled={doesExist(source) === false}
|
||||||
variant='contained'
|
variant='contained'
|
||||||
|
|
|
@ -1,21 +1,23 @@
|
||||||
import { doesExist, mustExist } from '@apextoaster/js-utils';
|
import { doesExist, mustExist } from '@apextoaster/js-utils';
|
||||||
import { Alert, Box, Button, FormControl, FormControlLabel, InputLabel, MenuItem, Select, Stack } from '@mui/material';
|
import { Alert, Box, Button, FormControl, FormControlLabel, InputLabel, MenuItem, Select, Stack } from '@mui/material';
|
||||||
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
import { IMAGE_FILTER, STALE_TIME } from '../../config.js';
|
import { IMAGE_FILTER, STALE_TIME } from '../../config.js';
|
||||||
import { ClientContext, ConfigContext, StateContext } from '../../state.js';
|
import { ClientContext, ConfigContext, StateContext } from '../../state.js';
|
||||||
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
import { ImageControl } from '../control/ImageControl.js';
|
import { ImageControl } from '../control/ImageControl.js';
|
||||||
|
import { ModelControl } from '../control/ModelControl.js';
|
||||||
import { OutpaintControl } from '../control/OutpaintControl.js';
|
import { OutpaintControl } from '../control/OutpaintControl.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 { 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 { HighresControl } from '../control/HighresControl.js';
|
import { Profiles } from '../Profiles.js';
|
||||||
|
|
||||||
export function Inpaint() {
|
export function Inpaint() {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
|
@ -29,9 +31,6 @@ export function Inpaint() {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function uploadSource(): Promise<void> {
|
async function uploadSource(): Promise<void> {
|
||||||
// these are not watched by the component, only sent by the mutation
|
|
||||||
const { model, inpaint, outpaint, upscale, highres } = state.getState();
|
|
||||||
|
|
||||||
if (outpaint.enabled) {
|
if (outpaint.enabled) {
|
||||||
const { image, retry } = await client.outpaint(model, {
|
const { image, retry } = await client.outpaint(model, {
|
||||||
...inpaint,
|
...inpaint,
|
||||||
|
@ -57,21 +56,31 @@ export function Inpaint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function supportsInpaint(): boolean {
|
function supportsInpaint(): boolean {
|
||||||
return diffusionModel.includes('inpaint');
|
return model.model.includes('inpaint');
|
||||||
}
|
}
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const fillColor = useStore(state, (s) => s.inpaint.fillColor);
|
|
||||||
const filter = useStore(state, (s) => s.inpaint.filter);
|
|
||||||
const noise = useStore(state, (s) => s.inpaint.noise);
|
|
||||||
const mask = useStore(state, (s) => s.inpaint.mask);
|
const mask = useStore(state, (s) => s.inpaint.mask);
|
||||||
const source = useStore(state, (s) => s.inpaint.source);
|
const source = useStore(state, (s) => s.inpaint.source);
|
||||||
const strength = useStore(state, (s) => s.inpaint.strength);
|
const inpaint = useStore(state, (s) => s.inpaint);
|
||||||
const tileOrder = useStore(state, (s) => s.inpaint.tileOrder);
|
const outpaint = useStore(state, (s) => s.outpaint);
|
||||||
const diffusionModel = useStore(state, (s) => s.model.model);
|
|
||||||
|
const brush = useStore(state, (s) => s.inpaintBrush);
|
||||||
|
const highres = useStore(state, (s) => s.inpaintHighres);
|
||||||
|
const model = useStore(state, (s) => s.inpaintModel);
|
||||||
|
const upscale = useStore(state, (s) => s.inpaintUpscale);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setInpaint = useStore(state, (s) => s.setInpaint);
|
const setInpaint = useStore(state, (s) => s.setInpaint);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setBrush = useStore(state, (s) => s.setInpaintBrush);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setModel = useStore(state, (s) => s.setInpaintModel);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setHighres = useStore(state, (s) => s.setInpaintHighres);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setUpscale = useStore(state, (s) => s.setInpaintUpscale);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const pushHistory = useStore(state, (s) => s.pushHistory);
|
const pushHistory = useStore(state, (s) => s.pushHistory);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
@ -91,6 +100,8 @@ export function Inpaint() {
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
|
<Profiles params={inpaint} setParams={setInpaint} highres={highres} setHighres={setHighres} upscale={upscale} setUpscale={setUpscale} />
|
||||||
|
<ModelControl model={model} setModel={setModel} />
|
||||||
{renderBanner()}
|
{renderBanner()}
|
||||||
<ImageInput
|
<ImageInput
|
||||||
filter={IMAGE_FILTER}
|
filter={IMAGE_FILTER}
|
||||||
|
@ -115,6 +126,7 @@ export function Inpaint() {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<MaskCanvas
|
<MaskCanvas
|
||||||
|
brush={brush}
|
||||||
source={source}
|
source={source}
|
||||||
mask={mask}
|
mask={mask}
|
||||||
onSave={(file) => {
|
onSave={(file) => {
|
||||||
|
@ -122,6 +134,7 @@ export function Inpaint() {
|
||||||
mask: file,
|
mask: file,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
setBrush={setBrush}
|
||||||
/>
|
/>
|
||||||
<ImageControl
|
<ImageControl
|
||||||
selector={(s) => s.inpaint}
|
selector={(s) => s.inpaint}
|
||||||
|
@ -134,7 +147,7 @@ export function Inpaint() {
|
||||||
min={params.strength.min}
|
min={params.strength.min}
|
||||||
max={params.strength.max}
|
max={params.strength.max}
|
||||||
step={params.strength.step}
|
step={params.strength.step}
|
||||||
value={strength}
|
value={inpaint.strength}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
strength: value,
|
strength: value,
|
||||||
|
@ -150,7 +163,7 @@ export function Inpaint() {
|
||||||
result: filters,
|
result: filters,
|
||||||
selector: (f) => f.mask,
|
selector: (f) => f.mask,
|
||||||
}}
|
}}
|
||||||
value={filter}
|
value={inpaint.filter}
|
||||||
onChange={(newFilter) => {
|
onChange={(newFilter) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
filter: newFilter,
|
filter: newFilter,
|
||||||
|
@ -164,7 +177,7 @@ export function Inpaint() {
|
||||||
query={{
|
query={{
|
||||||
result: noises,
|
result: noises,
|
||||||
}}
|
}}
|
||||||
value={noise}
|
value={inpaint.noise}
|
||||||
onChange={(newNoise) => {
|
onChange={(newNoise) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
noise: newNoise,
|
noise: newNoise,
|
||||||
|
@ -176,7 +189,7 @@ export function Inpaint() {
|
||||||
<Select
|
<Select
|
||||||
labelId={'outpaint-tiling'}
|
labelId={'outpaint-tiling'}
|
||||||
label={t('parameter.tileOrder')}
|
label={t('parameter.tileOrder')}
|
||||||
value={tileOrder}
|
value={inpaint.tileOrder}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
tileOrder: e.target.value,
|
tileOrder: e.target.value,
|
||||||
|
@ -194,7 +207,7 @@ export function Inpaint() {
|
||||||
sx={{ mx: 1 }}
|
sx={{ mx: 1 }}
|
||||||
control={
|
control={
|
||||||
<input
|
<input
|
||||||
defaultValue={fillColor}
|
defaultValue={inpaint.fillColor}
|
||||||
name='fill-color'
|
name='fill-color'
|
||||||
type='color'
|
type='color'
|
||||||
onBlur={(event) => {
|
onBlur={(event) => {
|
||||||
|
@ -208,8 +221,8 @@ export function Inpaint() {
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
<OutpaintControl />
|
<OutpaintControl />
|
||||||
<HighresControl />
|
<HighresControl highres={highres} setHighres={setHighres} />
|
||||||
<UpscaleControl />
|
<UpscaleControl upscale={upscale} setUpscale={setUpscale} />
|
||||||
<Button
|
<Button
|
||||||
disabled={preventInpaint()}
|
disabled={preventInpaint()}
|
||||||
variant='contained'
|
variant='contained'
|
||||||
|
|
|
@ -11,12 +11,13 @@ import { HighresControl } from '../control/HighresControl.js';
|
||||||
import { ImageControl } from '../control/ImageControl.js';
|
import { ImageControl } from '../control/ImageControl.js';
|
||||||
import { UpscaleControl } from '../control/UpscaleControl.js';
|
import { UpscaleControl } from '../control/UpscaleControl.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
|
import { ModelControl } from '../control/ModelControl.js';
|
||||||
|
import { Profiles } from '../Profiles.js';
|
||||||
|
|
||||||
export function Txt2Img() {
|
export function Txt2Img() {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
|
|
||||||
async function generateImage() {
|
async function generateImage() {
|
||||||
const { model, txt2img, upscale, highres } = state.getState();
|
|
||||||
const { image, retry } = await client.txt2img(model, txt2img, upscale, highres);
|
const { image, retry } = await client.txt2img(model, txt2img, upscale, highres);
|
||||||
|
|
||||||
pushHistory(image, retry);
|
pushHistory(image, retry);
|
||||||
|
@ -29,26 +30,36 @@ export function Txt2Img() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const height = useStore(state, (s) => s.txt2img.height);
|
const txt2img = useStore(state, (s) => s.txt2img);
|
||||||
const width = useStore(state, (s) => s.txt2img.width);
|
const model = useStore(state, (s) => s.txt2imgModel);
|
||||||
|
const highres = useStore(state, (s) => s.txt2imgHighres);
|
||||||
|
const upscale = useStore(state, (s) => s.txt2imgUpscale);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setTxt2Img = useStore(state, (s) => s.setTxt2Img);
|
const setParams = useStore(state, (s) => s.setTxt2Img);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setHighres = useStore(state, (s) => s.setTxt2ImgHighres);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setUpscale = useStore(state, (s) => s.setTxt2ImgUpscale);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setModel = useStore(state, (s) => s.setTxt2ImgModel);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const pushHistory = useStore(state, (s) => s.pushHistory);
|
const pushHistory = useStore(state, (s) => s.pushHistory);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<ImageControl selector={(s) => s.txt2img} onChange={setTxt2Img} />
|
<Profiles params={txt2img} setParams={setParams} highres={highres} setHighres={setHighres} upscale={upscale} setUpscale={setUpscale} />
|
||||||
|
<ModelControl model={model} setModel={setModel} />
|
||||||
|
<ImageControl selector={(s) => s.txt2img} onChange={setParams} />
|
||||||
<Stack direction='row' spacing={4}>
|
<Stack direction='row' spacing={4}>
|
||||||
<NumericField
|
<NumericField
|
||||||
label={t('parameter.width')}
|
label={t('parameter.width')}
|
||||||
min={params.width.min}
|
min={params.width.min}
|
||||||
max={params.width.max}
|
max={params.width.max}
|
||||||
step={params.width.step}
|
step={params.width.step}
|
||||||
value={width}
|
value={txt2img.width}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setTxt2Img({
|
setParams({
|
||||||
width: value,
|
width: value,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
@ -58,16 +69,16 @@ export function Txt2Img() {
|
||||||
min={params.height.min}
|
min={params.height.min}
|
||||||
max={params.height.max}
|
max={params.height.max}
|
||||||
step={params.height.step}
|
step={params.height.step}
|
||||||
value={height}
|
value={txt2img.height}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setTxt2Img({
|
setParams({
|
||||||
height: value,
|
height: value,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<HighresControl />
|
<HighresControl highres={highres} setHighres={setHighres} />
|
||||||
<UpscaleControl />
|
<UpscaleControl upscale={upscale} setUpscale={setUpscale} />
|
||||||
<Button
|
<Button
|
||||||
variant='contained'
|
variant='contained'
|
||||||
onClick={() => generate.mutate()}
|
onClick={() => generate.mutate()}
|
||||||
|
|
|
@ -1,25 +1,27 @@
|
||||||
import { doesExist, mustExist } from '@apextoaster/js-utils';
|
import { doesExist, mustExist } from '@apextoaster/js-utils';
|
||||||
import { Box, Button, Stack } from '@mui/material';
|
import { Box, Button, Stack } from '@mui/material';
|
||||||
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
import { IMAGE_FILTER } from '../../config.js';
|
import { IMAGE_FILTER } from '../../config.js';
|
||||||
import { ClientContext, StateContext } from '../../state.js';
|
import { ClientContext, StateContext } from '../../state.js';
|
||||||
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
|
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 { HighresControl } from '../control/HighresControl.js';
|
import { Profiles } from '../Profiles.js';
|
||||||
|
|
||||||
export function Upscale() {
|
export function Upscale() {
|
||||||
async function uploadSource() {
|
async function uploadSource() {
|
||||||
const { highres, model, upscale } = state.getState();
|
const { upscaleHighres, upscaleUpscale, upscaleModel, upscale } = state.getState();
|
||||||
const { image, retry } = await client.upscale(model, {
|
const { image, retry } = await client.upscale(upscaleModel, {
|
||||||
...params,
|
...upscale,
|
||||||
source: mustExist(params.source), // TODO: show an error if this doesn't exist
|
source: mustExist(upscale.source), // TODO: show an error if this doesn't exist
|
||||||
}, upscale, highres);
|
}, upscaleUpscale, upscaleHighres);
|
||||||
|
|
||||||
pushHistory(image, retry);
|
pushHistory(image, retry);
|
||||||
}
|
}
|
||||||
|
@ -31,21 +33,32 @@ export function Upscale() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const params = useStore(state, (s) => s.upscaleTab);
|
const highres = useStore(state, (s) => s.upscaleHighres);
|
||||||
|
const model = useStore(state, (s) => s.upscaleModel);
|
||||||
|
const params = useStore(state, (s) => s.upscale);
|
||||||
|
const upscale = useStore(state, (s) => s.upscaleUpscale);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setSource = useStore(state, (s) => s.setUpscaleTab);
|
const setModel = useStore(state, (s) => s.setUpscalingModel);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setHighres = useStore(state, (s) => s.setUpscaleHighres);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setUpscale = useStore(state, (s) => s.setUpscaleUpscale);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
const setParams = useStore(state, (s) => s.setUpscale);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const pushHistory = useStore(state, (s) => s.pushHistory);
|
const pushHistory = useStore(state, (s) => s.pushHistory);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
|
<Profiles params={params} setParams={setParams} highres={highres} setHighres={setHighres} upscale={upscale} setUpscale={setUpscale} />
|
||||||
|
<ModelControl model={model} setModel={setModel} />
|
||||||
<ImageInput
|
<ImageInput
|
||||||
filter={IMAGE_FILTER}
|
filter={IMAGE_FILTER}
|
||||||
image={params.source}
|
image={params.source}
|
||||||
label={t('input.image.source')}
|
label={t('input.image.source')}
|
||||||
onChange={(file) => {
|
onChange={(file) => {
|
||||||
setSource({
|
setParams({
|
||||||
source: file,
|
source: file,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
@ -54,11 +67,11 @@ export function Upscale() {
|
||||||
prompt={params.prompt}
|
prompt={params.prompt}
|
||||||
negativePrompt={params.negativePrompt}
|
negativePrompt={params.negativePrompt}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setSource(value);
|
setParams(value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<HighresControl />
|
<HighresControl highres={highres} setHighres={setHighres} />
|
||||||
<UpscaleControl />
|
<UpscaleControl upscale={upscale} setUpscale={setUpscale} />
|
||||||
<Button
|
<Button
|
||||||
disabled={doesExist(params.source) === false}
|
disabled={doesExist(params.source) === false}
|
||||||
variant='contained'
|
variant='contained'
|
||||||
|
|
|
@ -47,35 +47,27 @@ export async function renderApp(config: Config, params: ServerParams, logger: Lo
|
||||||
|
|
||||||
// prep zustand with a slice for each tab, using local storage
|
// prep zustand with a slice for each tab, using local storage
|
||||||
const {
|
const {
|
||||||
createBrushSlice,
|
|
||||||
createDefaultSlice,
|
createDefaultSlice,
|
||||||
createHistorySlice,
|
createHistorySlice,
|
||||||
createImg2ImgSlice,
|
createImg2ImgSlice,
|
||||||
createInpaintSlice,
|
createInpaintSlice,
|
||||||
createModelSlice,
|
createModelSlice,
|
||||||
createOutpaintSlice,
|
|
||||||
createTxt2ImgSlice,
|
createTxt2ImgSlice,
|
||||||
createUpscaleSlice,
|
createUpscaleSlice,
|
||||||
createHighresSlice,
|
|
||||||
createBlendSlice,
|
createBlendSlice,
|
||||||
createResetSlice,
|
createResetSlice,
|
||||||
createExtraSlice,
|
|
||||||
createProfileSlice,
|
createProfileSlice,
|
||||||
} = createStateSlices(params);
|
} = createStateSlices(params);
|
||||||
const state = createStore<OnnxState, [['zustand/persist', OnnxState]]>(persist((...slice) => ({
|
const state = createStore<OnnxState, [['zustand/persist', OnnxState]]>(persist((...slice) => ({
|
||||||
...createBrushSlice(...slice),
|
|
||||||
...createDefaultSlice(...slice),
|
...createDefaultSlice(...slice),
|
||||||
...createHistorySlice(...slice),
|
...createHistorySlice(...slice),
|
||||||
...createImg2ImgSlice(...slice),
|
...createImg2ImgSlice(...slice),
|
||||||
...createInpaintSlice(...slice),
|
...createInpaintSlice(...slice),
|
||||||
...createModelSlice(...slice),
|
...createModelSlice(...slice),
|
||||||
...createTxt2ImgSlice(...slice),
|
...createTxt2ImgSlice(...slice),
|
||||||
...createOutpaintSlice(...slice),
|
|
||||||
...createUpscaleSlice(...slice),
|
...createUpscaleSlice(...slice),
|
||||||
...createHighresSlice(...slice),
|
|
||||||
...createBlendSlice(...slice),
|
...createBlendSlice(...slice),
|
||||||
...createResetSlice(...slice),
|
...createResetSlice(...slice),
|
||||||
...createExtraSlice(...slice),
|
|
||||||
...createProfileSlice(...slice),
|
...createProfileSlice(...slice),
|
||||||
}), {
|
}), {
|
||||||
name: STATE_KEY,
|
name: STATE_KEY,
|
||||||
|
@ -91,8 +83,8 @@ export async function renderApp(config: Config, params: ServerParams, logger: Lo
|
||||||
mask: undefined,
|
mask: undefined,
|
||||||
source: undefined,
|
source: undefined,
|
||||||
},
|
},
|
||||||
upscaleTab: {
|
upscale: {
|
||||||
...s.upscaleTab,
|
...s.upscale,
|
||||||
source: undefined,
|
source: undefined,
|
||||||
},
|
},
|
||||||
blend: {
|
blend: {
|
||||||
|
|
511
gui/src/state.ts
511
gui/src/state.ts
|
@ -48,12 +48,6 @@ interface ProfileItem {
|
||||||
upscaleParams?: Maybe<UpscaleParams>;
|
upscaleParams?: Maybe<UpscaleParams>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BrushSlice {
|
|
||||||
brush: BrushParams;
|
|
||||||
|
|
||||||
setBrush(brush: Partial<BrushParams>): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DefaultSlice {
|
interface DefaultSlice {
|
||||||
defaults: TabState<BaseImgParams>;
|
defaults: TabState<BaseImgParams>;
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
|
@ -62,24 +56,6 @@ interface DefaultSlice {
|
||||||
setTheme(theme: Theme): void;
|
setTheme(theme: Theme): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExtraSlice {
|
|
||||||
extras: ExtrasFile;
|
|
||||||
|
|
||||||
setExtras(extras: Partial<ExtrasFile>): void;
|
|
||||||
|
|
||||||
setCorrectionModel(model: CorrectionModel): void;
|
|
||||||
setDiffusionModel(model: DiffusionModel): void;
|
|
||||||
setExtraNetwork(model: ExtraNetwork): void;
|
|
||||||
setExtraSource(model: ExtraSource): void;
|
|
||||||
setUpscalingModel(model: UpscalingModel): void;
|
|
||||||
|
|
||||||
removeCorrectionModel(model: CorrectionModel): void;
|
|
||||||
removeDiffusionModel(model: DiffusionModel): void;
|
|
||||||
removeExtraNetwork(model: ExtraNetwork): void;
|
|
||||||
removeExtraSource(model: ExtraSource): void;
|
|
||||||
removeUpscalingModel(model: UpscalingModel): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface HistorySlice {
|
interface HistorySlice {
|
||||||
history: Array<HistoryItem>;
|
history: Array<HistoryItem>;
|
||||||
limit: number;
|
limit: number;
|
||||||
|
@ -91,60 +67,96 @@ interface HistorySlice {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ModelSlice {
|
interface ModelSlice {
|
||||||
model: ModelParams;
|
extras: ExtrasFile;
|
||||||
|
|
||||||
setModel(model: Partial<ModelParams>): void;
|
removeCorrectionModel(model: CorrectionModel): void;
|
||||||
|
removeDiffusionModel(model: DiffusionModel): void;
|
||||||
|
removeExtraNetwork(model: ExtraNetwork): void;
|
||||||
|
removeExtraSource(model: ExtraSource): void;
|
||||||
|
removeUpscalingModel(model: UpscalingModel): void;
|
||||||
|
|
||||||
|
setExtras(extras: Partial<ExtrasFile>): void;
|
||||||
|
|
||||||
|
setCorrectionModel(model: CorrectionModel): void;
|
||||||
|
setDiffusionModel(model: DiffusionModel): void;
|
||||||
|
setExtraNetwork(model: ExtraNetwork): void;
|
||||||
|
setExtraSource(model: ExtraSource): void;
|
||||||
|
setUpscalingModel(model: UpscalingModel): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #region tab slices
|
// #region tab slices
|
||||||
interface Txt2ImgSlice {
|
interface Txt2ImgSlice {
|
||||||
txt2img: TabState<Txt2ImgParams>;
|
txt2img: TabState<Txt2ImgParams>;
|
||||||
|
txt2imgModel: ModelParams;
|
||||||
|
txt2imgHighres: HighresParams;
|
||||||
|
txt2imgUpscale: UpscaleParams;
|
||||||
|
|
||||||
|
resetTxt2Img(): void;
|
||||||
|
|
||||||
setTxt2Img(params: Partial<Txt2ImgParams>): void;
|
setTxt2Img(params: Partial<Txt2ImgParams>): void;
|
||||||
resetTxt2Img(): void;
|
setTxt2ImgModel(params: Partial<ModelParams>): void;
|
||||||
|
setTxt2ImgHighres(params: Partial<HighresParams>): void;
|
||||||
|
setTxt2ImgUpscale(params: Partial<UpscaleParams>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Img2ImgSlice {
|
interface Img2ImgSlice {
|
||||||
img2img: TabState<Img2ImgParams>;
|
img2img: TabState<Img2ImgParams>;
|
||||||
|
img2imgModel: ModelParams;
|
||||||
|
img2imgHighres: HighresParams;
|
||||||
|
img2imgUpscale: UpscaleParams;
|
||||||
|
|
||||||
|
resetImg2Img(): void;
|
||||||
|
|
||||||
setImg2Img(params: Partial<Img2ImgParams>): void;
|
setImg2Img(params: Partial<Img2ImgParams>): void;
|
||||||
resetImg2Img(): void;
|
setImg2ImgModel(params: Partial<ModelParams>): void;
|
||||||
|
setImg2ImgHighres(params: Partial<HighresParams>): void;
|
||||||
|
setImg2ImgUpscale(params: Partial<UpscaleParams>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InpaintSlice {
|
interface InpaintSlice {
|
||||||
inpaint: TabState<InpaintParams>;
|
inpaint: TabState<InpaintParams>;
|
||||||
|
inpaintBrush: BrushParams;
|
||||||
setInpaint(params: Partial<InpaintParams>): void;
|
inpaintModel: ModelParams;
|
||||||
resetInpaint(): void;
|
inpaintHighres: HighresParams;
|
||||||
}
|
inpaintUpscale: UpscaleParams;
|
||||||
|
|
||||||
interface OutpaintSlice {
|
|
||||||
outpaint: OutpaintPixels;
|
outpaint: OutpaintPixels;
|
||||||
|
|
||||||
|
resetInpaint(): void;
|
||||||
|
|
||||||
|
setInpaint(params: Partial<InpaintParams>): void;
|
||||||
|
setInpaintBrush(brush: Partial<BrushParams>): void;
|
||||||
|
setInpaintModel(params: Partial<ModelParams>): void;
|
||||||
|
setInpaintHighres(params: Partial<HighresParams>): void;
|
||||||
|
setInpaintUpscale(params: Partial<UpscaleParams>): void;
|
||||||
setOutpaint(pixels: Partial<OutpaintPixels>): void;
|
setOutpaint(pixels: Partial<OutpaintPixels>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HighresSlice {
|
|
||||||
highres: HighresParams;
|
|
||||||
|
|
||||||
setHighres(params: Partial<HighresParams>): void;
|
|
||||||
resetHighres(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UpscaleSlice {
|
interface UpscaleSlice {
|
||||||
upscale: UpscaleParams;
|
upscale: TabState<UpscaleReqParams>;
|
||||||
upscaleTab: TabState<UpscaleReqParams>;
|
upscaleHighres: HighresParams;
|
||||||
|
upscaleModel: ModelParams;
|
||||||
|
upscaleUpscale: UpscaleParams;
|
||||||
|
|
||||||
setUpscale(upscale: Partial<UpscaleParams>): void;
|
resetUpscale(): void;
|
||||||
setUpscaleTab(params: Partial<UpscaleReqParams>): void;
|
|
||||||
resetUpscaleTab(): void;
|
setUpscale(params: Partial<UpscaleReqParams>): void;
|
||||||
|
setUpscaleHighres(params: Partial<HighresParams>): void;
|
||||||
|
setUpscaleModel(params: Partial<ModelParams>): void;
|
||||||
|
setUpscaleUpscale(params: Partial<UpscaleParams>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BlendSlice {
|
interface BlendSlice {
|
||||||
blend: TabState<BlendParams>;
|
blend: TabState<BlendParams>;
|
||||||
|
blendBrush: BrushParams;
|
||||||
|
blendModel: ModelParams;
|
||||||
|
blendUpscale: UpscaleParams;
|
||||||
|
|
||||||
|
resetBlend(): void;
|
||||||
|
|
||||||
setBlend(blend: Partial<BlendParams>): void;
|
setBlend(blend: Partial<BlendParams>): void;
|
||||||
resetBlend(): void;
|
setBlendBrush(brush: Partial<BrushParams>): void;
|
||||||
|
setBlendModel(model: Partial<ModelParams>): void;
|
||||||
|
setBlendUpscale(params: Partial<UpscaleParams>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ResetSlice {
|
interface ResetSlice {
|
||||||
|
@ -154,8 +166,9 @@ interface ResetSlice {
|
||||||
interface ProfileSlice {
|
interface ProfileSlice {
|
||||||
profiles: Array<ProfileItem>;
|
profiles: Array<ProfileItem>;
|
||||||
|
|
||||||
saveProfile(profile: ProfileItem): void;
|
|
||||||
removeProfile(profileName: string): void;
|
removeProfile(profileName: string): void;
|
||||||
|
|
||||||
|
saveProfile(profile: ProfileItem): void;
|
||||||
}
|
}
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
@ -163,19 +176,16 @@ interface ProfileSlice {
|
||||||
* Full merged state including all slices.
|
* Full merged state including all slices.
|
||||||
*/
|
*/
|
||||||
export type OnnxState
|
export type OnnxState
|
||||||
= BrushSlice
|
= DefaultSlice
|
||||||
& DefaultSlice
|
|
||||||
& HistorySlice
|
& HistorySlice
|
||||||
& Img2ImgSlice
|
& Img2ImgSlice
|
||||||
& InpaintSlice
|
& InpaintSlice
|
||||||
& ModelSlice
|
& ModelSlice
|
||||||
& OutpaintSlice
|
|
||||||
& Txt2ImgSlice
|
& Txt2ImgSlice
|
||||||
& HighresSlice
|
|
||||||
& UpscaleSlice
|
& UpscaleSlice
|
||||||
& BlendSlice
|
& BlendSlice
|
||||||
& ResetSlice
|
& ResetSlice
|
||||||
& ExtraSlice
|
& ModelSlice
|
||||||
& ProfileSlice;
|
& ProfileSlice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -268,14 +278,49 @@ export function baseParamsFromServer(defaults: ServerParams): Required<BaseImgPa
|
||||||
* else should be initialized from the default value in the base parameters.
|
* else should be initialized from the default value in the base parameters.
|
||||||
*/
|
*/
|
||||||
export function createStateSlices(server: ServerParams) {
|
export function createStateSlices(server: ServerParams) {
|
||||||
const base = baseParamsFromServer(server);
|
const defaultParams = baseParamsFromServer(server);
|
||||||
|
const defaultHighres: HighresParams = {
|
||||||
|
enabled: false,
|
||||||
|
highresIterations: server.highresIterations.default,
|
||||||
|
highresMethod: '',
|
||||||
|
highresSteps: server.highresSteps.default,
|
||||||
|
highresScale: server.highresScale.default,
|
||||||
|
highresStrength: server.highresStrength.default,
|
||||||
|
};
|
||||||
|
const defaultModel: ModelParams = {
|
||||||
|
control: server.control.default,
|
||||||
|
correction: server.correction.default,
|
||||||
|
model: server.model.default,
|
||||||
|
pipeline: server.pipeline.default,
|
||||||
|
platform: server.platform.default,
|
||||||
|
upscaling: server.upscaling.default,
|
||||||
|
};
|
||||||
|
const defaultUpscale: UpscaleParams = {
|
||||||
|
denoise: server.denoise.default,
|
||||||
|
enabled: false,
|
||||||
|
faces: false,
|
||||||
|
faceOutscale: server.faceOutscale.default,
|
||||||
|
faceStrength: server.faceStrength.default,
|
||||||
|
outscale: server.outscale.default,
|
||||||
|
scale: server.scale.default,
|
||||||
|
upscaleOrder: server.upscaleOrder.default,
|
||||||
|
};
|
||||||
|
|
||||||
const createTxt2ImgSlice: Slice<Txt2ImgSlice> = (set) => ({
|
const createTxt2ImgSlice: Slice<Txt2ImgSlice> = (set) => ({
|
||||||
txt2img: {
|
txt2img: {
|
||||||
...base,
|
...defaultParams,
|
||||||
width: server.width.default,
|
width: server.width.default,
|
||||||
height: server.height.default,
|
height: server.height.default,
|
||||||
},
|
},
|
||||||
|
txt2imgHighres: {
|
||||||
|
...defaultHighres,
|
||||||
|
},
|
||||||
|
txt2imgModel: {
|
||||||
|
...defaultModel,
|
||||||
|
},
|
||||||
|
txt2imgUpscale: {
|
||||||
|
...defaultUpscale,
|
||||||
|
},
|
||||||
setTxt2Img(params) {
|
setTxt2Img(params) {
|
||||||
set((prev) => ({
|
set((prev) => ({
|
||||||
txt2img: {
|
txt2img: {
|
||||||
|
@ -284,10 +329,34 @@ export function createStateSlices(server: ServerParams) {
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
setTxt2ImgHighres(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
txt2imgHighres: {
|
||||||
|
...prev.txt2imgHighres,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setTxt2ImgModel(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
txt2imgModel: {
|
||||||
|
...prev.txt2imgModel,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setTxt2ImgUpscale(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
txt2imgUpscale: {
|
||||||
|
...prev.txt2imgUpscale,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
resetTxt2Img() {
|
resetTxt2Img() {
|
||||||
set({
|
set({
|
||||||
txt2img: {
|
txt2img: {
|
||||||
...base,
|
...defaultParams,
|
||||||
width: server.width.default,
|
width: server.width.default,
|
||||||
height: server.height.default,
|
height: server.height.default,
|
||||||
},
|
},
|
||||||
|
@ -297,12 +366,32 @@ export function createStateSlices(server: ServerParams) {
|
||||||
|
|
||||||
const createImg2ImgSlice: Slice<Img2ImgSlice> = (set) => ({
|
const createImg2ImgSlice: Slice<Img2ImgSlice> = (set) => ({
|
||||||
img2img: {
|
img2img: {
|
||||||
...base,
|
...defaultParams,
|
||||||
loopback: server.loopback.default,
|
loopback: server.loopback.default,
|
||||||
source: null,
|
source: null,
|
||||||
sourceFilter: '',
|
sourceFilter: '',
|
||||||
strength: server.strength.default,
|
strength: server.strength.default,
|
||||||
},
|
},
|
||||||
|
img2imgHighres: {
|
||||||
|
...defaultHighres,
|
||||||
|
},
|
||||||
|
img2imgModel: {
|
||||||
|
...defaultModel,
|
||||||
|
},
|
||||||
|
img2imgUpscale: {
|
||||||
|
...defaultUpscale,
|
||||||
|
},
|
||||||
|
resetImg2Img() {
|
||||||
|
set({
|
||||||
|
img2img: {
|
||||||
|
...defaultParams,
|
||||||
|
loopback: server.loopback.default,
|
||||||
|
source: null,
|
||||||
|
sourceFilter: '',
|
||||||
|
strength: server.strength.default,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
setImg2Img(params) {
|
setImg2Img(params) {
|
||||||
set((prev) => ({
|
set((prev) => ({
|
||||||
img2img: {
|
img2img: {
|
||||||
|
@ -311,22 +400,35 @@ export function createStateSlices(server: ServerParams) {
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
resetImg2Img() {
|
setImg2ImgHighres(params) {
|
||||||
set({
|
set((prev) => ({
|
||||||
img2img: {
|
img2imgHighres: {
|
||||||
...base,
|
...prev.img2imgHighres,
|
||||||
loopback: server.loopback.default,
|
...params,
|
||||||
source: null,
|
|
||||||
sourceFilter: '',
|
|
||||||
strength: server.strength.default,
|
|
||||||
},
|
},
|
||||||
});
|
}));
|
||||||
|
},
|
||||||
|
setImg2ImgModel(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
img2imgModel: {
|
||||||
|
...prev.img2imgModel,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setImg2ImgUpscale(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
img2imgUpscale: {
|
||||||
|
...prev.img2imgUpscale,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const createInpaintSlice: Slice<InpaintSlice> = (set) => ({
|
const createInpaintSlice: Slice<InpaintSlice> = (set) => ({
|
||||||
inpaint: {
|
inpaint: {
|
||||||
...base,
|
...defaultParams,
|
||||||
fillColor: server.fillColor.default,
|
fillColor: server.fillColor.default,
|
||||||
filter: server.filter.default,
|
filter: server.filter.default,
|
||||||
mask: null,
|
mask: null,
|
||||||
|
@ -335,18 +437,29 @@ export function createStateSlices(server: ServerParams) {
|
||||||
strength: server.strength.default,
|
strength: server.strength.default,
|
||||||
tileOrder: server.tileOrder.default,
|
tileOrder: server.tileOrder.default,
|
||||||
},
|
},
|
||||||
setInpaint(params) {
|
inpaintBrush: {
|
||||||
set((prev) => ({
|
...DEFAULT_BRUSH,
|
||||||
inpaint: {
|
},
|
||||||
...prev.inpaint,
|
inpaintHighres: {
|
||||||
...params,
|
...defaultHighres,
|
||||||
},
|
},
|
||||||
}));
|
inpaintModel: {
|
||||||
|
...defaultModel,
|
||||||
|
},
|
||||||
|
inpaintUpscale: {
|
||||||
|
...defaultUpscale,
|
||||||
|
},
|
||||||
|
outpaint: {
|
||||||
|
enabled: false,
|
||||||
|
left: server.left.default,
|
||||||
|
right: server.right.default,
|
||||||
|
top: server.top.default,
|
||||||
|
bottom: server.bottom.default,
|
||||||
},
|
},
|
||||||
resetInpaint() {
|
resetInpaint() {
|
||||||
set({
|
set({
|
||||||
inpaint: {
|
inpaint: {
|
||||||
...base,
|
...defaultParams,
|
||||||
fillColor: server.fillColor.default,
|
fillColor: server.fillColor.default,
|
||||||
filter: server.filter.default,
|
filter: server.filter.default,
|
||||||
mask: null,
|
mask: null,
|
||||||
|
@ -357,6 +470,54 @@ export function createStateSlices(server: ServerParams) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
setInpaint(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
inpaint: {
|
||||||
|
...prev.inpaint,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setInpaintBrush(brush) {
|
||||||
|
set((prev) => ({
|
||||||
|
inpaintBrush: {
|
||||||
|
...prev.inpaintBrush,
|
||||||
|
...brush,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setInpaintHighres(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
inpaintHighres: {
|
||||||
|
...prev.inpaintHighres,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setInpaintModel(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
inpaintModel: {
|
||||||
|
...prev.inpaintModel,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setInpaintUpscale(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
inpaintUpscale: {
|
||||||
|
...prev.inpaintUpscale,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setOutpaint(pixels) {
|
||||||
|
set((prev) => ({
|
||||||
|
outpaint: {
|
||||||
|
...prev.outpaint,
|
||||||
|
...pixels,
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const createHistorySlice: Slice<HistorySlice> = (set) => ({
|
const createHistorySlice: Slice<HistorySlice> = (set) => ({
|
||||||
|
@ -405,109 +566,59 @@ export function createStateSlices(server: ServerParams) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const createOutpaintSlice: Slice<OutpaintSlice> = (set) => ({
|
|
||||||
outpaint: {
|
|
||||||
enabled: false,
|
|
||||||
left: server.left.default,
|
|
||||||
right: server.right.default,
|
|
||||||
top: server.top.default,
|
|
||||||
bottom: server.bottom.default,
|
|
||||||
},
|
|
||||||
setOutpaint(pixels) {
|
|
||||||
set((prev) => ({
|
|
||||||
outpaint: {
|
|
||||||
...prev.outpaint,
|
|
||||||
...pixels,
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const createBrushSlice: Slice<BrushSlice> = (set) => ({
|
|
||||||
brush: {
|
|
||||||
...DEFAULT_BRUSH,
|
|
||||||
},
|
|
||||||
setBrush(brush) {
|
|
||||||
set((prev) => ({
|
|
||||||
brush: {
|
|
||||||
...prev.brush,
|
|
||||||
...brush,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const createUpscaleSlice: Slice<UpscaleSlice> = (set) => ({
|
const createUpscaleSlice: Slice<UpscaleSlice> = (set) => ({
|
||||||
upscale: {
|
upscale: {
|
||||||
denoise: server.denoise.default,
|
...defaultParams,
|
||||||
enabled: false,
|
|
||||||
faces: false,
|
|
||||||
faceOutscale: server.faceOutscale.default,
|
|
||||||
faceStrength: server.faceStrength.default,
|
|
||||||
outscale: server.outscale.default,
|
|
||||||
scale: server.scale.default,
|
|
||||||
upscaleOrder: server.upscaleOrder.default,
|
|
||||||
},
|
|
||||||
upscaleTab: {
|
|
||||||
negativePrompt: server.negativePrompt.default,
|
|
||||||
prompt: server.prompt.default,
|
|
||||||
source: null,
|
source: null,
|
||||||
},
|
},
|
||||||
setUpscale(upscale) {
|
upscaleHighres: {
|
||||||
set((prev) => ({
|
...defaultHighres,
|
||||||
upscale: {
|
|
||||||
...prev.upscale,
|
|
||||||
...upscale,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
setUpscaleTab(source) {
|
upscaleModel: {
|
||||||
set((prev) => ({
|
...defaultModel,
|
||||||
upscaleTab: {
|
|
||||||
...prev.upscaleTab,
|
|
||||||
...source,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
resetUpscaleTab() {
|
upscaleUpscale: {
|
||||||
|
...defaultUpscale,
|
||||||
|
},
|
||||||
|
resetUpscale() {
|
||||||
set({
|
set({
|
||||||
upscaleTab: {
|
upscale: {
|
||||||
negativePrompt: server.negativePrompt.default,
|
...defaultParams,
|
||||||
prompt: server.prompt.default,
|
|
||||||
source: null,
|
source: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
setUpscale(source) {
|
||||||
|
|
||||||
const createHighresSlice: Slice<HighresSlice> = (set) => ({
|
|
||||||
highres: {
|
|
||||||
enabled: false,
|
|
||||||
highresIterations: server.highresIterations.default,
|
|
||||||
highresMethod: '',
|
|
||||||
highresSteps: server.highresSteps.default,
|
|
||||||
highresScale: server.highresScale.default,
|
|
||||||
highresStrength: server.highresStrength.default,
|
|
||||||
},
|
|
||||||
setHighres(params) {
|
|
||||||
set((prev) => ({
|
set((prev) => ({
|
||||||
highres: {
|
upscale: {
|
||||||
...prev.highres,
|
...prev.upscale,
|
||||||
|
...source,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setUpscaleHighres(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
upscaleHighres: {
|
||||||
|
...prev.upscaleHighres,
|
||||||
...params,
|
...params,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
resetHighres() {
|
setUpscaleModel(params) {
|
||||||
set({
|
set((prev) => ({
|
||||||
highres: {
|
upscaleModel: {
|
||||||
enabled: false,
|
...prev.upscaleModel,
|
||||||
highresIterations: server.highresIterations.default,
|
...defaultModel,
|
||||||
highresMethod: '',
|
|
||||||
highresSteps: server.highresSteps.default,
|
|
||||||
highresScale: server.highresScale.default,
|
|
||||||
highresStrength: server.highresStrength.default,
|
|
||||||
},
|
},
|
||||||
});
|
}));
|
||||||
|
},
|
||||||
|
setUpscaleUpscale(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
upscaleUpscale: {
|
||||||
|
...prev.upscaleUpscale,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -516,13 +627,14 @@ export function createStateSlices(server: ServerParams) {
|
||||||
mask: null,
|
mask: null,
|
||||||
sources: [],
|
sources: [],
|
||||||
},
|
},
|
||||||
setBlend(blend) {
|
blendBrush: {
|
||||||
set((prev) => ({
|
...DEFAULT_BRUSH,
|
||||||
blend: {
|
},
|
||||||
...prev.blend,
|
blendModel: {
|
||||||
...blend,
|
...defaultModel,
|
||||||
},
|
},
|
||||||
}));
|
blendUpscale: {
|
||||||
|
...defaultUpscale,
|
||||||
},
|
},
|
||||||
resetBlend() {
|
resetBlend() {
|
||||||
set({
|
set({
|
||||||
|
@ -532,11 +644,43 @@ export function createStateSlices(server: ServerParams) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
setBlend(blend) {
|
||||||
|
set((prev) => ({
|
||||||
|
blend: {
|
||||||
|
...prev.blend,
|
||||||
|
...blend,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setBlendBrush(brush) {
|
||||||
|
set((prev) => ({
|
||||||
|
blendBrush: {
|
||||||
|
...prev.blendBrush,
|
||||||
|
...brush,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setBlendModel(model) {
|
||||||
|
set((prev) => ({
|
||||||
|
blendModel: {
|
||||||
|
...prev.blendModel,
|
||||||
|
...model,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
setBlendUpscale(params) {
|
||||||
|
set((prev) => ({
|
||||||
|
blendUpscale: {
|
||||||
|
...prev.blendUpscale,
|
||||||
|
...params,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const createDefaultSlice: Slice<DefaultSlice> = (set) => ({
|
const createDefaultSlice: Slice<DefaultSlice> = (set) => ({
|
||||||
defaults: {
|
defaults: {
|
||||||
...base,
|
...defaultParams,
|
||||||
},
|
},
|
||||||
theme: '',
|
theme: '',
|
||||||
setDefaults(params) {
|
setDefaults(params) {
|
||||||
|
@ -554,25 +698,6 @@ export function createStateSlices(server: ServerParams) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const createModelSlice: Slice<ModelSlice> = (set) => ({
|
|
||||||
model: {
|
|
||||||
control: server.control.default,
|
|
||||||
correction: server.correction.default,
|
|
||||||
model: server.model.default,
|
|
||||||
pipeline: server.pipeline.default,
|
|
||||||
platform: server.platform.default,
|
|
||||||
upscaling: server.upscaling.default,
|
|
||||||
},
|
|
||||||
setModel(params) {
|
|
||||||
set((prev) => ({
|
|
||||||
model: {
|
|
||||||
...prev.model,
|
|
||||||
...params,
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const createResetSlice: Slice<ResetSlice> = (set) => ({
|
const createResetSlice: Slice<ResetSlice> = (set) => ({
|
||||||
resetAll() {
|
resetAll() {
|
||||||
set((prev) => {
|
set((prev) => {
|
||||||
|
@ -580,7 +705,7 @@ export function createStateSlices(server: ServerParams) {
|
||||||
next.resetImg2Img();
|
next.resetImg2Img();
|
||||||
next.resetInpaint();
|
next.resetInpaint();
|
||||||
next.resetTxt2Img();
|
next.resetTxt2Img();
|
||||||
next.resetUpscaleTab();
|
next.resetUpscale();
|
||||||
next.resetBlend();
|
next.resetBlend();
|
||||||
return next;
|
return next;
|
||||||
});
|
});
|
||||||
|
@ -620,7 +745,7 @@ export function createStateSlices(server: ServerParams) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||||
const createExtraSlice: Slice<ExtraSlice> = (set) => ({
|
const createModelSlice: Slice<ModelSlice> = (set) => ({
|
||||||
extras: {
|
extras: {
|
||||||
correction: [],
|
correction: [],
|
||||||
diffusion: [],
|
diffusion: [],
|
||||||
|
@ -799,19 +924,15 @@ export function createStateSlices(server: ServerParams) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createBrushSlice,
|
|
||||||
createDefaultSlice,
|
createDefaultSlice,
|
||||||
createHistorySlice,
|
createHistorySlice,
|
||||||
createImg2ImgSlice,
|
createImg2ImgSlice,
|
||||||
createInpaintSlice,
|
createInpaintSlice,
|
||||||
createModelSlice,
|
|
||||||
createOutpaintSlice,
|
|
||||||
createTxt2ImgSlice,
|
createTxt2ImgSlice,
|
||||||
createUpscaleSlice,
|
createUpscaleSlice,
|
||||||
createHighresSlice,
|
|
||||||
createBlendSlice,
|
createBlendSlice,
|
||||||
createResetSlice,
|
createResetSlice,
|
||||||
createExtraSlice,
|
createModelSlice,
|
||||||
createProfileSlice,
|
createProfileSlice,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue