feat: Remove Header

Remove header and incorporate everything else into the side bar and other areas
This commit is contained in:
blessedcoolant 2024-01-04 00:17:57 +05:30 committed by Kent Keirsey
parent 4ce39a5974
commit 2250bca8d9
9 changed files with 165 additions and 175 deletions

View File

@ -156,6 +156,7 @@
"save": "Save",
"saveAs": "Save As",
"settingsLabel": "Settings",
"preferencesLabel": "Preferences",
"simple": "Simple",
"somethingWentWrong": "Something went wrong",
"statusConnected": "Connected",

View File

@ -1,9 +1,7 @@
import { Flex, Grid } from '@chakra-ui/react';
import { useStore } from '@nanostores/react';
import { useSocketIO } from 'app/hooks/useSocketIO';
import { useLogger } from 'app/logging/useLogger';
import { appStarted } from 'app/store/middleware/listenerMiddleware/listeners/appStarted';
import { $headerComponent } from 'app/store/nanostores/headerComponent';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import type { PartialAppConfig } from 'app/types/invokeai';
import ImageUploader from 'common/components/ImageUploader';
@ -13,7 +11,6 @@ import { useGlobalModifiersInit } from 'common/hooks/useGlobalModifiers';
import ChangeBoardModal from 'features/changeBoardModal/components/ChangeBoardModal';
import DeleteImageModal from 'features/deleteImageModal/components/DeleteImageModal';
import { DynamicPromptsModal } from 'features/dynamicPrompts/components/DynamicPromptsPreviewModal';
import SiteHeader from 'features/system/components/SiteHeader';
import { configChanged } from 'features/system/store/configSlice';
import { languageSelector } from 'features/system/store/systemSelectors';
import InvokeTabs from 'features/ui/components/InvokeTabs';
@ -68,8 +65,6 @@ const App = ({ config = DEFAULT_CONFIG, selectedImage }: Props) => {
dispatch(appStarted());
}, [dispatch]);
const headerComponent = useStore($headerComponent);
return (
<ErrorBoundary
onReset={handleReset}
@ -77,12 +72,9 @@ const App = ({ config = DEFAULT_CONFIG, selectedImage }: Props) => {
>
<Grid w="100vw" h="100vh" position="relative" overflow="hidden">
<ImageUploader>
<Grid p={4} gridAutoRows="min-content auto" w="full" h="full">
{headerComponent || <SiteHeader />}
<Flex gap={4} w="full" h="full">
<InvokeTabs />
</Flex>
</Grid>
<Flex gap={4} p={4} w="full" h="full">
<InvokeTabs />
</Flex>
</ImageUploader>
</Grid>
<DeleteImageModal />

View File

@ -3,6 +3,7 @@ import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup'
import ClearQueueButton from 'features/queue/components/ClearQueueButton';
import QueueFrontButton from 'features/queue/components/QueueFrontButton';
import ProgressBar from 'features/system/components/ProgressBar';
import StatusIndicator from 'features/system/components/StatusIndicator';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { memo } from 'react';
@ -29,8 +30,9 @@ const QueueControls = () => {
{isPauseEnabled && <PauseProcessorButton asIconButton />} */}
<ClearQueueButton asIconButton />
</InvButtonGroup>
<Flex h={2} w="full">
<ProgressBar />
<Flex h={5} w="full" alignItems="center">
<StatusIndicator />
<ProgressBar height={2} />
</Flex>
</Flex>
);

View File

@ -2,6 +2,7 @@
import { Flex, Image } from '@chakra-ui/react';
import InvokeLogoYellow from 'assets/images/invoke-key-ylw-sm.svg';
import { InvText } from 'common/components/InvText/wrapper';
import { InvTooltip } from 'common/components/InvTooltip/InvTooltip';
import type { AnimationProps } from 'framer-motion';
import { AnimatePresence, motion } from 'framer-motion';
import { memo, useRef } from 'react';
@ -14,8 +15,29 @@ const InvokeAILogoComponent = () => {
const isHovered = useHoverDirty(ref);
return (
<Flex alignItems="center" gap={5} ps={1} ref={ref}>
<InvTooltip
placement="right"
label={
<Flex gap={3} alignItems="center">
<AnimatePresence>
{isHovered && appVersion && (
<motion.div
key="statusText"
initial={initial}
animate={animate}
exit={exit}
>
<InvText fontWeight="semibold" marginTop={1} color="base.900">
v{appVersion.version}
</InvText>
</motion.div>
)}
</AnimatePresence>
</Flex>
}
>
<Image
ref={ref}
src={InvokeLogoYellow}
alt="invoke-logo"
w="24px"
@ -24,23 +46,7 @@ const InvokeAILogoComponent = () => {
minH="24px"
userSelect="none"
/>
<Flex gap={3} alignItems="center">
<AnimatePresence>
{isHovered && appVersion && (
<motion.div
key="statusText"
initial={initial}
animate={animate}
exit={exit}
>
<InvText fontWeight="semibold" marginTop={1} color="base.300">
v{appVersion.version}
</InvText>
</motion.div>
)}
</AnimatePresence>
</Flex>
</Flex>
</InvTooltip>
);
};

View File

@ -16,7 +16,12 @@ const progressBarSelector = createMemoizedSelector(
}
);
const ProgressBar = () => {
type ProgressBarProps = {
height?: number | string;
};
const ProgressBar = (props: ProgressBarProps) => {
const { height = 'full' } = props;
const { t } = useTranslation();
const { data: queueStatus } = useGetQueueStatusQuery();
const { hasSteps, value, isConnected } = useAppSelector(progressBarSelector);
@ -29,7 +34,7 @@ const ProgressBar = () => {
isIndeterminate={
isConnected && Boolean(queueStatus?.queue.in_progress) && !hasSteps
}
h="full"
h={height}
w="full"
colorScheme="invokeYellow"
/>

View File

@ -0,0 +1,101 @@
import { useDisclosure } from '@chakra-ui/react';
import { InvIconButton } from 'common/components/InvIconButton/InvIconButton';
import { InvMenuItem } from 'common/components/InvMenu/InvMenuItem';
import { InvMenuList } from 'common/components/InvMenu/InvMenuList';
import {
InvMenu,
InvMenuButton,
InvMenuGroup,
} from 'common/components/InvMenu/wrapper';
import { InvTooltip } from 'common/components/InvTooltip/InvTooltip';
import { useGlobalMenuCloseTrigger } from 'common/hooks/useGlobalMenuCloseTrigger';
import HotkeysModal from 'features/system/components/HotkeysModal/HotkeysModal';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import {
FaBars,
FaBug,
FaCog,
FaDiscord,
FaGithub,
FaKeyboard,
} from 'react-icons/fa';
import SettingsModal from './SettingsModal';
const SettingsMenu = () => {
const { t } = useTranslation();
const { isOpen, onOpen, onClose } = useDisclosure();
useGlobalMenuCloseTrigger(onClose);
const isBugLinkEnabled = useFeatureStatus('bugLink').isFeatureEnabled;
const isDiscordLinkEnabled = useFeatureStatus('discordLink').isFeatureEnabled;
const isGithubLinkEnabled = useFeatureStatus('githubLink').isFeatureEnabled;
const githubLink = 'http://github.com/invoke-ai/InvokeAI';
const discordLink = 'https://discord.gg/ZmtBAhwWhy';
return (
<InvMenu isOpen={isOpen} onOpen={onOpen} onClose={onClose}>
<InvTooltip label={t('common.preferencesLabel')} placement="right">
<InvMenuButton
as={InvIconButton}
variant="link"
aria-label={t('accessibility.menu')}
icon={<FaCog fontSize={20} />}
boxSize={8}
/>
</InvTooltip>
<InvMenuList>
<InvMenuGroup title={t('common.communityLabel')}>
{isGithubLinkEnabled && (
<InvMenuItem
as="a"
href={githubLink}
target="_blank"
icon={<FaGithub />}
>
{t('common.githubLabel')}
</InvMenuItem>
)}
{isBugLinkEnabled && (
<InvMenuItem
as="a"
href={`${githubLink}/issues`}
target="_blank"
icon={<FaBug />}
>
{t('common.reportBugLabel')}
</InvMenuItem>
)}
{isDiscordLinkEnabled && (
<InvMenuItem
as="a"
href={discordLink}
target="_blank"
icon={<FaDiscord />}
>
{t('common.discordLabel')}
</InvMenuItem>
)}
</InvMenuGroup>
<InvMenuGroup title={t('common.settingsLabel')}>
<HotkeysModal>
<InvMenuItem as="button" icon={<FaKeyboard />}>
{t('common.hotkeysLabel')}
</InvMenuItem>
</HotkeysModal>
<SettingsModal>
<InvMenuItem as="button" icon={<FaBars />}>
{t('common.settingsLabel')}
</InvMenuItem>
</SettingsModal>
</InvMenuGroup>
</InvMenuList>
</InvMenu>
);
};
export default memo(SettingsMenu);

View File

@ -1,105 +0,0 @@
import { Flex, Spacer, useDisclosure } from '@chakra-ui/react';
import { InvIconButton } from 'common/components/InvIconButton/InvIconButton';
import { InvMenuItem } from 'common/components/InvMenu/InvMenuItem';
import { InvMenuList } from 'common/components/InvMenu/InvMenuList';
import {
InvMenu,
InvMenuButton,
InvMenuGroup,
} from 'common/components/InvMenu/wrapper';
import { useGlobalMenuCloseTrigger } from 'common/hooks/useGlobalMenuCloseTrigger';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import {
FaBars,
FaBug,
FaCog,
FaDiscord,
FaGithub,
FaKeyboard,
} from 'react-icons/fa';
import HotkeysModal from './HotkeysModal/HotkeysModal';
import InvokeAILogoComponent from './InvokeAILogoComponent';
import SettingsModal from './SettingsModal/SettingsModal';
import StatusIndicator from './StatusIndicator';
const SiteHeader = () => {
const { t } = useTranslation();
const { isOpen, onOpen, onClose } = useDisclosure();
useGlobalMenuCloseTrigger(onClose);
const isBugLinkEnabled = useFeatureStatus('bugLink').isFeatureEnabled;
const isDiscordLinkEnabled = useFeatureStatus('discordLink').isFeatureEnabled;
const isGithubLinkEnabled = useFeatureStatus('githubLink').isFeatureEnabled;
const githubLink = 'http://github.com/invoke-ai/InvokeAI';
const discordLink = 'https://discord.gg/ZmtBAhwWhy';
return (
<Flex gap={2} alignItems="center">
<InvokeAILogoComponent />
<Spacer />
<StatusIndicator />
<InvMenu isOpen={isOpen} onOpen={onOpen} onClose={onClose}>
<InvMenuButton
as={InvIconButton}
variant="link"
aria-label={t('accessibility.menu')}
icon={<FaBars />}
boxSize={8}
/>
<InvMenuList>
<InvMenuGroup title={t('common.communityLabel')}>
{isGithubLinkEnabled && (
<InvMenuItem
as="a"
href={githubLink}
target="_blank"
icon={<FaGithub />}
>
{t('common.githubLabel')}
</InvMenuItem>
)}
{isBugLinkEnabled && (
<InvMenuItem
as="a"
href={`${githubLink}/issues`}
target="_blank"
icon={<FaBug />}
>
{t('common.reportBugLabel')}
</InvMenuItem>
)}
{isDiscordLinkEnabled && (
<InvMenuItem
as="a"
href={discordLink}
target="_blank"
icon={<FaDiscord />}
>
{t('common.discordLabel')}
</InvMenuItem>
)}
</InvMenuGroup>
<InvMenuGroup title={t('common.settingsLabel')}>
<HotkeysModal>
<InvMenuItem as="button" icon={<FaKeyboard />}>
{t('common.hotkeysLabel')}
</InvMenuItem>
</HotkeysModal>
<SettingsModal>
<InvMenuItem as="button" icon={<FaCog />}>
{t('common.settingsLabel')}
</InvMenuItem>
</SettingsModal>
</InvMenuGroup>
</InvMenuList>
</InvMenu>
</Flex>
);
};
export default memo(SiteHeader);

View File

@ -3,9 +3,8 @@ import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { stateSelector } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import { InvText } from 'common/components/InvText/wrapper';
import { InvTooltip } from 'common/components/InvTooltip/InvTooltip';
import { STATUS_TRANSLATION_KEYS } from 'features/system/store/types';
import type { AnimationProps } from 'framer-motion';
import { AnimatePresence, motion } from 'framer-motion';
import type { ResourceKey } from 'i18next';
import { memo, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
@ -54,15 +53,13 @@ const StatusIndicator = () => {
const isHovered = useHoverDirty(ref);
return (
<Flex ref={ref} h="full" px={2} alignItems="center" gap={5}>
<AnimatePresence>
{isHovered && (
<motion.div
key="statusText"
initial={initial}
animate={animate}
exit={exit}
>
<Flex ref={ref} alignItems="center" p={2} pl={0}>
<InvTooltip
left={10}
bottom={-24}
background="base.800"
label={
isHovered && (
<InvText
fontSize="sm"
fontWeight="semibold"
@ -72,24 +69,13 @@ const StatusIndicator = () => {
>
{t(statusTranslationKey as ResourceKey)}
</InvText>
</motion.div>
)}
</AnimatePresence>
<Icon as={FaCircle} boxSize="0.5rem" color={COLOR_MAP[statusColor]} />
)
}
>
<Icon as={FaCircle} boxSize="0.6rem" color={COLOR_MAP[statusColor]} />
</InvTooltip>
</Flex>
);
};
export default memo(StatusIndicator);
const initial: AnimationProps['initial'] = {
opacity: 0,
};
const animate: AnimationProps['animate'] = {
opacity: 1,
transition: { duration: 0.1 },
};
const exit: AnimationProps['exit'] = {
opacity: 0,
transition: { delay: 0.8 },
};

View File

@ -1,4 +1,4 @@
import { Spacer } from '@chakra-ui/react';
import { Flex, Spacer } from '@chakra-ui/react';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
@ -13,6 +13,8 @@ import {
import { InvTooltip } from 'common/components/InvTooltip/InvTooltip';
import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent';
import NodeEditorPanelGroup from 'features/nodes/components/sidePanel/NodeEditorPanelGroup';
import InvokeAILogoComponent from 'features/system/components/InvokeAILogoComponent';
import SettingsMenu from 'features/system/components/SettingsModal/SettingsMenu';
import type { UsePanelOptions } from 'features/ui/hooks/usePanel';
import { usePanel } from 'features/ui/hooks/usePanel';
import { usePanelStorage } from 'features/ui/hooks/usePanelStorage';
@ -249,10 +251,14 @@ const InvokeTabs = () => {
gap={4}
isLazy
>
<InvTabList gap={4} pt={4} flexDir="column">
{tabs}
<Spacer />
</InvTabList>
<Flex flexDir="column" alignItems="center" pt={2}>
<InvokeAILogoComponent />
<InvTabList gap={4} pt={8} pb={4} h="full" flexDir="column">
{tabs}
<Spacer />
<SettingsMenu />
</InvTabList>
</Flex>
<PanelGroup
ref={panelGroupRef}
id={appPanelGroupId}
@ -272,7 +278,6 @@ const InvokeTabs = () => {
onCollapse={onCollapseOptionsPanel}
onExpand={onExpandOptionsPanel}
collapsible
style={paddingTop4}
>
{activeTabName === 'nodes' ? (
<NodeEditorPanelGroup />
@ -287,7 +292,7 @@ const InvokeTabs = () => {
/>
</>
)}
<Panel id="main-panel" order={1} minSize={20} style={paddingTop4}>
<Panel id="main-panel" order={1} minSize={20}>
<InvTabPanels w="full" h="full">
{tabPanels}
</InvTabPanels>
@ -308,7 +313,6 @@ const InvokeTabs = () => {
onCollapse={onCollapseGalleryPanel}
onExpand={onExpandGalleryPanel}
collapsible
style={paddingTop4}
>
<ImageGalleryContent />
</Panel>
@ -320,5 +324,3 @@ const InvokeTabs = () => {
};
export default memo(InvokeTabs);
const paddingTop4: CSSProperties = { paddingTop: '8px' };