remove long loading state, introduce loading to gallery and model list

This commit is contained in:
Mary Hipp 2023-06-30 13:26:46 -04:00 committed by psychedelicious
parent 96212bb35f
commit 85a4d37883
4 changed files with 63 additions and 81 deletions

View File

@ -1,9 +1,8 @@
import { Box, Flex, Grid, Portal } from '@chakra-ui/react';
import { Flex, Grid, Portal } from '@chakra-ui/react';
import { useLogger } from 'app/logging/useLogger';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { PartialAppConfig } from 'app/types/invokeai';
import ImageUploader from 'common/components/ImageUploader';
import Loading from 'common/components/Loading/Loading';
import GalleryDrawer from 'features/gallery/components/GalleryPanel';
import Lightbox from 'features/lightbox/components/Lightbox';
import SiteHeader from 'features/system/components/SiteHeader';
@ -15,10 +14,8 @@ import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton'
import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons';
import InvokeTabs from 'features/ui/components/InvokeTabs';
import ParametersDrawer from 'features/ui/components/ParametersDrawer';
import { AnimatePresence, motion } from 'framer-motion';
import i18n from 'i18n';
import { ReactNode, memo, useCallback, useEffect, useState } from 'react';
import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants';
import GlobalHotkeys from './GlobalHotkeys';
import Toaster from './Toaster';
import DeleteImageModal from 'features/gallery/components/DeleteImageModal';
@ -59,9 +56,6 @@ const App = ({
const { data: embeddingModels } = useListModelsQuery({
model_type: 'embedding',
});
const [loadingOverridden, setLoadingOverridden] = useState(false);
const dispatch = useAppDispatch();
useEffect(() => {
@ -73,27 +67,6 @@ const App = ({
dispatch(configChanged(config));
}, [dispatch, config, log]);
const handleOverrideClicked = useCallback(() => {
setLoadingOverridden(true);
}, []);
useEffect(() => {
if (isApplicationReady && setIsReady) {
setIsReady(true);
}
if (isApplicationReady) {
// TODO: This is a jank fix for canvas not filling the screen on first load
setTimeout(() => {
dispatch(requestCanvasRescale());
}, 200);
}
return () => {
setIsReady && setIsReady(false);
};
}, [dispatch, isApplicationReady, setIsReady]);
return (
<>
<Grid w="100vw" h="100vh" position="relative" overflow="hidden">
@ -123,33 +96,6 @@ const App = ({
<GalleryDrawer />
<ParametersDrawer />
<AnimatePresence>
{!isApplicationReady && !loadingOverridden && (
<motion.div
key="loading"
initial={{ opacity: 1 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.3 }}
style={{ zIndex: 3 }}
>
<Box position="absolute" top={0} left={0} w="100vw" h="100vh">
<Loading />
</Box>
<Box
onClick={handleOverrideClicked}
position="absolute"
top={0}
right={0}
cursor="pointer"
w="2rem"
h="2rem"
/>
</motion.div>
)}
</AnimatePresence>
<Portal>
<FloatingParametersPanelButtons />
</Portal>

View File

@ -6,6 +6,7 @@ import {
FlexProps,
Grid,
Icon,
Skeleton,
Text,
VStack,
forwardRef,
@ -233,7 +234,7 @@ const ImageGalleryContent = () => {
borderRadius: 'base',
}}
>
<Box sx={{ w: 'full' }}>
<Box sx={{ w: 'full', minWidth: '200px' }}>
<Flex
ref={resizeObserverRef}
sx={{
@ -355,7 +356,9 @@ const ImageGalleryContent = () => {
</Box>
</Box>
<Flex direction="column" gap={2} h="full" w="full">
{images.length || areMoreAvailable ? (
{isLoading ? (
<LoadingGallery />
) : images.length || areMoreAvailable ? (
<>
<Box ref={rootRef} data-overlayscrollbars="" h="100%">
{shouldUseSingleGalleryColumn ? (
@ -407,27 +410,7 @@ const ImageGalleryContent = () => {
</IAIButton>
</>
) : (
<Flex
sx={{
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: 2,
padding: 8,
h: '100%',
w: '100%',
color: 'base.500',
}}
>
<Icon
as={MdPhotoLibrary}
sx={{
w: 16,
h: 16,
}}
/>
<Text textAlign="center">{t('gallery.noImagesInGallery')}</Text>
</Flex>
<EmptyGallery />
)}
</Flex>
</VStack>
@ -462,4 +445,50 @@ const ListContainer = forwardRef((props: ListContainerProps, ref) => {
);
});
const LoadingGallery = () => {
return (
<Box data-overlayscrollbars="" h="100%">
<VirtuosoGrid
style={{ height: '100%' }}
data={new Array(20)}
components={{
Item: ItemContainer,
List: ListContainer,
}}
itemContent={(index, item) => (
<Flex sx={{ pb: 2 }}>
<Skeleton sx={{ width: 'full', paddingBottom: '100%' }} />
</Flex>
)}
/>
</Box>
);
};
const EmptyGallery = () => {
const { t } = useTranslation();
return (
<Flex
sx={{
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: 2,
padding: 8,
h: '100%',
w: '100%',
color: 'base.500',
}}
>
<Icon
as={MdPhotoLibrary}
sx={{
w: 16,
h: 16,
}}
/>
<Text textAlign="center">{t('gallery.noImagesInGallery')}</Text>
</Flex>
);
};
export default memo(ImageGalleryContent);

View File

@ -41,7 +41,7 @@ export const initialImagesState =
offset: 0,
limit: 0,
total: 0,
isLoading: false,
isLoading: true,
categories: IMAGE_CATEGORIES,
});

View File

@ -23,7 +23,7 @@ const ModelSelect = () => {
(state: RootState) => state.generation.model
);
const { data: pipelineModels } = useListModelsQuery({
const { data: pipelineModels, isLoading } = useListModelsQuery({
model_type: 'main',
});
@ -78,7 +78,14 @@ const ModelSelect = () => {
handleChangeModel(firstModel);
}, [handleChangeModel, pipelineModels?.ids, selectedModelId]);
return (
return isLoading ? (
<IAIMantineSelect
label={t('modelManager.model')}
placeholder="Loading..."
disabled={true}
data={[]}
/>
) : (
<IAIMantineSelect
tooltip={selectedModel?.description}
label={t('modelManager.model')}