mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Implement a cancel after next iteration button
This commit is contained in:
parent
9eed1919c2
commit
c03d98cf46
5
invokeai/frontend/.gitignore
vendored
5
invokeai/frontend/.gitignore
vendored
@ -25,4 +25,7 @@ dist-ssr
|
|||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
# build stats
|
# build stats
|
||||||
stats.html
|
stats.html
|
||||||
|
|
||||||
|
# Yarn
|
||||||
|
.yarn
|
1
invokeai/frontend/.yarnrc.yml
Normal file
1
invokeai/frontend/.yarnrc.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
nodeLinker: node-modules
|
File diff suppressed because one or more lines are too long
2
invokeai/frontend/dist/index.html
vendored
2
invokeai/frontend/dist/index.html
vendored
@ -5,7 +5,7 @@
|
|||||||
<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-ad762ffd.js"></script>
|
<script type="module" crossorigin src="./assets/index-f007d4c5.js"></script>
|
||||||
<link rel="stylesheet" href="./assets/index-fecb6dd4.css">
|
<link rel="stylesheet" href="./assets/index-fecb6dd4.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
"toggleLoopback": "Toggle Loopback",
|
"toggleLoopback": "Toggle Loopback",
|
||||||
"invoke": "Invoke",
|
"invoke": "Invoke",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
|
"scheduleCancel": "Cancel after current iteration",
|
||||||
|
"cancelScheduled": "Canceling",
|
||||||
"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",
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
"toggleLoopback": "Toggle Loopback",
|
"toggleLoopback": "Toggle Loopback",
|
||||||
"invoke": "Invoke",
|
"invoke": "Invoke",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
|
"scheduleCancel": "Cancel after current iteration",
|
||||||
|
"cancelScheduled": "Canceling",
|
||||||
"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",
|
||||||
|
@ -7,10 +7,12 @@ import IAIIconButton, {
|
|||||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||||
import { SystemState } from 'features/system/store/systemSlice';
|
import { SystemState } from 'features/system/store/systemSlice';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
|
import { Spinner } 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 } from 'react-icons/md';
|
import { MdCancel, MdCancelScheduleSend } from 'react-icons/md';
|
||||||
|
|
||||||
const cancelButtonSelector = createSelector(
|
const cancelButtonSelector = createSelector(
|
||||||
systemSelector,
|
systemSelector,
|
||||||
@ -19,6 +21,8 @@ const cancelButtonSelector = createSelector(
|
|||||||
isProcessing: system.isProcessing,
|
isProcessing: system.isProcessing,
|
||||||
isConnected: system.isConnected,
|
isConnected: system.isConnected,
|
||||||
isCancelable: system.isCancelable,
|
isCancelable: system.isCancelable,
|
||||||
|
currentIteration: system.currentIteration,
|
||||||
|
totalIterations: system.totalIterations,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -31,14 +35,27 @@ const cancelButtonSelector = createSelector(
|
|||||||
export default function CancelButton(
|
export default function CancelButton(
|
||||||
props: Omit<IAIIconButtonProps, 'aria-label'>
|
props: Omit<IAIIconButtonProps, 'aria-label'>
|
||||||
) {
|
) {
|
||||||
const { ...rest } = props;
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { isProcessing, isConnected, isCancelable } =
|
const { ...rest } = props;
|
||||||
useAppSelector(cancelButtonSelector);
|
const {
|
||||||
const handleClickCancel = () => dispatch(cancelProcessing());
|
isProcessing,
|
||||||
|
isConnected,
|
||||||
|
isCancelable,
|
||||||
|
currentIteration,
|
||||||
|
totalIterations,
|
||||||
|
} = useAppSelector(cancelButtonSelector);
|
||||||
|
const [cancelAfterIteration, setCancelAfterIteration] = useState<number>(
|
||||||
|
Number.MAX_SAFE_INTEGER
|
||||||
|
);
|
||||||
|
const handleClickCancel = useCallback(() => {
|
||||||
|
dispatch(cancelProcessing());
|
||||||
|
setCancelAfterIteration(Number.MAX_SAFE_INTEGER);
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const isCancelScheduled = cancelAfterIteration !== Number.MAX_SAFE_INTEGER;
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'shift+x',
|
'shift+x',
|
||||||
() => {
|
() => {
|
||||||
@ -49,15 +66,50 @@ export default function CancelButton(
|
|||||||
[isConnected, isProcessing, isCancelable]
|
[isConnected, isProcessing, isCancelable]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (cancelAfterIteration < currentIteration) {
|
||||||
|
handleClickCancel();
|
||||||
|
}
|
||||||
|
}, [cancelAfterIteration, currentIteration, handleClickCancel]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IAIIconButton
|
<>
|
||||||
icon={<MdCancel />}
|
<IAIIconButton
|
||||||
tooltip={t('parameters:cancel')}
|
icon={<MdCancel />}
|
||||||
aria-label={t('parameters:cancel')}
|
tooltip={t('parameters:cancel')}
|
||||||
isDisabled={!isConnected || !isProcessing || !isCancelable}
|
aria-label={t('parameters:cancel')}
|
||||||
onClick={handleClickCancel}
|
isDisabled={!isConnected || !isProcessing || !isCancelable}
|
||||||
styleClass="cancel-btn"
|
onClick={handleClickCancel}
|
||||||
{...rest}
|
styleClass="cancel-btn"
|
||||||
/>
|
{...rest}
|
||||||
|
/>
|
||||||
|
<IAIIconButton
|
||||||
|
icon={isCancelScheduled ? <Spinner /> : <MdCancelScheduleSend />}
|
||||||
|
tooltip={
|
||||||
|
isCancelScheduled
|
||||||
|
? t('parameters:cancelScheduled')
|
||||||
|
: t('parameters:scheduleCancel')
|
||||||
|
}
|
||||||
|
aria-label={
|
||||||
|
isCancelScheduled
|
||||||
|
? t('parameters:cancelScheduled')
|
||||||
|
: t('parameters:scheduleCancel')
|
||||||
|
}
|
||||||
|
isDisabled={
|
||||||
|
!isConnected ||
|
||||||
|
!isProcessing ||
|
||||||
|
!isCancelable ||
|
||||||
|
currentIteration === totalIterations
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
// If a cancel request has already been made, and the user clicks again before the next iteration has been processed, stop the request.
|
||||||
|
if (isCancelScheduled)
|
||||||
|
setCancelAfterIteration(Number.MAX_SAFE_INTEGER);
|
||||||
|
else setCancelAfterIteration(currentIteration);
|
||||||
|
}}
|
||||||
|
styleClass="cancel-btn"
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user