mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
add option to fetch metadata from api instead of reading off of png
This commit is contained in:
parent
0e5eac7c21
commit
15d28bfdbf
@ -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[];
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}),
|
}),
|
||||||
|
Loading…
Reference in New Issue
Block a user