From 9820829edb64334a98fe070e762bbbd77c7378a9 Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Tue, 4 Apr 2023 14:12:19 -0400 Subject: [PATCH 1/4] feat(ui): disable panels based on app props --- invokeai/frontend/web/index.d.ts | 1 + invokeai/frontend/web/src/app/store.ts | 106 +++++++++++++----- invokeai/frontend/web/src/component.tsx | 7 +- .../components/ParametersAccordion.tsx | 29 +++-- .../ImageToImage/ImageToImageParameters.tsx | 2 +- .../TextToImage/TextToImageParameters.tsx | 2 +- .../web/src/features/ui/store/uiSlice.ts | 10 ++ .../web/src/features/ui/store/uiTypes.ts | 1 + invokeai/frontend/web/src/persistor.ts | 4 +- 9 files changed, 112 insertions(+), 50 deletions(-) diff --git a/invokeai/frontend/web/index.d.ts b/invokeai/frontend/web/index.d.ts index 06a362d3a2..9821091370 100644 --- a/invokeai/frontend/web/index.d.ts +++ b/invokeai/frontend/web/index.d.ts @@ -68,6 +68,7 @@ declare module '@invoke-ai/invoke-ai-ui' { interface InvokeProps extends PropsWithChildren { apiUrl?: string; + disabledPanels?: string[]; } declare function Invoke(props: InvokeProps): JSX.Element; diff --git a/invokeai/frontend/web/src/app/store.ts b/invokeai/frontend/web/src/app/store.ts index 1fc09a2c99..762607d64d 100644 --- a/invokeai/frontend/web/src/app/store.ts +++ b/invokeai/frontend/web/src/app/store.ts @@ -5,16 +5,28 @@ import storage from 'redux-persist/lib/storage'; // defaults to localStorage for import { getPersistConfig } from 'redux-deep-persist'; -import canvasReducer from 'features/canvas/store/canvasSlice'; -import galleryReducer from 'features/gallery/store/gallerySlice'; -import resultsReducer from 'features/gallery/store/resultsSlice'; -import uploadsReducer from 'features/gallery/store/uploadsSlice'; -import lightboxReducer from 'features/lightbox/store/lightboxSlice'; -import generationReducer from 'features/parameters/store/generationSlice'; -import postprocessingReducer from 'features/parameters/store/postprocessingSlice'; -import systemReducer from 'features/system/store/systemSlice'; -import uiReducer from 'features/ui/store/uiSlice'; -import apiReducer from 'services/apiSlice'; +import canvasReducer, { canvasSlice } from 'features/canvas/store/canvasSlice'; +import galleryReducer, { + gallerySlice, +} from 'features/gallery/store/gallerySlice'; +import resultsReducer, { + resultsSlice, +} from 'features/gallery/store/resultsSlice'; +import uploadsReducer, { + uploadsSlice, +} from 'features/gallery/store/uploadsSlice'; +import lightboxReducer, { + lightboxSlice, +} from 'features/lightbox/store/lightboxSlice'; +import generationReducer, { + generationSlice, +} from 'features/parameters/store/generationSlice'; +import postprocessingReducer, { + postprocessingSlice, +} from 'features/parameters/store/postprocessingSlice'; +import systemReducer, { systemSlice } from 'features/system/store/systemSlice'; +import uiReducer, { uiSlice } from 'features/ui/store/uiSlice'; +import apiReducer, { apiSlice } from 'services/apiSlice'; import { socketioMiddleware } from './socketio/middleware'; import { socketioMiddleware as nodesSocketioMiddleware } from './nodesSocketio/middleware'; @@ -113,28 +125,60 @@ function buildMiddleware() { } } +interface InitializeStore { + disabledPanels?: string[]; +} + +const disablePanels = ({ + disabledPanels, + enabledParameterPanels, +}: { + disabledPanels: string[]; + enabledParameterPanels: { [key: string]: boolean }; +}) => { + const updatedParameterPanels: { [key: string]: boolean } = {}; + Object.keys(enabledParameterPanels).forEach(function (key, index) { + updatedParameterPanels[key] = + disabledPanels.indexOf(key) >= 0 ? false : true; + }); + return updatedParameterPanels; +}; + // Continue with store setup -export const store = configureStore({ - reducer: persistedReducer, - middleware: (getDefaultMiddleware) => - getDefaultMiddleware({ - immutableCheck: false, - serializableCheck: false, - }).concat(buildMiddleware()), - devTools: { - // Uncommenting these very rapidly called actions makes the redux dev tools output much more readable - actionsDenylist: [ - 'canvas/setCursorPosition', - 'canvas/setStageCoordinates', - 'canvas/setStageScale', - 'canvas/setIsDrawing', - 'canvas/setBoundingBoxCoordinates', - 'canvas/setBoundingBoxDimensions', - 'canvas/setIsDrawing', - 'canvas/addPointToCurrentLine', - ], - }, -}); +export const initializeStore = ({ disabledPanels = [] }: InitializeStore) => + configureStore({ + reducer: persistedReducer, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + immutableCheck: false, + serializableCheck: false, + }).concat(buildMiddleware()), + preloadedState: { + ui: { + ...uiSlice.getInitialState(), + enabledParameterPanels: disablePanels({ + disabledPanels, + enabledParameterPanels: + uiSlice.getInitialState().enabledParameterPanels, + }), + }, + }, + devTools: { + // Uncommenting these very rapidly called actions makes the redux dev tools output much more readable + actionsDenylist: [ + 'canvas/setCursorPosition', + 'canvas/setStageCoordinates', + 'canvas/setStageScale', + 'canvas/setIsDrawing', + 'canvas/setBoundingBoxCoordinates', + 'canvas/setBoundingBoxDimensions', + 'canvas/setIsDrawing', + 'canvas/addPointToCurrentLine', + ], + }, + }); + +const store = initializeStore({}); export type AppGetState = typeof store.getState; export type RootState = ReturnType; diff --git a/invokeai/frontend/web/src/component.tsx b/invokeai/frontend/web/src/component.tsx index a642516417..a20b38774d 100644 --- a/invokeai/frontend/web/src/component.tsx +++ b/invokeai/frontend/web/src/component.tsx @@ -1,7 +1,7 @@ import React, { lazy, PropsWithChildren, useEffect } from 'react'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; -import { store } from './app/store'; +import { initializeStore } from './app/store'; import { persistor } from './persistor'; import { OpenAPI } from 'services/api'; import '@fontsource/inter/100.css'; @@ -24,16 +24,17 @@ const ThemeLocaleProvider = lazy(() => import('./app/ThemeLocaleProvider')); interface Props extends PropsWithChildren { apiUrl?: string; + disabledPanels?: string[]; } -export default function Component({ apiUrl, children }: Props) { +export default function Component({ apiUrl, disabledPanels, children }: Props) { useEffect(() => { if (apiUrl) OpenAPI.BASE = apiUrl; }, [apiUrl]); return ( - + } persistor={persistor}> }> diff --git a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx index 76277867de..e0f2e7ce98 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx @@ -21,9 +21,10 @@ type ParametersAccordionsType = { const ParametersAccordion = (props: ParametersAccordionsType) => { const { accordionInfo } = props; - const openAccordions = useAppSelector( - (state: RootState) => state.system.openAccordions - ); + const { system, ui } = useAppSelector((state: RootState) => state); + + const { openAccordions } = system; + const { enabledParameterPanels } = ui; const dispatch = useAppDispatch(); @@ -39,15 +40,19 @@ const ParametersAccordion = (props: ParametersAccordionsType) => { Object.keys(accordionInfo).forEach((key) => { const { header, feature, content, additionalHeaderComponents } = accordionInfo[key]; - accordionsToRender.push( - - ); + + // do not render if panel is disabled in global state + if (enabledParameterPanels[key] !== false) { + accordionsToRender.push( + + ); + } }); } return accordionsToRender; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageParameters.tsx index 4989ef034b..fe638bf180 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageParameters.tsx @@ -44,7 +44,7 @@ const ImageToImageParameters = () => { content: , additionalHeaderComponents: , }, - face_restore: { + faceRestore: { header: `${t('parameters.faceRestoration')}`, feature: Feature.FACE_CORRECTION, content: , diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageParameters.tsx index 126dd10228..df84ad2fe5 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageParameters.tsx @@ -38,7 +38,7 @@ const TextToImageParameters = () => { content: , additionalHeaderComponents: , }, - face_restore: { + faceRestore: { header: `${t('parameters.faceRestoration')}`, feature: Feature.FACE_CORRECTION, content: , diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index a0eaf46096..530f6ddf7b 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -16,6 +16,16 @@ const initialtabsState: UIState = { addNewModelUIOption: null, shouldPinGallery: true, shouldShowGallery: true, + enabledParameterPanels: { + general: true, + seed: true, + variations: true, + faceRestore: true, + upscale: true, + symmetry: true, + other: true, + imageToImage: true, + }, }; const initialState: UIState = initialtabsState; diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index 900ea703b4..bd3ef33577 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -13,4 +13,5 @@ export interface UIState { addNewModelUIOption: AddNewModelType; shouldPinGallery: boolean; shouldShowGallery: boolean; + enabledParameterPanels: { [key: string]: boolean }; } diff --git a/invokeai/frontend/web/src/persistor.ts b/invokeai/frontend/web/src/persistor.ts index ee860da3f3..9c76ca8771 100644 --- a/invokeai/frontend/web/src/persistor.ts +++ b/invokeai/frontend/web/src/persistor.ts @@ -1,4 +1,4 @@ -import { store } from 'app/store'; +import { initializeStore } from 'app/store'; import { persistStore } from 'redux-persist'; -export const persistor = persistStore(store); +export const persistor = persistStore(initializeStore({})); From 46aeeea29a34d40597a8910030a32a82e0388d03 Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Tue, 4 Apr 2023 14:23:20 -0400 Subject: [PATCH 2/4] feat(ui): invert logic to be disabled --- invokeai/frontend/web/src/app/store.ts | 51 ++++--------------- .../components/ParametersAccordion.tsx | 4 +- .../ImageToImage/ImageToImageParameters.tsx | 2 +- .../TextToImage/TextToImageParameters.tsx | 2 +- .../web/src/features/ui/store/uiSlice.ts | 11 +--- .../web/src/features/ui/store/uiTypes.ts | 2 +- 6 files changed, 16 insertions(+), 56 deletions(-) diff --git a/invokeai/frontend/web/src/app/store.ts b/invokeai/frontend/web/src/app/store.ts index 762607d64d..249a8d15a8 100644 --- a/invokeai/frontend/web/src/app/store.ts +++ b/invokeai/frontend/web/src/app/store.ts @@ -5,28 +5,16 @@ import storage from 'redux-persist/lib/storage'; // defaults to localStorage for import { getPersistConfig } from 'redux-deep-persist'; -import canvasReducer, { canvasSlice } from 'features/canvas/store/canvasSlice'; -import galleryReducer, { - gallerySlice, -} from 'features/gallery/store/gallerySlice'; -import resultsReducer, { - resultsSlice, -} from 'features/gallery/store/resultsSlice'; -import uploadsReducer, { - uploadsSlice, -} from 'features/gallery/store/uploadsSlice'; -import lightboxReducer, { - lightboxSlice, -} from 'features/lightbox/store/lightboxSlice'; -import generationReducer, { - generationSlice, -} from 'features/parameters/store/generationSlice'; -import postprocessingReducer, { - postprocessingSlice, -} from 'features/parameters/store/postprocessingSlice'; -import systemReducer, { systemSlice } from 'features/system/store/systemSlice'; +import canvasReducer from 'features/canvas/store/canvasSlice'; +import galleryReducer from 'features/gallery/store/gallerySlice'; +import resultsReducer from 'features/gallery/store/resultsSlice'; +import uploadsReducer from 'features/gallery/store/uploadsSlice'; +import lightboxReducer from 'features/lightbox/store/lightboxSlice'; +import generationReducer from 'features/parameters/store/generationSlice'; +import postprocessingReducer from 'features/parameters/store/postprocessingSlice'; +import systemReducer from 'features/system/store/systemSlice'; import uiReducer, { uiSlice } from 'features/ui/store/uiSlice'; -import apiReducer, { apiSlice } from 'services/apiSlice'; +import apiReducer from 'services/apiSlice'; import { socketioMiddleware } from './socketio/middleware'; import { socketioMiddleware as nodesSocketioMiddleware } from './nodesSocketio/middleware'; @@ -129,21 +117,6 @@ interface InitializeStore { disabledPanels?: string[]; } -const disablePanels = ({ - disabledPanels, - enabledParameterPanels, -}: { - disabledPanels: string[]; - enabledParameterPanels: { [key: string]: boolean }; -}) => { - const updatedParameterPanels: { [key: string]: boolean } = {}; - Object.keys(enabledParameterPanels).forEach(function (key, index) { - updatedParameterPanels[key] = - disabledPanels.indexOf(key) >= 0 ? false : true; - }); - return updatedParameterPanels; -}; - // Continue with store setup export const initializeStore = ({ disabledPanels = [] }: InitializeStore) => configureStore({ @@ -156,11 +129,7 @@ export const initializeStore = ({ disabledPanels = [] }: InitializeStore) => preloadedState: { ui: { ...uiSlice.getInitialState(), - enabledParameterPanels: disablePanels({ - disabledPanels, - enabledParameterPanels: - uiSlice.getInitialState().enabledParameterPanels, - }), + disabledParameterPanels: disabledPanels, }, }, devTools: { diff --git a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx index e0f2e7ce98..3869d9c8ab 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx @@ -24,7 +24,7 @@ const ParametersAccordion = (props: ParametersAccordionsType) => { const { system, ui } = useAppSelector((state: RootState) => state); const { openAccordions } = system; - const { enabledParameterPanels } = ui; + const { disabledParameterPanels } = ui; const dispatch = useAppDispatch(); @@ -42,7 +42,7 @@ const ParametersAccordion = (props: ParametersAccordionsType) => { accordionInfo[key]; // do not render if panel is disabled in global state - if (enabledParameterPanels[key] !== false) { + if (disabledParameterPanels.indexOf(key) > -1) { accordionsToRender.push( { content: , additionalHeaderComponents: , }, - faceRestore: { + face_restore: { header: `${t('parameters.faceRestoration')}`, feature: Feature.FACE_CORRECTION, content: , diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageParameters.tsx index df84ad2fe5..126dd10228 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageParameters.tsx @@ -38,7 +38,7 @@ const TextToImageParameters = () => { content: , additionalHeaderComponents: , }, - faceRestore: { + face_restore: { header: `${t('parameters.faceRestoration')}`, feature: Feature.FACE_CORRECTION, content: , diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index 530f6ddf7b..ff31d03a6e 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -16,16 +16,7 @@ const initialtabsState: UIState = { addNewModelUIOption: null, shouldPinGallery: true, shouldShowGallery: true, - enabledParameterPanels: { - general: true, - seed: true, - variations: true, - faceRestore: true, - upscale: true, - symmetry: true, - other: true, - imageToImage: true, - }, + disabledParameterPanels: [], }; const initialState: UIState = initialtabsState; diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index bd3ef33577..c188c5690b 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -13,5 +13,5 @@ export interface UIState { addNewModelUIOption: AddNewModelType; shouldPinGallery: boolean; shouldShowGallery: boolean; - enabledParameterPanels: { [key: string]: boolean }; + disabledParameterPanels: string[]; } From 42182b744c274d563cd5cc35e0aac16ab882e717 Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Tue, 4 Apr 2023 15:38:43 -0400 Subject: [PATCH 3/4] disable panels when app mounts --- invokeai/frontend/web/src/app/App.tsx | 16 +++++- invokeai/frontend/web/src/app/store.ts | 57 +++++++------------ invokeai/frontend/web/src/component.tsx | 12 ++-- .../components/ParametersAccordion.tsx | 2 +- .../web/src/features/ui/store/uiSlice.ts | 4 ++ invokeai/frontend/web/src/persistor.ts | 4 +- 6 files changed, 51 insertions(+), 44 deletions(-) diff --git a/invokeai/frontend/web/src/app/App.tsx b/invokeai/frontend/web/src/app/App.tsx index 40c15b38c0..c9b1ed249c 100644 --- a/invokeai/frontend/web/src/app/App.tsx +++ b/invokeai/frontend/web/src/app/App.tsx @@ -13,16 +13,28 @@ import { Box, Flex, Grid, Portal, useColorMode } from '@chakra-ui/react'; import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants'; import ImageGalleryPanel from 'features/gallery/components/ImageGalleryPanel'; import Lightbox from 'features/lightbox/components/Lightbox'; -import { useAppSelector } from './storeHooks'; +import { useAppDispatch, useAppSelector } from './storeHooks'; import { PropsWithChildren, useEffect } from 'react'; +import { setDisabledPanels } from 'features/ui/store/uiSlice'; keepGUIAlive(); -const App = (props: PropsWithChildren) => { +interface Props extends PropsWithChildren { + options: { + disabledPanels: string[]; + }; +} + +const App = (props: Props) => { useToastWatcher(); const currentTheme = useAppSelector((state) => state.ui.currentTheme); const { setColorMode } = useColorMode(); + const dispatch = useAppDispatch(); + + useEffect(() => { + dispatch(setDisabledPanels(props.options.disabledPanels)); + }, [dispatch, props.options.disabledPanels]); useEffect(() => { setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark'); diff --git a/invokeai/frontend/web/src/app/store.ts b/invokeai/frontend/web/src/app/store.ts index 249a8d15a8..1fc09a2c99 100644 --- a/invokeai/frontend/web/src/app/store.ts +++ b/invokeai/frontend/web/src/app/store.ts @@ -13,7 +13,7 @@ import lightboxReducer from 'features/lightbox/store/lightboxSlice'; import generationReducer from 'features/parameters/store/generationSlice'; import postprocessingReducer from 'features/parameters/store/postprocessingSlice'; import systemReducer from 'features/system/store/systemSlice'; -import uiReducer, { uiSlice } from 'features/ui/store/uiSlice'; +import uiReducer from 'features/ui/store/uiSlice'; import apiReducer from 'services/apiSlice'; import { socketioMiddleware } from './socketio/middleware'; @@ -113,41 +113,28 @@ function buildMiddleware() { } } -interface InitializeStore { - disabledPanels?: string[]; -} - // Continue with store setup -export const initializeStore = ({ disabledPanels = [] }: InitializeStore) => - configureStore({ - reducer: persistedReducer, - middleware: (getDefaultMiddleware) => - getDefaultMiddleware({ - immutableCheck: false, - serializableCheck: false, - }).concat(buildMiddleware()), - preloadedState: { - ui: { - ...uiSlice.getInitialState(), - disabledParameterPanels: disabledPanels, - }, - }, - devTools: { - // Uncommenting these very rapidly called actions makes the redux dev tools output much more readable - actionsDenylist: [ - 'canvas/setCursorPosition', - 'canvas/setStageCoordinates', - 'canvas/setStageScale', - 'canvas/setIsDrawing', - 'canvas/setBoundingBoxCoordinates', - 'canvas/setBoundingBoxDimensions', - 'canvas/setIsDrawing', - 'canvas/addPointToCurrentLine', - ], - }, - }); - -const store = initializeStore({}); +export const store = configureStore({ + reducer: persistedReducer, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + immutableCheck: false, + serializableCheck: false, + }).concat(buildMiddleware()), + devTools: { + // Uncommenting these very rapidly called actions makes the redux dev tools output much more readable + actionsDenylist: [ + 'canvas/setCursorPosition', + 'canvas/setStageCoordinates', + 'canvas/setStageScale', + 'canvas/setIsDrawing', + 'canvas/setBoundingBoxCoordinates', + 'canvas/setBoundingBoxDimensions', + 'canvas/setIsDrawing', + 'canvas/addPointToCurrentLine', + ], + }, +}); export type AppGetState = typeof store.getState; export type RootState = ReturnType; diff --git a/invokeai/frontend/web/src/component.tsx b/invokeai/frontend/web/src/component.tsx index a20b38774d..9d952c6434 100644 --- a/invokeai/frontend/web/src/component.tsx +++ b/invokeai/frontend/web/src/component.tsx @@ -1,7 +1,7 @@ import React, { lazy, PropsWithChildren, useEffect } from 'react'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; -import { initializeStore } from './app/store'; +import { store } from './app/store'; import { persistor } from './persistor'; import { OpenAPI } from 'services/api'; import '@fontsource/inter/100.css'; @@ -27,18 +27,22 @@ interface Props extends PropsWithChildren { disabledPanels?: string[]; } -export default function Component({ apiUrl, disabledPanels, children }: Props) { +export default function Component({ + apiUrl, + disabledPanels = [], + children, +}: Props) { useEffect(() => { if (apiUrl) OpenAPI.BASE = apiUrl; }, [apiUrl]); return ( - + } persistor={persistor}> }> - {children} + {children} diff --git a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx index 3869d9c8ab..e3218f71e2 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ParametersAccordion.tsx @@ -42,7 +42,7 @@ const ParametersAccordion = (props: ParametersAccordionsType) => { accordionInfo[key]; // do not render if panel is disabled in global state - if (disabledParameterPanels.indexOf(key) > -1) { + if (disabledParameterPanels.indexOf(key) === -1) { accordionsToRender.push( ) => { + state.disabledParameterPanels = action.payload; + }, }, }); @@ -114,6 +117,7 @@ export const { togglePinParametersPanel, toggleParametersPanel, toggleGalleryPanel, + setDisabledPanels, } = uiSlice.actions; export default uiSlice.reducer; diff --git a/invokeai/frontend/web/src/persistor.ts b/invokeai/frontend/web/src/persistor.ts index 9c76ca8771..ee860da3f3 100644 --- a/invokeai/frontend/web/src/persistor.ts +++ b/invokeai/frontend/web/src/persistor.ts @@ -1,4 +1,4 @@ -import { initializeStore } from 'app/store'; +import { store } from 'app/store'; import { persistStore } from 'redux-persist'; -export const persistor = persistStore(initializeStore({})); +export const persistor = persistStore(store); From 1a756e7f14faf20433343ecb088a33efaf633c80 Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Wed, 5 Apr 2023 10:20:37 -0400 Subject: [PATCH 4/4] feat(ui): add support to disableTabs --- invokeai/frontend/web/index.d.ts | 2 + invokeai/frontend/web/src/app/App.tsx | 8 +- invokeai/frontend/web/src/component.tsx | 5 +- .../src/features/ui/components/InvokeTabs.tsx | 84 +++++++++---------- .../web/src/features/ui/store/uiSlice.ts | 5 ++ .../web/src/features/ui/store/uiTypes.ts | 3 + 6 files changed, 63 insertions(+), 44 deletions(-) diff --git a/invokeai/frontend/web/index.d.ts b/invokeai/frontend/web/index.d.ts index 9821091370..4be14302cb 100644 --- a/invokeai/frontend/web/index.d.ts +++ b/invokeai/frontend/web/index.d.ts @@ -1,6 +1,7 @@ import React, { PropsWithChildren } from 'react'; import { IAIPopoverProps } from '../web/src/common/components/IAIPopover'; import { IAIIconButtonProps } from '../web/src/common/components/IAIIconButton'; +import { InvokeTabName } from 'features/ui/store/tabMap'; export {}; @@ -69,6 +70,7 @@ declare module '@invoke-ai/invoke-ai-ui' { interface InvokeProps extends PropsWithChildren { apiUrl?: string; disabledPanels?: string[]; + disabledTabs?: InvokeTabName[]; } declare function Invoke(props: InvokeProps): JSX.Element; diff --git a/invokeai/frontend/web/src/app/App.tsx b/invokeai/frontend/web/src/app/App.tsx index c9b1ed249c..ef843b047e 100644 --- a/invokeai/frontend/web/src/app/App.tsx +++ b/invokeai/frontend/web/src/app/App.tsx @@ -15,13 +15,15 @@ import ImageGalleryPanel from 'features/gallery/components/ImageGalleryPanel'; import Lightbox from 'features/lightbox/components/Lightbox'; import { useAppDispatch, useAppSelector } from './storeHooks'; import { PropsWithChildren, useEffect } from 'react'; -import { setDisabledPanels } from 'features/ui/store/uiSlice'; +import { setDisabledPanels, setDisabledTabs } from 'features/ui/store/uiSlice'; +import { InvokeTabName } from 'features/ui/store/tabMap'; keepGUIAlive(); interface Props extends PropsWithChildren { options: { disabledPanels: string[]; + disabledTabs: InvokeTabName[]; }; } @@ -36,6 +38,10 @@ const App = (props: Props) => { dispatch(setDisabledPanels(props.options.disabledPanels)); }, [dispatch, props.options.disabledPanels]); + useEffect(() => { + dispatch(setDisabledTabs(props.options.disabledTabs)); + }, [dispatch, props.options.disabledTabs]); + useEffect(() => { setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark'); }, [setColorMode, currentTheme]); diff --git a/invokeai/frontend/web/src/component.tsx b/invokeai/frontend/web/src/component.tsx index 9d952c6434..e83b8ff8d5 100644 --- a/invokeai/frontend/web/src/component.tsx +++ b/invokeai/frontend/web/src/component.tsx @@ -4,6 +4,7 @@ import { PersistGate } from 'redux-persist/integration/react'; import { store } from './app/store'; import { persistor } from './persistor'; import { OpenAPI } from 'services/api'; +import { InvokeTabName } from 'features/ui/store/tabMap'; import '@fontsource/inter/100.css'; import '@fontsource/inter/200.css'; import '@fontsource/inter/300.css'; @@ -25,11 +26,13 @@ const ThemeLocaleProvider = lazy(() => import('./app/ThemeLocaleProvider')); interface Props extends PropsWithChildren { apiUrl?: string; disabledPanels?: string[]; + disabledTabs?: InvokeTabName[]; } export default function Component({ apiUrl, disabledPanels = [], + disabledTabs = [], children, }: Props) { useEffect(() => { @@ -42,7 +45,7 @@ export default function Component({ } persistor={persistor}> }> - {children} + {children} diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx index 18db74791b..d7736eb9ea 100644 --- a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx +++ b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx @@ -45,38 +45,41 @@ const tabIconStyles: ChakraProps['sx'] = { boxSize: 6, }; -const tabInfo: InvokeTabInfo[] = [ - { - id: 'txt2img', - icon: , - workarea: , - }, - { - id: 'img2img', - icon: , - workarea: , - }, - { - id: 'unifiedCanvas', - icon: , - workarea: , - }, - { - id: 'nodes', - icon: , - workarea: , - }, - { - id: 'postprocessing', - icon: , - workarea: , - }, - { - id: 'training', - icon: , - workarea: , - }, -]; +const buildTabs = (disabledTabs: InvokeTabName[]): InvokeTabInfo[] => { + const tabs: InvokeTabInfo[] = [ + { + id: 'txt2img', + icon: , + workarea: , + }, + { + id: 'img2img', + icon: , + workarea: , + }, + { + id: 'unifiedCanvas', + icon: , + workarea: , + }, + { + id: 'nodes', + icon: , + workarea: , + }, + { + id: 'postprocessing', + icon: , + workarea: , + }, + { + id: 'training', + icon: , + workarea: , + }, + ]; + return tabs.filter((tab) => !disabledTabs.includes(tab.id)); +}; export default function InvokeTabs() { const activeTab = useAppSelector(activeTabIndexSelector); @@ -85,13 +88,10 @@ export default function InvokeTabs() { (state: RootState) => state.lightbox.isLightboxOpen ); - const shouldPinGallery = useAppSelector( - (state: RootState) => state.ui.shouldPinGallery - ); + const { shouldPinGallery, disabledTabs, shouldPinParametersPanel } = + useAppSelector((state: RootState) => state.ui); - const shouldPinParametersPanel = useAppSelector( - (state: RootState) => state.ui.shouldPinParametersPanel - ); + const activeTabs = buildTabs(disabledTabs); const { t } = useTranslation(); @@ -142,7 +142,7 @@ export default function InvokeTabs() { const tabs = useMemo( () => - tabInfo.map((tab) => ( + activeTabs.map((tab) => ( )), - [t] + [t, activeTabs] ); const tabPanels = useMemo( () => - tabInfo.map((tab) => {tab.workarea}), - [] + activeTabs.map((tab) => {tab.workarea}), + [activeTabs] ); return ( diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index 7fb36bf9b2..8ab2db57e3 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -17,6 +17,7 @@ const initialtabsState: UIState = { shouldPinGallery: true, shouldShowGallery: true, disabledParameterPanels: [], + disabledTabs: [], }; const initialState: UIState = initialtabsState; @@ -96,6 +97,9 @@ export const uiSlice = createSlice({ setDisabledPanels: (state, action: PayloadAction) => { state.disabledParameterPanels = action.payload; }, + setDisabledTabs: (state, action: PayloadAction) => { + state.disabledTabs = action.payload; + }, }, }); @@ -118,6 +122,7 @@ export const { toggleParametersPanel, toggleGalleryPanel, setDisabledPanels, + setDisabledTabs, } = uiSlice.actions; export default uiSlice.reducer; diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index c188c5690b..d4d8cfdcfe 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -1,3 +1,5 @@ +import { InvokeTabName } from './tabMap'; + export type AddNewModelType = 'ckpt' | 'diffusers' | null; export interface UIState { @@ -14,4 +16,5 @@ export interface UIState { shouldPinGallery: boolean; shouldShowGallery: boolean; disabledParameterPanels: string[]; + disabledTabs: InvokeTabName[]; }