chore(ui): lint

This commit is contained in:
psychedelicious
2025-06-20 13:39:58 +10:00
parent 553d1a6ac6
commit 7c4550cbd5
11 changed files with 8 additions and 539 deletions

View File

@@ -1,21 +1,11 @@
import { Flex, Tab, TabList, TabPanel, TabPanels, Tabs } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { GenerateLaunchpadPanel } from 'features/controlLayers/components/SimpleSession/GenerateLaunchpadPanel';
import { ImageViewer } from 'features/gallery/components/ImageViewer/ImageViewer2';
import { ProgressImage } from 'features/gallery/components/ImageViewer/ProgressImage2';
import { ViewerToolbar } from 'features/gallery/components/ImageViewer/ViewerToolbar2';
import { selectShowGenerateTabSplashScreen } from 'features/ui/store/uiSelectors';
import { showGenerateTabSplashScreenChanged } from 'features/ui/store/uiSlice';
import { memo, useCallback } from 'react';
import { memo } from 'react';
export const SimpleSession = memo(() => {
const showGenerateTabSplashScreen = useAppSelector(selectShowGenerateTabSplashScreen);
const dispatch = useAppDispatch();
const showSplashScreen = useCallback(() => {
dispatch(showGenerateTabSplashScreenChanged(true));
}, [dispatch]);
return (
<Tabs w="full" h="full" px={2}>
<TabList>

View File

@@ -1,17 +0,0 @@
import { Button } from '@invoke-ai/ui-library';
import { $simpleId } from 'features/ui/components/MainPanelContent';
import { memo, useCallback } from 'react';
export const StartOverButton = memo(() => {
const startOver = useCallback(() => {
// dispatch(canvasSessionTypeChanged({ type: 'simple' }));
$simpleId.set(null);
}, []);
return (
<Button size="sm" variant="link" alignSelf="stretch" onClick={startOver} px={2}>
Start Over
</Button>
);
});
StartOverButton.displayName = 'StartOverButton';

View File

@@ -2,7 +2,7 @@ import { IconButton } from '@invoke-ai/ui-library';
import { useIsRegionFocused } from 'common/hooks/focus';
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
import { memo } from 'react';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { PiArrowsOutBold } from 'react-icons/pi';
@@ -11,6 +11,10 @@ export const CanvasToolbarResetViewButton = memo(() => {
const canvasManager = useCanvasManager();
const isCanvasFocused = useIsRegionFocused('canvas');
const fitLayersToStage = useCallback(() => {
canvasManager.stage.fitLayersToStage();
}, [canvasManager.stage]);
useRegisteredHotkeys({
id: 'fitLayersToCanvas',
category: 'canvas',
@@ -58,7 +62,7 @@ export const CanvasToolbarResetViewButton = memo(() => {
<IconButton
tooltip={t('hotkeys.canvas.fitLayersToCanvas.title')}
aria-label={t('hotkeys.canvas.fitLayersToCanvas.title')}
onClick={canvasManager.stage.fitLayersToStage}
onClick={fitLayersToStage}
icon={<PiArrowsOutBold />}
variant="link"
alignSelf="stretch"

View File

@@ -1,16 +1,14 @@
import { Box, Flex } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { useAppSelector } from 'app/store/storeHooks';
import { CanvasAlertsInvocationProgress } from 'features/controlLayers/components/CanvasAlerts/CanvasAlertsInvocationProgress';
import { DndImage } from 'features/dnd/DndImage';
import ImageMetadataViewer from 'features/gallery/components/ImageMetadataViewer/ImageMetadataViewer';
import NextPrevImageButtons from 'features/gallery/components/NextPrevImageButtons';
import { selectShouldShowImageDetails, selectShouldShowProgressInViewer } from 'features/ui/store/uiSelectors';
import { selectShouldShowImageDetails } from 'features/ui/store/uiSelectors';
import type { AnimationProps } from 'framer-motion';
import { AnimatePresence, motion } from 'framer-motion';
import { memo, useCallback, useRef, useState } from 'react';
import type { ImageDTO } from 'services/api/types';
import { $hasLastProgressImage } from 'services/events/stores';
import { NoContentForViewer } from './NoContentForViewer';
@@ -82,9 +80,6 @@ export const CurrentImagePreview = memo(({ imageDTO }: { imageDTO?: ImageDTO })
CurrentImagePreview.displayName = 'CurrentImagePreview';
const ImageContent = memo(({ imageDTO }: { imageDTO?: ImageDTO }) => {
const hasProgressImage = useStore($hasLastProgressImage);
const shouldShowProgressInViewer = useAppSelector(selectShouldShowProgressInViewer);
if (!imageDTO) {
return <NoContentForViewer />;
}

View File

@@ -1,4 +1,3 @@
import type { FormLabelProps } from '@invoke-ai/ui-library';
import { Flex, StandaloneAccordion } from '@invoke-ai/ui-library';
import { skipToken } from '@reduxjs/toolkit/query';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
@@ -13,14 +12,6 @@ import { memo, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useGetModelConfigQuery } from 'services/api/endpoints/models';
const formLabelProps: FormLabelProps = {
minW: '9.2rem',
};
const formLabelProps2: FormLabelProps = {
flexGrow: 1,
};
export const AdvancedSettingsAccordion = memo(() => {
const vaeKey = useAppSelector(selectVAEKey);
const { currentData: vaeConfig } = useGetModelConfigQuery(vaeKey ?? skipToken);

View File

@@ -10,54 +10,16 @@ import { GenerateTabAutoLayout } from 'features/ui/layouts/generate-tab-auto-lay
import { UpscalingTabAutoLayout } from 'features/ui/layouts/upscaling-tab-auto-layout';
import { WorkflowsTabAutoLayout } from 'features/ui/layouts/workflows-tab-auto-layout';
import { selectActiveTabIndex } from 'features/ui/store/uiSelectors';
import { $isLeftPanelOpen, $isRightPanelOpen } from 'features/ui/store/uiSlice';
import type { CSSProperties } from 'react';
import { memo } from 'react';
import { TabMountGate } from './TabMountGate';
import ModelManagerTab from './tabs/ModelManagerTab';
import QueueTab from './tabs/QueueTab';
const panelStyles: CSSProperties = { position: 'relative', height: '100%', width: '100%', minWidth: 0 };
const onLeftPanelCollapse = (isCollapsed: boolean) => $isLeftPanelOpen.set(!isCollapsed);
const onRightPanelCollapse = (isCollapsed: boolean) => $isRightPanelOpen.set(!isCollapsed);
export const AppContent = memo(() => {
const tabIndex = useAppSelector(selectActiveTabIndex);
useDndMonitor();
// useRegisteredHotkeys({
// id: 'resetPanelLayout',
// category: 'app',
// callback: () => {
// leftPanel.reset();
// rightPanel.reset();
// },
// dependencies: [leftPanel.reset, rightPanel.reset],
// });
// useRegisteredHotkeys({
// id: 'togglePanels',
// category: 'app',
// callback: () => {
// if (leftPanel.isCollapsed || rightPanel.isCollapsed) {
// leftPanel.expand();
// rightPanel.expand();
// } else {
// leftPanel.collapse();
// rightPanel.collapse();
// }
// },
// dependencies: [
// leftPanel.isCollapsed,
// rightPanel.isCollapsed,
// leftPanel.expand,
// rightPanel.expand,
// leftPanel.collapse,
// rightPanel.collapse,
// ],
// });
return (
<Tabs index={tabIndex} display="flex" w="full" h="full" p={0} overflow="hidden">
<TabList>

View File

@@ -1,26 +0,0 @@
import { Box, Flex } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import WorkflowsTabLeftPanel from 'features/nodes/components/sidePanel/WorkflowsTabLeftPanel';
import QueueControls from 'features/queue/components/QueueControls';
import ParametersPanelTextToImage from 'features/ui/components/ParametersPanels/ParametersPanelTextToImage';
import { selectActiveTab } from 'features/ui/store/uiSelectors';
import { memo } from 'react';
import ParametersPanelUpscale from './ParametersPanels/ParametersPanelUpscale';
export const LeftPanelContent = memo(() => {
const tab = useAppSelector(selectActiveTab);
return (
<Flex flexDir="column" w="full" h="full" gap={2} py={2} pe={2}>
<QueueControls />
<Box position="relative" w="full" h="full">
{tab === 'generate' && <ParametersPanelTextToImage />}
{tab === 'canvas' && <ParametersPanelTextToImage />}
{tab === 'upscaling' && <ParametersPanelUpscale />}
{tab === 'workflows' && <WorkflowsTabLeftPanel />}
</Box>
</Flex>
);
});
LeftPanelContent.displayName = 'LeftPanelContent';

View File

@@ -1,94 +0,0 @@
import type { SystemStyleObject } from '@invoke-ai/ui-library';
import { useDisclosure } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import { FocusRegionWrapper } from 'common/components/FocusRegionWrapper';
import { CanvasLayersPanel } from 'features/controlLayers/components/CanvasLayersPanelContent';
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
import { BoardsPanel } from 'features/gallery/components/BoardsListPanelContent';
import { GalleryPanel } from 'features/gallery/components/Gallery';
import { GalleryTopBar } from 'features/gallery/components/GalleryTopBar';
import { selectBoardSearchText } from 'features/gallery/store/gallerySelectors';
import { HorizontalResizeHandle } from 'features/ui/components/tabs/ResizeHandle';
import type { UsePanelOptions } from 'features/ui/hooks/usePanel';
import { usePanel } from 'features/ui/hooks/usePanel';
import { selectActiveTab } from 'features/ui/store/uiSelectors';
import { memo, useMemo, useRef } from 'react';
import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
import { Panel, PanelGroup } from 'react-resizable-panels';
const FOCUS_REGION_STYLES: SystemStyleObject = {
width: 'full',
height: 'full',
position: 'relative',
flexDirection: 'column',
display: 'flex',
};
export const RightPanelContent = memo(() => {
const boardSearchText = useAppSelector(selectBoardSearchText);
const boardSearchDisclosure = useDisclosure({ defaultIsOpen: !!boardSearchText.length });
const imperativePanelGroupRef = useRef<ImperativePanelGroupHandle>(null);
const tab = useAppSelector(selectActiveTab);
const boardsListPanelOptions = useMemo<UsePanelOptions>(
() => ({
id: 'boards-list-panel',
minSizePx: 128,
defaultSizePx: 256,
imperativePanelGroupRef,
panelGroupDirection: 'vertical',
}),
[]
);
const boardsListPanel = usePanel(boardsListPanelOptions);
const galleryPanelOptions = useMemo<UsePanelOptions>(
() => ({
id: 'gallery-panel',
minSizePx: 128,
defaultSizePx: 256,
imperativePanelGroupRef,
panelGroupDirection: 'vertical',
}),
[]
);
const galleryPanel = usePanel(galleryPanelOptions);
const canvasLayersPanelOptions = useMemo<UsePanelOptions>(
() => ({
id: 'canvas-layers-panel',
minSizePx: 128,
defaultSizePx: 256,
imperativePanelGroupRef,
panelGroupDirection: 'vertical',
}),
[]
);
const canvasLayersPanel = usePanel(canvasLayersPanelOptions);
return (
<FocusRegionWrapper region="gallery" sx={FOCUS_REGION_STYLES}>
<GalleryTopBar boardsListPanel={boardsListPanel} boardSearchDisclosure={boardSearchDisclosure} />
<PanelGroup ref={imperativePanelGroupRef} direction="vertical" autoSaveId="boards-list-panel">
<Panel order={0} id="boards-panel" collapsible {...boardsListPanel.panelProps}>
<BoardsPanel boardSearchDisclosure={boardSearchDisclosure} />
</Panel>
<HorizontalResizeHandle id="boards-list-to-gallery-panel-handle" {...boardsListPanel.resizeHandleProps} />
<Panel order={1} id="gallery-wrapper-panel" collapsible {...galleryPanel.panelProps}>
<GalleryPanel />
</Panel>
{tab === 'canvas' && (
<>
<HorizontalResizeHandle id="gallery-panel-to-layers-handle" {...galleryPanel.resizeHandleProps} />
<Panel order={2} id="canvas-layers-panel" collapsible {...canvasLayersPanel.panelProps}>
<CanvasManagerProviderGate>
<CanvasLayersPanel />
</CanvasManagerProviderGate>
</Panel>
</>
)}
</PanelGroup>
</FocusRegionWrapper>
);
});
RightPanelContent.displayName = 'RightPanelContent';

View File

@@ -1,306 +0,0 @@
import { Flex } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import type { DockviewApi, GridviewApi, IDockviewReactProps, IGridviewReactProps } from 'dockview';
import { DockviewReact, GridviewReact, Orientation } from 'dockview';
import { CanvasLayersPanel } from 'features/controlLayers/components/CanvasLayersPanelContent';
import { CanvasLaunchpadPanel } from 'features/controlLayers/components/SimpleSession/CanvasLaunchpadPanel';
import { GenerateLaunchpadPanel } from 'features/controlLayers/components/SimpleSession/GenerateLaunchpadPanel';
import { BoardsPanel } from 'features/gallery/components/BoardsListPanelContent';
import { GalleryPanel } from 'features/gallery/components/Gallery';
import { GenerationProgressPanel } from 'features/gallery/components/ImageViewer/GenerationProgressPanel';
import { ImageViewerPanel } from 'features/gallery/components/ImageViewer/ImageViewerPanel';
import { AutoLayoutProvider } from 'features/ui/layouts/auto-layout-context';
import { CanvasWorkspacePanel } from 'features/ui/layouts/CanvasWorkspacePanel';
import { GenerateLeftPanel } from 'features/ui/layouts/generate-tab-auto-layout';
import { TabWithoutCloseButton } from 'features/ui/layouts/TabWithoutCloseButton';
import { selectActiveTab } from 'features/ui/store/uiSelectors';
import { LEFT_PANEL_MIN_SIZE_PX, RIGHT_PANEL_MIN_SIZE_PX } from 'features/ui/store/uiSlice';
import type { TabName } from 'features/ui/store/uiTypes';
import { dockviewTheme } from 'features/ui/styles/theme';
import { atom } from 'nanostores';
import { memo, useCallback, useEffect, useState } from 'react';
export const dockviewComponents: IDockviewReactProps['components'] = {
// Shared components
ImageViewer: ImageViewerPanel,
GenerationProgress: GenerationProgressPanel,
// Generate tab
GenerateLaunchpad: GenerateLaunchpadPanel,
// Upscaling tab
UpscalingLaunchpad: GenerateLaunchpadPanel,
// Workflows tab
WorkflowsLaunchpad: GenerateLaunchpadPanel,
// Canvas tab
CanvasLaunchpad: CanvasLaunchpadPanel,
CanvasWorkspace: CanvasWorkspacePanel,
};
const getGenerateLaunchpadPanel = (api: DockviewApi) => {
return (
api.getPanel('GenerateLaunchpad') ||
api.addPanel({
id: 'GenerateLaunchpad',
component: 'GenerateLaunchpad',
title: 'Launchpad',
})
);
};
const getCanvasLaunchpadPanel = (api: DockviewApi) => {
return (
api.getPanel('CanvasLaunchpad') ||
api.addPanel({
id: 'CanvasLaunchpad',
component: 'CanvasLaunchpad',
title: 'Launchpad',
})
);
};
const getCanvasWorkspacePanel = (api: DockviewApi) => {
return (
api.getPanel('CanvasWorkspace') ||
api.addPanel({
id: 'CanvasWorkspace',
component: 'CanvasWorkspace',
title: 'Canvas',
})
);
};
const getImageViewerPanel = (api: DockviewApi) => {
return (
api.getPanel('ImageViewer') ||
api.addPanel({
id: 'ImageViewer',
component: 'ImageViewer',
title: 'Image Viewer',
})
);
};
const getGenerationProgressPanel = (api: DockviewApi) => {
return (
api.getPanel('GenerationProgress') ||
api.addPanel({
id: 'GenerationProgress',
component: 'GenerationProgress',
title: 'Generation Progress',
})
);
};
const syncMainPanelLayout = (tab: TabName, api: DockviewApi) => {
if (tab === 'generate') {
const GenerateLaunchpad = getGenerateLaunchpadPanel(api);
const ImageViewer = getImageViewerPanel(api);
const GenerationProgress = getGenerationProgressPanel(api);
const panelsToKeep = [GenerateLaunchpad.id, ImageViewer.id, GenerationProgress.id];
for (const panel of api.panels) {
if (!panelsToKeep.includes(panel.id)) {
api.removePanel(panel);
}
}
} else if (tab === 'canvas') {
const CanvasLaunchpad = getCanvasLaunchpadPanel(api);
const CanvasWorkspace = getCanvasWorkspacePanel(api);
const ImageViewer = getImageViewerPanel(api);
const GenerationProgress = getGenerationProgressPanel(api);
const panelsToKeep = [CanvasLaunchpad.id, CanvasWorkspace.id, ImageViewer.id, GenerationProgress.id];
for (const panel of api.panels) {
if (!panelsToKeep.includes(panel.id)) {
api.removePanel(panel);
}
}
}
};
const MainPanel = memo(() => {
const tab = useAppSelector(selectActiveTab);
const [api, setApi] = useState<DockviewApi | null>(null);
const onReady = useCallback<IDockviewReactProps['onReady']>((event) => {
console.log('MainPanel onReady', event.api);
setApi(event.api);
}, []);
useEffect(() => {
if (api) {
syncMainPanelLayout(tab, api);
}
}, [api, tab]);
return (
<Flex w="full" h="full">
<DockviewReact
disableDnd={true}
locked={true}
disableFloatingGroups={true}
dndEdges={false}
defaultTabComponent={TabWithoutCloseButton}
components={dockviewComponents}
onReady={onReady}
theme={dockviewTheme}
/>
</Flex>
);
});
MainPanel.displayName = 'MainPanel';
export const gridviewComponents: IGridviewReactProps['components'] = {
// Shared components
Gallery: GalleryPanel,
Boards: BoardsPanel,
Main: MainPanel,
GenerateLeft: GenerateLeftPanel,
CanvasLeft: GenerateLeftPanel,
CanvasLayers: CanvasLayersPanel,
};
const syncGridviewLayout = (tab: TabName, api: GridviewApi) => {
if (tab === 'generate') {
const MainPanel =
api.getPanel('Main') ??
api.addPanel({
id: 'Main',
component: 'Main',
});
const GenerateLeftPanel =
api.getPanel('GenerateLeft') ??
api.addPanel({
id: 'GenerateLeft',
component: 'GenerateLeft',
minimumWidth: LEFT_PANEL_MIN_SIZE_PX,
position: {
direction: 'left',
referencePanel: MainPanel.id,
},
});
const GalleryPanel =
api.getPanel('Gallery') ??
api.addPanel({
id: 'Gallery',
component: 'Gallery',
minimumWidth: RIGHT_PANEL_MIN_SIZE_PX,
minimumHeight: 232,
position: {
direction: 'right',
referencePanel: MainPanel.id,
},
});
const BoardsPanel =
api.getPanel('Boards') ??
api.addPanel({
id: 'Boards',
component: 'Boards',
minimumWidth: RIGHT_PANEL_MIN_SIZE_PX,
minimumHeight: 36,
position: {
direction: 'above',
referencePanel: GalleryPanel.id,
},
});
const panelsToKeep = [MainPanel.id, GenerateLeftPanel.id, GalleryPanel.id, BoardsPanel.id];
for (const panel of api.panels) {
if (!panelsToKeep.includes(panel.id)) {
api.removePanel(panel);
}
}
} else if (tab === 'canvas') {
const MainPanel =
api.getPanel('Main') ??
api.addPanel({
id: 'Main',
component: 'Main',
});
const CanvasLeftPanel =
api.getPanel('CanvasLeft') ??
api.addPanel({
id: 'CanvasLeft',
component: 'CanvasLeft',
minimumWidth: LEFT_PANEL_MIN_SIZE_PX,
position: {
direction: 'left',
referencePanel: MainPanel.id,
},
});
const GalleryPanel =
api.getPanel('Gallery') ??
api.addPanel({
id: 'Gallery',
component: 'Gallery',
minimumWidth: RIGHT_PANEL_MIN_SIZE_PX,
minimumHeight: 232,
position: {
direction: 'right',
referencePanel: MainPanel.id,
},
});
const BoardsPanel =
api.getPanel('Boards') ??
api.addPanel({
id: 'Boards',
component: 'Boards',
minimumWidth: RIGHT_PANEL_MIN_SIZE_PX,
minimumHeight: 36,
position: {
direction: 'above',
referencePanel: GalleryPanel.id,
},
});
const CanvasLayersPanel =
api.getPanel('CanvasLayers') ??
api.addPanel({
id: 'CanvasLayers',
component: 'CanvasLayers',
minimumWidth: RIGHT_PANEL_MIN_SIZE_PX,
minimumHeight: 232,
position: {
direction: 'below',
referencePanel: GalleryPanel.id,
},
});
const panelsToKeep = [MainPanel.id, CanvasLeftPanel.id, GalleryPanel.id, BoardsPanel.id, CanvasLayersPanel.id];
for (const panel of api.panels) {
if (!panelsToKeep.includes(panel.id)) {
api.removePanel(panel);
}
}
}
};
export const AutoLayout = memo(() => {
const tab = useAppSelector(selectActiveTab);
const $api = useState(() => atom<GridviewApi | null>(null))[0];
const onReady = useCallback<IGridviewReactProps['onReady']>(
(event) => {
$api.set(event.api);
},
[$api]
);
useEffect(() => {
const api = $api.get();
if (api) {
syncGridviewLayout(tab, api);
}
}, [$api, tab]);
return (
<AutoLayoutProvider $api={$api}>
<GridviewReact
className="dockview-theme-invoke"
components={gridviewComponents}
onReady={onReady}
orientation={Orientation.VERTICAL}
/>
</AutoLayoutProvider>
);
});
AutoLayout.displayName = 'AutoLayout';

View File

@@ -12,7 +12,6 @@ export const TabWithoutCloseButton = (props: IDockviewPanelHeaderProps) => {
}, [props.api]);
useCallbackOnDragEnter(setActive, ref, 300);
console.log(props.api.title);
return (
<Flex ref={ref}>

View File

@@ -1,29 +0,0 @@
import type { IDockviewReactProps, IGridviewReactProps } from 'dockview';
import { CanvasLayersPanel } from 'features/controlLayers/components/CanvasLayersPanelContent';
import { GenerateLaunchpadPanel } from 'features/controlLayers/components/SimpleSession/GenerateLaunchpadPanel';
import { BoardsPanel } from 'features/gallery/components/BoardsListPanelContent';
import { GalleryPanel } from 'features/gallery/components/Gallery';
import { GenerationProgressPanel } from 'features/gallery/components/ImageViewer/GenerationProgressPanel';
import { ImageViewerPanel } from 'features/gallery/components/ImageViewer/ImageViewerPanel';
import { CanvasWorkspacePanel } from 'features/ui/layouts/canvas-tab-auto-layout';
import { GenerateLeftPanel } from 'features/ui/layouts/generate-tab-auto-layout';
export const components: IDockviewReactProps['components'] & IGridviewReactProps['components'] = {
// Shared components
Gallery: GalleryPanel,
Boards: BoardsPanel,
ImageViewer: ImageViewerPanel,
GenerationProgress: GenerationProgressPanel,
// Generate tab
GenerateLaunchpad: GenerateLaunchpadPanel,
GenerateLeft: GenerateLeftPanel,
// Upscaling tab
UpscalingLaunchpad: GenerateLaunchpadPanel,
// Workflows tab
WorkflowsLaunchpad: GenerateLaunchpadPanel,
// Canvas tab
CanvasLaunchpad: GenerateLaunchpadPanel,
CanvasLayers: CanvasLayersPanel,
CanvasWorkspace: CanvasWorkspacePanel,
CanvasLeft: GenerateLeftPanel,
};