mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
(ui): improve loader/fetching state while searching, make search term a string in redux
This commit is contained in:
parent
134d831ebf
commit
20d5c3a8bf
@ -19,11 +19,10 @@ const GalleryImageGrid = () => {
|
|||||||
useGalleryHotkeys();
|
useGalleryHotkeys();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const queryArgs = useAppSelector(selectListImagesQueryArgs);
|
const queryArgs = useAppSelector(selectListImagesQueryArgs);
|
||||||
const { imageDTOs, isLoading, isFetching, isError } = useListImagesQuery(queryArgs, {
|
const { imageDTOs, isLoading, isError } = useListImagesQuery(queryArgs, {
|
||||||
selectFromResult: ({ data, isLoading, isFetching, isSuccess, isError }) => ({
|
selectFromResult: ({ data, isLoading, isSuccess, isError }) => ({
|
||||||
imageDTOs: data?.items ?? EMPTY_ARRAY,
|
imageDTOs: data?.items ?? EMPTY_ARRAY,
|
||||||
isLoading,
|
isLoading,
|
||||||
isFetching,
|
|
||||||
isSuccess,
|
isSuccess,
|
||||||
isError,
|
isError,
|
||||||
}),
|
}),
|
||||||
@ -37,7 +36,7 @@ const GalleryImageGrid = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLoading || isFetching) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<Flex w="full" h="full" alignItems="center" justifyContent="center">
|
<Flex w="full" h="full" alignItems="center" justifyContent="center">
|
||||||
<IAINoContentFallback label={t('gallery.loading')} icon={PiImageBold} />
|
<IAINoContentFallback label={t('gallery.loading')} icon={PiImageBold} />
|
||||||
|
@ -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 { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { selectListImagesQueryArgs } from 'features/gallery/store/gallerySelectors';
|
||||||
import { searchTermChanged } from 'features/gallery/store/gallerySlice';
|
import { searchTermChanged } from 'features/gallery/store/gallerySlice';
|
||||||
import { debounce } from 'lodash-es';
|
import { debounce } from 'lodash-es';
|
||||||
import type { ChangeEvent } from 'react';
|
import type { ChangeEvent } from 'react';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiXBold } from 'react-icons/pi';
|
import { PiXBold } from 'react-icons/pi';
|
||||||
|
import { useListImagesQuery } from 'services/api/endpoints/images';
|
||||||
|
|
||||||
export const GallerySearch = () => {
|
export const GallerySearch = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { searchTerm } = useAppSelector((s) => s.gallery);
|
const { searchTerm } = useAppSelector((s) => s.gallery);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const queryArgs = useAppSelector(selectListImagesQueryArgs);
|
||||||
|
const { isFetching } = useListImagesQuery(queryArgs);
|
||||||
|
|
||||||
const [searchTermInput, setSearchTermInput] = useState(searchTerm);
|
const [searchTermInput, setSearchTermInput] = useState(searchTerm);
|
||||||
|
|
||||||
const debouncedSetSearchTerm = useMemo(() => {
|
const debouncedSetSearchTerm = useMemo(() => {
|
||||||
@ -40,17 +45,24 @@ export const GallerySearch = () => {
|
|||||||
value={searchTermInput}
|
value={searchTermInput}
|
||||||
onChange={handleChangeInput}
|
onChange={handleChangeInput}
|
||||||
data-testid="image-search-input"
|
data-testid="image-search-input"
|
||||||
|
disabled={isFetching}
|
||||||
/>
|
/>
|
||||||
{searchTermInput && searchTermInput.length && (
|
{isFetching ? (
|
||||||
<InputRightElement h="full" pe={2}>
|
<InputRightElement h="full" pe={2}>
|
||||||
<IconButton
|
<Spinner size="sm" />
|
||||||
onClick={handleClearInput}
|
|
||||||
size="sm"
|
|
||||||
variant="link"
|
|
||||||
aria-label={t('boards.clearSearch')}
|
|
||||||
icon={<PiXBold />}
|
|
||||||
/>
|
|
||||||
</InputRightElement>
|
</InputRightElement>
|
||||||
|
) : (
|
||||||
|
searchTermInput.length && (
|
||||||
|
<InputRightElement h="full" pe={2}>
|
||||||
|
<IconButton
|
||||||
|
onClick={handleClearInput}
|
||||||
|
size="sm"
|
||||||
|
variant="link"
|
||||||
|
aria-label={t('boards.clearSearch')}
|
||||||
|
icon={<PiXBold />}
|
||||||
|
/>
|
||||||
|
</InputRightElement>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
);
|
);
|
||||||
|
@ -22,7 +22,7 @@ export const selectListImagesQueryArgs = createMemoizedSelector(
|
|||||||
is_intermediate: false,
|
is_intermediate: false,
|
||||||
starred_first: gallery.starredFirst,
|
starred_first: gallery.starredFirst,
|
||||||
order_dir: gallery.orderDir,
|
order_dir: gallery.orderDir,
|
||||||
search_term: gallery.searchTerm,
|
search_term: gallery.searchTerm.length ? gallery.searchTerm : undefined,
|
||||||
}
|
}
|
||||||
: skipToken
|
: skipToken
|
||||||
);
|
);
|
||||||
|
@ -20,6 +20,7 @@ const initialGalleryState: GalleryState = {
|
|||||||
offset: 0,
|
offset: 0,
|
||||||
starredFirst: true,
|
starredFirst: true,
|
||||||
orderDir: 'ASC',
|
orderDir: 'ASC',
|
||||||
|
searchTerm: '',
|
||||||
isImageViewerOpen: true,
|
isImageViewerOpen: true,
|
||||||
imageToCompare: null,
|
imageToCompare: null,
|
||||||
comparisonMode: 'slider',
|
comparisonMode: 'slider',
|
||||||
@ -118,7 +119,7 @@ export const gallerySlice = createSlice({
|
|||||||
orderDirChanged: (state, action: PayloadAction<OrderDir>) => {
|
orderDirChanged: (state, action: PayloadAction<OrderDir>) => {
|
||||||
state.orderDir = action.payload;
|
state.orderDir = action.payload;
|
||||||
},
|
},
|
||||||
searchTermChanged: (state, action: PayloadAction<string | undefined>) => {
|
searchTermChanged: (state, action: PayloadAction<string>) => {
|
||||||
state.searchTerm = action.payload;
|
state.searchTerm = action.payload;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -22,7 +22,7 @@ export type GalleryState = {
|
|||||||
limit: number;
|
limit: number;
|
||||||
starredFirst: boolean;
|
starredFirst: boolean;
|
||||||
orderDir: OrderDir;
|
orderDir: OrderDir;
|
||||||
searchTerm?: string;
|
searchTerm: string;
|
||||||
alwaysShowImageSizeBadge: boolean;
|
alwaysShowImageSizeBadge: boolean;
|
||||||
imageToCompare: ImageDTO | null;
|
imageToCompare: ImageDTO | null;
|
||||||
comparisonMode: ComparisonMode;
|
comparisonMode: ComparisonMode;
|
||||||
|
Loading…
Reference in New Issue
Block a user