add option to fetch metadata from api instead of reading off of png

This commit is contained in:
Mary Hipp 2023-09-05 16:54:29 -04:00
parent 0e5eac7c21
commit 15d28bfdbf
5 changed files with 67 additions and 20 deletions

View File

@ -45,6 +45,7 @@ export type AppConfig = {
* Whether or not we should update image urls when image loading errors * Whether or not we should update image urls when image loading errors
*/ */
shouldUpdateImagesOnConnect: boolean; shouldUpdateImagesOnConnect: boolean;
shouldFetchMetadataFromApi: boolean;
disabledTabs: InvokeTabName[]; disabledTabs: InvokeTabName[];
disabledFeatures: AppFeature[]; disabledFeatures: AppFeature[];
disabledSDFeatures: SDFeature[]; disabledSDFeatures: SDFeature[];

View File

@ -27,7 +27,7 @@ import {
setShouldShowImageDetails, setShouldShowImageDetails,
setShouldShowProgressInViewer, setShouldShowProgressInViewer,
} from 'features/ui/store/uiSlice'; } from 'features/ui/store/uiSlice';
import { memo, useCallback } from 'react'; import { memo, useCallback, useMemo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
@ -49,7 +49,7 @@ import SingleSelectionMenuItems from '../ImageContextMenu/SingleSelectionMenuIte
const currentImageButtonsSelector = createSelector( const currentImageButtonsSelector = createSelector(
[stateSelector, activeTabNameSelector], [stateSelector, activeTabNameSelector],
({ gallery, system, ui }, activeTabName) => { ({ gallery, system, ui, config }, activeTabName) => {
const { isProcessing, isConnected, shouldConfirmOnDelete, progressImage } = const { isProcessing, isConnected, shouldConfirmOnDelete, progressImage } =
system; system;
@ -59,6 +59,8 @@ const currentImageButtonsSelector = createSelector(
shouldShowProgressInViewer, shouldShowProgressInViewer,
} = ui; } = ui;
const { shouldFetchMetadataFromApi } = config;
const lastSelectedImage = gallery.selection[gallery.selection.length - 1]; const lastSelectedImage = gallery.selection[gallery.selection.length - 1];
return { return {
@ -72,6 +74,7 @@ const currentImageButtonsSelector = createSelector(
shouldHidePreview, shouldHidePreview,
shouldShowProgressInViewer, shouldShowProgressInViewer,
lastSelectedImage, lastSelectedImage,
shouldFetchMetadataFromApi,
}; };
}, },
{ {
@ -92,6 +95,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
shouldShowImageDetails, shouldShowImageDetails,
lastSelectedImage, lastSelectedImage,
shouldShowProgressInViewer, shouldShowProgressInViewer,
shouldFetchMetadataFromApi,
} = useAppSelector(currentImageButtonsSelector); } = useAppSelector(currentImageButtonsSelector);
const isUpscalingEnabled = useFeatureStatus('upscaling').isFeatureEnabled; const isUpscalingEnabled = useFeatureStatus('upscaling').isFeatureEnabled;
@ -106,8 +110,16 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
lastSelectedImage?.image_name ?? skipToken lastSelectedImage?.image_name ?? skipToken
); );
const getMetadataArg = useMemo(() => {
if (lastSelectedImage) {
return { image: lastSelectedImage, shouldFetchMetadataFromApi };
} else {
return skipToken;
}
}, [lastSelectedImage, shouldFetchMetadataFromApi]);
const { metadata, workflow, isLoading } = useGetImageMetadataFromFileQuery( const { metadata, workflow, isLoading } = useGetImageMetadataFromFileQuery(
lastSelectedImage ?? skipToken, getMetadataArg,
{ {
selectFromResult: (res) => ({ selectFromResult: (res) => ({
isLoading: res.isFetching, isLoading: res.isFetching,

View File

@ -1,6 +1,6 @@
import { Flex, MenuItem, Spinner } from '@chakra-ui/react'; import { Flex, MenuItem, Spinner } from '@chakra-ui/react';
import { useAppToaster } from 'app/components/Toaster'; import { useAppToaster } from 'app/components/Toaster';
import { useAppDispatch } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice'; import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
import { import {
imagesToChangeSelected, imagesToChangeSelected,
@ -34,6 +34,7 @@ import {
import { ImageDTO } from 'services/api/types'; import { ImageDTO } from 'services/api/types';
import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions'; import { sentImageToCanvas, sentImageToImg2Img } from '../../store/actions';
import { workflowLoadRequested } from 'features/nodes/store/actions'; import { workflowLoadRequested } from 'features/nodes/store/actions';
import { configSelector } from '../../../system/store/configSelectors';
type SingleSelectionMenuItemsProps = { type SingleSelectionMenuItemsProps = {
imageDTO: ImageDTO; imageDTO: ImageDTO;
@ -48,9 +49,10 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
const toaster = useAppToaster(); const toaster = useAppToaster();
const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled; const isCanvasEnabled = useFeatureStatus('unifiedCanvas').isFeatureEnabled;
const { shouldFetchMetadataFromApi } = useAppSelector(configSelector);
const { metadata, workflow, isLoading } = useGetImageMetadataFromFileQuery( const { metadata, workflow, isLoading } = useGetImageMetadataFromFileQuery(
imageDTO, { image: imageDTO, shouldFetchMetadataFromApi },
{ {
selectFromResult: (res) => ({ selectFromResult: (res) => ({
isLoading: res.isFetching, isLoading: res.isFetching,

View File

@ -15,6 +15,8 @@ import { useGetImageMetadataFromFileQuery } from 'services/api/endpoints/images'
import { ImageDTO } from 'services/api/types'; import { ImageDTO } from 'services/api/types';
import DataViewer from './DataViewer'; import DataViewer from './DataViewer';
import ImageMetadataActions from './ImageMetadataActions'; import ImageMetadataActions from './ImageMetadataActions';
import { useAppSelector } from '../../../../app/store/storeHooks';
import { configSelector } from '../../../system/store/configSelectors';
type ImageMetadataViewerProps = { type ImageMetadataViewerProps = {
image: ImageDTO; image: ImageDTO;
@ -27,12 +29,17 @@ const ImageMetadataViewer = ({ image }: ImageMetadataViewerProps) => {
// dispatch(setShouldShowImageDetails(false)); // dispatch(setShouldShowImageDetails(false));
// }); // });
const { metadata, workflow } = useGetImageMetadataFromFileQuery(image, { const { shouldFetchMetadataFromApi } = useAppSelector(configSelector);
const { metadata, workflow } = useGetImageMetadataFromFileQuery(
{ image, shouldFetchMetadataFromApi },
{
selectFromResult: (res) => ({ selectFromResult: (res) => ({
metadata: res?.currentData?.metadata, metadata: res?.currentData?.metadata,
workflow: res?.currentData?.workflow, workflow: res?.currentData?.workflow,
}), }),
}); }
);
return ( return (
<Flex <Flex

View File

@ -7,7 +7,7 @@ import {
IMAGE_LIMIT, IMAGE_LIMIT,
} from 'features/gallery/store/types'; } from 'features/gallery/store/types';
import { getMetadataAndWorkflowFromImageBlob } from 'features/nodes/util/getMetadataAndWorkflowFromImageBlob'; import { getMetadataAndWorkflowFromImageBlob } from 'features/nodes/util/getMetadataAndWorkflowFromImageBlob';
import { keyBy } from 'lodash-es'; import { isUndefined, keyBy } from 'lodash-es';
import { ApiFullTagDescription, LIST_TAG, api } from '..'; import { ApiFullTagDescription, LIST_TAG, api } from '..';
import { components, paths } from '../schema'; import { components, paths } from '../schema';
import { import {
@ -28,8 +28,12 @@ import {
} from '../util'; } from '../util';
import { boardsApi } from './boards'; import { boardsApi } from './boards';
import { ImageMetadataAndWorkflow } from 'features/nodes/types/types'; import { ImageMetadataAndWorkflow } from 'features/nodes/types/types';
import { fetchBaseQuery } from '@reduxjs/toolkit/dist/query'; import {
FetchBaseQueryError,
fetchBaseQuery,
} from '@reduxjs/toolkit/dist/query';
import { $authToken, $projectId } from '../client'; import { $authToken, $projectId } from '../client';
import { QueryReturnValue } from '@reduxjs/toolkit/dist/query/baseQueryTypes';
export const imagesApi = api.injectEndpoints({ export const imagesApi = api.injectEndpoints({
endpoints: (build) => ({ endpoints: (build) => ({
@ -117,8 +121,16 @@ export const imagesApi = api.injectEndpoints({
], ],
keepUnusedDataFor: 86400, // 24 hours keepUnusedDataFor: 86400, // 24 hours
}), }),
getImageMetadataFromFile: build.query<ImageMetadataAndWorkflow, ImageDTO>({ getImageMetadataFromFile: build.query<
queryFn: async (args: ImageDTO, api, extraOptions) => { ImageMetadataAndWorkflow,
{ image: ImageDTO; shouldFetchMetadataFromApi: boolean }
>({
queryFn: async (
args: { image: ImageDTO; shouldFetchMetadataFromApi: boolean },
api,
extraOptions,
fetchWithBaseQuery
) => {
const authToken = $authToken.get(); const authToken = $authToken.get();
const projectId = $projectId.get(); const projectId = $projectId.get();
const customBaseQuery = fetchBaseQuery({ const customBaseQuery = fetchBaseQuery({
@ -139,17 +151,30 @@ export const imagesApi = api.injectEndpoints({
}); });
const response = await customBaseQuery( const response = await customBaseQuery(
args.image_url, args.image.image_url,
api, api,
extraOptions extraOptions
); );
const data = await getMetadataAndWorkflowFromImageBlob( const blobData = await getMetadataAndWorkflowFromImageBlob(
response.data as Blob response.data as Blob
); );
return { data };
let metadata = blobData.metadata;
if (args.shouldFetchMetadataFromApi) {
const metadataResult = await fetchWithBaseQuery(
`images/i/${args.image.image_name}/metadata`
);
if (metadataResult.data) {
metadata = (metadataResult.data as UnsafeImageMetadata)
.metadata as UnsafeImageMetadata['metadata'];
}
}
return { data: { ...blobData, metadata } };
}, },
providesTags: (result, error, image_dto) => [ providesTags: (result, error, { image, shouldFetchMetadataFromApi }) => [
{ type: 'ImageMetadataFromFile', id: image_dto.image_name }, { type: 'ImageMetadataFromFile', id: image.image_name },
], ],
keepUnusedDataFor: 86400, // 24 hours keepUnusedDataFor: 86400, // 24 hours
}), }),