diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index 0505689184..ccc4a9aa24 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -11,7 +11,7 @@ import { Text, useDisclosure, } from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; +import { createSelector, current } from '@reduxjs/toolkit'; import { VALID_LOG_LEVELS } from 'app/logging/useLogger'; import { LOCALSTORAGE_KEYS, LOCALSTORAGE_PREFIX } from 'app/store/constants'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; @@ -23,6 +23,7 @@ import { SystemState, consoleLogLevelChanged, setEnableImageDebugging, + setIsNodesEnabled, setShouldConfirmOnDelete, setShouldDisplayGuides, shouldAntialiasProgressImageChanged, @@ -60,6 +61,7 @@ const selector = createSelector( consoleLogLevel, shouldLogToConsole, shouldAntialiasProgressImage, + isNodesEnabled, } = system; const { @@ -80,6 +82,7 @@ const selector = createSelector( shouldLogToConsole, shouldAntialiasProgressImage, shouldShowAdvancedOptions, + isNodesEnabled, }; }, { @@ -93,6 +96,7 @@ type ConfigOptions = { shouldShowBetaLayout: boolean; shouldShowAdvancedOptionsSettings: boolean; shouldShowClearIntermediates: boolean; + shouldShowNodesToggle: boolean; }; type SettingsModalProps = { @@ -113,6 +117,7 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => { config?.shouldShowAdvancedOptionsSettings ?? true; const shouldShowClearIntermediates = config?.shouldShowClearIntermediates ?? true; + const shouldShowNodesToggle = config?.shouldShowNodesToggle ?? true; useEffect(() => { if (!shouldShowDeveloperSettings) { @@ -143,6 +148,7 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => { shouldLogToConsole, shouldAntialiasProgressImage, shouldShowAdvancedOptions, + isNodesEnabled, } = useAppSelector(selector); const handleClickResetWebUI = useCallback(() => { @@ -173,6 +179,13 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => { [dispatch] ); + const handleToggleNodes = useCallback( + (e: ChangeEvent) => { + dispatch(setIsNodesEnabled(e.target.checked)); + }, + [dispatch] + ); + return ( <> {cloneElement(children, { @@ -257,6 +270,13 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => { ) } /> + {shouldShowNodesToggle && ( + + )} {shouldShowDeveloperSettings && ( diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 723bf3c483..5bbaa2265f 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -85,6 +85,7 @@ export interface SystemState { language: keyof typeof LANGUAGES; isUploading: boolean; boardIdToAddTo?: string; + isNodesEnabled: boolean; } export const initialSystemState: SystemState = { @@ -117,6 +118,7 @@ export const initialSystemState: SystemState = { isPersisted: false, language: 'en', isUploading: false, + isNodesEnabled: false, }; export const systemSlice = createSlice({ @@ -192,6 +194,9 @@ export const systemSlice = createSlice({ progressImageSet(state, action: PayloadAction) { state.progressImage = action.payload; }, + setIsNodesEnabled(state, action: PayloadAction) { + state.isNodesEnabled = action.payload; + }, }, extraReducers(builder) { /** @@ -400,6 +405,7 @@ export const { shouldAntialiasProgressImageChanged, languageChanged, progressImageSet, + setIsNodesEnabled, } = systemSlice.actions; export default systemSlice.reducer; diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx index a4e0773695..94195a27c1 100644 --- a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx +++ b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx @@ -37,6 +37,7 @@ import NodesTab from './tabs/Nodes/NodesTab'; import ResizeHandle from './tabs/ResizeHandle'; import TextToImageTab from './tabs/TextToImage/TextToImageTab'; import UnifiedCanvasTab from './tabs/UnifiedCanvas/UnifiedCanvasTab'; +import { systemSelector } from '../../system/store/systemSelectors'; export interface InvokeTabInfo { id: InvokeTabName; @@ -84,11 +85,20 @@ const tabs: InvokeTabInfo[] = [ ]; const enabledTabsSelector = createSelector( - configSelector, - (config) => { + [configSelector, systemSelector], + (config, system) => { const { disabledTabs } = config; + const { isNodesEnabled } = system; - return tabs.filter((tab) => !disabledTabs.includes(tab.id)); + const enabledTabs = tabs.filter((tab) => { + if (tab.id === 'nodes') { + return isNodesEnabled && !disabledTabs.includes(tab.id); + } else { + return !disabledTabs.includes(tab.id); + } + }); + + return enabledTabs; }, { memoizeOptions: { resultEqualityCheck: isEqual },