mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): rename main app components
This commit is contained in:
parent
de574eb4d9
commit
d582949488
@ -1,70 +1,126 @@
|
|||||||
import React, { lazy, memo, PropsWithChildren, useEffect } from 'react';
|
import ImageUploader from 'common/components/ImageUploader';
|
||||||
import { Provider } from 'react-redux';
|
import Console from 'features/system/components/Console';
|
||||||
import { PersistGate } from 'redux-persist/integration/react';
|
import ProgressBar from 'features/system/components/ProgressBar';
|
||||||
import { buildMiddleware, store } from 'app/store/store';
|
import SiteHeader from 'features/system/components/SiteHeader';
|
||||||
import { persistor } from '../store/persistor';
|
import InvokeTabs from 'features/ui/components/InvokeTabs';
|
||||||
import { OpenAPI } from 'services/api';
|
|
||||||
import '@fontsource/inter/100.css';
|
|
||||||
import '@fontsource/inter/200.css';
|
|
||||||
import '@fontsource/inter/300.css';
|
|
||||||
import '@fontsource/inter/400.css';
|
|
||||||
import '@fontsource/inter/500.css';
|
|
||||||
import '@fontsource/inter/600.css';
|
|
||||||
import '@fontsource/inter/700.css';
|
|
||||||
import '@fontsource/inter/800.css';
|
|
||||||
import '@fontsource/inter/900.css';
|
|
||||||
|
|
||||||
import Loading from '../../common/components/Loading/Loading';
|
import useToastWatcher from 'features/system/hooks/useToastWatcher';
|
||||||
import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares';
|
|
||||||
|
import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton';
|
||||||
|
import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons';
|
||||||
|
import { Box, Flex, Grid, Portal, useColorMode } from '@chakra-ui/react';
|
||||||
|
import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants';
|
||||||
|
import ImageGalleryPanel from 'features/gallery/components/ImageGalleryPanel';
|
||||||
|
import Lightbox from 'features/lightbox/components/Lightbox';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import {
|
||||||
|
memo,
|
||||||
|
PropsWithChildren,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
import Loading from 'common/components/Loading/Loading';
|
||||||
|
import { useIsApplicationReady } from 'features/system/hooks/useIsApplicationReady';
|
||||||
import { PartialAppConfig } from 'app/types/invokeai';
|
import { PartialAppConfig } from 'app/types/invokeai';
|
||||||
|
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
|
||||||
import '../../i18n';
|
import { configChanged } from 'features/system/store/configSlice';
|
||||||
|
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||||
const InvokeAIUI = lazy(() => import('./InvokeAIUI'));
|
|
||||||
const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider'));
|
|
||||||
|
|
||||||
interface Props extends PropsWithChildren {
|
interface Props extends PropsWithChildren {
|
||||||
apiUrl?: string;
|
|
||||||
token?: string;
|
|
||||||
config?: PartialAppConfig;
|
config?: PartialAppConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
const App = ({ apiUrl, token, config, children }: Props) => {
|
const App = ({ config = {}, children }: Props) => {
|
||||||
|
useToastWatcher();
|
||||||
|
useGlobalHotkeys();
|
||||||
|
|
||||||
|
const currentTheme = useAppSelector((state) => state.ui.currentTheme);
|
||||||
|
|
||||||
|
const isLightboxEnabled = useFeatureStatus('lightbox').isFeatureEnabled;
|
||||||
|
|
||||||
|
const isApplicationReady = useIsApplicationReady();
|
||||||
|
|
||||||
|
const [loadingOverridden, setLoadingOverridden] = useState(false);
|
||||||
|
|
||||||
|
const { setColorMode } = useColorMode();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// configure API client token
|
console.log('Received config: ', config);
|
||||||
if (token) {
|
dispatch(configChanged(config));
|
||||||
OpenAPI.TOKEN = token;
|
}, [dispatch, config]);
|
||||||
}
|
|
||||||
|
|
||||||
// configure API client base url
|
useEffect(() => {
|
||||||
if (apiUrl) {
|
setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark');
|
||||||
OpenAPI.BASE = apiUrl;
|
}, [setColorMode, currentTheme]);
|
||||||
}
|
|
||||||
|
|
||||||
// reset dynamically added middlewares
|
const handleOverrideClicked = useCallback(() => {
|
||||||
resetMiddlewares();
|
setLoadingOverridden(true);
|
||||||
|
}, []);
|
||||||
// TODO: at this point, after resetting the middleware, we really ought to clean up the socket
|
|
||||||
// stuff by calling `dispatch(socketReset())`. but we cannot dispatch from here as we are
|
|
||||||
// outside the provider. it's not needed until there is the possibility that we will change
|
|
||||||
// the `apiUrl`/`token` dynamically.
|
|
||||||
|
|
||||||
// rebuild socket middleware with token and apiUrl
|
|
||||||
addMiddleware(buildMiddleware());
|
|
||||||
}, [apiUrl, token]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.StrictMode>
|
<Grid w="100vw" h="100vh" position="relative">
|
||||||
<Provider store={store}>
|
{isLightboxEnabled && <Lightbox />}
|
||||||
<PersistGate loading={<Loading />} persistor={persistor}>
|
<ImageUploader>
|
||||||
<React.Suspense fallback={<Loading />}>
|
<ProgressBar />
|
||||||
<ThemeLocaleProvider>
|
<Grid
|
||||||
<InvokeAIUI config={config}>{children}</InvokeAIUI>
|
gap={4}
|
||||||
</ThemeLocaleProvider>
|
p={4}
|
||||||
</React.Suspense>
|
gridAutoRows="min-content auto"
|
||||||
</PersistGate>
|
w={APP_WIDTH}
|
||||||
</Provider>
|
h={APP_HEIGHT}
|
||||||
</React.StrictMode>
|
>
|
||||||
|
{children || <SiteHeader />}
|
||||||
|
<Flex
|
||||||
|
gap={4}
|
||||||
|
w={{ base: '100vw', xl: 'full' }}
|
||||||
|
h="full"
|
||||||
|
flexDir={{ base: 'column', xl: 'row' }}
|
||||||
|
>
|
||||||
|
<InvokeTabs />
|
||||||
|
<ImageGalleryPanel />
|
||||||
|
</Flex>
|
||||||
|
</Grid>
|
||||||
|
</ImageUploader>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
<Portal>
|
||||||
|
<FloatingGalleryButton />
|
||||||
|
</Portal>
|
||||||
|
<Portal>
|
||||||
|
<Console />
|
||||||
|
</Portal>
|
||||||
|
</Grid>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,126 +1,70 @@
|
|||||||
import ImageUploader from 'common/components/ImageUploader';
|
import React, { lazy, memo, PropsWithChildren, useEffect } from 'react';
|
||||||
import Console from 'features/system/components/Console';
|
import { Provider } from 'react-redux';
|
||||||
import ProgressBar from 'features/system/components/ProgressBar';
|
import { PersistGate } from 'redux-persist/integration/react';
|
||||||
import SiteHeader from 'features/system/components/SiteHeader';
|
import { buildMiddleware, store } from 'app/store/store';
|
||||||
import InvokeTabs from 'features/ui/components/InvokeTabs';
|
import { persistor } from '../store/persistor';
|
||||||
|
import { OpenAPI } from 'services/api';
|
||||||
|
import '@fontsource/inter/100.css';
|
||||||
|
import '@fontsource/inter/200.css';
|
||||||
|
import '@fontsource/inter/300.css';
|
||||||
|
import '@fontsource/inter/400.css';
|
||||||
|
import '@fontsource/inter/500.css';
|
||||||
|
import '@fontsource/inter/600.css';
|
||||||
|
import '@fontsource/inter/700.css';
|
||||||
|
import '@fontsource/inter/800.css';
|
||||||
|
import '@fontsource/inter/900.css';
|
||||||
|
|
||||||
import useToastWatcher from 'features/system/hooks/useToastWatcher';
|
import Loading from '../../common/components/Loading/Loading';
|
||||||
|
import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares';
|
||||||
import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton';
|
|
||||||
import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons';
|
|
||||||
import { Box, Flex, Grid, Portal, useColorMode } from '@chakra-ui/react';
|
|
||||||
import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants';
|
|
||||||
import ImageGalleryPanel from 'features/gallery/components/ImageGalleryPanel';
|
|
||||||
import Lightbox from 'features/lightbox/components/Lightbox';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import {
|
|
||||||
memo,
|
|
||||||
PropsWithChildren,
|
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
|
||||||
import Loading from 'common/components/Loading/Loading';
|
|
||||||
import { useIsApplicationReady } from 'features/system/hooks/useIsApplicationReady';
|
|
||||||
import { PartialAppConfig } from 'app/types/invokeai';
|
import { PartialAppConfig } from 'app/types/invokeai';
|
||||||
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
|
|
||||||
import { configChanged } from 'features/system/store/configSlice';
|
import '../../i18n';
|
||||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
|
||||||
|
const App = lazy(() => import('./App'));
|
||||||
|
const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider'));
|
||||||
|
|
||||||
interface Props extends PropsWithChildren {
|
interface Props extends PropsWithChildren {
|
||||||
|
apiUrl?: string;
|
||||||
|
token?: string;
|
||||||
config?: PartialAppConfig;
|
config?: PartialAppConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InvokeAIUI = ({ config = {}, children }: Props) => {
|
const InvokeAIUI = ({ apiUrl, token, config, children }: Props) => {
|
||||||
useToastWatcher();
|
|
||||||
useGlobalHotkeys();
|
|
||||||
|
|
||||||
const currentTheme = useAppSelector((state) => state.ui.currentTheme);
|
|
||||||
|
|
||||||
const isLightboxEnabled = useFeatureStatus('lightbox').isFeatureEnabled;
|
|
||||||
|
|
||||||
const isApplicationReady = useIsApplicationReady();
|
|
||||||
|
|
||||||
const [loadingOverridden, setLoadingOverridden] = useState(false);
|
|
||||||
|
|
||||||
const { setColorMode } = useColorMode();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Received config: ', config);
|
// configure API client token
|
||||||
dispatch(configChanged(config));
|
if (token) {
|
||||||
}, [dispatch, config]);
|
OpenAPI.TOKEN = token;
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
// configure API client base url
|
||||||
setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark');
|
if (apiUrl) {
|
||||||
}, [setColorMode, currentTheme]);
|
OpenAPI.BASE = apiUrl;
|
||||||
|
}
|
||||||
|
|
||||||
const handleOverrideClicked = useCallback(() => {
|
// reset dynamically added middlewares
|
||||||
setLoadingOverridden(true);
|
resetMiddlewares();
|
||||||
}, []);
|
|
||||||
|
// TODO: at this point, after resetting the middleware, we really ought to clean up the socket
|
||||||
|
// stuff by calling `dispatch(socketReset())`. but we cannot dispatch from here as we are
|
||||||
|
// outside the provider. it's not needed until there is the possibility that we will change
|
||||||
|
// the `apiUrl`/`token` dynamically.
|
||||||
|
|
||||||
|
// rebuild socket middleware with token and apiUrl
|
||||||
|
addMiddleware(buildMiddleware());
|
||||||
|
}, [apiUrl, token]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid w="100vw" h="100vh" position="relative">
|
<React.StrictMode>
|
||||||
{isLightboxEnabled && <Lightbox />}
|
<Provider store={store}>
|
||||||
<ImageUploader>
|
<PersistGate loading={<Loading />} persistor={persistor}>
|
||||||
<ProgressBar />
|
<React.Suspense fallback={<Loading />}>
|
||||||
<Grid
|
<ThemeLocaleProvider>
|
||||||
gap={4}
|
<App config={config}>{children}</App>
|
||||||
p={4}
|
</ThemeLocaleProvider>
|
||||||
gridAutoRows="min-content auto"
|
</React.Suspense>
|
||||||
w={APP_WIDTH}
|
</PersistGate>
|
||||||
h={APP_HEIGHT}
|
</Provider>
|
||||||
>
|
</React.StrictMode>
|
||||||
{children || <SiteHeader />}
|
|
||||||
<Flex
|
|
||||||
gap={4}
|
|
||||||
w={{ base: '100vw', xl: 'full' }}
|
|
||||||
h="full"
|
|
||||||
flexDir={{ base: 'column', xl: 'row' }}
|
|
||||||
>
|
|
||||||
<InvokeTabs />
|
|
||||||
<ImageGalleryPanel />
|
|
||||||
</Flex>
|
|
||||||
</Grid>
|
|
||||||
</ImageUploader>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
<Portal>
|
|
||||||
<FloatingGalleryButton />
|
|
||||||
</Portal>
|
|
||||||
<Portal>
|
|
||||||
<Console />
|
|
||||||
</Portal>
|
|
||||||
</Grid>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
|
|
||||||
import App from './app/components/App';
|
import InvokeAIUI from './app/components/InvokeAIUI';
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||||
<App />
|
<InvokeAIUI />
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user