mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui): make image hotkeys global
This commit is contained in:
@@ -11,7 +11,7 @@ import { PiFlowArrowBold } from 'react-icons/pi';
|
||||
export const ImageMenuItemLoadWorkflow = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const imageDTO = useImageDTOContext();
|
||||
const { getAndLoadEmbeddedWorkflow, getAndLoadEmbeddedWorkflowResult } = useGetAndLoadEmbeddedWorkflow({});
|
||||
const [getAndLoadEmbeddedWorkflow, { isLoading }] = useGetAndLoadEmbeddedWorkflow();
|
||||
const hasTemplates = useStore($hasTemplates);
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
@@ -20,7 +20,7 @@ export const ImageMenuItemLoadWorkflow = memo(() => {
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
icon={getAndLoadEmbeddedWorkflowResult.isLoading ? <SpinnerIcon /> : <PiFlowArrowBold />}
|
||||
icon={isLoading ? <SpinnerIcon /> : <PiFlowArrowBold />}
|
||||
onClickCapture={onClick}
|
||||
isDisabled={!imageDTO.has_workflow || !hasTemplates}
|
||||
>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { MenuItem } from '@invoke-ai/ui-library';
|
||||
import { SpinnerIcon } from 'features/gallery/components/ImageContextMenu/SpinnerIcon';
|
||||
import { useImageDTOContext } from 'features/gallery/contexts/ImageDTOContext';
|
||||
import { useImageActions } from 'features/gallery/hooks/useImageActions';
|
||||
import { memo } from 'react';
|
||||
@@ -16,53 +15,24 @@ export const ImageMenuItemMetadataRecallActions = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const imageDTO = useImageDTOContext();
|
||||
|
||||
const {
|
||||
recallAll,
|
||||
remix,
|
||||
recallSeed,
|
||||
recallPrompts,
|
||||
hasMetadata,
|
||||
hasSeed,
|
||||
hasPrompts,
|
||||
isLoadingMetadata,
|
||||
createAsPreset,
|
||||
} = useImageActions(imageDTO?.image_name);
|
||||
const { recallAll, remix, recallSeed, recallPrompts, hasMetadata, hasSeed, hasPrompts, createAsPreset } =
|
||||
useImageActions(imageDTO);
|
||||
|
||||
return (
|
||||
<>
|
||||
<MenuItem
|
||||
icon={isLoadingMetadata ? <SpinnerIcon /> : <PiArrowsCounterClockwiseBold />}
|
||||
onClickCapture={remix}
|
||||
isDisabled={isLoadingMetadata || !hasMetadata}
|
||||
>
|
||||
<MenuItem icon={<PiArrowsCounterClockwiseBold />} onClickCapture={remix} isDisabled={!hasMetadata}>
|
||||
{t('parameters.remixImage')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={isLoadingMetadata ? <SpinnerIcon /> : <PiQuotesBold />}
|
||||
onClickCapture={recallPrompts}
|
||||
isDisabled={isLoadingMetadata || !hasPrompts}
|
||||
>
|
||||
<MenuItem icon={<PiQuotesBold />} onClickCapture={recallPrompts} isDisabled={!hasPrompts}>
|
||||
{t('parameters.usePrompt')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={isLoadingMetadata ? <SpinnerIcon /> : <PiPlantBold />}
|
||||
onClickCapture={recallSeed}
|
||||
isDisabled={isLoadingMetadata || !hasSeed}
|
||||
>
|
||||
<MenuItem icon={<PiPlantBold />} onClickCapture={recallSeed} isDisabled={!hasSeed}>
|
||||
{t('parameters.useSeed')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={isLoadingMetadata ? <SpinnerIcon /> : <PiAsteriskBold />}
|
||||
onClickCapture={recallAll}
|
||||
isDisabled={isLoadingMetadata || !hasMetadata}
|
||||
>
|
||||
<MenuItem icon={<PiAsteriskBold />} onClickCapture={recallAll} isDisabled={!hasMetadata}>
|
||||
{t('parameters.useAll')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={isLoadingMetadata ? <SpinnerIcon /> : <PiPaintBrushBold />}
|
||||
onClickCapture={createAsPreset}
|
||||
isDisabled={isLoadingMetadata || !hasPrompts}
|
||||
>
|
||||
<MenuItem icon={<PiPaintBrushBold />} onClickCapture={createAsPreset} isDisabled={!hasPrompts}>
|
||||
{t('stylePresets.useForTemplate')}
|
||||
</MenuItem>
|
||||
</>
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
import { ButtonGroup, IconButton, Menu, MenuButton, MenuList } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { adHocPostProcessingRequested } from 'app/store/middleware/listenerMiddleware/listeners/addAdHocPostProcessingRequestedListener';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useIsRegionFocused } from 'common/hooks/interactionScopes';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectIsStaging } from 'features/controlLayers/store/canvasStagingAreaSlice';
|
||||
import { DeleteImageButton } from 'features/deleteImageModal/components/DeleteImageButton';
|
||||
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
||||
import SingleSelectionMenuItems from 'features/gallery/components/ImageContextMenu/SingleSelectionMenuItems';
|
||||
import { useImageActions } from 'features/gallery/hooks/useImageActions';
|
||||
import { selectLastSelectedImage } from 'features/gallery/store/gallerySelectors';
|
||||
import { parseAndRecallImageDimensions } from 'features/metadata/util/handlers';
|
||||
import { $templates } from 'features/nodes/store/nodesSlice';
|
||||
import { $hasTemplates } from 'features/nodes/store/nodesSlice';
|
||||
import { PostProcessingPopover } from 'features/parameters/components/PostProcessing/PostProcessingPopover';
|
||||
import { useIsQueueMutationInProgress } from 'features/queue/hooks/useIsQueueMutationInProgress';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { useGetAndLoadEmbeddedWorkflow } from 'features/workflowLibrary/hooks/useGetAndLoadEmbeddedWorkflow';
|
||||
import { size } from 'lodash-es';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
PiArrowsCounterClockwiseBold,
|
||||
@@ -30,110 +22,31 @@ import {
|
||||
PiRulerBold,
|
||||
} from 'react-icons/pi';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import { $isConnected, $progressImage } from 'services/events/stores';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
|
||||
const CurrentImageButtons = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const isConnected = useStore($isConnected);
|
||||
const isStaging = useAppSelector(selectIsStaging);
|
||||
const lastSelectedImage = useAppSelector(selectLastSelectedImage);
|
||||
const progressImage = useStore($progressImage);
|
||||
const shouldDisableToolbarButtons = useMemo(() => {
|
||||
return Boolean(progressImage) || !lastSelectedImage;
|
||||
}, [lastSelectedImage, progressImage]);
|
||||
const templates = useStore($templates);
|
||||
const isUpscalingEnabled = useFeatureStatus('upscaling');
|
||||
const isQueueMutationInProgress = useIsQueueMutationInProgress();
|
||||
const { t } = useTranslation();
|
||||
const isGalleryFocused = useIsRegionFocused('gallery');
|
||||
const isViewerFocused = useIsRegionFocused('viewer');
|
||||
const { currentData: imageDTO } = useGetImageDTOQuery(lastSelectedImage?.image_name ?? skipToken);
|
||||
|
||||
const { recallAll, remix, recallSeed, recallPrompts, hasMetadata, hasSeed, hasPrompts, isLoadingMetadata } =
|
||||
useImageActions(lastSelectedImage?.image_name);
|
||||
if (!imageDTO) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { getAndLoadEmbeddedWorkflow, getAndLoadEmbeddedWorkflowResult } = useGetAndLoadEmbeddedWorkflow({});
|
||||
return <CurrentImageButtonsContent imageDTO={imageDTO} />;
|
||||
};
|
||||
|
||||
const handleLoadWorkflow = useCallback(() => {
|
||||
if (!lastSelectedImage || !lastSelectedImage.has_workflow) {
|
||||
return;
|
||||
}
|
||||
getAndLoadEmbeddedWorkflow(lastSelectedImage.image_name);
|
||||
}, [getAndLoadEmbeddedWorkflow, lastSelectedImage]);
|
||||
export default memo(CurrentImageButtons);
|
||||
|
||||
const handleUseSize = useCallback(() => {
|
||||
if (isStaging) {
|
||||
return;
|
||||
}
|
||||
parseAndRecallImageDimensions(lastSelectedImage);
|
||||
}, [isStaging, lastSelectedImage]);
|
||||
const handleClickUpscale = useCallback(() => {
|
||||
if (!imageDTO) {
|
||||
return;
|
||||
}
|
||||
dispatch(adHocPostProcessingRequested({ imageDTO }));
|
||||
}, [dispatch, imageDTO]);
|
||||
|
||||
const handleDelete = useCallback(() => {
|
||||
if (!imageDTO) {
|
||||
return;
|
||||
}
|
||||
dispatch(imagesToDeleteSelected([imageDTO]));
|
||||
}, [dispatch, imageDTO]);
|
||||
|
||||
useRegisteredHotkeys({
|
||||
id: 'loadWorkflow',
|
||||
category: 'viewer',
|
||||
callback: handleLoadWorkflow,
|
||||
options: { enabled: isGalleryFocused || isViewerFocused },
|
||||
dependencies: [handleLoadWorkflow, isGalleryFocused, isViewerFocused],
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
id: 'recallAll',
|
||||
category: 'viewer',
|
||||
callback: recallAll,
|
||||
options: { enabled: isGalleryFocused || isViewerFocused },
|
||||
dependencies: [recallAll, isGalleryFocused, isViewerFocused],
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
id: 'recallSeed',
|
||||
category: 'viewer',
|
||||
callback: recallSeed,
|
||||
options: { enabled: isGalleryFocused || isViewerFocused },
|
||||
dependencies: [recallSeed, isGalleryFocused, isViewerFocused],
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
id: 'recallPrompts',
|
||||
category: 'viewer',
|
||||
callback: recallPrompts,
|
||||
options: { enabled: isGalleryFocused || isViewerFocused },
|
||||
dependencies: [recallPrompts, isGalleryFocused, isViewerFocused],
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
id: 'remix',
|
||||
category: 'viewer',
|
||||
callback: remix,
|
||||
options: { enabled: isGalleryFocused || isViewerFocused },
|
||||
dependencies: [remix, isGalleryFocused, isViewerFocused],
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
id: 'useSize',
|
||||
category: 'viewer',
|
||||
callback: handleUseSize,
|
||||
options: { enabled: isGalleryFocused || isViewerFocused },
|
||||
dependencies: [handleUseSize, isGalleryFocused, isViewerFocused],
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
id: 'runPostprocessing',
|
||||
category: 'viewer',
|
||||
callback: handleClickUpscale,
|
||||
options: { enabled: Boolean(isUpscalingEnabled && isViewerFocused && isConnected) },
|
||||
dependencies: [isUpscalingEnabled, imageDTO, shouldDisableToolbarButtons, isConnected, isViewerFocused],
|
||||
});
|
||||
const CurrentImageButtonsContent = memo(({ imageDTO }: { imageDTO: ImageDTO }) => {
|
||||
const { t } = useTranslation();
|
||||
const hasTemplates = useStore($hasTemplates);
|
||||
const imageActions = useImageActions(imageDTO);
|
||||
const isStaging = useAppSelector(selectIsStaging);
|
||||
const isUpscalingEnabled = useFeatureStatus('upscaling');
|
||||
|
||||
return (
|
||||
<>
|
||||
<ButtonGroup isDisabled={shouldDisableToolbarButtons}>
|
||||
<ButtonGroup>
|
||||
<Menu isLazy>
|
||||
<MenuButton
|
||||
as={IconButton}
|
||||
@@ -146,68 +59,62 @@ const CurrentImageButtons = () => {
|
||||
</Menu>
|
||||
</ButtonGroup>
|
||||
|
||||
<ButtonGroup isDisabled={shouldDisableToolbarButtons}>
|
||||
<ButtonGroup>
|
||||
<IconButton
|
||||
icon={<PiFlowArrowBold />}
|
||||
tooltip={`${t('nodes.loadWorkflow')} (W)`}
|
||||
aria-label={`${t('nodes.loadWorkflow')} (W)`}
|
||||
isDisabled={!imageDTO?.has_workflow || !size(templates)}
|
||||
onClick={handleLoadWorkflow}
|
||||
isLoading={getAndLoadEmbeddedWorkflowResult.isLoading}
|
||||
isDisabled={!imageActions.hasWorkflow || !hasTemplates}
|
||||
onClick={imageActions.loadWorkflow}
|
||||
/>
|
||||
<IconButton
|
||||
isLoading={isLoadingMetadata}
|
||||
icon={<PiArrowsCounterClockwiseBold />}
|
||||
tooltip={`${t('parameters.remixImage')} (R)`}
|
||||
aria-label={`${t('parameters.remixImage')} (R)`}
|
||||
isDisabled={!hasMetadata}
|
||||
onClick={remix}
|
||||
isDisabled={!imageActions.hasMetadata}
|
||||
onClick={imageActions.remix}
|
||||
/>
|
||||
<IconButton
|
||||
isLoading={isLoadingMetadata}
|
||||
icon={<PiQuotesBold />}
|
||||
tooltip={`${t('parameters.usePrompt')} (P)`}
|
||||
aria-label={`${t('parameters.usePrompt')} (P)`}
|
||||
isDisabled={!hasPrompts}
|
||||
onClick={recallPrompts}
|
||||
isDisabled={!imageActions.hasPrompts}
|
||||
onClick={imageActions.recallPrompts}
|
||||
/>
|
||||
<IconButton
|
||||
isLoading={isLoadingMetadata}
|
||||
icon={<PiPlantBold />}
|
||||
tooltip={`${t('parameters.useSeed')} (S)`}
|
||||
aria-label={`${t('parameters.useSeed')} (S)`}
|
||||
isDisabled={!hasSeed}
|
||||
onClick={recallSeed}
|
||||
isDisabled={!imageActions.hasSeed}
|
||||
onClick={imageActions.recallSeed}
|
||||
/>
|
||||
<IconButton
|
||||
isLoading={isLoadingMetadata}
|
||||
icon={<PiRulerBold />}
|
||||
tooltip={`${t('parameters.useSize')} (D)`}
|
||||
aria-label={`${t('parameters.useSize')} (D)`}
|
||||
onClick={handleUseSize}
|
||||
onClick={imageActions.recallSize}
|
||||
isDisabled={isStaging}
|
||||
/>
|
||||
<IconButton
|
||||
isLoading={isLoadingMetadata}
|
||||
icon={<PiAsteriskBold />}
|
||||
tooltip={`${t('parameters.useAll')} (A)`}
|
||||
aria-label={`${t('parameters.useAll')} (A)`}
|
||||
isDisabled={!hasMetadata}
|
||||
onClick={recallAll}
|
||||
isDisabled={!imageActions.hasMetadata}
|
||||
onClick={imageActions.recallAll}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
|
||||
{isUpscalingEnabled && (
|
||||
<ButtonGroup isDisabled={isQueueMutationInProgress}>
|
||||
{isUpscalingEnabled && <PostProcessingPopover imageDTO={imageDTO} />}
|
||||
<ButtonGroup>
|
||||
<PostProcessingPopover imageDTO={imageDTO} />
|
||||
</ButtonGroup>
|
||||
)}
|
||||
|
||||
<ButtonGroup>
|
||||
<DeleteImageButton onClick={handleDelete} />
|
||||
<DeleteImageButton onClick={imageActions.delete} />
|
||||
</ButtonGroup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default memo(CurrentImageButtons);
|
||||
CurrentImageButtonsContent.displayName = 'CurrentImageButtonsContent';
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { adHocPostProcessingRequested } from 'app/store/middleware/listenerMiddleware/listeners/addAdHocPostProcessingRequestedListener';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectIsStaging } from 'features/controlLayers/store/canvasStagingAreaSlice';
|
||||
import { handlers, parseAndRecallAllMetadata, parseAndRecallPrompts } from 'features/metadata/util/handlers';
|
||||
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
||||
import {
|
||||
handlers,
|
||||
parseAndRecallAllMetadata,
|
||||
parseAndRecallImageDimensions,
|
||||
parseAndRecallPrompts,
|
||||
} from 'features/metadata/util/handlers';
|
||||
import { $hasTemplates } from 'features/nodes/store/nodesSlice';
|
||||
import { $stylePresetModalState } from 'features/stylePresets/store/stylePresetModal';
|
||||
import {
|
||||
activeStylePresetIdChanged,
|
||||
@@ -9,22 +17,23 @@ import {
|
||||
} from 'features/stylePresets/store/stylePresetSlice';
|
||||
import { toast } from 'features/toast/toast';
|
||||
import { selectActiveTab } from 'features/ui/store/uiSelectors';
|
||||
import { useGetAndLoadEmbeddedWorkflow } from 'features/workflowLibrary/hooks/useGetAndLoadEmbeddedWorkflow';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import { useDebouncedMetadata } from 'services/api/hooks/useDebouncedMetadata';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
|
||||
export const useImageActions = (image_name?: string) => {
|
||||
export const useImageActions = (imageDTO: ImageDTO) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const activeStylePresetId = useAppSelector(selectStylePresetActivePresetId);
|
||||
const isStaging = useAppSelector(selectIsStaging);
|
||||
const activeTabName = useAppSelector(selectActiveTab);
|
||||
const { metadata, isLoading: isLoadingMetadata } = useDebouncedMetadata(image_name);
|
||||
const { metadata } = useDebouncedMetadata(imageDTO.image_name);
|
||||
const [hasMetadata, setHasMetadata] = useState(false);
|
||||
const [hasSeed, setHasSeed] = useState(false);
|
||||
const [hasPrompts, setHasPrompts] = useState(false);
|
||||
const { data: imageDTO } = useGetImageDTOQuery(image_name ?? skipToken);
|
||||
const hasTemplates = useStore($hasTemplates);
|
||||
|
||||
useEffect(() => {
|
||||
const parseMetadata = async () => {
|
||||
@@ -68,66 +77,107 @@ export const useImageActions = (image_name?: string) => {
|
||||
}, [dispatch, activeStylePresetId, t]);
|
||||
|
||||
const recallAll = useCallback(() => {
|
||||
if (!metadata) {
|
||||
return;
|
||||
}
|
||||
parseAndRecallAllMetadata(metadata, activeTabName === 'canvas', isStaging ? ['width', 'height'] : []);
|
||||
clearStylePreset();
|
||||
}, [metadata, activeTabName, isStaging, clearStylePreset]);
|
||||
|
||||
const remix = useCallback(() => {
|
||||
if (!metadata) {
|
||||
return;
|
||||
}
|
||||
// Recalls all metadata parameters except seed
|
||||
parseAndRecallAllMetadata(metadata, activeTabName === 'canvas', ['seed']);
|
||||
clearStylePreset();
|
||||
}, [activeTabName, metadata, clearStylePreset]);
|
||||
|
||||
const recallSeed = useCallback(() => {
|
||||
if (!metadata) {
|
||||
return;
|
||||
}
|
||||
handlers.seed.parse(metadata).then((seed) => {
|
||||
handlers.seed.recall && handlers.seed.recall(seed, true);
|
||||
});
|
||||
}, [metadata]);
|
||||
|
||||
const recallPrompts = useCallback(() => {
|
||||
if (!metadata) {
|
||||
return;
|
||||
}
|
||||
parseAndRecallPrompts(metadata);
|
||||
clearStylePreset();
|
||||
}, [metadata, clearStylePreset]);
|
||||
|
||||
const createAsPreset = useCallback(async () => {
|
||||
if (image_name && metadata && imageDTO) {
|
||||
let positivePrompt;
|
||||
let negativePrompt;
|
||||
|
||||
try {
|
||||
positivePrompt = await handlers.positivePrompt.parse(metadata);
|
||||
} catch (error) {
|
||||
positivePrompt = '';
|
||||
}
|
||||
try {
|
||||
negativePrompt = await handlers.negativePrompt.parse(metadata);
|
||||
} catch (error) {
|
||||
negativePrompt = '';
|
||||
}
|
||||
|
||||
$stylePresetModalState.set({
|
||||
prefilledFormData: {
|
||||
name: '',
|
||||
positivePrompt,
|
||||
negativePrompt,
|
||||
imageUrl: imageDTO.image_url,
|
||||
type: 'user',
|
||||
},
|
||||
updatingStylePresetId: null,
|
||||
isModalOpen: true,
|
||||
});
|
||||
if (!metadata) {
|
||||
return;
|
||||
}
|
||||
}, [image_name, metadata, imageDTO]);
|
||||
let positivePrompt;
|
||||
let negativePrompt;
|
||||
|
||||
try {
|
||||
positivePrompt = await handlers.positivePrompt.parse(metadata);
|
||||
} catch (error) {
|
||||
positivePrompt = '';
|
||||
}
|
||||
try {
|
||||
negativePrompt = await handlers.negativePrompt.parse(metadata);
|
||||
} catch (error) {
|
||||
negativePrompt = '';
|
||||
}
|
||||
|
||||
$stylePresetModalState.set({
|
||||
prefilledFormData: {
|
||||
name: '',
|
||||
positivePrompt,
|
||||
negativePrompt,
|
||||
imageUrl: imageDTO.image_url,
|
||||
type: 'user',
|
||||
},
|
||||
updatingStylePresetId: null,
|
||||
isModalOpen: true,
|
||||
});
|
||||
}, [metadata, imageDTO]);
|
||||
|
||||
const [getAndLoadEmbeddedWorkflow] = useGetAndLoadEmbeddedWorkflow();
|
||||
|
||||
const loadWorkflow = useCallback(() => {
|
||||
if (!imageDTO.has_workflow || !hasTemplates) {
|
||||
return;
|
||||
}
|
||||
getAndLoadEmbeddedWorkflow(imageDTO.image_name);
|
||||
}, [getAndLoadEmbeddedWorkflow, hasTemplates, imageDTO.has_workflow, imageDTO.image_name]);
|
||||
|
||||
const recallSize = useCallback(() => {
|
||||
if (isStaging) {
|
||||
return;
|
||||
}
|
||||
parseAndRecallImageDimensions(imageDTO);
|
||||
}, [imageDTO, isStaging]);
|
||||
|
||||
const upscale = useCallback(() => {
|
||||
dispatch(adHocPostProcessingRequested({ imageDTO }));
|
||||
}, [dispatch, imageDTO]);
|
||||
|
||||
const _delete = useCallback(() => {
|
||||
dispatch(imagesToDeleteSelected([imageDTO]));
|
||||
}, [dispatch, imageDTO]);
|
||||
|
||||
return {
|
||||
hasMetadata,
|
||||
hasSeed,
|
||||
hasPrompts,
|
||||
recallAll,
|
||||
remix,
|
||||
recallSeed,
|
||||
recallPrompts,
|
||||
hasMetadata,
|
||||
hasSeed,
|
||||
hasPrompts,
|
||||
isLoadingMetadata,
|
||||
createAsPreset,
|
||||
loadWorkflow,
|
||||
hasWorkflow: imageDTO.has_workflow,
|
||||
recallSize,
|
||||
upscale,
|
||||
delete: _delete,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,19 +10,10 @@ type UseGetAndLoadEmbeddedWorkflowOptions = {
|
||||
onError?: () => void;
|
||||
};
|
||||
|
||||
type UseGetAndLoadEmbeddedWorkflowReturn = {
|
||||
getAndLoadEmbeddedWorkflow: (imageName: string) => Promise<void>;
|
||||
getAndLoadEmbeddedWorkflowResult: ReturnType<typeof useLazyGetImageWorkflowQuery>[1];
|
||||
};
|
||||
|
||||
type UseGetAndLoadEmbeddedWorkflow = (
|
||||
options?: UseGetAndLoadEmbeddedWorkflowOptions
|
||||
) => UseGetAndLoadEmbeddedWorkflowReturn;
|
||||
|
||||
export const useGetAndLoadEmbeddedWorkflow: UseGetAndLoadEmbeddedWorkflow = (options) => {
|
||||
export const useGetAndLoadEmbeddedWorkflow = (options?: UseGetAndLoadEmbeddedWorkflowOptions) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const [_getAndLoadEmbeddedWorkflow, getAndLoadEmbeddedWorkflowResult] = useLazyGetImageWorkflowQuery();
|
||||
const [_getAndLoadEmbeddedWorkflow, result] = useLazyGetImageWorkflowQuery();
|
||||
const getAndLoadEmbeddedWorkflow = useCallback(
|
||||
async (imageName: string) => {
|
||||
try {
|
||||
@@ -50,5 +41,5 @@ export const useGetAndLoadEmbeddedWorkflow: UseGetAndLoadEmbeddedWorkflow = (opt
|
||||
[_getAndLoadEmbeddedWorkflow, dispatch, options, t]
|
||||
);
|
||||
|
||||
return { getAndLoadEmbeddedWorkflow, getAndLoadEmbeddedWorkflowResult };
|
||||
return [getAndLoadEmbeddedWorkflow, result] as const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user