mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Change scheduled send to be as part of context for Cancel button
This commit is contained in:
parent
d00571b5a4
commit
e683b574d1
10
invokeai/frontend/.gitignore
vendored
10
invokeai/frontend/.gitignore
vendored
@ -27,5 +27,11 @@ dist-ssr
|
|||||||
# build stats
|
# build stats
|
||||||
stats.html
|
stats.html
|
||||||
|
|
||||||
# Yarn
|
# Yarn - https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
|
||||||
.yarn
|
.pnp.*
|
||||||
|
.yarn/*
|
||||||
|
!.yarn/patches
|
||||||
|
!.yarn/plugins
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/sdks
|
||||||
|
!.yarn/versions
|
147529
invokeai/frontend/.yarn/releases/yarn-1.22.19.cjs
vendored
Normal file
147529
invokeai/frontend/.yarn/releases/yarn-1.22.19.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
5
invokeai/frontend/.yarnrc
Normal file
5
invokeai/frontend/.yarnrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
yarn-path ".yarn/releases/yarn-1.22.19.cjs"
|
1
invokeai/frontend/.yarnrc.yml
Normal file
1
invokeai/frontend/.yarnrc.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
yarnPath: .yarn/releases/yarn-1.22.19.cjs
|
@ -7,7 +7,7 @@ The UI is in `invokeai/frontend`.
|
|||||||
Install [node](https://nodejs.org/en/download/) (includes npm) and
|
Install [node](https://nodejs.org/en/download/) (includes npm) and
|
||||||
[yarn](https://yarnpkg.com/getting-started/install).
|
[yarn](https://yarnpkg.com/getting-started/install).
|
||||||
|
|
||||||
From `invokeai/frontend/` run `yarn install` to get everything set up.
|
From `invokeai/frontend/` run `yarn install --immutable` to get everything set up.
|
||||||
|
|
||||||
## Dev
|
## Dev
|
||||||
|
|
||||||
|
638
invokeai/frontend/dist/assets/index-285d1fa2.js
vendored
Normal file
638
invokeai/frontend/dist/assets/index-285d1fa2.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
invokeai/frontend/dist/assets/index-c53bb2f3.css
vendored
Normal file
1
invokeai/frontend/dist/assets/index-c53bb2f3.css
vendored
Normal file
File diff suppressed because one or more lines are too long
638
invokeai/frontend/dist/assets/index-f007d4c5.js
vendored
638
invokeai/frontend/dist/assets/index-f007d4c5.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
invokeai/frontend/dist/index.html
vendored
4
invokeai/frontend/dist/index.html
vendored
@ -5,8 +5,8 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>InvokeAI - A Stable Diffusion Toolkit</title>
|
<title>InvokeAI - A Stable Diffusion Toolkit</title>
|
||||||
<link rel="shortcut icon" type="icon" href="./assets/favicon-0d253ced.ico" />
|
<link rel="shortcut icon" type="icon" href="./assets/favicon-0d253ced.ico" />
|
||||||
<script type="module" crossorigin src="./assets/index-f007d4c5.js"></script>
|
<script type="module" crossorigin src="./assets/index-285d1fa2.js"></script>
|
||||||
<link rel="stylesheet" href="./assets/index-fecb6dd4.css">
|
<link rel="stylesheet" href="./assets/index-c53bb2f3.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -42,7 +42,13 @@
|
|||||||
"img2imgStrength": "Image To Image Strength",
|
"img2imgStrength": "Image To Image Strength",
|
||||||
"toggleLoopback": "Toggle Loopback",
|
"toggleLoopback": "Toggle Loopback",
|
||||||
"invoke": "Invoke",
|
"invoke": "Invoke",
|
||||||
"cancel": "Cancel",
|
"cancel":
|
||||||
|
{
|
||||||
|
"immediate": "Cancel immediately",
|
||||||
|
"schedule": "Cancel after current iteration",
|
||||||
|
"isScheduled": "Canceling",
|
||||||
|
"setType": "Set cancel type"
|
||||||
|
},
|
||||||
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
|
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
|
||||||
"sendTo": "Send to",
|
"sendTo": "Send to",
|
||||||
"sendToImg2Img": "Send to Image to Image",
|
"sendToImg2Img": "Send to Image to Image",
|
||||||
|
@ -43,9 +43,13 @@
|
|||||||
"img2imgStrength": "Image To Image Strength",
|
"img2imgStrength": "Image To Image Strength",
|
||||||
"toggleLoopback": "Toggle Loopback",
|
"toggleLoopback": "Toggle Loopback",
|
||||||
"invoke": "Invoke",
|
"invoke": "Invoke",
|
||||||
"cancel": "Cancel",
|
"cancel":
|
||||||
"scheduleCancel": "Cancel after current iteration",
|
{
|
||||||
"cancelScheduled": "Canceling",
|
"immediate": "Cancel immediately",
|
||||||
|
"schedule": "Cancel after current iteration",
|
||||||
|
"isScheduled": "Canceling",
|
||||||
|
"setType": "Set cancel type"
|
||||||
|
},
|
||||||
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
|
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
|
||||||
"negativePrompts": "Negative Prompts",
|
"negativePrompts": "Negative Prompts",
|
||||||
"sendTo": "Send to",
|
"sendTo": "Send to",
|
||||||
|
@ -42,7 +42,13 @@
|
|||||||
"img2imgStrength": "Image To Image Strength",
|
"img2imgStrength": "Image To Image Strength",
|
||||||
"toggleLoopback": "Toggle Loopback",
|
"toggleLoopback": "Toggle Loopback",
|
||||||
"invoke": "Invoke",
|
"invoke": "Invoke",
|
||||||
"cancel": "Cancel",
|
"cancel":
|
||||||
|
{
|
||||||
|
"immediate": "Cancel immediately",
|
||||||
|
"schedule": "Cancel after current iteration",
|
||||||
|
"isScheduled": "Canceling",
|
||||||
|
"setType": "Set cancel type"
|
||||||
|
},
|
||||||
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
|
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
|
||||||
"sendTo": "Send to",
|
"sendTo": "Send to",
|
||||||
"sendToImg2Img": "Send to Image to Image",
|
"sendToImg2Img": "Send to Image to Image",
|
||||||
|
@ -43,9 +43,13 @@
|
|||||||
"img2imgStrength": "Image To Image Strength",
|
"img2imgStrength": "Image To Image Strength",
|
||||||
"toggleLoopback": "Toggle Loopback",
|
"toggleLoopback": "Toggle Loopback",
|
||||||
"invoke": "Invoke",
|
"invoke": "Invoke",
|
||||||
"cancel": "Cancel",
|
"cancel":
|
||||||
"scheduleCancel": "Cancel after current iteration",
|
{
|
||||||
"cancelScheduled": "Canceling",
|
"immediate": "Cancel immediately",
|
||||||
|
"schedule": "Cancel after current iteration",
|
||||||
|
"isScheduled": "Canceling",
|
||||||
|
"setType": "Set cancel type"
|
||||||
|
},
|
||||||
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
|
"promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)",
|
||||||
"negativePrompts": "Negative Prompts",
|
"negativePrompts": "Negative Prompts",
|
||||||
"sendTo": "Send to",
|
"sendTo": "Send to",
|
||||||
|
@ -5,14 +5,30 @@ import IAIIconButton, {
|
|||||||
IAIIconButtonProps,
|
IAIIconButtonProps,
|
||||||
} from 'common/components/IAIIconButton';
|
} from 'common/components/IAIIconButton';
|
||||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||||
import { SystemState } from 'features/system/store/systemSlice';
|
import {
|
||||||
|
SystemState,
|
||||||
|
setCancelAfter,
|
||||||
|
setCancelType,
|
||||||
|
} from 'features/system/store/systemSlice';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useEffect, useCallback } from 'react';
|
||||||
import { Spinner } from '@chakra-ui/react';
|
import {
|
||||||
|
Menu,
|
||||||
|
MenuButton,
|
||||||
|
MenuList,
|
||||||
|
MenuItem,
|
||||||
|
ButtonSpinner,
|
||||||
|
ButtonGroup,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { MdCancel, MdCancelScheduleSend } from 'react-icons/md';
|
import {
|
||||||
|
MdCancel,
|
||||||
|
MdCancelScheduleSend,
|
||||||
|
MdArrowDropDown,
|
||||||
|
MdArrowDropUp,
|
||||||
|
} from 'react-icons/md';
|
||||||
|
|
||||||
const cancelButtonSelector = createSelector(
|
const cancelButtonSelector = createSelector(
|
||||||
systemSelector,
|
systemSelector,
|
||||||
@ -23,6 +39,8 @@ const cancelButtonSelector = createSelector(
|
|||||||
isCancelable: system.isCancelable,
|
isCancelable: system.isCancelable,
|
||||||
currentIteration: system.currentIteration,
|
currentIteration: system.currentIteration,
|
||||||
totalIterations: system.totalIterations,
|
totalIterations: system.totalIterations,
|
||||||
|
cancelType: system.cancelOptions.cancelType,
|
||||||
|
cancelAfter: system.cancelOptions.cancelAfter,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -43,18 +61,17 @@ export default function CancelButton(
|
|||||||
isCancelable,
|
isCancelable,
|
||||||
currentIteration,
|
currentIteration,
|
||||||
totalIterations,
|
totalIterations,
|
||||||
|
cancelType,
|
||||||
|
cancelAfter,
|
||||||
} = useAppSelector(cancelButtonSelector);
|
} = useAppSelector(cancelButtonSelector);
|
||||||
const [cancelAfterIteration, setCancelAfterIteration] = useState<number>(
|
|
||||||
Number.MAX_SAFE_INTEGER
|
|
||||||
);
|
|
||||||
const handleClickCancel = useCallback(() => {
|
const handleClickCancel = useCallback(() => {
|
||||||
dispatch(cancelProcessing());
|
dispatch(cancelProcessing());
|
||||||
setCancelAfterIteration(Number.MAX_SAFE_INTEGER);
|
dispatch(setCancelAfter(null));
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const isCancelScheduled = cancelAfterIteration !== Number.MAX_SAFE_INTEGER;
|
const isCancelScheduled = cancelAfter === null ? false : true;
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'shift+x',
|
'shift+x',
|
||||||
@ -67,49 +84,74 @@ export default function CancelButton(
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cancelAfterIteration < currentIteration) {
|
if (cancelAfter !== null && cancelAfter < currentIteration) {
|
||||||
handleClickCancel();
|
handleClickCancel();
|
||||||
}
|
}
|
||||||
}, [cancelAfterIteration, currentIteration, handleClickCancel]);
|
}, [cancelAfter, currentIteration, handleClickCancel]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ButtonGroup isAttached variant="link">
|
||||||
<IAIIconButton
|
{cancelType === 'immediate' ? (
|
||||||
icon={<MdCancel />}
|
<IAIIconButton
|
||||||
tooltip={t('parameters:cancel')}
|
icon={<MdCancel />}
|
||||||
aria-label={t('parameters:cancel')}
|
tooltip={t('parameters:cancel.immediate')}
|
||||||
isDisabled={!isConnected || !isProcessing || !isCancelable}
|
aria-label={t('parameters:cancel.immediate')}
|
||||||
onClick={handleClickCancel}
|
isDisabled={!isConnected || !isProcessing || !isCancelable}
|
||||||
styleClass="cancel-btn"
|
onClick={handleClickCancel}
|
||||||
{...rest}
|
className="cancel-btn"
|
||||||
/>
|
{...rest}
|
||||||
<IAIIconButton
|
/>
|
||||||
icon={isCancelScheduled ? <Spinner /> : <MdCancelScheduleSend />}
|
) : (
|
||||||
tooltip={
|
<IAIIconButton
|
||||||
isCancelScheduled
|
icon={
|
||||||
? t('parameters:cancelScheduled')
|
isCancelScheduled ? <ButtonSpinner /> : <MdCancelScheduleSend />
|
||||||
: t('parameters:scheduleCancel')
|
}
|
||||||
}
|
tooltip={
|
||||||
aria-label={
|
isCancelScheduled
|
||||||
isCancelScheduled
|
? t('parameters:cancel.isScheduled')
|
||||||
? t('parameters:cancelScheduled')
|
: t('parameters:cancel.schedule')
|
||||||
: t('parameters:scheduleCancel')
|
}
|
||||||
}
|
aria-label={
|
||||||
isDisabled={
|
isCancelScheduled
|
||||||
!isConnected ||
|
? t('parameters:cancel.isScheduled')
|
||||||
!isProcessing ||
|
: t('parameters:cancel.schedule')
|
||||||
!isCancelable ||
|
}
|
||||||
currentIteration === totalIterations
|
isDisabled={
|
||||||
}
|
!isConnected ||
|
||||||
onClick={() => {
|
!isProcessing ||
|
||||||
// If a cancel request has already been made, and the user clicks again before the next iteration has been processed, stop the request.
|
!isCancelable ||
|
||||||
if (isCancelScheduled)
|
currentIteration === totalIterations
|
||||||
setCancelAfterIteration(Number.MAX_SAFE_INTEGER);
|
}
|
||||||
else setCancelAfterIteration(currentIteration);
|
onClick={() => {
|
||||||
}}
|
// If a cancel request has already been made, and the user clicks again before the next iteration has been processed, stop the request.
|
||||||
styleClass="cancel-btn"
|
if (isCancelScheduled) dispatch(setCancelAfter(null));
|
||||||
{...rest}
|
else dispatch(setCancelAfter(currentIteration));
|
||||||
/>
|
}}
|
||||||
</>
|
className="cancel-btn"
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Menu>
|
||||||
|
{({ isOpen }) => (
|
||||||
|
<>
|
||||||
|
<MenuButton
|
||||||
|
as={IAIIconButton}
|
||||||
|
icon={isOpen ? <MdArrowDropUp /> : <MdArrowDropDown />}
|
||||||
|
className="cancel-options-btn"
|
||||||
|
tooltip={t('parameters:cancel.setType')}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
<MenuList className="cancel-options-btn-context-menu">
|
||||||
|
<MenuItem onClick={() => dispatch(setCancelType('immediate'))}>
|
||||||
|
{t('parameters:cancel.immediate')}
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={() => dispatch(setCancelType('scheduled'))}>
|
||||||
|
{t('parameters:cancel.schedule')}
|
||||||
|
</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Menu>
|
||||||
|
</ButtonGroup>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,32 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cancel-options-btn {
|
||||||
|
@include Button(
|
||||||
|
$btn-color: var(--destructive-color),
|
||||||
|
$btn-color-hover: var(--destructive-color-hover),
|
||||||
|
$btn-width: 1rem,
|
||||||
|
);
|
||||||
|
border-color: var(--background-color-secondary);
|
||||||
|
border-left-width: 0.05rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-options-btn-context-menu {
|
||||||
|
z-index: 15;
|
||||||
|
background-color: var(--background-color-secondary);
|
||||||
|
color: var(--text-color-secondary);
|
||||||
|
|
||||||
|
[role='menuitem'] {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-color-secondary);
|
||||||
|
background-color: var(--background-color-secondary);
|
||||||
|
&:focus {
|
||||||
|
color: var(--text-color);
|
||||||
|
background-color: var(--border-color-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.loopback-btn {
|
.loopback-btn {
|
||||||
&[data-as-checkbox='true'] {
|
&[data-as-checkbox='true'] {
|
||||||
background-color: var(--btn-btn-base-color);
|
background-color: var(--btn-btn-base-color);
|
||||||
|
@ -23,6 +23,8 @@ export type ReadinessPayload = {
|
|||||||
|
|
||||||
export type InProgressImageType = 'none' | 'full-res' | 'latents';
|
export type InProgressImageType = 'none' | 'full-res' | 'latents';
|
||||||
|
|
||||||
|
export type CancelType = 'immediate' | 'scheduled';
|
||||||
|
|
||||||
export interface SystemState
|
export interface SystemState
|
||||||
extends InvokeAI.SystemStatus,
|
extends InvokeAI.SystemStatus,
|
||||||
InvokeAI.SystemConfig {
|
InvokeAI.SystemConfig {
|
||||||
@ -50,6 +52,10 @@ export interface SystemState
|
|||||||
searchFolder: string | null;
|
searchFolder: string | null;
|
||||||
foundModels: InvokeAI.FoundModel[] | null;
|
foundModels: InvokeAI.FoundModel[] | null;
|
||||||
openModel: string | null;
|
openModel: string | null;
|
||||||
|
cancelOptions: {
|
||||||
|
cancelType: CancelType;
|
||||||
|
cancelAfter: number | null;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialSystemState: SystemState = {
|
const initialSystemState: SystemState = {
|
||||||
@ -88,6 +94,10 @@ const initialSystemState: SystemState = {
|
|||||||
searchFolder: null,
|
searchFolder: null,
|
||||||
foundModels: null,
|
foundModels: null,
|
||||||
openModel: null,
|
openModel: null,
|
||||||
|
cancelOptions: {
|
||||||
|
cancelType: 'immediate',
|
||||||
|
cancelAfter: null,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const systemSlice = createSlice({
|
export const systemSlice = createSlice({
|
||||||
@ -243,6 +253,12 @@ export const systemSlice = createSlice({
|
|||||||
setOpenModel: (state, action: PayloadAction<string | null>) => {
|
setOpenModel: (state, action: PayloadAction<string | null>) => {
|
||||||
state.openModel = action.payload;
|
state.openModel = action.payload;
|
||||||
},
|
},
|
||||||
|
setCancelType: (state, action: PayloadAction<CancelType>) => {
|
||||||
|
state.cancelOptions.cancelType = action.payload;
|
||||||
|
},
|
||||||
|
setCancelAfter: (state, action: PayloadAction<number | null>) => {
|
||||||
|
state.cancelOptions.cancelAfter = action.payload;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -274,6 +290,8 @@ export const {
|
|||||||
setSearchFolder,
|
setSearchFolder,
|
||||||
setFoundModels,
|
setFoundModels,
|
||||||
setOpenModel,
|
setOpenModel,
|
||||||
|
setCancelType,
|
||||||
|
setCancelAfter,
|
||||||
} = systemSlice.actions;
|
} = systemSlice.actions;
|
||||||
|
|
||||||
export default systemSlice.reducer;
|
export default systemSlice.reducer;
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user