mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): use singleton for clear q confirm dialog
This commit is contained in:
parent
d0464330f7
commit
3af577b210
@ -14,6 +14,7 @@ import ChangeBoardModal from 'features/changeBoardModal/components/ChangeBoardMo
|
|||||||
import DeleteImageModal from 'features/deleteImageModal/components/DeleteImageModal';
|
import DeleteImageModal from 'features/deleteImageModal/components/DeleteImageModal';
|
||||||
import { DynamicPromptsModal } from 'features/dynamicPrompts/components/DynamicPromptsPreviewModal';
|
import { DynamicPromptsModal } from 'features/dynamicPrompts/components/DynamicPromptsPreviewModal';
|
||||||
import { useStarterModelsToast } from 'features/modelManagerV2/hooks/useStarterModelsToast';
|
import { useStarterModelsToast } from 'features/modelManagerV2/hooks/useStarterModelsToast';
|
||||||
|
import { ClearQueueConfirmationsAlertDialog } from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
||||||
import { StylePresetModal } from 'features/stylePresets/components/StylePresetForm/StylePresetModal';
|
import { StylePresetModal } from 'features/stylePresets/components/StylePresetForm/StylePresetModal';
|
||||||
import { configChanged } from 'features/system/store/configSlice';
|
import { configChanged } from 'features/system/store/configSlice';
|
||||||
import { languageSelector } from 'features/system/store/systemSelectors';
|
import { languageSelector } from 'features/system/store/systemSelectors';
|
||||||
@ -118,6 +119,7 @@ const App = ({ config = DEFAULT_CONFIG, selectedImage, selectedWorkflowId, desti
|
|||||||
<ChangeBoardModal />
|
<ChangeBoardModal />
|
||||||
<DynamicPromptsModal />
|
<DynamicPromptsModal />
|
||||||
<StylePresetModal />
|
<StylePresetModal />
|
||||||
|
<ClearQueueConfirmationsAlertDialog />
|
||||||
<PreselectedImage selectedImage={selectedImage} />
|
<PreselectedImage selectedImage={selectedImage} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import type { WritableAtom } from 'nanostores';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
export const useBoolean = (initialValue: boolean) => {
|
export const useBoolean = (initialValue: boolean) => {
|
||||||
@ -19,3 +20,33 @@ export const useBoolean = (initialValue: boolean) => {
|
|||||||
|
|
||||||
return api;
|
return api;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const buildUseBoolean = ($boolean: WritableAtom<boolean>) => {
|
||||||
|
return () => {
|
||||||
|
const setTrue = useCallback(() => {
|
||||||
|
$boolean.set(true);
|
||||||
|
}, []);
|
||||||
|
const setFalse = useCallback(() => {
|
||||||
|
$boolean.set(false);
|
||||||
|
}, []);
|
||||||
|
const set = useCallback((value: boolean) => {
|
||||||
|
$boolean.set(value);
|
||||||
|
}, []);
|
||||||
|
const toggle = useCallback(() => {
|
||||||
|
$boolean.set(!$boolean.get());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const api = useMemo(
|
||||||
|
() => ({
|
||||||
|
setTrue,
|
||||||
|
setFalse,
|
||||||
|
set,
|
||||||
|
toggle,
|
||||||
|
$boolean,
|
||||||
|
}),
|
||||||
|
[set, setFalse, setTrue, toggle]
|
||||||
|
);
|
||||||
|
|
||||||
|
return api;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { ButtonProps } from '@invoke-ai/ui-library';
|
import type { ButtonProps } from '@invoke-ai/ui-library';
|
||||||
import { Button, useDisclosure } from '@invoke-ai/ui-library';
|
import { Button } from '@invoke-ai/ui-library';
|
||||||
import ClearQueueConfirmationAlertDialog from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
import { useClearQueueConfirmationAlertDialog } from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
||||||
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -10,7 +10,7 @@ type Props = ButtonProps;
|
|||||||
|
|
||||||
const ClearQueueButton = (props: Props) => {
|
const ClearQueueButton = (props: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const disclosure = useDisclosure();
|
const dialogState = useClearQueueConfirmationAlertDialog();
|
||||||
const { isLoading, isDisabled } = useClearQueue();
|
const { isLoading, isDisabled } = useClearQueue();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -21,13 +21,12 @@ const ClearQueueButton = (props: Props) => {
|
|||||||
tooltip={t('queue.clearTooltip')}
|
tooltip={t('queue.clearTooltip')}
|
||||||
leftIcon={<PiTrashSimpleFill />}
|
leftIcon={<PiTrashSimpleFill />}
|
||||||
colorScheme="error"
|
colorScheme="error"
|
||||||
onClick={disclosure.onOpen}
|
onClick={dialogState.setTrue}
|
||||||
data-testid={t('queue.clear')}
|
data-testid={t('queue.clear')}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{t('queue.clear')}
|
{t('queue.clear')}
|
||||||
</Button>
|
</Button>
|
||||||
<ClearQueueConfirmationAlertDialog disclosure={disclosure} />
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,21 +1,24 @@
|
|||||||
import type { UseDisclosureReturn } from '@invoke-ai/ui-library';
|
|
||||||
import { ConfirmationAlertDialog, Text } from '@invoke-ai/ui-library';
|
import { ConfirmationAlertDialog, Text } from '@invoke-ai/ui-library';
|
||||||
|
import { useStore } from '@nanostores/react';
|
||||||
|
import { buildUseBoolean } from 'common/hooks/useBoolean';
|
||||||
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
||||||
|
import { atom } from 'nanostores';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
type Props = {
|
const $boolean = atom(false);
|
||||||
disclosure: UseDisclosureReturn;
|
export const useClearQueueConfirmationAlertDialog = buildUseBoolean($boolean);
|
||||||
};
|
|
||||||
|
|
||||||
const ClearQueueButton = ({ disclosure }: Props) => {
|
export const ClearQueueConfirmationsAlertDialog = memo(() => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const dialogState = useClearQueueConfirmationAlertDialog();
|
||||||
|
const isOpen = useStore(dialogState.$boolean);
|
||||||
const { clearQueue } = useClearQueue();
|
const { clearQueue } = useClearQueue();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfirmationAlertDialog
|
<ConfirmationAlertDialog
|
||||||
isOpen={disclosure.isOpen}
|
isOpen={isOpen}
|
||||||
onClose={disclosure.onClose}
|
onClose={dialogState.setFalse}
|
||||||
title={t('queue.clearTooltip')}
|
title={t('queue.clearTooltip')}
|
||||||
acceptCallback={clearQueue}
|
acceptCallback={clearQueue}
|
||||||
acceptButtonText={t('queue.clear')}
|
acceptButtonText={t('queue.clear')}
|
||||||
@ -25,6 +28,6 @@ const ClearQueueButton = ({ disclosure }: Props) => {
|
|||||||
<Text>{t('queue.clearQueueAlertDialog2')}</Text>
|
<Text>{t('queue.clearQueueAlertDialog2')}</Text>
|
||||||
</ConfirmationAlertDialog>
|
</ConfirmationAlertDialog>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default memo(ClearQueueButton);
|
ClearQueueConfirmationsAlertDialog.displayName = 'ClearQueueConfirmationsAlertDialog';
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
import type { IconButtonProps } from '@invoke-ai/ui-library';
|
import type { IconButtonProps } from '@invoke-ai/ui-library';
|
||||||
import { IconButton, useDisclosure, useShiftModifier } from '@invoke-ai/ui-library';
|
import { IconButton, useShiftModifier } from '@invoke-ai/ui-library';
|
||||||
import ClearQueueConfirmationAlertDialog from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
import { useClearQueueConfirmationAlertDialog } from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
||||||
import { useCancelCurrentQueueItem } from 'features/queue/hooks/useCancelCurrentQueueItem';
|
import { useCancelCurrentQueueItem } from 'features/queue/hooks/useCancelCurrentQueueItem';
|
||||||
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
||||||
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiTrashSimpleBold, PiXBold } from 'react-icons/pi';
|
import { PiTrashSimpleBold, PiXBold } from 'react-icons/pi';
|
||||||
|
|
||||||
type ClearQueueButtonProps = Omit<IconButtonProps, 'aria-label'>;
|
type ClearQueueButtonProps = Omit<IconButtonProps, 'aria-label'>;
|
||||||
|
|
||||||
type ClearQueueIconButtonProps = ClearQueueButtonProps & {
|
export const ClearAllQueueIconButton = memo((props: ClearQueueButtonProps) => {
|
||||||
onOpen: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ClearAllQueueIconButton = ({ onOpen, ...props }: ClearQueueIconButtonProps) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const dialogState = useClearQueueConfirmationAlertDialog();
|
||||||
const { isLoading, isDisabled } = useClearQueue();
|
const { isLoading, isDisabled } = useClearQueue();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -24,14 +22,16 @@ export const ClearAllQueueIconButton = ({ onOpen, ...props }: ClearQueueIconButt
|
|||||||
tooltip={t('queue.clearTooltip')}
|
tooltip={t('queue.clearTooltip')}
|
||||||
icon={<PiTrashSimpleBold size="16px" />}
|
icon={<PiTrashSimpleBold size="16px" />}
|
||||||
colorScheme="error"
|
colorScheme="error"
|
||||||
onClick={onOpen}
|
onClick={dialogState.setTrue}
|
||||||
data-testid={t('queue.clear')}
|
data-testid={t('queue.clear')}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
const ClearSingleQueueItemIconButton = (props: ClearQueueButtonProps) => {
|
ClearAllQueueIconButton.displayName = 'ClearAllQueueIconButton';
|
||||||
|
|
||||||
|
const ClearSingleQueueItemIconButton = memo((props: ClearQueueButtonProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { cancelQueueItem, isLoading, isDisabled } = useCancelCurrentQueueItem();
|
const { cancelQueueItem, isLoading, isDisabled } = useCancelCurrentQueueItem();
|
||||||
|
|
||||||
@ -48,22 +48,20 @@ const ClearSingleQueueItemIconButton = (props: ClearQueueButtonProps) => {
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export const ClearQueueIconButton = (props: ClearQueueButtonProps) => {
|
ClearSingleQueueItemIconButton.displayName = 'ClearSingleQueueItemIconButton';
|
||||||
|
|
||||||
|
export const ClearQueueIconButton = memo((props: ClearQueueButtonProps) => {
|
||||||
// Show the single item clear button when shift is pressed
|
// Show the single item clear button when shift is pressed
|
||||||
// Otherwise show the clear queue button
|
// Otherwise show the clear queue button
|
||||||
const shift = useShiftModifier();
|
const shift = useShiftModifier();
|
||||||
const disclosure = useDisclosure();
|
|
||||||
|
|
||||||
return (
|
if (shift) {
|
||||||
<>
|
return <ClearAllQueueIconButton {...props} />;
|
||||||
{shift ? (
|
}
|
||||||
<ClearAllQueueIconButton {...props} onOpen={disclosure.onOpen} />
|
|
||||||
) : (
|
return <ClearSingleQueueItemIconButton {...props} />;
|
||||||
<ClearSingleQueueItemIconButton {...props} />
|
});
|
||||||
)}
|
|
||||||
<ClearQueueConfirmationAlertDialog disclosure={disclosure} />
|
ClearQueueIconButton.displayName = 'ClearQueueIconButton';
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@invoke-ai/ui-library';
|
} from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import ClearQueueConfirmationAlertDialog from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
import { useClearQueueConfirmationAlertDialog } from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
||||||
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
import { useClearQueue } from 'features/queue/hooks/useClearQueue';
|
||||||
import { usePauseProcessor } from 'features/queue/hooks/usePauseProcessor';
|
import { usePauseProcessor } from 'features/queue/hooks/usePauseProcessor';
|
||||||
import { useResumeProcessor } from 'features/queue/hooks/useResumeProcessor';
|
import { useResumeProcessor } from 'features/queue/hooks/useResumeProcessor';
|
||||||
@ -26,7 +26,7 @@ export const QueueActionsMenuButton = memo(() => {
|
|||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const clearQueueDisclosure = useDisclosure();
|
const dialogState = useClearQueueConfirmationAlertDialog();
|
||||||
const isPauseEnabled = useFeatureStatus('pauseQueue');
|
const isPauseEnabled = useFeatureStatus('pauseQueue');
|
||||||
const isResumeEnabled = useFeatureStatus('resumeQueue');
|
const isResumeEnabled = useFeatureStatus('resumeQueue');
|
||||||
const { queueSize } = useGetQueueStatusQuery(undefined, {
|
const { queueSize } = useGetQueueStatusQuery(undefined, {
|
||||||
@ -51,15 +51,13 @@ export const QueueActionsMenuButton = memo(() => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box pos="relative">
|
<Box pos="relative">
|
||||||
<ClearQueueConfirmationAlertDialog disclosure={clearQueueDisclosure} />
|
|
||||||
|
|
||||||
<Menu isOpen={isOpen} onOpen={onOpen} onClose={onClose} placement="bottom-end">
|
<Menu isOpen={isOpen} onOpen={onOpen} onClose={onClose} placement="bottom-end">
|
||||||
<MenuButton as={IconButton} aria-label="Queue Actions Menu" icon={<RiListCheck />} />
|
<MenuButton as={IconButton} aria-label="Queue Actions Menu" icon={<RiListCheck />} />
|
||||||
<MenuList>
|
<MenuList>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
isDestructive
|
isDestructive
|
||||||
icon={<PiTrashSimpleBold size="16px" />}
|
icon={<PiTrashSimpleBold size="16px" />}
|
||||||
onClick={clearQueueDisclosure.onOpen}
|
onClick={dialogState.setTrue}
|
||||||
isLoading={isLoadingClearQueue}
|
isLoading={isLoadingClearQueue}
|
||||||
isDisabled={isDisabledClearQueue}
|
isDisabled={isDisabledClearQueue}
|
||||||
>
|
>
|
||||||
|
@ -17,9 +17,6 @@ const QueueControls = () => {
|
|||||||
<InvokeQueueBackButton />
|
<InvokeQueueBackButton />
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<QueueActionsMenuButton />
|
<QueueActionsMenuButton />
|
||||||
{/* <CancelCurrentQueueItemButton asIconButton />
|
|
||||||
{isResumeEnabled && <ResumeProcessorButton asIconButton />}
|
|
||||||
{isPauseEnabled && <PauseProcessorButton asIconButton />} */}
|
|
||||||
<ClearQueueIconButton />
|
<ClearQueueIconButton />
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ProgressBar />
|
<ProgressBar />
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import type { SystemStyleObject } from '@invoke-ai/ui-library';
|
import type { SystemStyleObject } from '@invoke-ai/ui-library';
|
||||||
import { ButtonGroup, Flex, Icon, IconButton, Portal, spinAnimation, useDisclosure } from '@invoke-ai/ui-library';
|
import { ButtonGroup, Flex, Icon, IconButton, Portal, spinAnimation } from '@invoke-ai/ui-library';
|
||||||
import CancelCurrentQueueItemIconButton from 'features/queue/components/CancelCurrentQueueItemIconButton';
|
import CancelCurrentQueueItemIconButton from 'features/queue/components/CancelCurrentQueueItemIconButton';
|
||||||
import ClearQueueConfirmationAlertDialog from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
|
||||||
import { ClearAllQueueIconButton } from 'features/queue/components/ClearQueueIconButton';
|
import { ClearAllQueueIconButton } from 'features/queue/components/ClearQueueIconButton';
|
||||||
import { QueueButtonTooltip } from 'features/queue/components/QueueButtonTooltip';
|
import { QueueButtonTooltip } from 'features/queue/components/QueueButtonTooltip';
|
||||||
import { useQueueBack } from 'features/queue/hooks/useQueueBack';
|
import { useQueueBack } from 'features/queue/hooks/useQueueBack';
|
||||||
@ -36,8 +35,6 @@ const FloatingSidePanelButtons = (props: Props) => {
|
|||||||
[isDisabled, queueStatus?.processor.is_processing]
|
[isDisabled, queueStatus?.processor.is_processing]
|
||||||
);
|
);
|
||||||
|
|
||||||
const disclosure = useDisclosure();
|
|
||||||
|
|
||||||
if (!props.panelApi.isCollapsed) {
|
if (!props.panelApi.isCollapsed) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -76,8 +73,7 @@ const FloatingSidePanelButtons = (props: Props) => {
|
|||||||
</QueueButtonTooltip>
|
</QueueButtonTooltip>
|
||||||
<CancelCurrentQueueItemIconButton sx={floatingButtonStyles} />
|
<CancelCurrentQueueItemIconButton sx={floatingButtonStyles} />
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<ClearAllQueueIconButton sx={floatingButtonStyles} onOpen={disclosure.onOpen} />
|
<ClearAllQueueIconButton sx={floatingButtonStyles} />
|
||||||
<ClearQueueConfirmationAlertDialog disclosure={disclosure} />
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Portal>
|
</Portal>
|
||||||
);
|
);
|
||||||
|
@ -25,7 +25,7 @@ const WorkflowLibraryMenu = () => {
|
|||||||
const shift = useShiftModifier();
|
const shift = useShiftModifier();
|
||||||
useGlobalMenuClose(onClose);
|
useGlobalMenuClose(onClose);
|
||||||
return (
|
return (
|
||||||
<Menu isOpen={isOpen} onOpen={onOpen} onClose={onClose}>
|
<Menu isOpen={isOpen} onOpen={onOpen} onClose={onClose} isLazy>
|
||||||
<MenuButton
|
<MenuButton
|
||||||
as={IconButton}
|
as={IconButton}
|
||||||
aria-label={t('workflows.workflowEditorMenu')}
|
aria-label={t('workflows.workflowEditorMenu')}
|
||||||
|
Loading…
Reference in New Issue
Block a user