feat(ui): revise image viewer

- Viewer only exists on Generation tab
- Viewer defaults to open
- When clicking the Control Layers tab on the left panel, close the viewer (i.e. open the CL editor)
- Do not switch to editor when adding layers (this is handled by clicking the Control Layers tab)
- Do not open viewer when single-clicking images in gallery
- _Do_ open viewer when _double_-clicking images in gallery
- Do not change viewer state when switching between app tabs (this no longer makes sense; the viewer only exists on generation tab)
- Change the button to a drop down menu that states what you are currently doing, e.g. Viewing vs Editing
This commit is contained in:
psychedelicious
2024-05-08 17:38:18 +10:00
committed by Kent Keirsey
parent e8023c44b0
commit e8e764be20
17 changed files with 249 additions and 187 deletions

View File

@@ -4,7 +4,6 @@ import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { $customNavComponent } from 'app/store/nanostores/customNavComponent';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent';
import { ImageViewer } from 'features/gallery/components/ImageViewer/ImageViewer';
import NodeEditorPanelGroup from 'features/nodes/components/sidePanel/NodeEditorPanelGroup';
import InvokeAILogoComponent from 'features/system/components/InvokeAILogoComponent';
import SettingsMenu from 'features/system/components/SettingsModal/SettingsMenu';
@@ -255,9 +254,8 @@ const InvokeTabs = () => {
</>
)}
<Panel id="main-panel" order={1} minSize={20}>
<TabPanels w="full" h="full" position="relative">
<TabPanels w="full" h="full">
{tabPanels}
<ImageViewer />
</TabPanels>
</Panel>
{shouldShowGalleryPanel && (

View File

@@ -1,8 +1,9 @@
import type { ChakraProps } from '@invoke-ai/ui-library';
import { Box, Flex, Tab, TabList, TabPanel, TabPanels, Tabs } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
import { ControlLayersPanelContent } from 'features/controlLayers/components/ControlLayersPanelContent';
import { isImageViewerOpenChanged } from 'features/gallery/store/gallerySlice';
import { Prompts } from 'features/parameters/components/Prompts/Prompts';
import QueueControls from 'features/queue/components/QueueControls';
import { SDXLPrompts } from 'features/sdxl/components/SDXLPrompts/SDXLPrompts';
@@ -15,7 +16,7 @@ import { RefinerSettingsAccordion } from 'features/settingsAccordions/components
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import type { CSSProperties } from 'react';
import { memo, useMemo } from 'react';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
const overlayScrollbarsStyles: CSSProperties = {
@@ -37,6 +38,7 @@ const selectedStyles: ChakraProps['sx'] = {
const ParametersPanelTextToImage = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const activeTabName = useAppSelector(activeTabNameSelector);
const controlLayersCount = useAppSelector((s) => s.controlLayers.present.layers.length);
const controlLayersTitle = useMemo(() => {
@@ -46,6 +48,14 @@ const ParametersPanelTextToImage = () => {
return `${t('controlLayers.controlLayers')} (${controlLayersCount})`;
}, [controlLayersCount, t]);
const isSDXL = useAppSelector((s) => s.generation.model?.base === 'sdxl');
const onChangeTabs = useCallback(
(i: number) => {
if (i === 1) {
dispatch(isImageViewerOpenChanged(false));
}
},
[dispatch]
);
return (
<Flex w="full" h="full" flexDir="column" gap={2}>
@@ -55,7 +65,15 @@ const ParametersPanelTextToImage = () => {
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
<Flex gap={2} flexDirection="column" h="full" w="full">
{isSDXL ? <SDXLPrompts /> : <Prompts />}
<Tabs variant="enclosed" display="flex" flexDir="column" w="full" h="full" gap={2}>
<Tabs
variant="enclosed"
display="flex"
flexDir="column"
w="full"
h="full"
gap={2}
onChange={onChangeTabs}
>
<TabList gap={2} fontSize="sm" borderColor="base.800">
<Tab sx={baseStyles} _selected={selectedStyles}>
{t('common.settingsLabel')}

View File

@@ -1,9 +1,20 @@
import { Box } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import { ImageViewerWorkflows } from 'features/gallery/components/ImageViewer/ImageViewerWorkflows';
import NodeEditor from 'features/nodes/components/NodeEditor';
import { memo } from 'react';
import { ReactFlowProvider } from 'reactflow';
const NodesTab = () => {
const mode = useAppSelector((s) => s.workflow.mode);
if (mode === 'view') {
return (
<Box layerStyle="first" position="relative" w="full" h="full" p={2} borderRadius="base">
<ImageViewerWorkflows />
</Box>
);
}
return (
<Box layerStyle="first" position="relative" w="full" h="full" p={2} borderRadius="base">
<ReactFlowProvider>

View File

@@ -1,11 +1,13 @@
import { Box } from '@invoke-ai/ui-library';
import { ControlLayersEditor } from 'features/controlLayers/components/ControlLayersEditor';
import { ImageViewer } from 'features/gallery/components/ImageViewer/ImageViewer';
import { memo } from 'react';
const TextToImageTab = () => {
return (
<Box layerStyle="first" position="relative" w="full" h="full" p={2} borderRadius="base">
<ControlLayersEditor />
<ImageViewer />
</Box>
);
};