feat(ui): split out new workflow dialog logic, use it in list menu, restore new workflow dialog

This commit is contained in:
psychedelicious
2024-10-10 12:10:20 +10:00
parent 849b9e8d86
commit c494e0642a
4 changed files with 62 additions and 62 deletions

View File

@@ -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 />

View File

@@ -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>
);
};

View File

@@ -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>
);
});

View File

@@ -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';