mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
remove long loading state, introduce loading to gallery and model list
This commit is contained in:
parent
96212bb35f
commit
85a4d37883
@ -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 { useLogger } from 'app/logging/useLogger';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { PartialAppConfig } from 'app/types/invokeai';
|
import { PartialAppConfig } from 'app/types/invokeai';
|
||||||
import ImageUploader from 'common/components/ImageUploader';
|
import ImageUploader from 'common/components/ImageUploader';
|
||||||
import Loading from 'common/components/Loading/Loading';
|
|
||||||
import GalleryDrawer from 'features/gallery/components/GalleryPanel';
|
import GalleryDrawer from 'features/gallery/components/GalleryPanel';
|
||||||
import Lightbox from 'features/lightbox/components/Lightbox';
|
import Lightbox from 'features/lightbox/components/Lightbox';
|
||||||
import SiteHeader from 'features/system/components/SiteHeader';
|
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 FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons';
|
||||||
import InvokeTabs from 'features/ui/components/InvokeTabs';
|
import InvokeTabs from 'features/ui/components/InvokeTabs';
|
||||||
import ParametersDrawer from 'features/ui/components/ParametersDrawer';
|
import ParametersDrawer from 'features/ui/components/ParametersDrawer';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
|
||||||
import i18n from 'i18n';
|
import i18n from 'i18n';
|
||||||
import { ReactNode, memo, useCallback, useEffect, useState } from 'react';
|
import { ReactNode, memo, useCallback, useEffect, useState } from 'react';
|
||||||
import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants';
|
|
||||||
import GlobalHotkeys from './GlobalHotkeys';
|
import GlobalHotkeys from './GlobalHotkeys';
|
||||||
import Toaster from './Toaster';
|
import Toaster from './Toaster';
|
||||||
import DeleteImageModal from 'features/gallery/components/DeleteImageModal';
|
import DeleteImageModal from 'features/gallery/components/DeleteImageModal';
|
||||||
@ -59,9 +56,6 @@ const App = ({
|
|||||||
const { data: embeddingModels } = useListModelsQuery({
|
const { data: embeddingModels } = useListModelsQuery({
|
||||||
model_type: 'embedding',
|
model_type: 'embedding',
|
||||||
});
|
});
|
||||||
|
|
||||||
const [loadingOverridden, setLoadingOverridden] = useState(false);
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -73,27 +67,6 @@ const App = ({
|
|||||||
dispatch(configChanged(config));
|
dispatch(configChanged(config));
|
||||||
}, [dispatch, config, log]);
|
}, [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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<Grid w="100vw" h="100vh" position="relative" overflow="hidden">
|
<Grid w="100vw" h="100vh" position="relative" overflow="hidden">
|
||||||
@ -123,33 +96,6 @@ const App = ({
|
|||||||
|
|
||||||
<GalleryDrawer />
|
<GalleryDrawer />
|
||||||
<ParametersDrawer />
|
<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>
|
<Portal>
|
||||||
<FloatingParametersPanelButtons />
|
<FloatingParametersPanelButtons />
|
||||||
</Portal>
|
</Portal>
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
FlexProps,
|
FlexProps,
|
||||||
Grid,
|
Grid,
|
||||||
Icon,
|
Icon,
|
||||||
|
Skeleton,
|
||||||
Text,
|
Text,
|
||||||
VStack,
|
VStack,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
@ -233,7 +234,7 @@ const ImageGalleryContent = () => {
|
|||||||
borderRadius: 'base',
|
borderRadius: 'base',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ w: 'full' }}>
|
<Box sx={{ w: 'full', minWidth: '200px' }}>
|
||||||
<Flex
|
<Flex
|
||||||
ref={resizeObserverRef}
|
ref={resizeObserverRef}
|
||||||
sx={{
|
sx={{
|
||||||
@ -355,7 +356,9 @@ const ImageGalleryContent = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Flex direction="column" gap={2} h="full" w="full">
|
<Flex direction="column" gap={2} h="full" w="full">
|
||||||
{images.length || areMoreAvailable ? (
|
{isLoading ? (
|
||||||
|
<LoadingGallery />
|
||||||
|
) : images.length || areMoreAvailable ? (
|
||||||
<>
|
<>
|
||||||
<Box ref={rootRef} data-overlayscrollbars="" h="100%">
|
<Box ref={rootRef} data-overlayscrollbars="" h="100%">
|
||||||
{shouldUseSingleGalleryColumn ? (
|
{shouldUseSingleGalleryColumn ? (
|
||||||
@ -407,27 +410,7 @@ const ImageGalleryContent = () => {
|
|||||||
</IAIButton>
|
</IAIButton>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Flex
|
<EmptyGallery />
|
||||||
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>
|
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
</VStack>
|
</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);
|
export default memo(ImageGalleryContent);
|
||||||
|
@ -41,7 +41,7 @@ export const initialImagesState =
|
|||||||
offset: 0,
|
offset: 0,
|
||||||
limit: 0,
|
limit: 0,
|
||||||
total: 0,
|
total: 0,
|
||||||
isLoading: false,
|
isLoading: true,
|
||||||
categories: IMAGE_CATEGORIES,
|
categories: IMAGE_CATEGORIES,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ const ModelSelect = () => {
|
|||||||
(state: RootState) => state.generation.model
|
(state: RootState) => state.generation.model
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: pipelineModels } = useListModelsQuery({
|
const { data: pipelineModels, isLoading } = useListModelsQuery({
|
||||||
model_type: 'main',
|
model_type: 'main',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -78,7 +78,14 @@ const ModelSelect = () => {
|
|||||||
handleChangeModel(firstModel);
|
handleChangeModel(firstModel);
|
||||||
}, [handleChangeModel, pipelineModels?.ids, selectedModelId]);
|
}, [handleChangeModel, pipelineModels?.ids, selectedModelId]);
|
||||||
|
|
||||||
return (
|
return isLoading ? (
|
||||||
|
<IAIMantineSelect
|
||||||
|
label={t('modelManager.model')}
|
||||||
|
placeholder="Loading..."
|
||||||
|
disabled={true}
|
||||||
|
data={[]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<IAIMantineSelect
|
<IAIMantineSelect
|
||||||
tooltip={selectedModel?.description}
|
tooltip={selectedModel?.description}
|
||||||
label={t('modelManager.model')}
|
label={t('modelManager.model')}
|
||||||
|
Loading…
Reference in New Issue
Block a user