try using fns instead;

This commit is contained in:
Mary Hipp 2024-01-29 10:27:47 -05:00
parent 7fde19730e
commit aad486e59e
7 changed files with 92 additions and 29 deletions

View File

@ -34,10 +34,10 @@ interface Props extends PropsWithChildren {
openAPISchemaUrl?: string; openAPISchemaUrl?: string;
token?: string; token?: string;
config?: PartialAppConfig; config?: PartialAppConfig;
customNavComponent?: ReactNode; customNavComponent?: () => JSX.Element;
middleware?: Middleware[]; middleware?: Middleware[];
projectId?: string; projectId?: string;
galleryHeader?: ReactNode; galleryHeader?: () => JSX.Element;
queueId?: string; queueId?: string;
selectedImage?: { selectedImage?: {
imageName: string; imageName: string;
@ -46,7 +46,7 @@ interface Props extends PropsWithChildren {
customStarUi?: CustomStarUi; customStarUi?: CustomStarUi;
socketOptions?: Partial<ManagerOptions & SocketOptions>; socketOptions?: Partial<ManagerOptions & SocketOptions>;
isDebugging?: boolean; isDebugging?: boolean;
logo?: ReactNode; logo?: () => JSX.Element;
workflowCategories?: WorkflowCategory[]; workflowCategories?: WorkflowCategory[];
} }

View File

@ -1,4 +1,3 @@
import { atom } from 'nanostores'; import { atom } from 'nanostores';
import type { ReactNode } from 'react';
export const $customNavComponent = atom<ReactNode | undefined>(undefined); export const $customNavComponent = atom<undefined | (() => JSX.Element)>(undefined);

View File

@ -1,4 +1,3 @@
import { atom } from 'nanostores'; import { atom } from 'nanostores';
import type { ReactNode } from 'react';
export const $galleryHeader = atom<ReactNode | undefined>(undefined); export const $galleryHeader = atom<undefined | (() => JSX.Element)>(undefined);

View File

@ -1,4 +1,3 @@
import { atom } from 'nanostores'; import { atom } from 'nanostores';
import type { ReactNode } from 'react';
export const $logo = atom<ReactNode | undefined>(undefined); export const $logo = atom<undefined | (() => JSX.Element)>(undefined);

View File

@ -1,4 +1,14 @@
import { Box, Button, ButtonGroup, Flex, Tab, TabList, Tabs, useDisclosure, VStack } from '@invoke-ai/ui-library'; import {
Box,
Button,
ButtonGroup,
Flex,
Tab,
TabList,
Tabs,
useDisclosure,
VStack,
} from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { $galleryHeader } from 'app/store/nanostores/galleryHeader'; import { $galleryHeader } from 'app/store/nanostores/galleryHeader';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
@ -20,7 +30,8 @@ const ImageGalleryContent = () => {
const galleryView = useAppSelector((s) => s.gallery.galleryView); const galleryView = useAppSelector((s) => s.gallery.galleryView);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const galleryHeader = useStore($galleryHeader); const galleryHeader = useStore($galleryHeader);
const { isOpen: isBoardListOpen, onToggle: onToggleBoardList } = useDisclosure({ defaultIsOpen: true }); const { isOpen: isBoardListOpen, onToggle: onToggleBoardList } =
useDisclosure({ defaultIsOpen: true });
const handleClickImages = useCallback(() => { const handleClickImages = useCallback(() => {
dispatch(galleryViewChanged('images')); dispatch(galleryViewChanged('images'));
@ -31,11 +42,26 @@ const ImageGalleryContent = () => {
}, [dispatch]); }, [dispatch]);
return ( return (
<VStack layerStyle="first" flexDirection="column" h="full" w="full" borderRadius="base" p={2}> <VStack
{galleryHeader} layerStyle="first"
flexDirection="column"
h="full"
w="full"
borderRadius="base"
p={2}
>
{galleryHeader && galleryHeader()}
<Box w="full"> <Box w="full">
<Flex ref={resizeObserverRef} alignItems="center" justifyContent="space-between" gap={2}> <Flex
<GalleryBoardName isOpen={isBoardListOpen} onToggle={onToggleBoardList} /> ref={resizeObserverRef}
alignItems="center"
justifyContent="space-between"
gap={2}
>
<GalleryBoardName
isOpen={isBoardListOpen}
onToggle={onToggleBoardList}
/>
<GallerySettingsPopover /> <GallerySettingsPopover />
</Flex> </Flex>
<Box> <Box>
@ -44,7 +70,12 @@ const ImageGalleryContent = () => {
</Box> </Box>
<Flex ref={galleryGridRef} direction="column" gap={2} h="full" w="full"> <Flex ref={galleryGridRef} direction="column" gap={2} h="full" w="full">
<Flex alignItems="center" justifyContent="space-between" gap={2}> <Flex alignItems="center" justifyContent="space-between" gap={2}>
<Tabs index={galleryView === 'images' ? 0 : 1} variant="unstyled" size="sm" w="full"> <Tabs
index={galleryView === 'images' ? 0 : 1}
variant="unstyled"
size="sm"
w="full"
>
<TabList> <TabList>
<ButtonGroup w="full"> <ButtonGroup w="full">
<Tab <Tab

View File

@ -18,7 +18,7 @@ const InvokeAILogoComponent = () => {
}, [appVersion]); }, [appVersion]);
if (logoOverride) { if (logoOverride) {
return logoOverride; return logoOverride();
} }
return ( return (

View File

@ -1,4 +1,14 @@
import { Flex, IconButton, Spacer, Tab, TabList, TabPanel, TabPanels, Tabs, Tooltip } from '@invoke-ai/ui-library'; import {
Flex,
IconButton,
Spacer,
Tab,
TabList,
TabPanel,
TabPanels,
Tabs,
Tooltip,
} from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { $customNavComponent } from 'app/store/nanostores/customNavComponent'; import { $customNavComponent } from 'app/store/nanostores/customNavComponent';
@ -15,14 +25,23 @@ import type { UsePanelOptions } from 'features/ui/hooks/usePanel';
import { usePanel } from 'features/ui/hooks/usePanel'; import { usePanel } from 'features/ui/hooks/usePanel';
import { usePanelStorage } from 'features/ui/hooks/usePanelStorage'; import { usePanelStorage } from 'features/ui/hooks/usePanelStorage';
import type { InvokeTabName } from 'features/ui/store/tabMap'; import type { InvokeTabName } from 'features/ui/store/tabMap';
import { activeTabIndexSelector, activeTabNameSelector } from 'features/ui/store/uiSelectors'; import {
activeTabIndexSelector,
activeTabNameSelector,
} from 'features/ui/store/uiSelectors';
import { setActiveTab } from 'features/ui/store/uiSlice'; import { setActiveTab } from 'features/ui/store/uiSlice';
import type { CSSProperties, MouseEvent, ReactElement, ReactNode } from 'react'; import type { CSSProperties, MouseEvent, ReactElement, ReactNode } from 'react';
import { memo, useCallback, useMemo, useRef } from 'react'; import { memo, useCallback, useMemo, useRef } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { PiFlowArrowBold } from 'react-icons/pi'; import { PiFlowArrowBold } from 'react-icons/pi';
import { RiBox2Line, RiBrushLine, RiImage2Line, RiInputMethodLine, RiPlayList2Fill } from 'react-icons/ri'; import {
RiBox2Line,
RiBrushLine,
RiImage2Line,
RiInputMethodLine,
RiPlayList2Fill,
} from 'react-icons/ri';
import type { ImperativePanelGroupHandle } from 'react-resizable-panels'; import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
import { Panel, PanelGroup } from 'react-resizable-panels'; import { Panel, PanelGroup } from 'react-resizable-panels';
@ -81,8 +100,9 @@ const tabs: InvokeTabInfo[] = [
}, },
]; ];
const enabledTabsSelector = createMemoizedSelector(selectConfigSlice, (config) => const enabledTabsSelector = createMemoizedSelector(
tabs.filter((tab) => !config.disabledTabs.includes(tab.id)) selectConfigSlice,
(config) => tabs.filter((tab) => !config.disabledTabs.includes(tab.id))
); );
export const NO_GALLERY_PANEL_TABS: InvokeTabName[] = ['modelManager', 'queue']; export const NO_GALLERY_PANEL_TABS: InvokeTabName[] = ['modelManager', 'queue'];
@ -108,8 +128,14 @@ const InvokeTabs = () => {
e.target.blur(); e.target.blur();
} }
}, []); }, []);
const shouldShowOptionsPanel = useMemo(() => !NO_OPTIONS_PANEL_TABS.includes(activeTabName), [activeTabName]); const shouldShowOptionsPanel = useMemo(
const shouldShowGalleryPanel = useMemo(() => !NO_GALLERY_PANEL_TABS.includes(activeTabName), [activeTabName]); () => !NO_OPTIONS_PANEL_TABS.includes(activeTabName),
[activeTabName]
);
const shouldShowGalleryPanel = useMemo(
() => !NO_GALLERY_PANEL_TABS.includes(activeTabName),
[activeTabName]
);
const tabs = useMemo( const tabs = useMemo(
() => () =>
@ -133,7 +159,8 @@ const InvokeTabs = () => {
); );
const tabPanels = useMemo( const tabPanels = useMemo(
() => enabledTabs.map((tab) => <TabPanel key={tab.id}>{tab.content}</TabPanel>), () =>
enabledTabs.map((tab) => <TabPanel key={tab.id}>{tab.content}</TabPanel>),
[enabledTabs] [enabledTabs]
); );
@ -227,7 +254,7 @@ const InvokeTabs = () => {
</TabList> </TabList>
<Spacer /> <Spacer />
<StatusIndicator /> <StatusIndicator />
{customNavComponent ? customNavComponent : <SettingsMenu />} {customNavComponent ? customNavComponent() : <SettingsMenu />}
</Flex> </Flex>
<PanelGroup <PanelGroup
ref={panelGroupRef} ref={panelGroupRef}
@ -249,7 +276,11 @@ const InvokeTabs = () => {
onExpand={optionsPanel.onExpand} onExpand={optionsPanel.onExpand}
collapsible collapsible
> >
{activeTabName === 'nodes' ? <NodeEditorPanelGroup /> : <ParametersPanel />} {activeTabName === 'nodes' ? (
<NodeEditorPanelGroup />
) : (
<ParametersPanel />
)}
</Panel> </Panel>
<ResizeHandle <ResizeHandle
id="options-main-handle" id="options-main-handle"
@ -285,8 +316,12 @@ const InvokeTabs = () => {
</> </>
)} )}
</PanelGroup> </PanelGroup>
{shouldShowOptionsPanel && <FloatingParametersPanelButtons panelApi={optionsPanel} />} {shouldShowOptionsPanel && (
{shouldShowGalleryPanel && <FloatingGalleryButton panelApi={galleryPanel} />} <FloatingParametersPanelButtons panelApi={optionsPanel} />
)}
{shouldShowGalleryPanel && (
<FloatingGalleryButton panelApi={galleryPanel} />
)}
</Tabs> </Tabs>
); );
}; };