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:
psychedelicious 2023-10-18 21:23:09 +11:00
parent 2faed653d7
commit f04462973b
7 changed files with 62 additions and 42 deletions

View File

@ -59,6 +59,8 @@ export type AppConfig = {
nodesAllowlist: string[] | undefined;
nodesDenylist: string[] | undefined;
maxUpscalePixels?: number;
metadataFetchDebounce?: number;
workflowFetchDebounce?: number;
sd: {
defaultModel?: string;
disabledControlNetModels: string[];

View File

@ -38,15 +38,12 @@ import {
FaSeedling,
} from 'react-icons/fa';
import { FaCircleNodes, FaEllipsis } from 'react-icons/fa6';
import {
useGetImageDTOQuery,
useGetImageMetadataQuery,
} from 'services/api/endpoints/images';
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
import { useDebouncedMetadata } from 'services/api/hooks/useDebouncedMetadata';
import { useDebouncedWorkflow } from 'services/api/hooks/useDebouncedWorkflow';
import { menuListMotionProps } from 'theme/components/menu';
import { useDebounce } from 'use-debounce';
import { sentImageToImg2Img } from '../../store/actions';
import SingleSelectionMenuItems from '../ImageContextMenu/SingleSelectionMenuItems';
import { useGetWorkflowQuery } from 'services/api/endpoints/workflows';
const currentImageButtonsSelector = createSelector(
[stateSelector, activeTabNameSelector],
@ -105,17 +102,12 @@ const CurrentImageButtons = () => {
lastSelectedImage?.image_name ?? skipToken
);
const [debouncedImageName] = useDebounce(lastSelectedImage?.image_name, 300);
const [debouncedWorkflowId] = useDebounce(
lastSelectedImage?.workflow_id,
300
const { metadata, isLoading: isLoadingMetadata } = useDebouncedMetadata(
lastSelectedImage?.image_name
);
const { data: metadata, isLoading: isLoadingMetadata } =
useGetImageMetadataQuery(debouncedImageName ?? skipToken);
const { data: workflow, isLoading: isLoadingWorkflow } = useGetWorkflowQuery(
debouncedWorkflowId ?? skipToken
const { workflow, isLoading: isLoadingWorkflow } = useDebouncedWorkflow(
lastSelectedImage?.workflow_id
);
const handleLoadWorkflow = useCallback(() => {

View File

@ -1,6 +1,5 @@
import { Flex, MenuItem, Spinner } from '@chakra-ui/react';
import { useStore } from '@nanostores/react';
import { skipToken } from '@reduxjs/toolkit/dist/query';
import { useAppToaster } from 'app/components/Toaster';
import { $customStarUI } from 'app/store/nanostores/customStarUI';
import { useAppDispatch } from 'app/store/storeHooks';
@ -33,13 +32,12 @@ import {
import { FaCircleNodes } from 'react-icons/fa6';
import { MdStar, MdStarBorder } from 'react-icons/md';
import {
useGetImageMetadataQuery,
useStarImagesMutation,
useUnstarImagesMutation,
} 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 { useDebounce } from 'use-debounce';
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
type SingleSelectionMenuItemsProps = {
@ -57,14 +55,11 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled;
const customStarUi = useStore($customStarUI);
const [debouncedImageName] = useDebounce(imageDTO?.image_name, 300);
const [debouncedWorkflowId] = useDebounce(imageDTO?.workflow_id, 300);
const { data: metadata, isLoading: isLoadingMetadata } =
useGetImageMetadataQuery(debouncedImageName ?? skipToken);
const { data: workflow, isLoading: isLoadingWorkflow } = useGetWorkflowQuery(
debouncedWorkflowId ?? skipToken
const { metadata, isLoading: isLoadingMetadata } = useDebouncedMetadata(
imageDTO?.image_name
);
const { workflow, isLoading: isLoadingWorkflow } = useDebouncedWorkflow(
imageDTO?.workflow_id
);
const [starImages] = useStarImagesMutation();

View File

@ -9,15 +9,13 @@ import {
Tabs,
Text,
} from '@chakra-ui/react';
import { skipToken } from '@reduxjs/toolkit/dist/query';
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
import ScrollableContent from 'features/nodes/components/sidePanel/ScrollableContent';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { useGetImageMetadataQuery } 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 { useDebounce } from 'use-debounce';
import DataViewer from './DataViewer';
import ImageMetadataActions from './ImageMetadataActions';
@ -33,16 +31,8 @@ const ImageMetadataViewer = ({ image }: ImageMetadataViewerProps) => {
// });
const { t } = useTranslation();
const [debouncedImageName] = useDebounce(image.image_name, 300);
const [debouncedWorkflowId] = useDebounce(image.workflow_id, 300);
const { data: metadata } = useGetImageMetadataQuery(
debouncedImageName ?? skipToken
);
const { data: workflow } = useGetWorkflowQuery(
debouncedWorkflowId ?? skipToken
);
const { metadata } = useDebouncedMetadata(image.image_name);
const { workflow } = useDebouncedWorkflow(image.workflow_id);
return (
<Flex

View File

@ -7,7 +7,6 @@ export const workflowsApi = api.injectEndpoints({
endpoints: (build) => ({
getWorkflow: build.query<Workflow | undefined, string>({
query: (workflow_id) => `workflows/i/${workflow_id}`,
keepUnusedDataFor: 86400, // 24 hours
providesTags: (result, error, workflow_id) => [
{ type: 'Workflow', id: workflow_id },
],

View File

@ -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 };
};

View File

@ -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 };
};