refactor(ui): workflows left panel internal components structure

This commit is contained in:
psychedelicious
2025-01-20 13:55:38 +11:00
parent 5ec173b9bb
commit a8b0c1c10c
7 changed files with 104 additions and 96 deletions

View File

@@ -0,0 +1,49 @@
import 'reactflow/dist/style.css';
import { Box } from '@invoke-ai/ui-library';
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
import type { CSSProperties } from 'react';
import { memo, useCallback, useRef } from 'react';
import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
import { Panel, PanelGroup } from 'react-resizable-panels';
import WorkflowNodeInspectorPanel from './inspector/WorkflowNodeInspectorPanel';
import WorkflowFieldsLinearViewPanel from './workflow/WorkflowPanel';
const panelGroupStyles: CSSProperties = { height: '100%', width: '100%' };
export const LinearViewLeftPanelContent = memo(() => {
const panelGroupRef = useRef<ImperativePanelGroupHandle>(null);
const handleDoubleClickHandle = useCallback(() => {
if (!panelGroupRef.current) {
return;
}
panelGroupRef.current.setLayout([50, 50]);
}, []);
return (
<Box position="relative" w="full" h="full">
<ScrollableContent>
<PanelGroup
ref={panelGroupRef}
id="workflow-panel-group"
autoSaveId="workflow-panel-group"
direction="vertical"
style={panelGroupStyles}
>
<Panel id="workflow" collapsible minSize={25}>
<WorkflowFieldsLinearViewPanel />
</Panel>
<ResizeHandle onDoubleClick={handleDoubleClickHandle} />
<Panel id="inspector" collapsible minSize={25}>
<WorkflowNodeInspectorPanel />
</Panel>
</PanelGroup>
</ScrollableContent>
</Box>
);
});
LinearViewLeftPanelContent.displayName = 'LinearViewLeftPanelContent';

View File

@@ -1,79 +0,0 @@
import 'reactflow/dist/style.css';
import { Box, Flex } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
import { useWorkflowListMenu } from 'features/nodes/store/workflowListMenu';
import { selectWorkflowMode } from 'features/nodes/store/workflowSlice';
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import type { CSSProperties } from 'react';
import { memo, useCallback, useRef } from 'react';
import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
import { Panel, PanelGroup } from 'react-resizable-panels';
import WorkflowNodeInspectorPanel from './inspector/WorkflowNodeInspectorPanel';
import { FieldsSimpleView } from './viewMode/WorkflowSimpleView';
import WorkflowFieldsLinearViewPanel from './workflow/WorkflowPanel';
import { WorkflowListMenu } from './WorkflowListMenu/WorkflowListMenu';
import { WorkflowListMenuTrigger } from './WorkflowListMenu/WorkflowListMenuTrigger';
const panelGroupStyles: CSSProperties = { height: '100%', width: '100%' };
const overlayScrollbarsStyles: CSSProperties = {
height: '100%',
width: '100%',
};
const WorkflowsLeftPanel = () => {
const mode = useAppSelector(selectWorkflowMode);
const panelGroupRef = useRef<ImperativePanelGroupHandle>(null);
const workflowListMenu = useWorkflowListMenu();
const handleDoubleClickHandle = useCallback(() => {
if (!panelGroupRef.current) {
return;
}
panelGroupRef.current.setLayout([50, 50]);
}, []);
return (
<Flex w="full" h="full" gap={2} flexDir="column">
<WorkflowListMenuTrigger />
<Flex w="full" h="full" position="relative">
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
{workflowListMenu.isOpen && (
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
<Flex gap={2} flexDirection="column" h="full" w="full">
<WorkflowListMenu />
</Flex>
</OverlayScrollbarsComponent>
)}
{mode === 'view' && <FieldsSimpleView />}
{mode === 'edit' && (
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
<PanelGroup
ref={panelGroupRef}
id="workflow-panel-group"
autoSaveId="workflow-panel-group"
direction="vertical"
style={panelGroupStyles}
>
<Panel id="workflow" collapsible minSize={25}>
<WorkflowFieldsLinearViewPanel />
</Panel>
<ResizeHandle onDoubleClick={handleDoubleClickHandle} />
<Panel id="inspector" collapsible minSize={25}>
<WorkflowNodeInspectorPanel />
</Panel>
</PanelGroup>
</OverlayScrollbarsComponent>
)}
</Box>
</Flex>
</Flex>
);
};
export default memo(WorkflowsLeftPanel);

View File

@@ -1,28 +1,34 @@
import { Flex } from '@invoke-ai/ui-library';
import { Box, Flex } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { $workflowCategories } from 'app/store/nanostores/workflowCategories';
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
import UploadWorkflowButton from 'features/workflowLibrary/components/UploadWorkflowButton';
import { memo } from 'react';
import { WorkflowList } from './WorkflowList';
import WorkflowSearch from './WorkflowSearch';
import { WorkflowSortControl } from './WorkflowSortControl';
export const WorkflowListMenu = () => {
export const WorkflowListMenu = memo(() => {
const workflowCategories = useStore($workflowCategories);
return (
<Flex flexDir="column" gap={2} padding={3} layerStyle="second" borderRadius="base">
<Flex w="full" h="full" flexDir="column" gap={2} padding={3} layerStyle="second" borderRadius="base">
<Flex alignItems="center" gap={2} w="full" justifyContent="space-between">
<WorkflowSearch />
<WorkflowSortControl />
<UploadWorkflowButton />
</Flex>
{workflowCategories.map((category) => (
<WorkflowList key={category} category={category} />
))}
<Box position="relative" w="full" h="full">
<ScrollableContent>
{workflowCategories.map((category) => (
<WorkflowList key={category} category={category} />
))}
</ScrollableContent>
</Box>
</Flex>
);
};
});
WorkflowListMenu.displayName = 'WorkflowListMenu';

View File

@@ -0,0 +1,32 @@
import 'reactflow/dist/style.css';
import { Box, Flex } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import { LinearViewLeftPanelContent } from 'features/nodes/components/sidePanel/LinearViewLeftPanelContent';
import { useWorkflowListMenu } from 'features/nodes/store/workflowListMenu';
import { selectWorkflowMode } from 'features/nodes/store/workflowSlice';
import { memo } from 'react';
import { SimpleViewLeftPanelContent } from './viewMode/SimpleViewLeftPanelContent';
import { WorkflowListMenu } from './WorkflowListMenu/WorkflowListMenu';
import { WorkflowListMenuTrigger } from './WorkflowListMenu/WorkflowListMenuTrigger';
const WorkflowsTabLeftPanel = () => {
const mode = useAppSelector(selectWorkflowMode);
const workflowListMenu = useWorkflowListMenu();
return (
<Flex w="full" h="full" gap={2} flexDir="column">
<WorkflowListMenuTrigger />
<Flex w="full" h="full" position="relative">
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
{workflowListMenu.isOpen && <WorkflowListMenu />}
{mode === 'view' && <SimpleViewLeftPanelContent />}
{mode === 'edit' && <LinearViewLeftPanelContent />}
</Box>
</Flex>
</Flex>
);
};
export default memo(WorkflowsTabLeftPanel);

View File

@@ -14,20 +14,20 @@ import { EmptyState } from './EmptyState';
const selectExposedFields = createMemoizedSelector(selectWorkflowSlice, (workflow) => workflow.exposedFields);
export const FieldsSimpleView = memo(() => {
export const SimpleViewLeftPanelContent = memo(() => {
return (
<Box position="relative" w="full" h="full">
<ScrollableContent>
<Flex position="relative" flexDir="column" alignItems="flex-start" p={1} gap={2} w="full" h="full">
<FieldSimpleViewContent />
<SimpleViewLeftPanelContentInner />
</Flex>
</ScrollableContent>
</Box>
);
});
FieldsSimpleView.displayName = 'FieldsSimpleView';
SimpleViewLeftPanelContent.displayName = 'SimpleViewLeftPanelContent';
const FieldSimpleViewContent = memo(() => {
const SimpleViewLeftPanelContentInner = memo(() => {
const { isLoading } = useGetOpenAPISchemaQuery();
const exposedFields = useAppSelector(selectExposedFields);
@@ -49,4 +49,4 @@ const FieldSimpleViewContent = memo(() => {
</>
);
});
FieldSimpleViewContent.displayName = 'FieldSimpleViewContent';
SimpleViewLeftPanelContentInner.displayName = ' SimpleViewLeftPanelContentInner';

View File

@@ -1,7 +1,7 @@
import { useFieldTemplate } from 'features/nodes/hooks/useFieldTemplate';
import { useMemo } from 'react';
export const useFieldTemplateTitle = (nodeId: string, fieldName: string, kind: 'inputs' | 'outputs'): string | null => {
export const useFieldTemplateTitle = (nodeId: string, fieldName: string, kind: 'inputs' | 'outputs'): string => {
const fieldTemplate = useFieldTemplate(nodeId, fieldName, kind);
const fieldTemplateTitle = useMemo(() => fieldTemplate.title, [fieldTemplate]);
return fieldTemplateTitle;

View File

@@ -5,7 +5,7 @@ import { CanvasRightPanel } from 'features/controlLayers/components/CanvasRightP
import { useDndMonitor } from 'features/dnd/useDndMonitor';
import GalleryPanelContent from 'features/gallery/components/GalleryPanelContent';
import { ImageViewer } from 'features/gallery/components/ImageViewer/ImageViewer';
import WorkflowsLeftPanel from 'features/nodes/components/sidePanel/NodeEditorPanelGroup';
import WorkflowsTabLeftPanel from 'features/nodes/components/sidePanel/WorkflowsTabLeftPanel';
import QueueControls from 'features/queue/components/QueueControls';
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton';
@@ -183,7 +183,7 @@ const LeftPanelContent = memo(() => {
return <ParametersPanelUpscale />;
}
if (tab === 'workflows') {
return <WorkflowsLeftPanel />;
return <WorkflowsTabLeftPanel />;
}
return null;