mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-02-14 07:45:12 -05:00
fix(ui): really do not load disabled tabs
Ensure disabled tabs are never mounted: - Add didLoad flag to configSlice, default false - Always merge in config - even it is is empty - On first merge, set didLoad to true - Until didLoad is true, mark _all_ tabs as disabled This gets around an issue where tabs are all enabled for a brief moment before the config is loaded. A bit hacky but it works.
This commit is contained in:
committed by
Mary Hipp Rogers
parent
79fea1ac40
commit
3f78ac9295
@@ -10,7 +10,6 @@ import type { PartialAppConfig } from 'app/types/invokeai';
|
||||
import { useFocusRegionWatcher } from 'common/hooks/focus';
|
||||
import { useCloseChakraTooltipsOnDragFix } from 'common/hooks/useCloseChakraTooltipsOnDragFix';
|
||||
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
|
||||
import { size } from 'es-toolkit/compat';
|
||||
import { useDynamicPromptsWatcher } from 'features/dynamicPrompts/hooks/useDynamicPromptsWatcher';
|
||||
import { useStarterModelsToast } from 'features/modelManagerV2/hooks/useStarterModelsToast';
|
||||
import { useWorkflowBuilderWatcher } from 'features/nodes/components/sidePanel/workflow/IsolatedWorkflowBuilderWatcher';
|
||||
@@ -55,10 +54,8 @@ export const GlobalHookIsolator = memo(
|
||||
}, [language]);
|
||||
|
||||
useEffect(() => {
|
||||
if (size(config)) {
|
||||
logger.info({ config }, 'Received config');
|
||||
dispatch(configChanged(config));
|
||||
}
|
||||
logger.info({ config }, 'Received config');
|
||||
dispatch(configChanged(config));
|
||||
}, [dispatch, config, logger]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -16,7 +16,8 @@ const baseDimensionConfig: NumericalParameterConfig = {
|
||||
coarseStep: 64,
|
||||
};
|
||||
|
||||
const initialConfigState: AppConfig = {
|
||||
const initialConfigState: AppConfig & { didLoad: boolean } = {
|
||||
didLoad: false,
|
||||
isLocal: true,
|
||||
shouldUpdateImagesOnConnect: false,
|
||||
shouldFetchMetadataFromApi: false,
|
||||
@@ -191,6 +192,7 @@ export const configSlice = createSlice({
|
||||
reducers: {
|
||||
configChanged: (state, action: PayloadAction<PartialAppConfig>) => {
|
||||
merge(state, action.payload);
|
||||
state.didLoad = true;
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -198,7 +200,8 @@ export const configSlice = createSlice({
|
||||
export const { configChanged } = configSlice.actions;
|
||||
|
||||
export const selectConfigSlice = (state: RootState) => state.config;
|
||||
const createConfigSelector = <T>(selector: Selector<AppConfig, T>) => createSelector(selectConfigSlice, selector);
|
||||
const createConfigSelector = <T>(selector: Selector<typeof initialConfigState, T>) =>
|
||||
createSelector(selectConfigSlice, selector);
|
||||
|
||||
export const selectWidthConfig = createConfigSelector((config) => config.sd.width);
|
||||
export const selectHeightConfig = createConfigSelector((config) => config.sd.height);
|
||||
@@ -236,3 +239,23 @@ export const selectEnabledTabs = createConfigSelector((config) => {
|
||||
}
|
||||
return enabledTabs;
|
||||
});
|
||||
const selectDisabledTabs = createConfigSelector((config) => config.disabledTabs);
|
||||
const selectDidLoad = createConfigSelector((config) => config.didLoad);
|
||||
export const selectWithGenerateTab = createSelector(selectDidLoad, selectDisabledTabs, (didLoad, disabledTabs) =>
|
||||
didLoad ? !disabledTabs.includes('generate') : false
|
||||
);
|
||||
export const selectWithCanvasTab = createSelector(selectDidLoad, selectDisabledTabs, (didLoad, disabledTabs) =>
|
||||
didLoad ? !disabledTabs.includes('canvas') : false
|
||||
);
|
||||
export const selectWithUpscalingTab = createSelector(selectDidLoad, selectDisabledTabs, (didLoad, disabledTabs) =>
|
||||
didLoad ? !disabledTabs.includes('upscaling') : false
|
||||
);
|
||||
export const selectWithWorkflowsTab = createSelector(selectDidLoad, selectDisabledTabs, (didLoad, disabledTabs) =>
|
||||
didLoad ? !disabledTabs.includes('workflows') : false
|
||||
);
|
||||
export const selectWithModelsTab = createSelector(selectDidLoad, selectDisabledTabs, (didLoad, disabledTabs) =>
|
||||
didLoad ? !disabledTabs.includes('models') : false
|
||||
);
|
||||
export const selectWithQueueTab = createSelector(selectDidLoad, selectDisabledTabs, (didLoad, disabledTabs) =>
|
||||
didLoad ? !disabledTabs.includes('queue') : false
|
||||
);
|
||||
|
||||
@@ -4,6 +4,14 @@ import 'features/ui/styles/dockview-theme-invoke.css';
|
||||
import { TabPanel, TabPanels, Tabs } from '@invoke-ai/ui-library';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { useDndMonitor } from 'features/dnd/useDndMonitor';
|
||||
import {
|
||||
selectWithCanvasTab,
|
||||
selectWithGenerateTab,
|
||||
selectWithModelsTab,
|
||||
selectWithQueueTab,
|
||||
selectWithUpscalingTab,
|
||||
selectWithWorkflowsTab,
|
||||
} from 'features/system/store/configSlice';
|
||||
import { VerticalNavBar } from 'features/ui/components/VerticalNavBar';
|
||||
import { CanvasTabAutoLayout } from 'features/ui/layouts/canvas-tab-auto-layout';
|
||||
import { GenerateTabAutoLayout } from 'features/ui/layouts/generate-tab-auto-layout';
|
||||
@@ -12,48 +20,53 @@ import { WorkflowsTabAutoLayout } from 'features/ui/layouts/workflows-tab-auto-l
|
||||
import { selectActiveTabIndex } from 'features/ui/store/uiSelectors';
|
||||
import { memo } from 'react';
|
||||
|
||||
import { TabMountGate } from './TabMountGate';
|
||||
import ModelManagerTab from './tabs/ModelManagerTab';
|
||||
import QueueTab from './tabs/QueueTab';
|
||||
|
||||
export const AppContent = memo(() => {
|
||||
const tabIndex = useAppSelector(selectActiveTabIndex);
|
||||
useDndMonitor();
|
||||
const tabIndex = useAppSelector(selectActiveTabIndex);
|
||||
const withGenerateTab = useAppSelector(selectWithGenerateTab);
|
||||
const withCanvasTab = useAppSelector(selectWithCanvasTab);
|
||||
const withUpscalingTab = useAppSelector(selectWithUpscalingTab);
|
||||
const withWorkflowsTab = useAppSelector(selectWithWorkflowsTab);
|
||||
const withModelsTab = useAppSelector(selectWithModelsTab);
|
||||
const withQueueTab = useAppSelector(selectWithQueueTab);
|
||||
|
||||
return (
|
||||
<Tabs index={tabIndex} display="flex" w="full" h="full" p={0} overflow="hidden">
|
||||
<VerticalNavBar />
|
||||
<TabPanels w="full" h="full" p={0}>
|
||||
<TabMountGate tab="generate">
|
||||
{withGenerateTab && (
|
||||
<TabPanel w="full" h="full" p={0}>
|
||||
<GenerateTabAutoLayout />
|
||||
</TabPanel>
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="canvas">
|
||||
)}
|
||||
{withCanvasTab && (
|
||||
<TabPanel w="full" h="full" p={0}>
|
||||
<CanvasTabAutoLayout />
|
||||
</TabPanel>
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="upscaling">
|
||||
)}
|
||||
{withUpscalingTab && (
|
||||
<TabPanel w="full" h="full" p={0}>
|
||||
<UpscalingTabAutoLayout />
|
||||
</TabPanel>
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="workflows">
|
||||
)}
|
||||
{withWorkflowsTab && (
|
||||
<TabPanel w="full" h="full" p={0}>
|
||||
<WorkflowsTabAutoLayout />
|
||||
</TabPanel>
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="models">
|
||||
)}
|
||||
{withModelsTab && (
|
||||
<TabPanel w="full" h="full" p={0}>
|
||||
<ModelManagerTab />
|
||||
</TabPanel>
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="queue">
|
||||
)}
|
||||
{withQueueTab && (
|
||||
<TabPanel w="full" h="full" p={0}>
|
||||
<QueueTab />
|
||||
</TabPanel>
|
||||
</TabMountGate>
|
||||
)}
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
);
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
import { Flex, Spacer } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { $customNavComponent } from 'app/store/nanostores/customNavComponent';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import InvokeAILogoComponent from 'features/system/components/InvokeAILogoComponent';
|
||||
import SettingsMenu from 'features/system/components/SettingsModal/SettingsMenu';
|
||||
import StatusIndicator from 'features/system/components/StatusIndicator';
|
||||
import { VideosModalButton } from 'features/system/components/VideosModal/VideosModalButton';
|
||||
import { TabMountGate } from 'features/ui/components/TabMountGate';
|
||||
import {
|
||||
selectWithCanvasTab,
|
||||
selectWithGenerateTab,
|
||||
selectWithModelsTab,
|
||||
selectWithQueueTab,
|
||||
selectWithUpscalingTab,
|
||||
selectWithWorkflowsTab,
|
||||
} from 'features/system/store/configSlice';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
@@ -23,29 +31,23 @@ import { TabButton } from './TabButton';
|
||||
export const VerticalNavBar = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const customNavComponent = useStore($customNavComponent);
|
||||
const withGenerateTab = useAppSelector(selectWithGenerateTab);
|
||||
const withCanvasTab = useAppSelector(selectWithCanvasTab);
|
||||
const withUpscalingTab = useAppSelector(selectWithUpscalingTab);
|
||||
const withWorkflowsTab = useAppSelector(selectWithWorkflowsTab);
|
||||
const withModelsTab = useAppSelector(selectWithModelsTab);
|
||||
const withQueueTab = useAppSelector(selectWithQueueTab);
|
||||
|
||||
return (
|
||||
<Flex flexDir="column" alignItems="center" py={6} ps={4} pe={2} gap={4} minW={0} flexShrink={0}>
|
||||
<InvokeAILogoComponent />
|
||||
<Flex gap={6} pt={6} h="full" flexDir="column">
|
||||
<TabMountGate tab="generate">
|
||||
<TabButton tab="generate" icon={<PiTextAaBold />} label="Generate" />
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="canvas">
|
||||
<TabButton tab="canvas" icon={<PiBoundingBoxBold />} label={t('ui.tabs.canvas')} />
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="upscaling">
|
||||
<TabButton tab="upscaling" icon={<PiFrameCornersBold />} label={t('ui.tabs.upscaling')} />
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="workflows">
|
||||
<TabButton tab="workflows" icon={<PiFlowArrowBold />} label={t('ui.tabs.workflows')} />
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="models">
|
||||
<TabButton tab="models" icon={<PiCubeBold />} label={t('ui.tabs.models')} />
|
||||
</TabMountGate>
|
||||
<TabMountGate tab="queue">
|
||||
<TabButton tab="queue" icon={<PiQueueBold />} label={t('ui.tabs.queue')} />
|
||||
</TabMountGate>
|
||||
{withGenerateTab && <TabButton tab="generate" icon={<PiTextAaBold />} label="Generate" />}
|
||||
{withCanvasTab && <TabButton tab="canvas" icon={<PiBoundingBoxBold />} label={t('ui.tabs.canvas')} />}
|
||||
{withUpscalingTab && <TabButton tab="upscaling" icon={<PiFrameCornersBold />} label={t('ui.tabs.upscaling')} />}
|
||||
{withWorkflowsTab && <TabButton tab="workflows" icon={<PiFlowArrowBold />} label={t('ui.tabs.workflows')} />}
|
||||
{withModelsTab && <TabButton tab="models" icon={<PiCubeBold />} label={t('ui.tabs.models')} />}
|
||||
{withQueueTab && <TabButton tab="queue" icon={<PiQueueBold />} label={t('ui.tabs.queue')} />}
|
||||
</Flex>
|
||||
<Spacer />
|
||||
<StatusIndicator />
|
||||
|
||||
Reference in New Issue
Block a user