Change scheduled send to be as part of context for Cancel button

This commit is contained in:
blhook 2023-02-15 10:53:42 -08:00
parent d00571b5a4
commit e683b574d1
18 changed files with 148349 additions and 702 deletions

View File

@ -27,5 +27,11 @@ dist-ssr
# build stats
stats.html
# Yarn
.yarn
# Yarn - https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

File diff suppressed because one or more lines are too long

View 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"

View File

@ -0,0 +1 @@
yarnPath: .yarn/releases/yarn-1.22.19.cjs

View File

@ -7,7 +7,7 @@ The UI is in `invokeai/frontend`.
Install [node](https://nodejs.org/en/download/) (includes npm) and
[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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,8 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>InvokeAI - A Stable Diffusion Toolkit</title>
<link rel="shortcut icon" type="icon" href="./assets/favicon-0d253ced.ico" />
<script type="module" crossorigin src="./assets/index-f007d4c5.js"></script>
<link rel="stylesheet" href="./assets/index-fecb6dd4.css">
<script type="module" crossorigin src="./assets/index-285d1fa2.js"></script>
<link rel="stylesheet" href="./assets/index-c53bb2f3.css">
</head>
<body>

View File

@ -42,7 +42,13 @@
"img2imgStrength": "Image To Image Strength",
"toggleLoopback": "Toggle Loopback",
"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)",
"sendTo": "Send to",
"sendToImg2Img": "Send to Image to Image",

View File

@ -43,9 +43,13 @@
"img2imgStrength": "Image To Image Strength",
"toggleLoopback": "Toggle Loopback",
"invoke": "Invoke",
"cancel": "Cancel",
"scheduleCancel": "Cancel after current iteration",
"cancelScheduled": "Canceling",
"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)",
"negativePrompts": "Negative Prompts",
"sendTo": "Send to",

View File

@ -42,7 +42,13 @@
"img2imgStrength": "Image To Image Strength",
"toggleLoopback": "Toggle Loopback",
"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)",
"sendTo": "Send to",
"sendToImg2Img": "Send to Image to Image",

View File

@ -43,9 +43,13 @@
"img2imgStrength": "Image To Image Strength",
"toggleLoopback": "Toggle Loopback",
"invoke": "Invoke",
"cancel": "Cancel",
"scheduleCancel": "Cancel after current iteration",
"cancelScheduled": "Canceling",
"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)",
"negativePrompts": "Negative Prompts",
"sendTo": "Send to",

View File

@ -5,14 +5,30 @@ import IAIIconButton, {
IAIIconButtonProps,
} from 'common/components/IAIIconButton';
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 { useState, useEffect, useCallback } from 'react';
import { Spinner } from '@chakra-ui/react';
import { useEffect, useCallback } from 'react';
import {
Menu,
MenuButton,
MenuList,
MenuItem,
ButtonSpinner,
ButtonGroup,
} from '@chakra-ui/react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
import { MdCancel, MdCancelScheduleSend } from 'react-icons/md';
import {
MdCancel,
MdCancelScheduleSend,
MdArrowDropDown,
MdArrowDropUp,
} from 'react-icons/md';
const cancelButtonSelector = createSelector(
systemSelector,
@ -23,6 +39,8 @@ const cancelButtonSelector = createSelector(
isCancelable: system.isCancelable,
currentIteration: system.currentIteration,
totalIterations: system.totalIterations,
cancelType: system.cancelOptions.cancelType,
cancelAfter: system.cancelOptions.cancelAfter,
};
},
{
@ -43,18 +61,17 @@ export default function CancelButton(
isCancelable,
currentIteration,
totalIterations,
cancelType,
cancelAfter,
} = useAppSelector(cancelButtonSelector);
const [cancelAfterIteration, setCancelAfterIteration] = useState<number>(
Number.MAX_SAFE_INTEGER
);
const handleClickCancel = useCallback(() => {
dispatch(cancelProcessing());
setCancelAfterIteration(Number.MAX_SAFE_INTEGER);
dispatch(setCancelAfter(null));
}, [dispatch]);
const { t } = useTranslation();
const isCancelScheduled = cancelAfterIteration !== Number.MAX_SAFE_INTEGER;
const isCancelScheduled = cancelAfter === null ? false : true;
useHotkeys(
'shift+x',
@ -67,49 +84,74 @@ export default function CancelButton(
);
useEffect(() => {
if (cancelAfterIteration < currentIteration) {
if (cancelAfter !== null && cancelAfter < currentIteration) {
handleClickCancel();
}
}, [cancelAfterIteration, currentIteration, handleClickCancel]);
}, [cancelAfter, currentIteration, handleClickCancel]);
return (
<>
<IAIIconButton
icon={<MdCancel />}
tooltip={t('parameters:cancel')}
aria-label={t('parameters:cancel')}
isDisabled={!isConnected || !isProcessing || !isCancelable}
onClick={handleClickCancel}
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}
/>
</>
<ButtonGroup isAttached variant="link">
{cancelType === 'immediate' ? (
<IAIIconButton
icon={<MdCancel />}
tooltip={t('parameters:cancel.immediate')}
aria-label={t('parameters:cancel.immediate')}
isDisabled={!isConnected || !isProcessing || !isCancelable}
onClick={handleClickCancel}
className="cancel-btn"
{...rest}
/>
) : (
<IAIIconButton
icon={
isCancelScheduled ? <ButtonSpinner /> : <MdCancelScheduleSend />
}
tooltip={
isCancelScheduled
? t('parameters:cancel.isScheduled')
: t('parameters:cancel.schedule')
}
aria-label={
isCancelScheduled
? t('parameters:cancel.isScheduled')
: t('parameters:cancel.schedule')
}
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) dispatch(setCancelAfter(null));
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>
);
}

View File

@ -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 {
&[data-as-checkbox='true'] {
background-color: var(--btn-btn-base-color);

View File

@ -23,6 +23,8 @@ export type ReadinessPayload = {
export type InProgressImageType = 'none' | 'full-res' | 'latents';
export type CancelType = 'immediate' | 'scheduled';
export interface SystemState
extends InvokeAI.SystemStatus,
InvokeAI.SystemConfig {
@ -50,6 +52,10 @@ export interface SystemState
searchFolder: string | null;
foundModels: InvokeAI.FoundModel[] | null;
openModel: string | null;
cancelOptions: {
cancelType: CancelType;
cancelAfter: number | null;
};
}
const initialSystemState: SystemState = {
@ -88,6 +94,10 @@ const initialSystemState: SystemState = {
searchFolder: null,
foundModels: null,
openModel: null,
cancelOptions: {
cancelType: 'immediate',
cancelAfter: null,
},
};
export const systemSlice = createSlice({
@ -243,6 +253,12 @@ export const systemSlice = createSlice({
setOpenModel: (state, action: PayloadAction<string | null>) => {
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,
setFoundModels,
setOpenModel,
setCancelType,
setCancelAfter,
} = systemSlice.actions;
export default systemSlice.reducer;

File diff suppressed because one or more lines are too long