Skip to content

Commit 5361b6e

Browse files
refactor(ui): image actions sep of concerns
1 parent ff34617 commit 5361b6e

File tree

25 files changed

+931
-783
lines changed

25 files changed

+931
-783
lines changed

invokeai/frontend/web/src/features/controlLayers/components/CanvasDropArea.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import { Grid, GridItem } from '@invoke-ai/ui-library';
22
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
3+
import { newCanvasEntityFromImageDndTarget } from 'features/dnd/dnd';
34
import { DndDropTarget } from 'features/dnd/DndDropTarget';
45
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
5-
import { newCanvasEntityFromImageActionApi } from 'features/imageActions/actions';
66
import { memo } from 'react';
77
import { useTranslation } from 'react-i18next';
88

9-
const addRasterLayerFromImageDndTargetData = newCanvasEntityFromImageActionApi.getData({ type: 'raster_layer' });
10-
const addControlLayerFromImageDndTargetData = newCanvasEntityFromImageActionApi.getData({ type: 'control_layer' });
11-
const addRegionalGuidanceReferenceImageFromImageDndTargetData = newCanvasEntityFromImageActionApi.getData({
9+
const addRasterLayerFromImageDndTargetData = newCanvasEntityFromImageDndTarget.getData({ type: 'raster_layer' });
10+
const addControlLayerFromImageDndTargetData = newCanvasEntityFromImageDndTarget.getData({
11+
type: 'control_layer',
12+
});
13+
const addRegionalGuidanceReferenceImageFromImageDndTargetData = newCanvasEntityFromImageDndTarget.getData({
1214
type: 'regional_guidance_with_reference_image',
1315
});
14-
const addGlobalReferenceImageFromImageDndTargetData = newCanvasEntityFromImageActionApi.getData({ type: 'reference_image' });
16+
const addGlobalReferenceImageFromImageDndTargetData = newCanvasEntityFromImageDndTarget.getData({
17+
type: 'reference_image',
18+
});
1519

1620
export const CanvasDropArea = memo(() => {
1721
const { t } = useTranslation();
@@ -36,29 +40,33 @@ export const CanvasDropArea = memo(() => {
3640
>
3741
<GridItem position="relative">
3842
<DndDropTarget
39-
targetData={addRasterLayerFromImageDndTargetData}
43+
dndTarget={newCanvasEntityFromImageDndTarget}
44+
dndTargetData={addRasterLayerFromImageDndTargetData}
4045
label={t('controlLayers.canvasContextMenu.newRasterLayer')}
4146
isDisabled={isBusy}
4247
/>
4348
</GridItem>
4449
<GridItem position="relative">
4550
<DndDropTarget
46-
targetData={addControlLayerFromImageDndTargetData}
51+
dndTarget={newCanvasEntityFromImageDndTarget}
52+
dndTargetData={addControlLayerFromImageDndTargetData}
4753
label={t('controlLayers.canvasContextMenu.newControlLayer')}
4854
isDisabled={isBusy}
4955
/>
5056
</GridItem>
5157

5258
<GridItem position="relative">
5359
<DndDropTarget
54-
targetData={addRegionalGuidanceReferenceImageFromImageDndTargetData}
60+
dndTarget={newCanvasEntityFromImageDndTarget}
61+
dndTargetData={addRegionalGuidanceReferenceImageFromImageDndTargetData}
5562
label={t('controlLayers.canvasContextMenu.newRegionalReferenceImage')}
5663
isDisabled={isBusy}
5764
/>
5865
</GridItem>
5966
<GridItem position="relative">
6067
<DndDropTarget
61-
targetData={addGlobalReferenceImageFromImageDndTargetData}
68+
dndTarget={newCanvasEntityFromImageDndTarget}
69+
dndTargetData={addGlobalReferenceImageFromImageDndTargetData}
6270
label={t('controlLayers.canvasContextMenu.newGlobalReferenceImage')}
6371
isDisabled={isBusy}
6472
/>

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/CanvasEntityGroupList.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { InformationalPopover } from 'common/components/InformationalPopover/Inf
77
import { useBoolean } from 'common/hooks/useBoolean';
88
import { colorTokenToCssVar } from 'common/util/colorTokenToCssVar';
99
import { fixTooltipCloseOnScrollStyles } from 'common/util/fixTooltipCloseOnScrollStyles';
10-
import { singleCanvasEntity } from 'features/controlLayers/components/CanvasEntityList/useCanvasEntityListDnd';
1110
import { CanvasEntityAddOfTypeButton } from 'features/controlLayers/components/common/CanvasEntityAddOfTypeButton';
1211
import { CanvasEntityMergeVisibleButton } from 'features/controlLayers/components/common/CanvasEntityMergeVisibleButton';
1312
import { CanvasEntityTypeIsHiddenToggle } from 'features/controlLayers/components/common/CanvasEntityTypeIsHiddenToggle';
@@ -16,6 +15,7 @@ import { useEntityTypeTitle } from 'features/controlLayers/hooks/useEntityTypeTi
1615
import { entitiesReordered } from 'features/controlLayers/store/canvasSlice';
1716
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
1817
import { isRenderableEntityType } from 'features/controlLayers/store/types';
18+
import { singleCanvasEntityDndSource } from 'features/dnd/dnd';
1919
import { triggerPostMoveFlash } from 'features/dnd/util';
2020
import type { PropsWithChildren } from 'react';
2121
import { memo, useEffect } from 'react';
@@ -37,7 +37,7 @@ export const CanvasEntityGroupList = memo(({ isSelected, type, children, entityI
3737
useEffect(() => {
3838
return monitorForElements({
3939
canMonitor({ source }) {
40-
if (!singleCanvasEntity.typeGuard(source.data)) {
40+
if (!singleCanvasEntityDndSource.typeGuard(source.data)) {
4141
return false;
4242
}
4343
if (source.data.payload.entityIdentifier.type !== type) {
@@ -54,7 +54,7 @@ export const CanvasEntityGroupList = memo(({ isSelected, type, children, entityI
5454
const sourceData = source.data;
5555
const targetData = target.data;
5656

57-
if (!singleCanvasEntity.typeGuard(sourceData) || !singleCanvasEntity.typeGuard(targetData)) {
57+
if (!singleCanvasEntityDndSource.typeGuard(sourceData) || !singleCanvasEntityDndSource.typeGuard(targetData)) {
5858
return;
5959
}
6060

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/useCanvasEntityListDnd.ts

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,11 @@ import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
22
import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
33
import { attachClosestEdge, extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
44
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
5+
import { singleCanvasEntityDndSource } from 'features/dnd/dnd';
56
import { type DndListTargetState, idle } from 'features/dnd/types';
6-
import type { ActionData, ActionSourceApi } from 'features/imageActions/actions';
7-
import { buildGetData, buildTypeAndKey, buildTypeGuard } from 'features/imageActions/actions';
87
import type { RefObject } from 'react';
98
import { useEffect, useState } from 'react';
109

11-
const _singleCanvasEntity = buildTypeAndKey('single-canvas-entity');
12-
type SingleCanvasEntitySourceData = ActionData<
13-
typeof _singleCanvasEntity.type,
14-
typeof _singleCanvasEntity.key,
15-
{ entityIdentifier: CanvasEntityIdentifier }
16-
>;
17-
export const singleCanvasEntity: ActionSourceApi<SingleCanvasEntitySourceData> = {
18-
..._singleCanvasEntity,
19-
typeGuard: buildTypeGuard(_singleCanvasEntity.key),
20-
getData: buildGetData(_singleCanvasEntity.key, _singleCanvasEntity.type),
21-
};
22-
2310
export const useCanvasEntityListDnd = (ref: RefObject<HTMLElement>, entityIdentifier: CanvasEntityIdentifier) => {
2411
const [dndListState, setDndListState] = useState<DndListTargetState>(idle);
2512
const [isDragging, setIsDragging] = useState(false);
@@ -33,7 +20,7 @@ export const useCanvasEntityListDnd = (ref: RefObject<HTMLElement>, entityIdenti
3320
draggable({
3421
element,
3522
getInitialData() {
36-
return singleCanvasEntity.getData({ entityIdentifier });
23+
return singleCanvasEntityDndSource.getData({ entityIdentifier });
3724
},
3825
onDragStart() {
3926
setDndListState({ type: 'is-dragging' });
@@ -47,7 +34,7 @@ export const useCanvasEntityListDnd = (ref: RefObject<HTMLElement>, entityIdenti
4734
dropTargetForElements({
4835
element,
4936
canDrop({ source }) {
50-
if (!singleCanvasEntity.typeGuard(source.data)) {
37+
if (!singleCanvasEntityDndSource.typeGuard(source.data)) {
5138
return false;
5239
}
5340
if (source.data.payload.entityIdentifier.type !== entityIdentifier.type) {
@@ -56,7 +43,7 @@ export const useCanvasEntityListDnd = (ref: RefObject<HTMLElement>, entityIdenti
5643
return true;
5744
},
5845
getData({ input }) {
59-
const data = singleCanvasEntity.getData({ entityIdentifier });
46+
const data = singleCanvasEntityDndSource.getData({ entityIdentifier });
6047
return attachClosestEdge(data, {
6148
element,
6249
input,

invokeai/frontend/web/src/features/controlLayers/components/CanvasRightPanel.tsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { useAppDispatch, useAppSelector, useAppStore } from 'app/store/storeHook
66
import { CanvasLayersPanelContent } from 'features/controlLayers/components/CanvasLayersPanelContent';
77
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
88
import { selectEntityCountActive } from 'features/controlLayers/store/selectors';
9+
import { multipleImageDndSource, singleImageDndSource } from 'features/dnd/dnd';
910
import { DndDropOverlay } from 'features/dnd/DndDropOverlay';
1011
import type { DndTargetState } from 'features/dnd/types';
1112
import GalleryPanelContent from 'features/gallery/components/GalleryPanelContent';
1213
import { useImageViewer } from 'features/gallery/components/ImageViewer/useImageViewer';
13-
import { multipleImageSourceApi, singleImageSourceApi } from 'features/imageActions/actions';
1414
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
1515
import { selectActiveTabCanvasRightPanel } from 'features/ui/store/uiSelectors';
1616
import { activeTabCanvasRightPanelChanged } from 'features/ui/store/uiSlice';
@@ -103,9 +103,11 @@ const PanelTabs = memo(() => {
103103
return;
104104
}
105105

106+
const getIsOnLayersTab = () => selectActiveTabCanvasRightPanel(store.getState()) === 'layers';
107+
106108
const onDragEnter = () => {
107109
// If we are already on the layers tab, do nothing
108-
if (selectActiveTabCanvasRightPanel(store.getState()) === 'layers') {
110+
if (getIsOnLayersTab()) {
109111
return;
110112
}
111113

@@ -121,7 +123,7 @@ const PanelTabs = memo(() => {
121123
};
122124
const onDragLeave = () => {
123125
// Set the state to idle or pending depending on the current tab
124-
if (selectActiveTabCanvasRightPanel(store.getState()) === 'layers') {
126+
if (getIsOnLayersTab()) {
125127
setLayersTabDndState('idle');
126128
} else {
127129
setLayersTabDndState('potential');
@@ -131,10 +133,6 @@ const PanelTabs = memo(() => {
131133
clearTimeout(timeoutRef.current);
132134
}
133135
};
134-
const canMonitor = () => {
135-
// Only monitor if we are not already on the layers tab
136-
return selectActiveTabCanvasRightPanel(store.getState()) !== 'layers';
137-
};
138136
const onDragStart = () => {
139137
// Set the state to pending when a drag starts
140138
setLayersTabDndState('potential');
@@ -146,7 +144,13 @@ const PanelTabs = memo(() => {
146144
onDragLeave,
147145
}),
148146
monitorForElements({
149-
canMonitor,
147+
canMonitor: ({ source }) => {
148+
if (!singleImageDndSource.typeGuard(source.data) && !multipleImageDndSource.typeGuard(source.data)) {
149+
return false;
150+
}
151+
// Only monitor if we are not already on the gallery tab
152+
return !getIsOnLayersTab();
153+
},
150154
onDragStart,
151155
}),
152156
dropTargetForExternal({
@@ -155,7 +159,7 @@ const PanelTabs = memo(() => {
155159
onDragLeave,
156160
}),
157161
monitorForExternal({
158-
canMonitor,
162+
canMonitor: () => !getIsOnLayersTab(),
159163
onDragStart,
160164
})
161165
);
@@ -166,9 +170,11 @@ const PanelTabs = memo(() => {
166170
return;
167171
}
168172

173+
const getIsOnGalleryTab = () => selectActiveTabCanvasRightPanel(store.getState()) === 'gallery';
174+
169175
const onDragEnter = () => {
170176
// If we are already on the gallery tab, do nothing
171-
if (selectActiveTabCanvasRightPanel(store.getState()) === 'gallery') {
177+
if (getIsOnGalleryTab()) {
172178
return;
173179
}
174180

@@ -185,7 +191,7 @@ const PanelTabs = memo(() => {
185191

186192
const onDragLeave = () => {
187193
// Set the state to idle or pending depending on the current tab
188-
if (selectActiveTabCanvasRightPanel(store.getState()) === 'gallery') {
194+
if (getIsOnGalleryTab()) {
189195
setGalleryTabDndState('idle');
190196
} else {
191197
setGalleryTabDndState('potential');
@@ -209,11 +215,11 @@ const PanelTabs = memo(() => {
209215
}),
210216
monitorForElements({
211217
canMonitor: ({ source }) => {
212-
if (!singleImageSourceApi.typeGuard(source.data) || !multipleImageSourceApi.typeGuard(source.data)) {
218+
if (!singleImageDndSource.typeGuard(source.data) && !multipleImageDndSource.typeGuard(source.data)) {
213219
return false;
214220
}
215221
// Only monitor if we are not already on the gallery tab
216-
return selectActiveTabCanvasRightPanel(store.getState()) !== 'gallery';
222+
return !getIsOnGalleryTab();
217223
},
218224
onDragStart,
219225
}),
@@ -223,7 +229,7 @@ const PanelTabs = memo(() => {
223229
onDragLeave,
224230
}),
225231
monitorForExternal({
226-
canMonitor: () => selectActiveTabCanvasRightPanel(store.getState()) !== 'gallery',
232+
canMonitor: () => !getIsOnGalleryTab(),
227233
onDragStart,
228234
})
229235
);

invokeai/frontend/web/src/features/controlLayers/components/ControlLayer/ControlLayer.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import { ControlLayerAdapterGate } from 'features/controlLayers/contexts/EntityA
1111
import { EntityIdentifierContext } from 'features/controlLayers/contexts/EntityIdentifierContext';
1212
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
1313
import type { CanvasEntityIdentifier } from 'features/controlLayers/store/types';
14+
import type { ReplaceCanvasEntityObjectsWithImageDndTargetData } from 'features/dnd/dnd';
15+
import { replaceCanvasEntityObjectsWithImageDndTarget } from 'features/dnd/dnd';
1416
import { DndDropTarget } from 'features/dnd/DndDropTarget';
15-
import type { ReplaceCanvasEntityObjectsWithImageActionData} from 'features/imageActions/actions';
16-
import {replaceCanvasEntityObjectsWithImageActionApi } from 'features/imageActions/actions';
1717
import { memo, useMemo } from 'react';
1818
import { useTranslation } from 'react-i18next';
1919

@@ -28,8 +28,8 @@ export const ControlLayer = memo(({ id }: Props) => {
2828
() => ({ id, type: 'control_layer' }),
2929
[id]
3030
);
31-
const targetData = useMemo<ReplaceCanvasEntityObjectsWithImageActionData>(
32-
() => replaceCanvasEntityObjectsWithImageActionApi.getData({ entityIdentifier }, entityIdentifier.id),
31+
const dndTargetData = useMemo<ReplaceCanvasEntityObjectsWithImageDndTargetData>(
32+
() => replaceCanvasEntityObjectsWithImageDndTarget.getData({ entityIdentifier }, entityIdentifier.id),
3333
[entityIdentifier]
3434
);
3535

@@ -47,7 +47,12 @@ export const ControlLayer = memo(({ id }: Props) => {
4747
<CanvasEntitySettingsWrapper>
4848
<ControlLayerSettings />
4949
</CanvasEntitySettingsWrapper>
50-
<DndDropTarget targetData={targetData} label={t('controlLayers.replaceLayer')} isDisabled={isBusy} />
50+
<DndDropTarget
51+
dndTarget={replaceCanvasEntityObjectsWithImageDndTarget}
52+
dndTargetData={dndTargetData}
53+
label={t('controlLayers.replaceLayer')}
54+
isDisabled={isBusy}
55+
/>
5156
</CanvasEntityContainer>
5257
</ControlLayerAdapterGate>
5358
</EntityIdentifierContext.Provider>

0 commit comments

Comments
 (0)