mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui): split out new workflow dialog logic, use it in list menu, restore new workflow dialog
This commit is contained in:
@@ -27,6 +27,7 @@ import RefreshAfterResetModal from 'features/system/components/SettingsModal/Ref
|
||||
import { configChanged } from 'features/system/store/configSlice';
|
||||
import { selectLanguage } from 'features/system/store/systemSelectors';
|
||||
import { AppContent } from 'features/ui/components/AppContent';
|
||||
import { NewWorkflowConfirmationAlertDialog } from 'features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import i18n from 'i18n';
|
||||
import { size } from 'lodash-es';
|
||||
@@ -107,6 +108,7 @@ const App = ({ config = DEFAULT_CONFIG, studioInitAction }: Props) => {
|
||||
<DynamicPromptsModal />
|
||||
<StylePresetModal />
|
||||
<ClearQueueConfirmationsAlertDialog />
|
||||
<NewWorkflowConfirmationAlertDialog />
|
||||
<RefreshAfterResetModal />
|
||||
<DeleteBoardModal />
|
||||
<GlobalImageHotkeys />
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Flex, IconButton, Spacer, Text, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { ModeToggle } from 'features/nodes/components/sidePanel/ModeToggle';
|
||||
import { nodeEditorReset } from 'features/nodes/store/nodesSlice';
|
||||
import { useWorkflowListMenu } from 'features/nodes/store/workflowListMenu';
|
||||
import { selectWorkflowDescription, selectWorkflowMode, selectWorkflowName } from 'features/nodes/store/workflowSlice';
|
||||
import type { MouseEventHandler } from 'react';
|
||||
import { useNewWorkflow } from 'features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog';
|
||||
import type { MouseEvent } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiXBold } from 'react-icons/pi';
|
||||
import { PiFilePlusBold } from 'react-icons/pi';
|
||||
|
||||
import SaveWorkflowButton from './SaveWorkflowButton';
|
||||
|
||||
@@ -15,18 +14,17 @@ export const ActiveWorkflow = () => {
|
||||
const activeWorkflowName = useAppSelector(selectWorkflowName);
|
||||
const activeWorkflowDescription = useAppSelector(selectWorkflowDescription);
|
||||
const mode = useAppSelector(selectWorkflowMode);
|
||||
const workflowListMenu = useWorkflowListMenu();
|
||||
const newWorkflow = useNewWorkflow();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleNewWorkflow = useCallback<MouseEventHandler<HTMLButtonElement>>(
|
||||
(e) => {
|
||||
const onClickNewWorkflow = useCallback(
|
||||
(e: MouseEvent<HTMLButtonElement>) => {
|
||||
// We need to stop the event from propagating to the parent element, else the click will open the list menu
|
||||
e.stopPropagation();
|
||||
dispatch(nodeEditorReset());
|
||||
workflowListMenu.close();
|
||||
newWorkflow.createWithDialog();
|
||||
},
|
||||
[dispatch, workflowListMenu]
|
||||
[newWorkflow]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -45,16 +43,14 @@ export const ActiveWorkflow = () => {
|
||||
<Spacer />
|
||||
{mode === 'edit' && <SaveWorkflowButton />}
|
||||
<ModeToggle />
|
||||
<Tooltip label={t('nodes.clearWorkflow')}>
|
||||
<IconButton
|
||||
onClick={handleNewWorkflow}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-label={t('nodes.clearWorkflow')}
|
||||
icon={<PiXBold />}
|
||||
colorScheme="error"
|
||||
/>
|
||||
</Tooltip>
|
||||
<IconButton
|
||||
onClick={onClickNewWorkflow}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-label={t('nodes.newWorkflow')}
|
||||
tooltip={t('nodes.newWorkflow')}
|
||||
icon={<PiFilePlusBold />}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
import { ConfirmationAlertDialog, Flex, Text, useDisclosure } from '@invoke-ai/ui-library';
|
||||
import { ConfirmationAlertDialog, Flex, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { buildUseDisclosure } from 'common/hooks/useBoolean';
|
||||
import { nodeEditorReset } from 'features/nodes/store/nodesSlice';
|
||||
import { selectWorkflowIsTouched, workflowModeChanged } from 'features/nodes/store/workflowSlice';
|
||||
import { toast } from 'features/toast/toast';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type Props = {
|
||||
renderButton: (onClick: () => void) => JSX.Element;
|
||||
};
|
||||
const [useDialogState] = buildUseDisclosure(false);
|
||||
|
||||
export const NewWorkflowConfirmationAlertDialog = memo((props: Props) => {
|
||||
export const useNewWorkflow = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const dialog = useDialogState();
|
||||
const isTouched = useAppSelector(selectWorkflowIsTouched);
|
||||
|
||||
const handleNewWorkflow = useCallback(() => {
|
||||
const createImmediate = useCallback(() => {
|
||||
dispatch(nodeEditorReset());
|
||||
dispatch(workflowModeChanged('edit'));
|
||||
|
||||
@@ -26,34 +25,41 @@ export const NewWorkflowConfirmationAlertDialog = memo((props: Props) => {
|
||||
status: 'success',
|
||||
});
|
||||
|
||||
onClose();
|
||||
}, [dispatch, onClose, t]);
|
||||
dialog.close();
|
||||
}, [dialog, dispatch, t]);
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
const createWithDialog = useCallback(() => {
|
||||
if (!isTouched) {
|
||||
handleNewWorkflow();
|
||||
createImmediate();
|
||||
return;
|
||||
}
|
||||
onOpen();
|
||||
}, [handleNewWorkflow, isTouched, onOpen]);
|
||||
dialog.open();
|
||||
}, [dialog, createImmediate, isTouched]);
|
||||
|
||||
return {
|
||||
createImmediate,
|
||||
createWithDialog,
|
||||
} as const;
|
||||
};
|
||||
|
||||
export const NewWorkflowConfirmationAlertDialog = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const dialog = useDialogState();
|
||||
const newWorkflow = useNewWorkflow();
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.renderButton(onClick)}
|
||||
|
||||
<ConfirmationAlertDialog
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
title={t('nodes.newWorkflow')}
|
||||
acceptCallback={handleNewWorkflow}
|
||||
useInert={false}
|
||||
>
|
||||
<Flex flexDir="column" gap={2}>
|
||||
<Text>{t('nodes.newWorkflowDesc')}</Text>
|
||||
<Text variant="subtext">{t('nodes.newWorkflowDesc2')}</Text>
|
||||
</Flex>
|
||||
</ConfirmationAlertDialog>
|
||||
</>
|
||||
<ConfirmationAlertDialog
|
||||
isOpen={dialog.isOpen}
|
||||
onClose={dialog.close}
|
||||
title={t('nodes.newWorkflow')}
|
||||
acceptCallback={newWorkflow.createImmediate}
|
||||
useInert={false}
|
||||
>
|
||||
<Flex flexDir="column" gap={2}>
|
||||
<Text>{t('nodes.newWorkflowDesc')}</Text>
|
||||
<Text variant="subtext">{t('nodes.newWorkflowDesc2')}</Text>
|
||||
</Flex>
|
||||
</ConfirmationAlertDialog>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
import { MenuItem } from '@invoke-ai/ui-library';
|
||||
import { NewWorkflowConfirmationAlertDialog } from 'features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useNewWorkflow } from 'features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiFilePlusBold } from 'react-icons/pi';
|
||||
|
||||
export const NewWorkflowMenuItem = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const newWorkflow = useNewWorkflow();
|
||||
|
||||
const renderButton = useCallback(
|
||||
(onClick: () => void) => (
|
||||
<MenuItem as="button" icon={<PiFilePlusBold />} onClick={onClick}>
|
||||
{t('nodes.newWorkflow')}
|
||||
</MenuItem>
|
||||
),
|
||||
[t]
|
||||
return (
|
||||
<MenuItem as="button" icon={<PiFilePlusBold />} onClick={newWorkflow.createWithDialog}>
|
||||
{t('nodes.newWorkflow')}
|
||||
</MenuItem>
|
||||
);
|
||||
|
||||
return <NewWorkflowConfirmationAlertDialog renderButton={renderButton} />;
|
||||
});
|
||||
|
||||
NewWorkflowMenuItem.displayName = 'NewWorkflowMenuItem';
|
||||
|
||||
Reference in New Issue
Block a user