From ff84b0a495954feea486162770f4ad8b377f1edd Mon Sep 17 00:00:00 2001
From: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Date: Fri, 4 Jul 2025 12:09:51 +1000
Subject: [PATCH] refactor(ui): navigation api
---
.../src/features/ui/components/AppContent.tsx | 55 ++++++-------------
.../ui/layouts/canvas-tab-auto-layout.tsx | 15 ++---
.../ui/layouts/generate-tab-auto-layout.tsx | 15 ++---
.../src/features/ui/layouts/navigation-api.ts | 2 +-
.../ui/layouts/upscaling-tab-auto-layout.tsx | 16 +++---
.../ui/layouts/workflows-tab-auto-layout.tsx | 15 ++---
6 files changed, 50 insertions(+), 68 deletions(-)
diff --git a/invokeai/frontend/web/src/features/ui/components/AppContent.tsx b/invokeai/frontend/web/src/features/ui/components/AppContent.tsx
index 618877f578..2e67c94b2f 100644
--- a/invokeai/frontend/web/src/features/ui/components/AppContent.tsx
+++ b/invokeai/frontend/web/src/features/ui/components/AppContent.tsx
@@ -1,8 +1,9 @@
import 'dockview/dist/styles/dockview.css';
import 'features/ui/styles/dockview-theme-invoke.css';
-import { TabPanel, TabPanels, Tabs } from '@invoke-ai/ui-library';
+import { Flex } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
+import Loading from 'common/components/Loading/Loading';
import { useDndMonitor } from 'features/dnd/useDndMonitor';
import {
selectWithCanvasTab,
@@ -17,15 +18,16 @@ import { CanvasTabAutoLayout } from 'features/ui/layouts/canvas-tab-auto-layout'
import { GenerateTabAutoLayout } from 'features/ui/layouts/generate-tab-auto-layout';
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 { memo } from 'react';
+import { selectActiveTab } from 'features/ui/store/uiSelectors';
+import { memo, useState } from 'react';
import ModelManagerTab from './tabs/ModelManagerTab';
import QueueTab from './tabs/QueueTab';
export const AppContent = memo(() => {
useDndMonitor();
- const tabIndex = useAppSelector(selectActiveTabIndex);
+ const tab = useAppSelector(selectActiveTab);
+ const [isLoading, setIsLoading] = useState(true);
const withGenerateTab = useAppSelector(selectWithGenerateTab);
const withCanvasTab = useAppSelector(selectWithCanvasTab);
const withUpscalingTab = useAppSelector(selectWithUpscalingTab);
@@ -34,41 +36,18 @@ export const AppContent = memo(() => {
const withQueueTab = useAppSelector(selectWithQueueTab);
return (
-
+
-
- {withGenerateTab && (
-
-
-
- )}
- {withCanvasTab && (
-
-
-
- )}
- {withUpscalingTab && (
-
-
-
- )}
- {withWorkflowsTab && (
-
-
-
- )}
- {withModelsTab && (
-
-
-
- )}
- {withQueueTab && (
-
-
-
- )}
-
-
+
+ {withGenerateTab && tab === 'generate' && }
+ {withCanvasTab && tab === 'canvas' && }
+ {withUpscalingTab && tab === 'upscaling' && }
+ {withWorkflowsTab && tab === 'workflows' && }
+ {withModelsTab && tab === 'models' && }
+ {withQueueTab && tab === 'queue' && }
+ {isLoading && }
+
+
);
});
AppContent.displayName = 'AppContent';
diff --git a/invokeai/frontend/web/src/features/ui/layouts/canvas-tab-auto-layout.tsx b/invokeai/frontend/web/src/features/ui/layouts/canvas-tab-auto-layout.tsx
index 27f78fd49d..980ffedf2b 100644
--- a/invokeai/frontend/web/src/features/ui/layouts/canvas-tab-auto-layout.tsx
+++ b/invokeai/frontend/web/src/features/ui/layouts/canvas-tab-auto-layout.tsx
@@ -56,7 +56,6 @@ import {
} from './shared';
import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon';
import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator';
-import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
const tabComponents = {
[DEFAULT_TAB_ID]: TabWithoutCloseButton,
@@ -326,28 +325,30 @@ export const initializeRootPanelLayout = (api: GridviewApi) => {
return { main, left, right } satisfies Record;
};
-export const CanvasTabAutoLayout = memo(() => {
+export const CanvasTabAutoLayout = memo(({ setIsLoading }: { setIsLoading: (isLoading: boolean) => void }) => {
const rootRef = useRef(null);
const [rootApi, setRootApi] = useState(null);
const onReady = useCallback(({ api }) => {
setRootApi(api);
}, []);
- useResizeMainPanelOnFirstVisit(rootApi, rootRef);
-
useEffect(() => {
+ setIsLoading(true);
+
if (!rootApi) {
return;
}
+
initializeRootPanelLayout(rootApi);
- // Focus the launchpad panel once it's ready
- navigationApi.focusPanel('canvas', LAUNCHPAD_PANEL_ID);
+ setTimeout(() => {
+ setIsLoading(false);
+ }, 300);
return () => {
navigationApi.unregisterTab('canvas');
};
- }, [rootApi]);
+ }, [rootApi, setIsLoading]);
return (
diff --git a/invokeai/frontend/web/src/features/ui/layouts/generate-tab-auto-layout.tsx b/invokeai/frontend/web/src/features/ui/layouts/generate-tab-auto-layout.tsx
index 1cd6e1eab6..3a5d99eb7b 100644
--- a/invokeai/frontend/web/src/features/ui/layouts/generate-tab-auto-layout.tsx
+++ b/invokeai/frontend/web/src/features/ui/layouts/generate-tab-auto-layout.tsx
@@ -51,7 +51,6 @@ import {
} from './shared';
import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon';
import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator';
-import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
const tabComponents = {
[DEFAULT_TAB_ID]: TabWithoutCloseButton,
@@ -288,28 +287,30 @@ export const initializeRootPanelLayout = (layoutApi: GridviewApi) => {
return { main, left, right } satisfies Record;
};
-export const GenerateTabAutoLayout = memo(() => {
+export const GenerateTabAutoLayout = memo(({ setIsLoading }: { setIsLoading: (isLoading: boolean) => void }) => {
const rootRef = useRef(null);
const [rootApi, setRootApi] = useState(null);
const onReady = useCallback(({ api }) => {
setRootApi(api);
}, []);
- useResizeMainPanelOnFirstVisit(rootApi, rootRef);
-
useEffect(() => {
+ setIsLoading(true);
+
if (!rootApi) {
return;
}
+
initializeRootPanelLayout(rootApi);
- // Focus the launchpad panel once it's ready
- navigationApi.focusPanel('generate', LAUNCHPAD_PANEL_ID);
+ setTimeout(() => {
+ setIsLoading(false);
+ }, 300);
return () => {
navigationApi.unregisterTab('generate');
};
- }, [rootApi]);
+ }, [rootApi, setIsLoading]);
return (
diff --git a/invokeai/frontend/web/src/features/ui/layouts/navigation-api.ts b/invokeai/frontend/web/src/features/ui/layouts/navigation-api.ts
index ddc9384b16..5a5018ca5e 100644
--- a/invokeai/frontend/web/src/features/ui/layouts/navigation-api.ts
+++ b/invokeai/frontend/web/src/features/ui/layouts/navigation-api.ts
@@ -14,7 +14,7 @@ type Waiter = {
timeoutId: ReturnType | null;
};
-const PANEL_ENABLED_TABS: TabName[] = ['canvas', 'generate', 'workflows', 'queue'];
+const PANEL_ENABLED_TABS: TabName[] = ['canvas', 'generate', 'workflows', 'upscaling'];
export class NavigationApi {
private panels: Map = new Map();
diff --git a/invokeai/frontend/web/src/features/ui/layouts/upscaling-tab-auto-layout.tsx b/invokeai/frontend/web/src/features/ui/layouts/upscaling-tab-auto-layout.tsx
index dbc9771c2a..f9a5667fcd 100644
--- a/invokeai/frontend/web/src/features/ui/layouts/upscaling-tab-auto-layout.tsx
+++ b/invokeai/frontend/web/src/features/ui/layouts/upscaling-tab-auto-layout.tsx
@@ -51,7 +51,6 @@ import {
import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon';
import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator';
import { UpscalingTabLeftPanel } from './UpscalingTabLeftPanel';
-import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
const tabComponents = {
[DEFAULT_TAB_ID]: TabWithoutCloseButton,
@@ -288,28 +287,29 @@ export const initializeRootPanelLayout = (layoutApi: GridviewApi) => {
return { main, left, right } satisfies Record;
};
-export const UpscalingTabAutoLayout = memo(() => {
+export const UpscalingTabAutoLayout = memo(({ setIsLoading }: { setIsLoading: (isLoading: boolean) => void }) => {
const rootRef = useRef(null);
const [rootApi, setRootApi] = useState(null);
const onReady = useCallback(({ api }) => {
setRootApi(api);
}, []);
- useResizeMainPanelOnFirstVisit(rootApi, rootRef);
-
useEffect(() => {
+ setIsLoading(true);
+
if (!rootApi) {
return;
}
+
initializeRootPanelLayout(rootApi);
- // Focus the launchpad panel once it's ready
- navigationApi.focusPanel('upscaling', LAUNCHPAD_PANEL_ID);
-
+ setTimeout(() => {
+ setIsLoading(false);
+ }, 300);
return () => {
navigationApi.unregisterTab('upscaling');
};
- }, [rootApi]);
+ }, [rootApi, setIsLoading]);
return (
diff --git a/invokeai/frontend/web/src/features/ui/layouts/workflows-tab-auto-layout.tsx b/invokeai/frontend/web/src/features/ui/layouts/workflows-tab-auto-layout.tsx
index 6003c2b650..d4bc09b586 100644
--- a/invokeai/frontend/web/src/features/ui/layouts/workflows-tab-auto-layout.tsx
+++ b/invokeai/frontend/web/src/features/ui/layouts/workflows-tab-auto-layout.tsx
@@ -53,7 +53,6 @@ import {
} from './shared';
import { TabWithLaunchpadIcon } from './TabWithLaunchpadIcon';
import { TabWithoutCloseButtonAndWithProgressIndicator } from './TabWithoutCloseButtonAndWithProgressIndicator';
-import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
const tabComponents = {
[DEFAULT_TAB_ID]: TabWithoutCloseButton,
@@ -305,28 +304,30 @@ export const initializeRootPanelLayout = (api: GridviewApi) => {
return { main, left, right } satisfies Record;
};
-export const WorkflowsTabAutoLayout = memo(() => {
+export const WorkflowsTabAutoLayout = memo(({ setIsLoading }: { setIsLoading: (isLoading: boolean) => void }) => {
const rootRef = useRef(null);
const [rootApi, setRootApi] = useState(null);
const onReady = useCallback(({ api }) => {
setRootApi(api);
}, []);
- useResizeMainPanelOnFirstVisit(rootApi, rootRef);
-
useEffect(() => {
+ setIsLoading(true);
+
if (!rootApi) {
return;
}
+
initializeRootPanelLayout(rootApi);
- // Focus the launchpad panel once it's ready
- navigationApi.focusPanel('workflows', LAUNCHPAD_PANEL_ID);
+ setTimeout(() => {
+ setIsLoading(false);
+ }, 300);
return () => {
navigationApi.unregisterTab('workflows');
};
- }, [rootApi]);
+ }, [rootApi, setIsLoading]);
return (