mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): create debounced metadata/workflow query hooks
Also added config options for metadata and workflow debounce times (`metadataFetchDebounce` & `workflowFetchDebounce`). Falls back to 0 if not provided. In OSS, because we have no major latency concerns, the debounce is 0. But in other environments, it may be desirable to set this to something like 300ms.
This commit is contained in:
parent
2faed653d7
commit
f04462973b
@ -59,6 +59,8 @@ export type AppConfig = {
|
|||||||
nodesAllowlist: string[] | undefined;
|
nodesAllowlist: string[] | undefined;
|
||||||
nodesDenylist: string[] | undefined;
|
nodesDenylist: string[] | undefined;
|
||||||
maxUpscalePixels?: number;
|
maxUpscalePixels?: number;
|
||||||
|
metadataFetchDebounce?: number;
|
||||||
|
workflowFetchDebounce?: number;
|
||||||
sd: {
|
sd: {
|
||||||
defaultModel?: string;
|
defaultModel?: string;
|
||||||
disabledControlNetModels: string[];
|
disabledControlNetModels: string[];
|
||||||
|
@ -38,15 +38,12 @@ import {
|
|||||||
FaSeedling,
|
FaSeedling,
|
||||||
} from 'react-icons/fa';
|
} from 'react-icons/fa';
|
||||||
import { FaCircleNodes, FaEllipsis } from 'react-icons/fa6';
|
import { FaCircleNodes, FaEllipsis } from 'react-icons/fa6';
|
||||||
import {
|
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||||
useGetImageDTOQuery,
|
import { useDebouncedMetadata } from 'services/api/hooks/useDebouncedMetadata';
|
||||||
useGetImageMetadataQuery,
|
import { useDebouncedWorkflow } from 'services/api/hooks/useDebouncedWorkflow';
|
||||||
} from 'services/api/endpoints/images';
|
|
||||||
import { menuListMotionProps } from 'theme/components/menu';
|
import { menuListMotionProps } from 'theme/components/menu';
|
||||||
import { useDebounce } from 'use-debounce';
|
|
||||||
import { sentImageToImg2Img } from '../../store/actions';
|
import { sentImageToImg2Img } from '../../store/actions';
|
||||||
import SingleSelectionMenuItems from '../ImageContextMenu/SingleSelectionMenuItems';
|
import SingleSelectionMenuItems from '../ImageContextMenu/SingleSelectionMenuItems';
|
||||||
import { useGetWorkflowQuery } from 'services/api/endpoints/workflows';
|
|
||||||
|
|
||||||
const currentImageButtonsSelector = createSelector(
|
const currentImageButtonsSelector = createSelector(
|
||||||
[stateSelector, activeTabNameSelector],
|
[stateSelector, activeTabNameSelector],
|
||||||
@ -105,17 +102,12 @@ const CurrentImageButtons = () => {
|
|||||||
lastSelectedImage?.image_name ?? skipToken
|
lastSelectedImage?.image_name ?? skipToken
|
||||||
);
|
);
|
||||||
|
|
||||||
const [debouncedImageName] = useDebounce(lastSelectedImage?.image_name, 300);
|
const { metadata, isLoading: isLoadingMetadata } = useDebouncedMetadata(
|
||||||
const [debouncedWorkflowId] = useDebounce(
|
lastSelectedImage?.image_name
|
||||||
lastSelectedImage?.workflow_id,
|
|
||||||
300
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: metadata, isLoading: isLoadingMetadata } =
|
const { workflow, isLoading: isLoadingWorkflow } = useDebouncedWorkflow(
|
||||||
useGetImageMetadataQuery(debouncedImageName ?? skipToken);
|
lastSelectedImage?.workflow_id
|
||||||
|
|
||||||
const { data: workflow, isLoading: isLoadingWorkflow } = useGetWorkflowQuery(
|
|
||||||
debouncedWorkflowId ?? skipToken
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleLoadWorkflow = useCallback(() => {
|
const handleLoadWorkflow = useCallback(() => {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Flex, MenuItem, Spinner } from '@chakra-ui/react';
|
import { Flex, MenuItem, Spinner } from '@chakra-ui/react';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
|
||||||
import { useAppToaster } from 'app/components/Toaster';
|
import { useAppToaster } from 'app/components/Toaster';
|
||||||
import { $customStarUI } from 'app/store/nanostores/customStarUI';
|
import { $customStarUI } from 'app/store/nanostores/customStarUI';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
@ -33,13 +32,12 @@ import {
|
|||||||
import { FaCircleNodes } from 'react-icons/fa6';
|
import { FaCircleNodes } from 'react-icons/fa6';
|
||||||
import { MdStar, MdStarBorder } from 'react-icons/md';
|
import { MdStar, MdStarBorder } from 'react-icons/md';
|
||||||
import {
|
import {
|
||||||
useGetImageMetadataQuery,
|
|
||||||
useStarImagesMutation,
|
useStarImagesMutation,
|
||||||
useUnstarImagesMutation,
|
useUnstarImagesMutation,
|
||||||
} from 'services/api/endpoints/images';
|
} from 'services/api/endpoints/images';
|
||||||
import { useGetWorkflowQuery } from 'services/api/endpoints/workflows';
|
import { useDebouncedMetadata } from 'services/api/hooks/useDebouncedMetadata';
|
||||||
|
import { useDebouncedWorkflow } from 'services/api/hooks/useDebouncedWorkflow';
|
||||||
import { ImageDTO } from 'services/api/types';
|
import { ImageDTO } from 'services/api/types';
|
||||||
import { useDebounce } from 'use-debounce';
|
|
||||||
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
|
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
|
||||||
|
|
||||||
type SingleSelectionMenuItemsProps = {
|
type SingleSelectionMenuItemsProps = {
|
||||||
@ -57,14 +55,11 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
|||||||
const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled;
|
const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled;
|
||||||
const customStarUi = useStore($customStarUI);
|
const customStarUi = useStore($customStarUI);
|
||||||
|
|
||||||
const [debouncedImageName] = useDebounce(imageDTO?.image_name, 300);
|
const { metadata, isLoading: isLoadingMetadata } = useDebouncedMetadata(
|
||||||
const [debouncedWorkflowId] = useDebounce(imageDTO?.workflow_id, 300);
|
imageDTO?.image_name
|
||||||
|
);
|
||||||
const { data: metadata, isLoading: isLoadingMetadata } =
|
const { workflow, isLoading: isLoadingWorkflow } = useDebouncedWorkflow(
|
||||||
useGetImageMetadataQuery(debouncedImageName ?? skipToken);
|
imageDTO?.workflow_id
|
||||||
|
|
||||||
const { data: workflow, isLoading: isLoadingWorkflow } = useGetWorkflowQuery(
|
|
||||||
debouncedWorkflowId ?? skipToken
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const [starImages] = useStarImagesMutation();
|
const [starImages] = useStarImagesMutation();
|
||||||
|
@ -9,15 +9,13 @@ import {
|
|||||||
Tabs,
|
Tabs,
|
||||||
Text,
|
Text,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
|
||||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||||
import ScrollableContent from 'features/nodes/components/sidePanel/ScrollableContent';
|
import ScrollableContent from 'features/nodes/components/sidePanel/ScrollableContent';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useGetImageMetadataQuery } from 'services/api/endpoints/images';
|
import { useDebouncedMetadata } from 'services/api/hooks/useDebouncedMetadata';
|
||||||
import { useGetWorkflowQuery } from 'services/api/endpoints/workflows';
|
import { useDebouncedWorkflow } from 'services/api/hooks/useDebouncedWorkflow';
|
||||||
import { ImageDTO } from 'services/api/types';
|
import { ImageDTO } from 'services/api/types';
|
||||||
import { useDebounce } from 'use-debounce';
|
|
||||||
import DataViewer from './DataViewer';
|
import DataViewer from './DataViewer';
|
||||||
import ImageMetadataActions from './ImageMetadataActions';
|
import ImageMetadataActions from './ImageMetadataActions';
|
||||||
|
|
||||||
@ -33,16 +31,8 @@ const ImageMetadataViewer = ({ image }: ImageMetadataViewerProps) => {
|
|||||||
// });
|
// });
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [debouncedImageName] = useDebounce(image.image_name, 300);
|
const { metadata } = useDebouncedMetadata(image.image_name);
|
||||||
const [debouncedWorkflowId] = useDebounce(image.workflow_id, 300);
|
const { workflow } = useDebouncedWorkflow(image.workflow_id);
|
||||||
|
|
||||||
const { data: metadata } = useGetImageMetadataQuery(
|
|
||||||
debouncedImageName ?? skipToken
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data: workflow } = useGetWorkflowQuery(
|
|
||||||
debouncedWorkflowId ?? skipToken
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
@ -7,7 +7,6 @@ export const workflowsApi = api.injectEndpoints({
|
|||||||
endpoints: (build) => ({
|
endpoints: (build) => ({
|
||||||
getWorkflow: build.query<Workflow | undefined, string>({
|
getWorkflow: build.query<Workflow | undefined, string>({
|
||||||
query: (workflow_id) => `workflows/i/${workflow_id}`,
|
query: (workflow_id) => `workflows/i/${workflow_id}`,
|
||||||
keepUnusedDataFor: 86400, // 24 hours
|
|
||||||
providesTags: (result, error, workflow_id) => [
|
providesTags: (result, error, workflow_id) => [
|
||||||
{ type: 'Workflow', id: workflow_id },
|
{ type: 'Workflow', id: workflow_id },
|
||||||
],
|
],
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
import { skipToken } from '@reduxjs/toolkit/query';
|
||||||
|
import { useDebounce } from 'use-debounce';
|
||||||
|
import { useGetImageMetadataQuery } from '../endpoints/images';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
|
||||||
|
export const useDebouncedMetadata = (imageName?: string | null) => {
|
||||||
|
const metadataFetchDebounce = useAppSelector(
|
||||||
|
(state) => state.config.metadataFetchDebounce
|
||||||
|
);
|
||||||
|
|
||||||
|
const [debouncedImageName] = useDebounce(
|
||||||
|
imageName,
|
||||||
|
metadataFetchDebounce ?? 0
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: metadata, isLoading } = useGetImageMetadataQuery(
|
||||||
|
debouncedImageName ?? skipToken
|
||||||
|
);
|
||||||
|
|
||||||
|
return { metadata, isLoading };
|
||||||
|
};
|
@ -0,0 +1,21 @@
|
|||||||
|
import { skipToken } from '@reduxjs/toolkit/query';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { useDebounce } from 'use-debounce';
|
||||||
|
import { useGetWorkflowQuery } from '../endpoints/workflows';
|
||||||
|
|
||||||
|
export const useDebouncedWorkflow = (workflowId?: string | null) => {
|
||||||
|
const workflowFetchDebounce = useAppSelector(
|
||||||
|
(state) => state.config.workflowFetchDebounce
|
||||||
|
);
|
||||||
|
|
||||||
|
const [debouncedWorkflowID] = useDebounce(
|
||||||
|
workflowId,
|
||||||
|
workflowFetchDebounce ?? 0
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: workflow, isLoading } = useGetWorkflowQuery(
|
||||||
|
debouncedWorkflowID ?? skipToken
|
||||||
|
);
|
||||||
|
|
||||||
|
return { workflow, isLoading };
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user