From c494e0642aa78c2b7bc074fefdc730a9705ecb75 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:10:20 +1000 Subject: [PATCH] feat(ui): split out new workflow dialog logic, use it in list menu, restore new workflow dialog --- .../frontend/web/src/app/components/App.tsx | 2 + .../WorkflowListMenu/ActiveWorkflow.tsx | 40 ++++++------ .../NewWorkflowConfirmationAlertDialog.tsx | 64 ++++++++++--------- .../NewWorkflowMenuItem.tsx | 18 ++---- 4 files changed, 62 insertions(+), 62 deletions(-) diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index b18fe8c20e..d2d37108f5 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -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) => { + diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/ActiveWorkflow.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/ActiveWorkflow.tsx index 01e258cd05..e6e7a4c0a4 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/ActiveWorkflow.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/ActiveWorkflow.tsx @@ -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>( - (e) => { + const onClickNewWorkflow = useCallback( + (e: MouseEvent) => { + // 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 = () => { {mode === 'edit' && } - - } - colorScheme="error" - /> - + } + /> ); }; diff --git a/invokeai/frontend/web/src/features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog.tsx b/invokeai/frontend/web/src/features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog.tsx index c0b5fee85b..a9a1033169 100644 --- a/invokeai/frontend/web/src/features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog.tsx +++ b/invokeai/frontend/web/src/features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog.tsx @@ -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)} - - - - {t('nodes.newWorkflowDesc')} - {t('nodes.newWorkflowDesc2')} - - - + + + {t('nodes.newWorkflowDesc')} + {t('nodes.newWorkflowDesc2')} + + ); }); diff --git a/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem.tsx b/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem.tsx index 6c5baa584f..2225b8c302 100644 --- a/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem.tsx +++ b/invokeai/frontend/web/src/features/workflowLibrary/components/WorkflowLibraryMenu/NewWorkflowMenuItem.tsx @@ -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) => ( - } onClick={onClick}> - {t('nodes.newWorkflow')} - - ), - [t] + return ( + } onClick={newWorkflow.createWithDialog}> + {t('nodes.newWorkflow')} + ); - - return ; }); NewWorkflowMenuItem.displayName = 'NewWorkflowMenuItem';