From 20d5c3a8bfb9e61039fc6ba17ba525b2b9847d53 Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Sun, 30 Jun 2024 20:55:18 -0400 Subject: [PATCH] (ui): improve loader/fetching state while searching, make search term a string in redux --- .../components/ImageGrid/GalleryImageGrid.tsx | 7 ++--- .../components/ImageGrid/GallerySearch.tsx | 30 +++++++++++++------ .../gallery/store/gallerySelectors.ts | 2 +- .../features/gallery/store/gallerySlice.ts | 3 +- .../web/src/features/gallery/store/types.ts | 2 +- 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx index cfcf527c6e..0be30505d5 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx @@ -19,11 +19,10 @@ const GalleryImageGrid = () => { useGalleryHotkeys(); const { t } = useTranslation(); const queryArgs = useAppSelector(selectListImagesQueryArgs); - const { imageDTOs, isLoading, isFetching, isError } = useListImagesQuery(queryArgs, { - selectFromResult: ({ data, isLoading, isFetching, isSuccess, isError }) => ({ + const { imageDTOs, isLoading, isError } = useListImagesQuery(queryArgs, { + selectFromResult: ({ data, isLoading, isSuccess, isError }) => ({ imageDTOs: data?.items ?? EMPTY_ARRAY, isLoading, - isFetching, isSuccess, isError, }), @@ -37,7 +36,7 @@ const GalleryImageGrid = () => { ); } - if (isLoading || isFetching) { + if (isLoading) { return ( diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GallerySearch.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GallerySearch.tsx index 0221a53533..064783329d 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GallerySearch.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GallerySearch.tsx @@ -1,17 +1,22 @@ -import { IconButton, Input, InputGroup, InputRightElement } from '@invoke-ai/ui-library'; +import { IconButton, Input, InputGroup, InputRightElement, Spinner } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { selectListImagesQueryArgs } from 'features/gallery/store/gallerySelectors'; import { searchTermChanged } from 'features/gallery/store/gallerySlice'; import { debounce } from 'lodash-es'; import type { ChangeEvent } from 'react'; import { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { PiXBold } from 'react-icons/pi'; +import { useListImagesQuery } from 'services/api/endpoints/images'; export const GallerySearch = () => { const dispatch = useAppDispatch(); const { searchTerm } = useAppSelector((s) => s.gallery); const { t } = useTranslation(); + const queryArgs = useAppSelector(selectListImagesQueryArgs); + const { isFetching } = useListImagesQuery(queryArgs); + const [searchTermInput, setSearchTermInput] = useState(searchTerm); const debouncedSetSearchTerm = useMemo(() => { @@ -40,17 +45,24 @@ export const GallerySearch = () => { value={searchTermInput} onChange={handleChangeInput} data-testid="image-search-input" + disabled={isFetching} /> - {searchTermInput && searchTermInput.length && ( + {isFetching ? ( - } - /> + + ) : ( + searchTermInput.length && ( + + } + /> + + ) )} ); diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts index 76ed4c6659..b9d78eb4c3 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts @@ -22,7 +22,7 @@ export const selectListImagesQueryArgs = createMemoizedSelector( is_intermediate: false, starred_first: gallery.starredFirst, order_dir: gallery.orderDir, - search_term: gallery.searchTerm, + search_term: gallery.searchTerm.length ? gallery.searchTerm : undefined, } : skipToken ); diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index 9ae7be7606..76376df4dd 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -20,6 +20,7 @@ const initialGalleryState: GalleryState = { offset: 0, starredFirst: true, orderDir: 'ASC', + searchTerm: '', isImageViewerOpen: true, imageToCompare: null, comparisonMode: 'slider', @@ -118,7 +119,7 @@ export const gallerySlice = createSlice({ orderDirChanged: (state, action: PayloadAction) => { state.orderDir = action.payload; }, - searchTermChanged: (state, action: PayloadAction) => { + searchTermChanged: (state, action: PayloadAction) => { state.searchTerm = action.payload; }, }, diff --git a/invokeai/frontend/web/src/features/gallery/store/types.ts b/invokeai/frontend/web/src/features/gallery/store/types.ts index 03d2082d10..7d7a321515 100644 --- a/invokeai/frontend/web/src/features/gallery/store/types.ts +++ b/invokeai/frontend/web/src/features/gallery/store/types.ts @@ -22,7 +22,7 @@ export type GalleryState = { limit: number; starredFirst: boolean; orderDir: OrderDir; - searchTerm?: string; + searchTerm: string; alwaysShowImageSizeBadge: boolean; imageToCompare: ImageDTO | null; comparisonMode: ComparisonMode;