mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): support image dnd to canvas
This commit is contained in:
parent
2c77563dcc
commit
7bd94eac0e
@ -30,6 +30,7 @@ import {
|
|||||||
} from './canvasTypes';
|
} from './canvasTypes';
|
||||||
import { ImageDTO } from 'services/api';
|
import { ImageDTO } from 'services/api';
|
||||||
import { sessionCanceled } from 'services/thunks/session';
|
import { sessionCanceled } from 'services/thunks/session';
|
||||||
|
import { setShouldUseCanvasBetaLayout } from 'features/ui/store/uiSlice';
|
||||||
|
|
||||||
export const initialLayerState: CanvasLayerState = {
|
export const initialLayerState: CanvasLayerState = {
|
||||||
objects: [],
|
objects: [],
|
||||||
@ -851,6 +852,10 @@ export const canvasSlice = createSlice({
|
|||||||
state.layerState.stagingArea = initialLayerState.stagingArea;
|
state.layerState.stagingArea = initialLayerState.stagingArea;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.addCase(setShouldUseCanvasBetaLayout, (state, action) => {
|
||||||
|
state.doesCanvasNeedScaling = true;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
// import IAICanvas from 'features/canvas/components/IAICanvas';
|
|
||||||
import { Box, Flex } from '@chakra-ui/react';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAICanvas from 'features/canvas/components/IAICanvas';
|
|
||||||
import IAICanvasResizer from 'features/canvas/components/IAICanvasResizer';
|
|
||||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
|
||||||
|
|
||||||
import { isEqual } from 'lodash-es';
|
|
||||||
import { useLayoutEffect } from 'react';
|
|
||||||
import UnifiedCanvasToolbarBeta from './UnifiedCanvasToolbarBeta';
|
|
||||||
import UnifiedCanvasToolSettingsBeta from './UnifiedCanvasToolSettingsBeta';
|
|
||||||
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
|
|
||||||
|
|
||||||
const selector = createSelector(
|
|
||||||
[canvasSelector],
|
|
||||||
(canvas) => {
|
|
||||||
const { doesCanvasNeedScaling } = canvas;
|
|
||||||
return {
|
|
||||||
doesCanvasNeedScaling,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
{
|
|
||||||
memoizeOptions: {
|
|
||||||
resultEqualityCheck: isEqual,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const UnifiedCanvasContentBeta = () => {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const { doesCanvasNeedScaling } = useAppSelector(selector);
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
dispatch(requestCanvasRescale());
|
|
||||||
const resizeCallback = () => {
|
|
||||||
dispatch(requestCanvasRescale());
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('resize', resizeCallback);
|
|
||||||
|
|
||||||
return () => window.removeEventListener('resize', resizeCallback);
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
borderRadius: 'base',
|
|
||||||
bg: 'base.850',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Flex
|
|
||||||
flexDirection="row"
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
columnGap={4}
|
|
||||||
padding={4}
|
|
||||||
>
|
|
||||||
<UnifiedCanvasToolbarBeta />
|
|
||||||
<Flex width="100%" height="100%" flexDirection="column" rowGap={4}>
|
|
||||||
<UnifiedCanvasToolSettingsBeta />
|
|
||||||
{doesCanvasNeedScaling ? <IAICanvasResizer /> : <IAICanvas />}
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UnifiedCanvasContentBeta;
|
|
@ -1,34 +1,58 @@
|
|||||||
import { Box, Flex } from '@chakra-ui/react';
|
import { Box, Flex } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import IAICanvas from 'features/canvas/components/IAICanvas';
|
import IAICanvas from 'features/canvas/components/IAICanvas';
|
||||||
import IAICanvasResizer from 'features/canvas/components/IAICanvasResizer';
|
import IAICanvasResizer from 'features/canvas/components/IAICanvasResizer';
|
||||||
import IAICanvasToolbar from 'features/canvas/components/IAICanvasToolbar/IAICanvasToolbar';
|
import IAICanvasToolbar from 'features/canvas/components/IAICanvasToolbar/IAICanvasToolbar';
|
||||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
|
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
|
||||||
import { isEqual } from 'lodash-es';
|
import { uiSelector } from 'features/ui/store/uiSelectors';
|
||||||
|
|
||||||
import { memo, useLayoutEffect } from 'react';
|
import { memo, useCallback, useLayoutEffect } from 'react';
|
||||||
|
import UnifiedCanvasToolbarBeta from './UnifiedCanvasBeta/UnifiedCanvasToolbarBeta';
|
||||||
|
import UnifiedCanvasToolSettingsBeta from './UnifiedCanvasBeta/UnifiedCanvasToolSettingsBeta';
|
||||||
|
import { ImageDTO } from 'services/api';
|
||||||
|
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
||||||
|
import { useDroppable } from '@dnd-kit/core';
|
||||||
|
import IAIDropOverlay from 'common/components/IAIDropOverlay';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
[canvasSelector],
|
[canvasSelector, uiSelector],
|
||||||
(canvas) => {
|
(canvas, ui) => {
|
||||||
const { doesCanvasNeedScaling } = canvas;
|
const { doesCanvasNeedScaling } = canvas;
|
||||||
|
const { shouldUseCanvasBetaLayout } = ui;
|
||||||
return {
|
return {
|
||||||
doesCanvasNeedScaling,
|
doesCanvasNeedScaling,
|
||||||
|
shouldUseCanvasBetaLayout,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
defaultSelectorOptions
|
||||||
memoizeOptions: {
|
|
||||||
resultEqualityCheck: isEqual,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const UnifiedCanvasContent = () => {
|
const UnifiedCanvasContent = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const { doesCanvasNeedScaling } = useAppSelector(selector);
|
const { doesCanvasNeedScaling, shouldUseCanvasBetaLayout } =
|
||||||
|
useAppSelector(selector);
|
||||||
|
|
||||||
|
const onDrop = useCallback(
|
||||||
|
(droppedImage: ImageDTO) => {
|
||||||
|
dispatch(setInitialCanvasImage(droppedImage));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
isOver,
|
||||||
|
setNodeRef: setDroppableRef,
|
||||||
|
active,
|
||||||
|
} = useDroppable({
|
||||||
|
id: 'unifiedCanvas',
|
||||||
|
data: {
|
||||||
|
handleDrop: onDrop,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
dispatch(requestCanvasRescale());
|
dispatch(requestCanvasRescale());
|
||||||
@ -42,14 +66,55 @@ const UnifiedCanvasContent = () => {
|
|||||||
return () => window.removeEventListener('resize', resizeCallback);
|
return () => window.removeEventListener('resize', resizeCallback);
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
|
if (shouldUseCanvasBetaLayout) {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
ref={setDroppableRef}
|
||||||
sx={{
|
sx={{
|
||||||
width: '100%',
|
w: 'full',
|
||||||
height: '100%',
|
h: 'full',
|
||||||
padding: 4,
|
|
||||||
borderRadius: 'base',
|
borderRadius: 'base',
|
||||||
bg: 'base.850',
|
bg: 'base.850',
|
||||||
|
p: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
w: 'full',
|
||||||
|
h: 'full',
|
||||||
|
gap: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<UnifiedCanvasToolbarBeta />
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
flexDir: 'column',
|
||||||
|
w: 'full',
|
||||||
|
h: 'full',
|
||||||
|
gap: 4,
|
||||||
|
position: 'relative',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<UnifiedCanvasToolSettingsBeta />
|
||||||
|
<Box sx={{ w: 'full', h: 'full', position: 'relative' }}>
|
||||||
|
{doesCanvasNeedScaling ? <IAICanvasResizer /> : <IAICanvas />}
|
||||||
|
{active && <IAIDropOverlay isOver={isOver} />}
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
ref={setDroppableRef}
|
||||||
|
sx={{
|
||||||
|
w: 'full',
|
||||||
|
h: 'full',
|
||||||
|
borderRadius: 'base',
|
||||||
|
bg: 'base.850',
|
||||||
|
p: 4,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex
|
<Flex
|
||||||
@ -57,8 +122,8 @@ const UnifiedCanvasContent = () => {
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 4,
|
gap: 4,
|
||||||
width: '100%',
|
w: 'full',
|
||||||
height: '100%',
|
h: 'full',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IAICanvasToolbar />
|
<IAICanvasToolbar />
|
||||||
@ -68,11 +133,14 @@ const UnifiedCanvasContent = () => {
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
gap: 4,
|
gap: 4,
|
||||||
width: '100%',
|
w: 'full',
|
||||||
height: '100%',
|
h: 'full',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Box sx={{ w: 'full', h: 'full', position: 'relative' }}>
|
||||||
{doesCanvasNeedScaling ? <IAICanvasResizer /> : <IAICanvas />}
|
{doesCanvasNeedScaling ? <IAICanvasResizer /> : <IAICanvas />}
|
||||||
|
{active && <IAIDropOverlay isOver={isOver} />}
|
||||||
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,34 +1,16 @@
|
|||||||
import { Flex } from '@chakra-ui/react';
|
import { Flex } from '@chakra-ui/react';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import UnifiedCanvasContent from './UnifiedCanvasContent';
|
import UnifiedCanvasContent from './UnifiedCanvasContent';
|
||||||
import UnifiedCanvasParameters from './UnifiedCanvasParameters';
|
import UnifiedCanvasParameters from './UnifiedCanvasParameters';
|
||||||
import UnifiedCanvasContentBeta from './UnifiedCanvasBeta/UnifiedCanvasContentBeta';
|
|
||||||
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
|
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
|
||||||
|
|
||||||
const selector = createSelector(uiSelector, (ui) => {
|
|
||||||
const { shouldUseCanvasBetaLayout } = ui;
|
|
||||||
|
|
||||||
return {
|
|
||||||
shouldUseCanvasBetaLayout,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const UnifiedCanvasTab = () => {
|
const UnifiedCanvasTab = () => {
|
||||||
const { shouldUseCanvasBetaLayout } = useAppSelector(selector);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex sx={{ gap: 4, w: 'full', h: 'full' }}>
|
<Flex sx={{ gap: 4, w: 'full', h: 'full' }}>
|
||||||
<ParametersPinnedWrapper>
|
<ParametersPinnedWrapper>
|
||||||
<UnifiedCanvasParameters />
|
<UnifiedCanvasParameters />
|
||||||
</ParametersPinnedWrapper>
|
</ParametersPinnedWrapper>
|
||||||
{shouldUseCanvasBetaLayout ? (
|
|
||||||
<UnifiedCanvasContentBeta />
|
|
||||||
) : (
|
|
||||||
<UnifiedCanvasContent />
|
<UnifiedCanvasContent />
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user