mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): clean up workflow library hooks
This commit is contained in:
parent
4a14ee0e01
commit
6d7b4b8e8a
@ -14,11 +14,11 @@ import {
|
||||
sentImageToCanvas,
|
||||
sentImageToImg2Img,
|
||||
} from 'features/gallery/store/actions';
|
||||
import { workflowLoadRequested } from 'features/nodes/store/actions';
|
||||
import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters';
|
||||
import { initialImageSelected } from 'features/parameters/store/actions';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { setActiveTab } from 'features/ui/store/uiSlice';
|
||||
import { useGetAndLoadEmbeddedWorkflow } from 'features/workflowLibrary/hooks/useGetAndLoadEmbeddedWorkflow';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -36,7 +36,6 @@ import {
|
||||
import { FaCircleNodes } from 'react-icons/fa6';
|
||||
import { MdStar, MdStarBorder } from 'react-icons/md';
|
||||
import {
|
||||
useLazyGetImageWorkflowQuery,
|
||||
useStarImagesMutation,
|
||||
useUnstarImagesMutation,
|
||||
} from 'services/api/endpoints/images';
|
||||
@ -62,12 +61,12 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
||||
imageDTO?.image_name
|
||||
);
|
||||
|
||||
const [getWorkflow, getWorkflowResult] = useLazyGetImageWorkflowQuery();
|
||||
const { getAndLoadEmbeddedWorkflow, getAndLoadEmbeddedWorkflowResult } =
|
||||
useGetAndLoadEmbeddedWorkflow({});
|
||||
|
||||
const handleLoadWorkflow = useCallback(() => {
|
||||
getWorkflow(imageDTO.image_name).then((workflow) => {
|
||||
dispatch(workflowLoadRequested(workflow.data));
|
||||
});
|
||||
}, [dispatch, getWorkflow, imageDTO]);
|
||||
getAndLoadEmbeddedWorkflow(imageDTO.image_name);
|
||||
}, [getAndLoadEmbeddedWorkflow, imageDTO.image_name]);
|
||||
|
||||
const [starImages] = useStarImagesMutation();
|
||||
const [unstarImages] = useUnstarImagesMutation();
|
||||
@ -176,7 +175,13 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
||||
{t('parameters.downloadImage')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={getWorkflowResult.isLoading ? <SpinnerIcon /> : <FaCircleNodes />}
|
||||
icon={
|
||||
getAndLoadEmbeddedWorkflowResult.isLoading ? (
|
||||
<SpinnerIcon />
|
||||
) : (
|
||||
<FaCircleNodes />
|
||||
)
|
||||
}
|
||||
onClickCapture={handleLoadWorkflow}
|
||||
isDisabled={!imageDTO.has_workflow}
|
||||
>
|
||||
|
@ -8,7 +8,7 @@ import { FaUpload } from 'react-icons/fa';
|
||||
const UploadWorkflowButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const resetRef = useRef<() => void>(null);
|
||||
const loadWorkflowFromFile = useLoadWorkflowFromFile(resetRef);
|
||||
const loadWorkflowFromFile = useLoadWorkflowFromFile({ resetRef });
|
||||
return (
|
||||
<FileButton
|
||||
resetRef={resetRef}
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { useSaveWorkflowAs } from 'features/workflowLibrary/hooks/useDuplicateWorkflow';
|
||||
import { useSaveWorkflowAs } from 'features/workflowLibrary/hooks/useSaveWorkflowAs';
|
||||
import { ChangeEvent, memo, useCallback, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaClone } from 'react-icons/fa';
|
||||
|
@ -3,15 +3,24 @@ import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDeleteWorkflowMutation } from 'services/api/endpoints/workflows';
|
||||
|
||||
type UseDeleteLibraryWorkflowArg = {
|
||||
type UseDeleteLibraryWorkflowOptions = {
|
||||
onSuccess?: () => void;
|
||||
onError?: () => void;
|
||||
};
|
||||
|
||||
export const useDeleteLibraryWorkflow = ({
|
||||
type UseDeleteLibraryWorkflowReturn = {
|
||||
deleteWorkflow: (workflow_id: string) => Promise<void>;
|
||||
deleteWorkflowResult: ReturnType<typeof useDeleteWorkflowMutation>[1];
|
||||
};
|
||||
|
||||
type UseDeleteLibraryWorkflow = (
|
||||
arg: UseDeleteLibraryWorkflowOptions
|
||||
) => UseDeleteLibraryWorkflowReturn;
|
||||
|
||||
export const useDeleteLibraryWorkflow: UseDeleteLibraryWorkflow = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
}: UseDeleteLibraryWorkflowArg) => {
|
||||
}) => {
|
||||
const toaster = useAppToaster();
|
||||
const { t } = useTranslation();
|
||||
const [_deleteWorkflow, deleteWorkflowResult] = useDeleteWorkflowMutation();
|
||||
|
@ -1,21 +1,52 @@
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { workflowLoadRequested } from 'features/nodes/store/actions';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLazyGetImageWorkflowQuery } from 'services/api/endpoints/images';
|
||||
|
||||
export const useGetAndLoadEmbeddedWorkflow = (
|
||||
image_name: string | undefined
|
||||
) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const [_trigger, result] = useLazyGetImageWorkflowQuery();
|
||||
const trigger = useCallback(() => {
|
||||
if (!image_name) {
|
||||
return;
|
||||
}
|
||||
_trigger(image_name).then((workflow) => {
|
||||
dispatch(workflowLoadRequested(workflow.data));
|
||||
});
|
||||
}, [dispatch, _trigger, image_name]);
|
||||
|
||||
return [trigger, result];
|
||||
type UseGetAndLoadEmbeddedWorkflowOptions = {
|
||||
onSuccess?: () => void;
|
||||
onError?: () => void;
|
||||
};
|
||||
|
||||
type UseGetAndLoadEmbeddedWorkflowReturn = {
|
||||
getAndLoadEmbeddedWorkflow: (imageName: string) => Promise<void>;
|
||||
getAndLoadEmbeddedWorkflowResult: ReturnType<
|
||||
typeof useLazyGetImageWorkflowQuery
|
||||
>[1];
|
||||
};
|
||||
|
||||
type UseGetAndLoadEmbeddedWorkflow = (
|
||||
options: UseGetAndLoadEmbeddedWorkflowOptions
|
||||
) => UseGetAndLoadEmbeddedWorkflowReturn;
|
||||
|
||||
export const useGetAndLoadEmbeddedWorkflow: UseGetAndLoadEmbeddedWorkflow = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
}) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const toaster = useAppToaster();
|
||||
const { t } = useTranslation();
|
||||
const [_getAndLoadEmbeddedWorkflow, getAndLoadEmbeddedWorkflowResult] =
|
||||
useLazyGetImageWorkflowQuery();
|
||||
const getAndLoadEmbeddedWorkflow = useCallback(
|
||||
async (imageName: string) => {
|
||||
try {
|
||||
const workflow = await _getAndLoadEmbeddedWorkflow(imageName);
|
||||
dispatch(workflowLoadRequested(workflow.data));
|
||||
// No toast - the listener for this action does that after the workflow is loaded
|
||||
onSuccess && onSuccess();
|
||||
} catch {
|
||||
toaster({
|
||||
title: t('toast.problemRetrievingWorkflow'),
|
||||
status: 'error',
|
||||
});
|
||||
onError && onError();
|
||||
}
|
||||
},
|
||||
[_getAndLoadEmbeddedWorkflow, dispatch, onSuccess, toaster, t, onError]
|
||||
);
|
||||
|
||||
return { getAndLoadEmbeddedWorkflow, getAndLoadEmbeddedWorkflowResult };
|
||||
};
|
||||
|
@ -5,15 +5,24 @@ import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLazyGetWorkflowQuery } from 'services/api/endpoints/workflows';
|
||||
|
||||
type UseGetAndLoadLibraryWorkflowArg = {
|
||||
type UseGetAndLoadLibraryWorkflowOptions = {
|
||||
onSuccess?: () => void;
|
||||
onError?: () => void;
|
||||
};
|
||||
|
||||
export const useGetAndLoadLibraryWorkflow = ({
|
||||
type UseGetAndLoadLibraryWorkflowReturn = {
|
||||
getAndLoadWorkflow: (workflow_id: string) => Promise<void>;
|
||||
getAndLoadWorkflowResult: ReturnType<typeof useLazyGetWorkflowQuery>[1];
|
||||
};
|
||||
|
||||
type UseGetAndLoadLibraryWorkflow = (
|
||||
arg: UseGetAndLoadLibraryWorkflowOptions
|
||||
) => UseGetAndLoadLibraryWorkflowReturn;
|
||||
|
||||
export const useGetAndLoadLibraryWorkflow: UseGetAndLoadLibraryWorkflow = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
}: UseGetAndLoadLibraryWorkflowArg) => {
|
||||
}) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const toaster = useAppToaster();
|
||||
const { t } = useTranslation();
|
||||
|
@ -1,15 +1,22 @@
|
||||
import { ListItem, Text, UnorderedList } from '@chakra-ui/react';
|
||||
import { useLogger } from 'app/logging/useLogger';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { workflowLoadRequested } from 'features/nodes/store/actions';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
import { makeToast } from 'features/system/util/makeToast';
|
||||
import { RefObject, memo, useCallback } from 'react';
|
||||
import { RefObject, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ZodError } from 'zod';
|
||||
import { fromZodIssue } from 'zod-validation-error';
|
||||
import { workflowLoadRequested } from 'features/nodes/store/actions';
|
||||
|
||||
export const useLoadWorkflowFromFile = (resetRef: RefObject<() => void>) => {
|
||||
type useLoadWorkflowFromFileOptions = {
|
||||
resetRef: RefObject<() => void>;
|
||||
};
|
||||
|
||||
type UseLoadWorkflowFromFile = (
|
||||
options: useLoadWorkflowFromFileOptions
|
||||
) => (file: File | null) => void;
|
||||
|
||||
export const useLoadWorkflowFromFile: UseLoadWorkflowFromFile = ({
|
||||
resetRef,
|
||||
}) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const logger = useLogger('nodes');
|
||||
const { t } = useTranslation();
|
||||
@ -41,6 +48,7 @@ export const useLoadWorkflowFromFile = (resetRef: RefObject<() => void>) => {
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
|
||||
// Reset the file picker internal state so that the same file can be loaded again
|
||||
resetRef.current?.();
|
||||
},
|
||||
@ -49,24 +57,3 @@ export const useLoadWorkflowFromFile = (resetRef: RefObject<() => void>) => {
|
||||
|
||||
return loadWorkflowFromFile;
|
||||
};
|
||||
|
||||
const WorkflowValidationErrorContent = memo((props: { error: ZodError }) => {
|
||||
if (props.error.issues[0]) {
|
||||
return (
|
||||
<Text>
|
||||
{fromZodIssue(props.error.issues[0], { prefix: null }).toString()}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<UnorderedList>
|
||||
{props.error.issues.map((issue, i) => (
|
||||
<ListItem key={i}>
|
||||
<Text>{fromZodIssue(issue, { prefix: null }).toString()}</Text>
|
||||
</ListItem>
|
||||
))}
|
||||
</UnorderedList>
|
||||
);
|
||||
});
|
||||
|
||||
WorkflowValidationErrorContent.displayName = 'WorkflowValidationErrorContent';
|
||||
|
@ -10,7 +10,15 @@ import {
|
||||
useUpdateWorkflowMutation,
|
||||
} from 'services/api/endpoints/workflows';
|
||||
|
||||
export const useSaveLibraryWorkflow = () => {
|
||||
type UseSaveLibraryWorkflowReturn = {
|
||||
saveWorkflow: () => Promise<void>;
|
||||
isLoading: boolean;
|
||||
isError: boolean;
|
||||
};
|
||||
|
||||
type UseSaveLibraryWorkflow = () => UseSaveLibraryWorkflowReturn;
|
||||
|
||||
export const useSaveLibraryWorkflow: UseSaveLibraryWorkflow = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const workflow = useWorkflow();
|
||||
|
@ -7,20 +7,28 @@ import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCreateWorkflowMutation } from 'services/api/endpoints/workflows';
|
||||
|
||||
type Arg = {
|
||||
type SaveWorkflowAsArg = {
|
||||
name: string;
|
||||
onSuccess?: () => void;
|
||||
onError?: () => void;
|
||||
};
|
||||
|
||||
export const useSaveWorkflowAs = () => {
|
||||
type UseSaveWorkflowAsReturn = {
|
||||
saveWorkflowAs: (arg: SaveWorkflowAsArg) => Promise<void>;
|
||||
isLoading: boolean;
|
||||
isError: boolean;
|
||||
};
|
||||
|
||||
type UseSaveWorkflowAs = () => UseSaveWorkflowAsReturn;
|
||||
|
||||
export const useSaveWorkflowAs: UseSaveWorkflowAs = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const workflow = useWorkflow();
|
||||
const [createWorkflow, createWorkflowResult] = useCreateWorkflowMutation();
|
||||
const toaster = useAppToaster();
|
||||
const saveWorkflowAs = useCallback(
|
||||
async ({ name: newName, onSuccess, onError }: Arg) => {
|
||||
async ({ name: newName, onSuccess, onError }: SaveWorkflowAsArg) => {
|
||||
try {
|
||||
workflow.id = undefined;
|
||||
workflow.name = newName;
|
Loading…
Reference in New Issue
Block a user