From c4b3a24ed701680b89289a07c7ceb7b54ae03da9 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 8 May 2023 22:57:05 +1000 Subject: [PATCH] feat(ui): revert tabs to txt2img/img2img --- .../frontend/web/src/app/components/App.tsx | 10 +- .../middleware/listenerMiddleware/index.ts | 6 +- .../listeners/userInvokedCanvas.ts | 2 +- .../listeners/userInvokedImageToImage.ts | 24 ++++ .../listeners/userInvokedNodes.ts | 2 +- ...kedCreate.ts => userInvokedTextToImage.ts} | 12 +- ...ingsHeader.tsx => ImageToImageButtons.tsx} | 4 +- .../components/SelectImagePlaceholder.tsx | 2 +- .../web/src/common/hooks/useGlobalHotkeys.ts | 17 +++ .../components/CurrentImageButtons.tsx | 4 +- .../gallery/components/ImageGalleryPanel.tsx | 54 ++++---- .../nodes/components/NodeGraphOverlay.tsx | 2 +- .../web/src/features/nodes/store/actions.ts | 10 +- .../buildEdges.ts | 0 .../{ => graphBuilders}/buildCanvasGraph.ts | 14 +-- .../buildImageToImageGraph.ts} | 16 +-- .../{ => graphBuilders}/buildNodesGraph.ts | 2 +- .../graphBuilders/buildTextToImageGraph.ts | 35 ++++++ .../buildImageToImageNode.ts | 11 +- .../buildInpaintNode.ts | 0 .../buildIterateNode.ts | 0 .../buildRangeNode.ts | 0 .../buildTextToImageNode.ts | 8 +- .../{ImageFit.tsx => ImageToImageFit.tsx} | 2 +- .../ImageToImage/ImageToImageSettings.tsx | 8 +- .../ImageToImage/InitialImageDisplay.tsx | 36 ++++++ .../ImageToImage/InitialImagePreview.tsx | 5 +- .../Parameters/Hires/ParamHiresCollapse.tsx | 3 - .../src/features/system/store/modelSlice.ts | 10 +- .../ui/components/CreateParametersDrawer.tsx | 115 ------------------ .../src/features/ui/components/InvokeTabs.tsx | 32 ++--- .../ui/components/ParametersDrawer.tsx | 32 +++++ .../ui/components/tabs/image/ImageTab.tsx | 48 ++++++-- .../tabs/image/ImageTabImageParameters.tsx | 61 ++++++++++ .../tabs/image/ImageTabParameters.tsx | 113 +++++++++++++++++ .../tabs/image/ImageTabSettings.tsx | 53 -------- .../ui/components/tabs/text/TextTab.tsx | 15 +-- .../ui/components/tabs/text/TextTabMain.tsx | 1 - .../tabs/text/TextTabParametersDrawer.tsx | 73 +++++++++++ .../tabs/text/TextTabSettingsPinned.tsx | 69 ----------- invokeai/frontend/web/tsconfig.json | 3 +- 41 files changed, 535 insertions(+), 379 deletions(-) create mode 100644 invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedImageToImage.ts rename invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/{userInvokedCreate.ts => userInvokedTextToImage.ts} (58%) rename invokeai/frontend/web/src/common/components/{ImageToImageSettingsHeader.tsx => ImageToImageButtons.tsx} (93%) rename invokeai/frontend/web/src/features/nodes/util/{linearGraphBuilder => edgeBuilders}/buildEdges.ts (100%) rename invokeai/frontend/web/src/features/nodes/util/{ => graphBuilders}/buildCanvasGraph.ts (88%) rename invokeai/frontend/web/src/features/nodes/util/{buildLinearGraph.ts => graphBuilders/buildImageToImageGraph.ts} (55%) rename invokeai/frontend/web/src/features/nodes/util/{ => graphBuilders}/buildNodesGraph.ts (97%) create mode 100644 invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildTextToImageGraph.ts rename invokeai/frontend/web/src/features/nodes/util/{linearGraphBuilder => nodeBuilders}/buildImageToImageNode.ts (94%) rename invokeai/frontend/web/src/features/nodes/util/{linearGraphBuilder => nodeBuilders}/buildInpaintNode.ts (100%) rename invokeai/frontend/web/src/features/nodes/util/{linearGraphBuilder => nodeBuilders}/buildIterateNode.ts (100%) rename invokeai/frontend/web/src/features/nodes/util/{linearGraphBuilder => nodeBuilders}/buildRangeNode.ts (100%) rename invokeai/frontend/web/src/features/nodes/util/{linearGraphBuilder => nodeBuilders}/buildTextToImageNode.ts (88%) rename invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/{ImageFit.tsx => ImageToImageFit.tsx} (94%) create mode 100644 invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImageDisplay.tsx delete mode 100644 invokeai/frontend/web/src/features/ui/components/CreateParametersDrawer.tsx create mode 100644 invokeai/frontend/web/src/features/ui/components/ParametersDrawer.tsx create mode 100644 invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabImageParameters.tsx create mode 100644 invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabParameters.tsx delete mode 100644 invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabSettings.tsx create mode 100644 invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabParametersDrawer.tsx delete mode 100644 invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabSettingsPinned.tsx diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index c5f2c6ff04..f65947a1fa 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -9,7 +9,7 @@ import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton' import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons'; 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 GalleryDrawer from 'features/gallery/components/ImageGalleryPanel'; import Lightbox from 'features/lightbox/components/Lightbox'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { @@ -28,9 +28,7 @@ import { configChanged } from 'features/system/store/configSlice'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { useLogger } from 'app/logging/useLogger'; import ProgressImagePreview from 'features/parameters/components/ProgressImagePreview'; -import ResizableDrawer from 'features/ui/components/common/ResizableDrawer/ResizableDrawer'; -import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent'; -import CreateParametersDrawer from 'features/ui/components/CreateParametersDrawer'; +import ParametersDrawer from 'features/ui/components/ParametersDrawer'; const DEFAULT_CONFIG = {}; @@ -91,8 +89,8 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => { - - + + {!isApplicationReady && !loadingOverridden && ( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts index 6e66e19780..36bf6adfe7 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts @@ -12,8 +12,9 @@ import { addImageResultReceivedListener } from './listeners/invocationComplete'; import { addImageUploadedListener } from './listeners/imageUploaded'; import { addRequestedImageDeletionListener } from './listeners/imageDeleted'; import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas'; -import { addUserInvokedCreateListener } from './listeners/userInvokedCreate'; import { addUserInvokedNodesListener } from './listeners/userInvokedNodes'; +import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage'; +import { addUserInvokedImageToImageListener } from './listeners/userInvokedImageToImage'; export const listenerMiddleware = createListenerMiddleware(); @@ -39,5 +40,6 @@ addImageResultReceivedListener(); addRequestedImageDeletionListener(); addUserInvokedCanvasListener(); -addUserInvokedCreateListener(); addUserInvokedNodesListener(); +addUserInvokedTextToImageListener(); +addUserInvokedImageToImageListener(); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts index 2490a358fe..cdb2c83e12 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts @@ -1,6 +1,6 @@ import { startAppListening } from '..'; import { sessionCreated, sessionInvoked } from 'services/thunks/session'; -import { buildCanvasGraphAndBlobs } from 'features/nodes/util/buildCanvasGraph'; +import { buildCanvasGraphAndBlobs } from 'features/nodes/util/graphBuilders/buildCanvasGraph'; import { log } from 'app/logging/useLogger'; import { canvasGraphBuilt } from 'features/nodes/store/actions'; import { imageUploaded } from 'services/thunks/image'; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedImageToImage.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedImageToImage.ts new file mode 100644 index 0000000000..d326e2a1d9 --- /dev/null +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedImageToImage.ts @@ -0,0 +1,24 @@ +import { startAppListening } from '..'; +import { buildImageToImageGraph } from 'features/nodes/util/graphBuilders/buildImageToImageGraph'; +import { sessionCreated } from 'services/thunks/session'; +import { log } from 'app/logging/useLogger'; +import { imageToImageGraphBuilt } from 'features/nodes/store/actions'; +import { userInvoked } from 'app/store/actions'; + +const moduleLog = log.child({ namespace: 'invoke' }); + +export const addUserInvokedImageToImageListener = () => { + startAppListening({ + predicate: (action): action is ReturnType => + userInvoked.match(action) && action.payload === 'image', + effect: (action, { getState, dispatch }) => { + const state = getState(); + + const graph = buildImageToImageGraph(state); + dispatch(imageToImageGraphBuilt(graph)); + moduleLog({ data: graph }, 'Image to Image graph built'); + + dispatch(sessionCreated({ graph })); + }, + }); +}; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedNodes.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedNodes.ts index baf7bc5baf..01e532d5ff 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedNodes.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedNodes.ts @@ -1,6 +1,6 @@ import { startAppListening } from '..'; import { sessionCreated } from 'services/thunks/session'; -import { buildNodesGraph } from 'features/nodes/util/buildNodesGraph'; +import { buildNodesGraph } from 'features/nodes/util/graphBuilders/buildNodesGraph'; import { log } from 'app/logging/useLogger'; import { nodesGraphBuilt } from 'features/nodes/store/actions'; import { userInvoked } from 'app/store/actions'; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCreate.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedTextToImage.ts similarity index 58% rename from invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCreate.ts rename to invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedTextToImage.ts index f07aa4530e..f4cced4ade 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCreate.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedTextToImage.ts @@ -1,22 +1,22 @@ import { startAppListening } from '..'; -import { buildLinearGraph } from 'features/nodes/util/buildLinearGraph'; +import { buildTextToImageGraph } from 'features/nodes/util/graphBuilders/buildTextToImageGraph'; import { sessionCreated } from 'services/thunks/session'; import { log } from 'app/logging/useLogger'; -import { createGraphBuilt } from 'features/nodes/store/actions'; +import { textToImageGraphBuilt } from 'features/nodes/store/actions'; import { userInvoked } from 'app/store/actions'; const moduleLog = log.child({ namespace: 'invoke' }); -export const addUserInvokedCreateListener = () => { +export const addUserInvokedTextToImageListener = () => { startAppListening({ predicate: (action): action is ReturnType => userInvoked.match(action) && action.payload === 'text', effect: (action, { getState, dispatch }) => { const state = getState(); - const graph = buildLinearGraph(state); - dispatch(createGraphBuilt(graph)); - moduleLog({ data: graph }, 'Create graph built'); + const graph = buildTextToImageGraph(state); + dispatch(textToImageGraphBuilt(graph)); + moduleLog({ data: graph }, 'Text to Image graph built'); dispatch(sessionCreated({ graph })); }, diff --git a/invokeai/frontend/web/src/common/components/ImageToImageSettingsHeader.tsx b/invokeai/frontend/web/src/common/components/ImageToImageButtons.tsx similarity index 93% rename from invokeai/frontend/web/src/common/components/ImageToImageSettingsHeader.tsx rename to invokeai/frontend/web/src/common/components/ImageToImageButtons.tsx index 042cef3818..00a6e70c1d 100644 --- a/invokeai/frontend/web/src/common/components/ImageToImageSettingsHeader.tsx +++ b/invokeai/frontend/web/src/common/components/ImageToImageButtons.tsx @@ -7,7 +7,7 @@ import { useAppDispatch } from 'app/store/storeHooks'; import { useCallback } from 'react'; import { clearInitialImage } from 'features/parameters/store/generationSlice'; -const ImagePromptHeading = () => { +const InitialImageButtons = () => { const dispatch = useAppDispatch(); const { t } = useTranslation(); @@ -38,4 +38,4 @@ const ImagePromptHeading = () => { ); }; -export default ImagePromptHeading; +export default InitialImageButtons; diff --git a/invokeai/frontend/web/src/common/components/SelectImagePlaceholder.tsx b/invokeai/frontend/web/src/common/components/SelectImagePlaceholder.tsx index 2c0d71ca69..a19d447755 100644 --- a/invokeai/frontend/web/src/common/components/SelectImagePlaceholder.tsx +++ b/invokeai/frontend/web/src/common/components/SelectImagePlaceholder.tsx @@ -7,7 +7,7 @@ const SelectImagePlaceholder = () => { sx={{ w: 'full', h: 'full', - bg: 'base.800', + // bg: 'base.800', borderRadius: 'base', alignItems: 'center', justifyContent: 'center', diff --git a/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts index 9f781bbc93..98aa824790 100644 --- a/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts +++ b/invokeai/frontend/web/src/common/hooks/useGlobalHotkeys.ts @@ -3,6 +3,7 @@ import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice'; import { + setActiveTab, toggleGalleryPanel, toggleParametersPanel, togglePinGalleryPanel, @@ -58,4 +59,20 @@ export const useGlobalHotkeys = () => { useHotkeys(['shift+g'], () => { dispatch(togglePinGalleryPanel()); }); + + useHotkeys('1', () => { + dispatch(setActiveTab('text')); + }); + + useHotkeys('2', () => { + dispatch(setActiveTab('image')); + }); + + useHotkeys('3', () => { + dispatch(setActiveTab('unifiedCanvas')); + }); + + useHotkeys('4', () => { + dispatch(setActiveTab('nodes')); + }); }; diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx index 824860e219..c9c472a9b8 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx @@ -441,13 +441,13 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { {t('parameters.sendToUnifiedCanvas')} - } > {t('parameters.copyImage')} - + */} = { - // txt2img: { galleryMinWidth: 200, galleryMaxWidth: 500 }, - // img2img: { galleryMinWidth: 200, galleryMaxWidth: 500 }, - generate: { galleryMinWidth: 200, galleryMaxWidth: 500 }, - unifiedCanvas: { galleryMinWidth: 200, galleryMaxWidth: 200 }, - nodes: { galleryMinWidth: 200, galleryMaxWidth: 500 }, - // postprocessing: { galleryMinWidth: 200, galleryMaxWidth: 500 }, - // training: { galleryMinWidth: 200, galleryMaxWidth: 500 }, -}; +// const GALLERY_TAB_WIDTHS: Record< +// InvokeTabName, +// { galleryMinWidth: number; galleryMaxWidth: number } +// > = { +// txt2img: { galleryMinWidth: 200, galleryMaxWidth: 500 }, +// img2img: { galleryMinWidth: 200, galleryMaxWidth: 500 }, +// generate: { galleryMinWidth: 200, galleryMaxWidth: 500 }, +// unifiedCanvas: { galleryMinWidth: 200, galleryMaxWidth: 200 }, +// nodes: { galleryMinWidth: 200, galleryMaxWidth: 500 }, +// postprocessing: { galleryMinWidth: 200, galleryMaxWidth: 500 }, +// training: { galleryMinWidth: 200, galleryMaxWidth: 500 }, +// }; const galleryPanelSelector = createSelector( [ @@ -73,34 +73,34 @@ const galleryPanelSelector = createSelector( } ); -const ImageGalleryPanel = () => { +const GalleryDrawer = () => { const dispatch = useAppDispatch(); const { shouldPinGallery, shouldShowGallery, galleryImageMinimumWidth, - activeTabName, - isStaging, - isResizable, - isLightboxOpen, + // activeTabName, + // isStaging, + // isResizable, + // isLightboxOpen, } = useAppSelector(galleryPanelSelector); - const handleSetShouldPinGallery = () => { - dispatch(togglePinGalleryPanel()); - dispatch(requestCanvasRescale()); - }; + // const handleSetShouldPinGallery = () => { + // dispatch(togglePinGalleryPanel()); + // dispatch(requestCanvasRescale()); + // }; - const handleToggleGallery = () => { - dispatch(toggleGalleryPanel()); - shouldPinGallery && dispatch(requestCanvasRescale()); - }; + // const handleToggleGallery = () => { + // dispatch(toggleGalleryPanel()); + // shouldPinGallery && dispatch(requestCanvasRescale()); + // }; const handleCloseGallery = () => { dispatch(setShouldShowGallery(false)); shouldPinGallery && dispatch(requestCanvasRescale()); }; - const resolution = useResolution(); + // const resolution = useResolution(); // useHotkeys( // 'g', @@ -229,4 +229,4 @@ const ImageGalleryPanel = () => { // return renderImageGallery(); }; -export default memo(ImageGalleryPanel); +export default memo(GalleryDrawer); diff --git a/invokeai/frontend/web/src/features/nodes/components/NodeGraphOverlay.tsx b/invokeai/frontend/web/src/features/nodes/components/NodeGraphOverlay.tsx index bcf02eabf5..e66f75792b 100644 --- a/invokeai/frontend/web/src/features/nodes/components/NodeGraphOverlay.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/NodeGraphOverlay.tsx @@ -2,7 +2,7 @@ import { Box } from '@chakra-ui/react'; import { RootState } from 'app/store/store'; import { useAppSelector } from 'app/store/storeHooks'; import { memo } from 'react'; -import { buildNodesGraph } from '../util/buildNodesGraph'; +import { buildNodesGraph } from '../util/graphBuilders/buildNodesGraph'; const NodeGraphOverlay = () => { const state = useAppSelector((state: RootState) => state); diff --git a/invokeai/frontend/web/src/features/nodes/store/actions.ts b/invokeai/frontend/web/src/features/nodes/store/actions.ts index e7bc6d6000..eda753b9dc 100644 --- a/invokeai/frontend/web/src/features/nodes/store/actions.ts +++ b/invokeai/frontend/web/src/features/nodes/store/actions.ts @@ -1,12 +1,18 @@ import { createAction, isAnyOf } from '@reduxjs/toolkit'; import { Graph } from 'services/api'; -export const createGraphBuilt = createAction('nodes/createGraphBuilt'); +export const textToImageGraphBuilt = createAction( + 'nodes/textToImageGraphBuilt' +); +export const imageToImageGraphBuilt = createAction( + 'nodes/imageToImageGraphBuilt' +); export const canvasGraphBuilt = createAction('nodes/canvasGraphBuilt'); export const nodesGraphBuilt = createAction('nodes/nodesGraphBuilt'); export const isAnyGraphBuilt = isAnyOf( - createGraphBuilt, + textToImageGraphBuilt, + imageToImageGraphBuilt, canvasGraphBuilt, nodesGraphBuilt ); diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildEdges.ts b/invokeai/frontend/web/src/features/nodes/util/edgeBuilders/buildEdges.ts similarity index 100% rename from invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildEdges.ts rename to invokeai/frontend/web/src/features/nodes/util/edgeBuilders/buildEdges.ts diff --git a/invokeai/frontend/web/src/features/nodes/util/buildCanvasGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasGraph.ts similarity index 88% rename from invokeai/frontend/web/src/features/nodes/util/buildCanvasGraph.ts rename to invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasGraph.ts index a9cb058de3..2ae31a261c 100644 --- a/invokeai/frontend/web/src/features/nodes/util/buildCanvasGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasGraph.ts @@ -10,17 +10,17 @@ import { RangeInvocation, TextToImageInvocation, } from 'services/api'; -import { buildImg2ImgNode } from './linearGraphBuilder/buildImageToImageNode'; -import { buildTxt2ImgNode } from './linearGraphBuilder/buildTextToImageNode'; -import { buildRangeNode } from './linearGraphBuilder/buildRangeNode'; -import { buildIterateNode } from './linearGraphBuilder/buildIterateNode'; -import { buildEdges } from './linearGraphBuilder/buildEdges'; +import { buildImg2ImgNode } from '../nodeBuilders/buildImageToImageNode'; +import { buildTxt2ImgNode } from '../nodeBuilders/buildTextToImageNode'; +import { buildRangeNode } from '../nodeBuilders/buildRangeNode'; +import { buildIterateNode } from '../nodeBuilders/buildIterateNode'; +import { buildEdges } from '../edgeBuilders/buildEdges'; import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider'; import { getCanvasData } from 'features/canvas/util/getCanvasData'; -import { getGenerationMode } from './getGenerationMode'; +import { getGenerationMode } from '../getGenerationMode'; import { v4 as uuidv4 } from 'uuid'; import { log } from 'app/logging/useLogger'; -import { buildInpaintNode } from './linearGraphBuilder/buildInpaintNode'; +import { buildInpaintNode } from '../nodeBuilders/buildInpaintNode'; const moduleLog = log.child({ namespace: 'buildCanvasGraph' }); diff --git a/invokeai/frontend/web/src/features/nodes/util/buildLinearGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildImageToImageGraph.ts similarity index 55% rename from invokeai/frontend/web/src/features/nodes/util/buildLinearGraph.ts rename to invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildImageToImageGraph.ts index f247964c72..d7a0fc66d3 100644 --- a/invokeai/frontend/web/src/features/nodes/util/buildLinearGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildImageToImageGraph.ts @@ -1,19 +1,15 @@ import { RootState } from 'app/store/store'; import { Graph } from 'services/api'; -import { buildImg2ImgNode } from './linearGraphBuilder/buildImageToImageNode'; -import { buildTxt2ImgNode } from './linearGraphBuilder/buildTextToImageNode'; -import { buildRangeNode } from './linearGraphBuilder/buildRangeNode'; -import { buildIterateNode } from './linearGraphBuilder/buildIterateNode'; -import { buildEdges } from './linearGraphBuilder/buildEdges'; +import { buildImg2ImgNode } from '../nodeBuilders/buildImageToImageNode'; +import { buildRangeNode } from '../nodeBuilders/buildRangeNode'; +import { buildIterateNode } from '../nodeBuilders/buildIterateNode'; +import { buildEdges } from '../edgeBuilders/buildEdges'; /** * Builds the Linear workflow graph. */ -export const buildLinearGraph = (state: RootState): Graph => { - // The base node is either a txt2img or img2img node - const baseNode = state.generation.isImageToImageEnabled - ? buildImg2ImgNode(state) - : buildTxt2ImgNode(state); +export const buildImageToImageGraph = (state: RootState): Graph => { + const baseNode = buildImg2ImgNode(state); // We always range and iterate nodes, no matter the iteration count // This is required to provide the correct seeds to the backend engine diff --git a/invokeai/frontend/web/src/features/nodes/util/buildNodesGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildNodesGraph.ts similarity index 97% rename from invokeai/frontend/web/src/features/nodes/util/buildNodesGraph.ts rename to invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildNodesGraph.ts index 7faa20bfd3..eef7379624 100644 --- a/invokeai/frontend/web/src/features/nodes/util/buildNodesGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildNodesGraph.ts @@ -2,7 +2,7 @@ import { Graph } from 'services/api'; import { v4 as uuidv4 } from 'uuid'; import { cloneDeep, reduce } from 'lodash-es'; import { RootState } from 'app/store/store'; -import { InputFieldValue } from '../types/types'; +import { InputFieldValue } from 'features/nodes/types/types'; /** * We need to do special handling for some fields diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildTextToImageGraph.ts new file mode 100644 index 0000000000..8b1d8edcc9 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildTextToImageGraph.ts @@ -0,0 +1,35 @@ +import { RootState } from 'app/store/store'; +import { Graph } from 'services/api'; +import { buildTxt2ImgNode } from '../nodeBuilders/buildTextToImageNode'; +import { buildRangeNode } from '../nodeBuilders/buildRangeNode'; +import { buildIterateNode } from '../nodeBuilders/buildIterateNode'; +import { buildEdges } from '../edgeBuilders/buildEdges'; + +/** + * Builds the Linear workflow graph. + */ +export const buildTextToImageGraph = (state: RootState): Graph => { + const baseNode = buildTxt2ImgNode(state); + + // We always range and iterate nodes, no matter the iteration count + // This is required to provide the correct seeds to the backend engine + const rangeNode = buildRangeNode(state); + const iterateNode = buildIterateNode(); + + // Build the edges for the nodes selected. + const edges = buildEdges(baseNode, rangeNode, iterateNode); + + // Assemble! + const graph = { + nodes: { + [rangeNode.id]: rangeNode, + [iterateNode.id]: iterateNode, + [baseNode.id]: baseNode, + }, + edges, + }; + + // TODO: hires fix requires latent space upscaling; we don't have nodes for this yet + + return graph; +}; diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildImageToImageNode.ts similarity index 94% rename from invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts rename to invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildImageToImageNode.ts index 53736cbe42..0e1937ced8 100644 --- a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildImageToImageNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildImageToImageNode.ts @@ -15,8 +15,6 @@ export const buildImg2ImgNode = ( const nodeId = uuidv4(); const { generation, system, models } = state; - const { selectedModelName } = models; - const { prompt, negativePrompt, @@ -26,10 +24,13 @@ export const buildImg2ImgNode = ( height, cfgScale, sampler, - seamless, + model, img2imgStrength: strength, shouldFitToWidthHeight: fit, shouldRandomizeSeed, + shouldUseSeamless, + seamlessXAxis, + seamlessYAxis, } = generation; const initialImage = initialImageSelector(state); @@ -48,9 +49,7 @@ export const buildImg2ImgNode = ( height, cfg_scale: cfgScale, scheduler: sampler as ImageToImageInvocation['scheduler'], - seamless, - model: selectedModelName, - progress_images: true, + model, image: initialImage ? { image_name: initialImage.name, diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildInpaintNode.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildInpaintNode.ts similarity index 100% rename from invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildInpaintNode.ts rename to invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildInpaintNode.ts diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildIterateNode.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildIterateNode.ts similarity index 100% rename from invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildIterateNode.ts rename to invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildIterateNode.ts diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildRangeNode.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildRangeNode.ts similarity index 100% rename from invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildRangeNode.ts rename to invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildRangeNode.ts diff --git a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildTextToImageNode.ts similarity index 88% rename from invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts rename to invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildTextToImageNode.ts index 42c0c12c1a..711c64ed67 100644 --- a/invokeai/frontend/web/src/features/nodes/util/linearGraphBuilder/buildTextToImageNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildTextToImageNode.ts @@ -10,8 +10,6 @@ export const buildTxt2ImgNode = ( const nodeId = uuidv4(); const { generation, models } = state; - const { selectedModelName } = models; - const { prompt, negativePrompt, @@ -21,8 +19,8 @@ export const buildTxt2ImgNode = ( height, cfgScale: cfg_scale, sampler, - seamless, shouldRandomizeSeed, + model, } = generation; const textToImageNode: NonNullable = { @@ -34,9 +32,7 @@ export const buildTxt2ImgNode = ( height, cfg_scale, scheduler: sampler as TextToImageInvocation['scheduler'], - seamless, - model: selectedModelName, - progress_images: true, + model, }; if (!shouldRandomizeSeed) { diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageFit.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageFit.tsx similarity index 94% rename from invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageFit.tsx rename to invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageFit.tsx index f479def1ab..03f502846c 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageFit.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageFit.tsx @@ -5,7 +5,7 @@ import { setShouldFitToWidthHeight } from 'features/parameters/store/generationS import { ChangeEvent } from 'react'; import { useTranslation } from 'react-i18next'; -export default function ImageFit() { +export default function ImageToImageFit() { const dispatch = useAppDispatch(); const shouldFitToWidthHeight = useAppSelector( diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings.tsx index f35d5ae9b8..ad6d31dd17 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings.tsx @@ -13,7 +13,7 @@ import { import { motion } from 'framer-motion'; import IAIButton from 'common/components/IAIButton'; -import ImageFit from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageFit'; +import ImageToImageFit from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageFit'; import ImageToImageStrength from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength'; import IAIIconButton from 'common/components/IAIIconButton'; @@ -21,16 +21,16 @@ import { useTranslation } from 'react-i18next'; import InitialImagePreview from './InitialImagePreview'; import { useState } from 'react'; import { FaUndo, FaUpload } from 'react-icons/fa'; -import ImagePromptHeading from 'common/components/ImageToImageSettingsHeader'; +import InitialImageButtons from 'common/components/ImageToImageSettingsHeader'; export default function ImageToImageSettings() { const { t } = useTranslation(); return ( - + - + ); } diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImageDisplay.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImageDisplay.tsx new file mode 100644 index 0000000000..236146099f --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImageDisplay.tsx @@ -0,0 +1,36 @@ +import { Flex } from '@chakra-ui/react'; +import InitialImagePreview from './InitialImagePreview'; +import InitialImageButtons from 'common/components/ImageToImageButtons'; + +const InitialImageDisplay = () => { + return ( + + + + + + + ); +}; + +export default InitialImageDisplay; diff --git a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx index 7d5a6f3422..184e88a505 100644 --- a/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview.tsx @@ -71,6 +71,7 @@ const InitialImagePreview = () => { { )} {!initialImage?.url && } - {!isImageToImageEnabled && ( + {/* {!isImageToImageEnabled && ( { Image to Image is Disabled - )} + )} */} ); }; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Hires/ParamHiresCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Hires/ParamHiresCollapse.tsx index 06ecd6762b..9c1f3a3f14 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Hires/ParamHiresCollapse.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Hires/ParamHiresCollapse.tsx @@ -7,9 +7,6 @@ import { memo } from 'react'; import { ParamHiresStrength } from './ParamHiresStrength'; import { setHiresFix } from 'features/parameters/store/postprocessingSlice'; -/** - * Seed & variation options. Includes iteration, seed, seed randomization, variation options. - */ const ParamHiresCollapse = () => { const { t } = useTranslation(); const hiresFix = useAppSelector( diff --git a/invokeai/frontend/web/src/features/system/store/modelSlice.ts b/invokeai/frontend/web/src/features/system/store/modelSlice.ts index 88ca71f2ff..6bd676762c 100644 --- a/invokeai/frontend/web/src/features/system/store/modelSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/modelSlice.ts @@ -61,12 +61,12 @@ export const modelsSlice = createSlice({ }, }); -export const selectedModelSelector = (state: RootState) => { - const { selectedModelName } = state.models; - const selectedModel = selectModelsById(state, selectedModelName); +// export const selectedModelSelector = (state: RootState) => { +// const { selectedModelName } = state.models; +// const selectedModel = selectModelsById(state, selectedModelName); - return selectedModel ?? null; -}; +// return selectedModel ?? null; +// }; export const { selectAll: selectModelsAll, diff --git a/invokeai/frontend/web/src/features/ui/components/CreateParametersDrawer.tsx b/invokeai/frontend/web/src/features/ui/components/CreateParametersDrawer.tsx deleted file mode 100644 index 0518d792cb..0000000000 --- a/invokeai/frontend/web/src/features/ui/components/CreateParametersDrawer.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { isEqual } from 'lodash-es'; -import ResizableDrawer from './common/ResizableDrawer/ResizableDrawer'; -import TextTabParameters from './tabs/text/TextTabParameters'; -import { createSelector } from '@reduxjs/toolkit'; -import { activeTabNameSelector, uiSelector } from '../store/uiSelectors'; -import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { - setShouldShowParametersPanel, - toggleParametersPanel, -} from '../store/uiSlice'; -import { memo } from 'react'; -import { Flex } from '@chakra-ui/react'; -import InvokeAILogoComponent from 'features/system/components/InvokeAILogoComponent'; -import PinParametersPanelButton from './PinParametersPanelButton'; -import { Panel, PanelGroup } from 'react-resizable-panels'; -import CreateSidePanelPinned from './tabs/text/TextTabSettingsPinned'; -import CreateTextParameters from './tabs/text/TextTabParameters'; -import ResizeHandle from './tabs/ResizeHandle'; -import CreateImageSettings from './tabs/image/ImageTabSettings'; - -const selector = createSelector( - [uiSelector, activeTabNameSelector, lightboxSelector], - (ui, activeTabName, lightbox) => { - const { - shouldPinParametersPanel, - shouldShowParametersPanel, - shouldShowImageParameters, - } = ui; - const { isLightboxOpen } = lightbox; - - return { - shouldPinParametersPanel, - shouldShowParametersPanel, - shouldShowImageParameters, - }; - }, - { - memoizeOptions: { - resultEqualityCheck: isEqual, - }, - } -); - -const CreateParametersPanel = () => { - const dispatch = useAppDispatch(); - const { - shouldPinParametersPanel, - shouldShowParametersPanel, - shouldShowImageParameters, - } = useAppSelector(selector); - - const handleClosePanel = () => { - dispatch(setShouldShowParametersPanel(false)); - }; - - if (shouldPinParametersPanel) { - return null; - } - - return ( - - - - - - - - <> - - - - {shouldShowImageParameters && ( - <> - - - - - - )} - - - - - ); -}; - -export default memo(CreateParametersPanel); diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx index 3cda3111b7..9ba1f7f58e 100644 --- a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx +++ b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx @@ -33,7 +33,6 @@ import { useTranslation } from 'react-i18next'; import { ResourceKey } from 'i18next'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import NodeEditor from 'features/nodes/components/NodeEditor'; -import GenerateWorkspace from './tabs/text/GenerateWorkspace'; import { createSelector } from '@reduxjs/toolkit'; import { BsLightningChargeFill } from 'react-icons/bs'; import { configSelector } from 'features/system/store/configSelectors'; @@ -43,7 +42,7 @@ import Scrollable from './common/Scrollable'; import TextTabParameters from './tabs/text/TextTabParameters'; import PinParametersPanelButton from './PinParametersPanelButton'; import ParametersSlide from './common/ParametersSlide'; -import ImageGalleryPanel from 'features/gallery/components/ImageGalleryPanel'; +import GalleryDrawer from 'features/gallery/components/ImageGalleryPanel'; import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent'; import TextTabMain from './tabs/text/TextTabMain'; @@ -54,6 +53,7 @@ import UnifiedCanvasTab from './tabs/UnifiedCanvas/UnifiedCanvasTab'; import NodesTab from './tabs/Nodes/NodesTab'; import { FaImage } from 'react-icons/fa'; import ResizeHandle from './tabs/ResizeHandle'; +import ImageTab from './tabs/image/ImageTab'; export interface InvokeTabInfo { id: InvokeTabName; @@ -70,7 +70,7 @@ const tabs: InvokeTabInfo[] = [ { id: 'image', icon: , - content: , + content: , }, { id: 'unifiedCanvas', @@ -114,22 +114,6 @@ const InvokeTabs = () => { const dispatch = useAppDispatch(); - useHotkeys('1', () => { - dispatch(setActiveTab('text')); - }); - - useHotkeys('2', () => { - dispatch(setActiveTab('image')); - }); - - useHotkeys('3', () => { - dispatch(setActiveTab('unifiedCanvas')); - }); - - useHotkeys('4', () => { - dispatch(setActiveTab('nodes')); - }); - // Lightbox Hotkey useHotkeys( 'z', @@ -200,7 +184,7 @@ const InvokeTabs = () => { direction="horizontal" style={{ height: '100%', width: '100%' }} > - + {tabPanels} @@ -208,7 +192,13 @@ const InvokeTabs = () => { {shouldPinGallery && shouldShowGallery && ( <> - + diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersDrawer.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersDrawer.tsx new file mode 100644 index 0000000000..72af8e6b14 --- /dev/null +++ b/invokeai/frontend/web/src/features/ui/components/ParametersDrawer.tsx @@ -0,0 +1,32 @@ +import { useAppSelector } from 'app/store/storeHooks'; +import { memo } from 'react'; +import { activeTabNameSelector } from '../store/uiSelectors'; +import TextTabParametersDrawer from './tabs/text/TextTabParametersDrawer'; +import { RootState } from 'app/store/store'; + +const ParametersDrawer = () => { + const activeTabName = useAppSelector(activeTabNameSelector); + const shouldPinParametersPanel = useAppSelector( + (state: RootState) => state.ui.shouldPinParametersPanel + ); + + if (shouldPinParametersPanel) { + return null; + } + + if (activeTabName === 'text') { + return ; + } + + if (activeTabName === 'image') { + return null; + } + + if (activeTabName === 'unifiedCanvas') { + return null; + } + + return null; +}; + +export default memo(ParametersDrawer); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTab.tsx index b069ff31db..c2d1b3ddea 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTab.tsx @@ -7,6 +7,11 @@ import { uiSelector } from 'features/ui/store/uiSelectors'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import ResizeHandle from '../ResizeHandle'; +import ImageTabParameters from './ImageTabParameters'; +import ImageTabImageParameters from './ImageTabImageParameters'; +import TextTabMain from '../text/TextTabMain'; +import InitialImagePreview from 'features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview'; +import InitialImageDisplay from 'features/parameters/components/AdvancedParameters/ImageToImage/InitialImageDisplay'; const selector = createSelector(uiSelector, (ui) => { const { @@ -38,20 +43,20 @@ const TextTab = () => { return ( {shouldPinParametersPanel && shouldShowParametersPanel && ( <> - {/* */} + @@ -59,15 +64,34 @@ const TextTab = () => { )} - { - dispatch(requestCanvasRescale()); - }} - > - {/* */} + + + + + + + { + dispatch(requestCanvasRescale()); + }} + > + + + ); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabImageParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabImageParameters.tsx new file mode 100644 index 0000000000..3d1fd3e950 --- /dev/null +++ b/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabImageParameters.tsx @@ -0,0 +1,61 @@ +import { Box, Flex } from '@chakra-ui/react'; +import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; +import { memo } from 'react'; +import OverlayScrollable from '../../common/OverlayScrollable'; +import ParamPositiveConditioning from 'features/parameters/components/Parameters/ParamPositiveConditioning'; +import ParamNegativeConditioning from 'features/parameters/components/Parameters/ParamNegativeConditioning'; +import { createSelector } from '@reduxjs/toolkit'; +import { uiSelector } from 'features/ui/store/uiSelectors'; +import { useAppSelector } from 'app/store/storeHooks'; +import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; +import ParamIterations from 'features/parameters/components/Parameters/ParamIterations'; +import ParamSteps from 'features/parameters/components/Parameters/ParamSteps'; +import ParamCFGScale from 'features/parameters/components/Parameters/ParamCFGScale'; +import ParamWidth from 'features/parameters/components/Parameters/ParamWidth'; +import ParamHeight from 'features/parameters/components/Parameters/ParamHeight'; +import ParamScheduler from 'features/parameters/components/Parameters/ParamScheduler'; +import ModelSelect from 'features/system/components/ModelSelect'; +import ParamSeedCollapse from 'features/parameters/components/Parameters/Seed/ParamSeedCollapse'; +import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse'; +import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse'; +import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse'; +import ParamHiresCollapse from 'features/parameters/components/Parameters/Hires/ParamHiresCollapse'; +import ParamSeamlessCollapse from 'features/parameters/components/Parameters/Seamless/ParamSeamlessCollapse'; +import InitialImagePreview from 'features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview'; +import ImageToImageStrength from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength'; +import ImageToImageFit from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageFit'; +import InitialImageButtons from 'common/components/ImageToImageButtons'; + +const selector = createSelector( + uiSelector, + (ui) => { + const { shouldUseSliders } = ui; + + return { shouldUseSliders }; + }, + defaultSelectorOptions +); + +const ImageTabParameters = () => { + const { shouldUseSliders } = useAppSelector(selector); + + return ( + + + + + + + + ); +}; + +export default memo(ImageTabParameters); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabParameters.tsx new file mode 100644 index 0000000000..09181b6669 --- /dev/null +++ b/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabParameters.tsx @@ -0,0 +1,113 @@ +import { Box, Flex } from '@chakra-ui/react'; +import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; +import { memo } from 'react'; +import OverlayScrollable from '../../common/OverlayScrollable'; +import ParamPositiveConditioning from 'features/parameters/components/Parameters/ParamPositiveConditioning'; +import ParamNegativeConditioning from 'features/parameters/components/Parameters/ParamNegativeConditioning'; +import { createSelector } from '@reduxjs/toolkit'; +import { uiSelector } from 'features/ui/store/uiSelectors'; +import { useAppSelector } from 'app/store/storeHooks'; +import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; +import ParamIterations from 'features/parameters/components/Parameters/ParamIterations'; +import ParamSteps from 'features/parameters/components/Parameters/ParamSteps'; +import ParamCFGScale from 'features/parameters/components/Parameters/ParamCFGScale'; +import ParamWidth from 'features/parameters/components/Parameters/ParamWidth'; +import ParamHeight from 'features/parameters/components/Parameters/ParamHeight'; +import ParamScheduler from 'features/parameters/components/Parameters/ParamScheduler'; +import ModelSelect from 'features/system/components/ModelSelect'; +import ParamSeedCollapse from 'features/parameters/components/Parameters/Seed/ParamSeedCollapse'; +import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse'; +import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse'; +import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse'; +import ParamHiresCollapse from 'features/parameters/components/Parameters/Hires/ParamHiresCollapse'; +import ParamSeamlessCollapse from 'features/parameters/components/Parameters/Seamless/ParamSeamlessCollapse'; +import ImageToImageStrength from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength'; +import ImageToImageFit from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageFit'; + +const selector = createSelector( + uiSelector, + (ui) => { + const { shouldUseSliders } = ui; + + return { shouldUseSliders }; + }, + defaultSelectorOptions +); + +const ImageTabParameters = () => { + const { shouldUseSliders } = useAppSelector(selector); + + return ( + + + + + + + {shouldUseSliders ? ( + + + + + + + + + + + + + + + + + + ) : ( + + + + + + + + + + + + + + + + + + + + )} + + + + + + + + + ); +}; + +export default memo(ImageTabParameters); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabSettings.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabSettings.tsx deleted file mode 100644 index ac80ae77f3..0000000000 --- a/invokeai/frontend/web/src/features/ui/components/tabs/image/ImageTabSettings.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { memo } from 'react'; -import OverlayScrollable from '../../common/OverlayScrollable'; -import ImageToImageSettings from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings'; -import { - Box, - ButtonGroup, - Collapse, - Flex, - Heading, - HStack, - Image, - Spacer, - useDisclosure, - VStack, -} from '@chakra-ui/react'; -import { motion } from 'framer-motion'; - -import IAIButton from 'common/components/IAIButton'; -import ImageFit from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageFit'; -import ImageToImageStrength from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength'; -import IAIIconButton from 'common/components/IAIIconButton'; - -import { useTranslation } from 'react-i18next'; -import { useState } from 'react'; -import { FaUndo, FaUpload } from 'react-icons/fa'; -import ImagePromptHeading from 'common/components/ImageToImageSettingsHeader'; -import InitialImagePreview from 'features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview'; - -const CreateImageSettings = () => { - return ( - - - - - - - - - ); -}; - -export default memo(CreateImageSettings); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTab.tsx index c26700a39d..b28cac2581 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTab.tsx @@ -8,7 +8,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import TextTabMain from './TextTabMain'; import ResizeHandle from '../ResizeHandle'; -import TextTabSettings from './TextTabParameters'; +import TextTabParameters from './TextTabParameters'; const selector = createSelector(uiSelector, (ui) => { const { @@ -47,13 +47,13 @@ const TextTab = () => { {shouldPinParametersPanel && shouldShowParametersPanel && ( <> - + @@ -61,14 +61,7 @@ const TextTab = () => { )} - { - dispatch(requestCanvasRescale()); - }} - > + diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabMain.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabMain.tsx index 36c5f9bd94..226d145e34 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabMain.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabMain.tsx @@ -1,6 +1,5 @@ import { Box, Flex } from '@chakra-ui/react'; import CurrentImageDisplay from 'features/gallery/components/CurrentImageDisplay'; -import ProgressImagePreview from 'features/parameters/components/ProgressImagePreview'; const TextTabMain = () => { return ( diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabParametersDrawer.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabParametersDrawer.tsx new file mode 100644 index 0000000000..d1de868ec7 --- /dev/null +++ b/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabParametersDrawer.tsx @@ -0,0 +1,73 @@ +import { isEqual } from 'lodash-es'; +import ResizableDrawer from '../../common/ResizableDrawer/ResizableDrawer'; +import TextTabParameters from './TextTabParameters'; +import { createSelector } from '@reduxjs/toolkit'; +import { activeTabNameSelector, uiSelector } from '../../../store/uiSelectors'; +import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { setShouldShowParametersPanel } from '../../../store/uiSlice'; +import { memo } from 'react'; +import { Flex } from '@chakra-ui/react'; +import InvokeAILogoComponent from 'features/system/components/InvokeAILogoComponent'; +import PinParametersPanelButton from '../../PinParametersPanelButton'; +import { Panel, PanelGroup } from 'react-resizable-panels'; + +const selector = createSelector( + [uiSelector, activeTabNameSelector, lightboxSelector], + (ui, activeTabName, lightbox) => { + const { + shouldPinParametersPanel, + shouldShowParametersPanel, + shouldShowImageParameters, + } = ui; + + const { isLightboxOpen } = lightbox; + + return { + activeTabName, + shouldPinParametersPanel, + shouldShowParametersPanel, + shouldShowImageParameters, + }; + }, + { + memoizeOptions: { + resultEqualityCheck: isEqual, + }, + } +); + +const TextTabParametersDrawer = () => { + const dispatch = useAppDispatch(); + const { shouldPinParametersPanel, shouldShowParametersPanel } = + useAppSelector(selector); + + const handleClosePanel = () => { + dispatch(setShouldShowParametersPanel(false)); + }; + + return ( + + + + + + + + + + ); +}; + +export default memo(TextTabParametersDrawer); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabSettingsPinned.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabSettingsPinned.tsx deleted file mode 100644 index 9d58eed899..0000000000 --- a/invokeai/frontend/web/src/features/ui/components/tabs/text/TextTabSettingsPinned.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { uiSelector } from 'features/ui/store/uiSelectors'; -import { memo } from 'react'; -import { Panel } from 'react-resizable-panels'; -import CreateTextParameters from './TextTabParameters'; -import PinParametersPanelButton from '../../PinParametersPanelButton'; -import ResizeHandle from '../ResizeHandle'; -import ImageToImageSettings from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import CreateImageSettings from '../image/ImageTabSettings'; - -const selector = createSelector( - uiSelector, - (ui) => { - const { - shouldPinParametersPanel, - shouldShowParametersPanel, - shouldShowImageParameters, - } = ui; - - return { - shouldPinParametersPanel, - shouldShowParametersPanel, - shouldShowImageParameters, - }; - }, - defaultSelectorOptions -); - -const CreateSidePanelPinned = () => { - const dispatch = useAppDispatch(); - const { - shouldPinParametersPanel, - shouldShowParametersPanel, - shouldShowImageParameters, - } = useAppSelector(selector); - return ( - <> - - - - - {shouldShowImageParameters && ( - <> - - - - - - )} - - - ); -}; - -export default memo(CreateSidePanelPinned); diff --git a/invokeai/frontend/web/tsconfig.json b/invokeai/frontend/web/tsconfig.json index fa8f1fd262..3c777b9318 100644 --- a/invokeai/frontend/web/tsconfig.json +++ b/invokeai/frontend/web/tsconfig.json @@ -24,7 +24,8 @@ "src/**/*.ts", "src/**/*.tsx", "*.d.ts", - "src/app/store/middleware/listenerMiddleware" + "src/app/store/middleware/listenerMiddleware", + "src/features/nodes/util/edgeBuilders" ], "exclude": ["src/services/fixtures/*", "node_modules", "dist"], "references": [{ "path": "./tsconfig.node.json" }]