mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): wip img2img layouting
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
import { isEqual } from 'lodash-es';
|
||||
import ResizableDrawer from './common/ResizableDrawer/ResizableDrawer';
|
||||
import GenerateParameters from './tabs/Create/GenerateParameters';
|
||||
import CreateBaseSettings from './tabs/Create/CreateBaseSettings';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { activeTabNameSelector, uiSelector } from '../store/uiSelectors';
|
||||
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
|
||||
@ -13,16 +13,26 @@ 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/Create/CreateSidePanelPinned';
|
||||
import CreateTextParameters from './tabs/Create/CreateBaseSettings';
|
||||
import ResizeHandle from './tabs/ResizeHandle';
|
||||
import CreateImageSettings from './tabs/Create/CreateImageSettings';
|
||||
|
||||
const selector = createSelector(
|
||||
[uiSelector, activeTabNameSelector, lightboxSelector],
|
||||
(ui, activeTabName, lightbox) => {
|
||||
const { shouldPinParametersPanel, shouldShowParametersPanel } = ui;
|
||||
const {
|
||||
shouldPinParametersPanel,
|
||||
shouldShowParametersPanel,
|
||||
shouldShowImageParameters,
|
||||
} = ui;
|
||||
const { isLightboxOpen } = lightbox;
|
||||
|
||||
return {
|
||||
shouldPinParametersPanel,
|
||||
shouldShowParametersPanel,
|
||||
shouldShowImageParameters,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -34,8 +44,11 @@ const selector = createSelector(
|
||||
|
||||
const CreateParametersPanel = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { shouldPinParametersPanel, shouldShowParametersPanel } =
|
||||
useAppSelector(selector);
|
||||
const {
|
||||
shouldPinParametersPanel,
|
||||
shouldShowParametersPanel,
|
||||
shouldShowImageParameters,
|
||||
} = useAppSelector(selector);
|
||||
|
||||
const handleClosePanel = () => {
|
||||
dispatch(setShouldShowParametersPanel(false));
|
||||
@ -53,13 +66,7 @@ const CreateParametersPanel = () => {
|
||||
onClose={handleClosePanel}
|
||||
minWidth={500}
|
||||
>
|
||||
<Flex
|
||||
flexDir="column"
|
||||
position="relative"
|
||||
h={{ base: 600, xl: 'full' }}
|
||||
w={{ sm: 'full', lg: '100vw', xl: 'full' }}
|
||||
paddingRight={{ base: 8, xl: 0 }}
|
||||
>
|
||||
<Flex flexDir="column" position="relative" h="full" w="full">
|
||||
<Flex
|
||||
paddingTop={1.5}
|
||||
paddingBottom={4}
|
||||
@ -69,7 +76,37 @@ const CreateParametersPanel = () => {
|
||||
<InvokeAILogoComponent />
|
||||
<PinParametersPanelButton />
|
||||
</Flex>
|
||||
<GenerateParameters />
|
||||
<PanelGroup
|
||||
autoSaveId="createTab_floatingParameters"
|
||||
direction="horizontal"
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
>
|
||||
<>
|
||||
<Panel
|
||||
id="createTab_textParameters"
|
||||
order={0}
|
||||
defaultSize={25}
|
||||
minSize={25}
|
||||
style={{ position: 'relative' }}
|
||||
>
|
||||
<CreateTextParameters />
|
||||
</Panel>
|
||||
{shouldShowImageParameters && (
|
||||
<>
|
||||
<ResizeHandle />
|
||||
<Panel
|
||||
id="createTab_imageParameters"
|
||||
order={1}
|
||||
defaultSize={25}
|
||||
minSize={25}
|
||||
style={{ position: 'relative' }}
|
||||
>
|
||||
<CreateImageSettings />
|
||||
</Panel>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</PanelGroup>
|
||||
</Flex>
|
||||
</ResizableDrawer>
|
||||
);
|
||||
|
@ -39,13 +39,13 @@ import { configSelector } from 'features/system/store/configSelectors';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import AnimatedImageToImagePanel from 'features/parameters/components/AnimatedImageToImagePanel';
|
||||
import Scrollable from './common/Scrollable';
|
||||
import GenerateParameters from './tabs/Create/GenerateParameters';
|
||||
import CreateBaseSettings from './tabs/Create/CreateBaseSettings';
|
||||
import PinParametersPanelButton from './PinParametersPanelButton';
|
||||
import ParametersSlide from './common/ParametersSlide';
|
||||
import ImageGalleryPanel from 'features/gallery/components/ImageGalleryPanel';
|
||||
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
|
||||
import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent';
|
||||
import CreateTabContent from './tabs/Create/GenerateContent';
|
||||
import CreateTabContent from './tabs/Create/CreateContent';
|
||||
import ParametersPanel from './ParametersPanel';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import CreateTab from './tabs/Create/CreateTab';
|
||||
|
@ -40,7 +40,7 @@ import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
|
||||
import OverlayScrollable from '../../common/OverlayScrollable';
|
||||
import AnimatedImageToImagePanel from 'features/parameters/components/AnimatedImageToImagePanel';
|
||||
|
||||
const GenerateParameters = () => {
|
||||
const CreateBaseSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const generateAccordionItems: ParametersAccordionItems = useMemo(
|
||||
@ -102,23 +102,22 @@ const GenerateParameters = () => {
|
||||
<PromptInput />
|
||||
<NegativePromptInput />
|
||||
<ProcessButtons />
|
||||
<ImageToImageToggle />
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
bg: 'base.800',
|
||||
p: 4,
|
||||
pb: 6,
|
||||
borderRadius: 'base',
|
||||
}}
|
||||
>
|
||||
<MainSettings />
|
||||
</Flex>
|
||||
<ImageToImageToggle />
|
||||
<ParametersAccordion accordionItems={generateAccordionItems} />
|
||||
</Flex>
|
||||
</OverlayScrollable>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(GenerateParameters);
|
||||
export default memo(CreateBaseSettings);
|
@ -10,10 +10,16 @@ const CreateTabContent = () => {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
borderRadius: 'base',
|
||||
bg: 'base.850',
|
||||
// bg: 'base.850',
|
||||
}}
|
||||
>
|
||||
<Flex sx={{ p: 4, width: '100%', height: '100%' }}>
|
||||
<Flex
|
||||
sx={{
|
||||
// p: 2,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<CurrentImageDisplay />
|
||||
</Flex>
|
||||
</Box>
|
@ -0,0 +1,53 @@
|
||||
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 (
|
||||
<OverlayScrollable>
|
||||
<Flex
|
||||
sx={{
|
||||
gap: 2,
|
||||
flexDirection: 'column',
|
||||
h: 'full',
|
||||
w: 'full',
|
||||
position: 'absolute',
|
||||
borderRadius: 'base',
|
||||
// bg: 'base.850',
|
||||
// p: 2,
|
||||
}}
|
||||
>
|
||||
<ImagePromptHeading />
|
||||
<InitialImagePreview />
|
||||
<ImageToImageStrength />
|
||||
<ImageFit />
|
||||
</Flex>
|
||||
</OverlayScrollable>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(CreateImageSettings);
|
@ -0,0 +1,69 @@
|
||||
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 './CreateBaseSettings';
|
||||
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 './CreateImageSettings';
|
||||
|
||||
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 (
|
||||
<>
|
||||
<Panel
|
||||
order={0}
|
||||
defaultSize={25}
|
||||
minSize={25}
|
||||
style={{ position: 'relative' }}
|
||||
>
|
||||
<CreateTextParameters />
|
||||
<PinParametersPanelButton
|
||||
sx={{ position: 'absolute', top: 0, insetInlineEnd: 0 }}
|
||||
/>
|
||||
</Panel>
|
||||
{shouldShowImageParameters && (
|
||||
<>
|
||||
<ResizeHandle />
|
||||
<Panel
|
||||
order={1}
|
||||
defaultSize={25}
|
||||
minSize={25}
|
||||
style={{ position: 'relative' }}
|
||||
>
|
||||
<CreateImageSettings />
|
||||
</Panel>
|
||||
</>
|
||||
)}
|
||||
<ResizeHandle />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(CreateSidePanelPinned);
|
@ -1,17 +1,20 @@
|
||||
import { Portal, TabPanel } from '@chakra-ui/react';
|
||||
import { memo } from 'react';
|
||||
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
|
||||
import GenerateParameters from './GenerateParameters';
|
||||
import CreateBaseSettings from './CreateBaseSettings';
|
||||
import PinParametersPanelButton from '../../PinParametersPanelButton';
|
||||
import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
|
||||
import CreateTabContent from './GenerateContent';
|
||||
import CreateTabContent from './CreateContent';
|
||||
import ResizeHandle from '../ResizeHandle';
|
||||
import AnimatedImageToImagePanel from 'features/parameters/components/AnimatedImageToImagePanel';
|
||||
import ImageToImageSettings from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings';
|
||||
import CreateSidePanelPinned from './CreateSidePanelPinned';
|
||||
import CreateTextParameters from './CreateBaseSettings';
|
||||
import CreateImageSettings from './CreateImageSettings';
|
||||
|
||||
const selector = createSelector(uiSelector, (ui) => {
|
||||
const {
|
||||
@ -19,6 +22,7 @@ const selector = createSelector(uiSelector, (ui) => {
|
||||
shouldShowGallery,
|
||||
shouldPinParametersPanel,
|
||||
shouldShowParametersPanel,
|
||||
shouldShowImageParameters,
|
||||
} = ui;
|
||||
|
||||
return {
|
||||
@ -26,6 +30,7 @@ const selector = createSelector(uiSelector, (ui) => {
|
||||
shouldShowGallery,
|
||||
shouldPinParametersPanel,
|
||||
shouldShowParametersPanel,
|
||||
shouldShowImageParameters,
|
||||
};
|
||||
});
|
||||
|
||||
@ -36,44 +41,49 @@ const CreateTab = () => {
|
||||
shouldShowGallery,
|
||||
shouldPinParametersPanel,
|
||||
shouldShowParametersPanel,
|
||||
shouldShowImageParameters,
|
||||
} = useAppSelector(selector);
|
||||
|
||||
return (
|
||||
<PanelGroup
|
||||
autoSaveId="createTab_pinned"
|
||||
direction="horizontal"
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
>
|
||||
{shouldPinParametersPanel && shouldShowParametersPanel && (
|
||||
<>
|
||||
<Panel
|
||||
id="createTab_textParameters"
|
||||
order={0}
|
||||
defaultSize={30}
|
||||
minSize={20}
|
||||
defaultSize={25}
|
||||
minSize={25}
|
||||
style={{ position: 'relative' }}
|
||||
>
|
||||
<GenerateParameters />
|
||||
<CreateTextParameters />
|
||||
<PinParametersPanelButton
|
||||
sx={{ position: 'absolute', top: 0, insetInlineEnd: 0 }}
|
||||
/>
|
||||
</Panel>
|
||||
<ResizeHandle />
|
||||
</>
|
||||
)}
|
||||
{shouldPinParametersPanel && shouldShowParametersPanel && (
|
||||
<>
|
||||
<Panel
|
||||
order={0}
|
||||
defaultSize={30}
|
||||
minSize={20}
|
||||
style={{ position: 'relative' }}
|
||||
>
|
||||
<ImageToImageSettings />
|
||||
</Panel>
|
||||
{shouldShowImageParameters && (
|
||||
<>
|
||||
<ResizeHandle />
|
||||
<Panel
|
||||
id="createTab_imageParameters"
|
||||
order={1}
|
||||
defaultSize={25}
|
||||
minSize={25}
|
||||
style={{ position: 'relative' }}
|
||||
>
|
||||
<CreateImageSettings />
|
||||
</Panel>
|
||||
</>
|
||||
)}
|
||||
<ResizeHandle />
|
||||
</>
|
||||
)}
|
||||
<Panel
|
||||
order={1}
|
||||
id="createTab_content"
|
||||
order={2}
|
||||
minSize={30}
|
||||
onResize={() => {
|
||||
dispatch(requestCanvasRescale());
|
||||
@ -84,7 +94,7 @@ const CreateTab = () => {
|
||||
{shouldPinGallery && shouldShowGallery && (
|
||||
<>
|
||||
<ResizeHandle />
|
||||
<Panel order={2} defaultSize={10} minSize={10}>
|
||||
<Panel id="createTab_gallery" order={3} defaultSize={10} minSize={10}>
|
||||
<ImageGalleryContent />
|
||||
</Panel>
|
||||
</>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { memo } from 'react';
|
||||
import CreateTabContent from './GenerateContent';
|
||||
import GenerateParameters from './GenerateParameters';
|
||||
import CreateTabContent from './CreateContent';
|
||||
import CreateBaseSettings from './CreateBaseSettings';
|
||||
import PinParametersPanelButton from '../../PinParametersPanelButton';
|
||||
import { RootState } from 'app/store/store';
|
||||
import Scrollable from '../../common/Scrollable';
|
||||
@ -35,7 +35,7 @@ const GenerateWorkspace = () => {
|
||||
}}
|
||||
>
|
||||
<Scrollable>
|
||||
<GenerateParameters />
|
||||
<CreateBaseSettings />
|
||||
</Scrollable>
|
||||
<PinParametersPanelButton
|
||||
sx={{ position: 'absolute', top: 0, insetInlineEnd: 0 }}
|
||||
@ -44,7 +44,7 @@ const GenerateWorkspace = () => {
|
||||
</Flex>
|
||||
) : (
|
||||
<ParametersSlide>
|
||||
<GenerateParameters />
|
||||
<CreateBaseSettings />
|
||||
</ParametersSlide>
|
||||
)}
|
||||
<CreateTabContent />
|
||||
|
@ -37,6 +37,7 @@ const NodesTab = () => {
|
||||
|
||||
return (
|
||||
<PanelGroup
|
||||
autoSaveId="nodesTab"
|
||||
direction="horizontal"
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
>
|
||||
|
@ -8,7 +8,7 @@ const ResizeHandle = () => {
|
||||
<Flex
|
||||
sx={{ w: 6, h: 'full', justifyContent: 'center', alignItems: 'center' }}
|
||||
>
|
||||
<Box sx={{ w: 0.5, h: 'calc(100% - 1rem)', py: 4, bg: 'base.800' }} />
|
||||
<Box sx={{ w: 0.5, h: 'calc(100% - 4px)', bg: 'base.850' }} />
|
||||
</Flex>
|
||||
</PanelResizeHandle>
|
||||
);
|
||||
|
@ -42,6 +42,7 @@ const UnifiedCanvasTab = () => {
|
||||
|
||||
return (
|
||||
<PanelGroup
|
||||
autoSaveId="canvasTab"
|
||||
direction="horizontal"
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
>
|
||||
|
@ -24,6 +24,7 @@ export const initialUIState: UIState = {
|
||||
floatingProgressImageRect: { x: 0, y: 0, width: 0, height: 0 },
|
||||
shouldShowProgressImages: false,
|
||||
shouldAutoShowProgressImages: false,
|
||||
shouldShowImageParameters: false,
|
||||
};
|
||||
|
||||
export const uiSlice = createSlice({
|
||||
@ -136,6 +137,12 @@ export const uiSlice = createSlice({
|
||||
) => {
|
||||
state.shouldAutoShowProgressImages = action.payload;
|
||||
},
|
||||
shouldShowImageParametersChanged: (
|
||||
state,
|
||||
action: PayloadAction<boolean>
|
||||
) => {
|
||||
state.shouldShowImageParameters = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -163,6 +170,7 @@ export const {
|
||||
floatingProgressImageResized,
|
||||
setShouldShowProgressImages,
|
||||
setShouldAutoShowProgressImages,
|
||||
shouldShowImageParametersChanged,
|
||||
} = uiSlice.actions;
|
||||
|
||||
export default uiSlice.reducer;
|
||||
|
@ -32,4 +32,5 @@ export interface UIState {
|
||||
floatingProgressImageRect: Rect;
|
||||
shouldShowProgressImages: boolean;
|
||||
shouldAutoShowProgressImages: boolean;
|
||||
shouldShowImageParameters: boolean;
|
||||
}
|
||||
|
Reference in New Issue
Block a user