Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(ui): migrate dnd library #7288

Merged
merged 39 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
2484473
feat(ui): migrate to `pragmatic-drag-and-drop` (wip)
psychedelicious Oct 27, 2024
2ecd2b6
feat(ui): migrate to `pragmatic-drag-and-drop` (wip 2)
psychedelicious Oct 27, 2024
806dc9e
perf(ui): improved gallery perf
psychedelicious Oct 27, 2024
f0903d9
perf(ui): more gallery perf improvements
psychedelicious Oct 27, 2024
80f6f3e
feat(ui): migrate to `pragmatic-drag-and-drop` (wip 3)
psychedelicious Oct 27, 2024
200c4a7
feat(ui): migrate to `pragmatic-drag-and-drop` (wip 4)
psychedelicious Oct 27, 2024
05ca94f
feat(ui): simpler dnd typing implementation
psychedelicious Oct 28, 2024
18c46b9
feat(ui): better type name
psychedelicious Oct 28, 2024
2b55462
feat(ui): better types for getData
psychedelicious Oct 28, 2024
98d9661
tidy(ui): document & clean up dnd
psychedelicious Oct 28, 2024
93b7cee
tidy(ui): clean up old dnd stuff
psychedelicious Oct 28, 2024
a664c5f
tidy(ui): move new dnd impl into features/dnd
psychedelicious Oct 28, 2024
b8f3388
feat(ui): multi-image drag preview
psychedelicious Oct 28, 2024
8853c00
tidy(ui): more efficient dnd overlay styling
psychedelicious Oct 28, 2024
294499e
feat(ui): use custom drag previews for images
psychedelicious Oct 30, 2024
b9d202e
feat(ui): dnd layer reordering (wip)
psychedelicious Oct 30, 2024
1f2063a
feat(ui): layer reordering styling
psychedelicious Oct 30, 2024
5a34d46
feat(ui): restore dnd to workflow fields
psychedelicious Oct 30, 2024
ce30f36
fix(ui): min height for workflow image field drop target
psychedelicious Oct 30, 2024
bfb6683
tidy(ui): dnd stuff
psychedelicious Oct 30, 2024
279406c
feat(ui): more dnd cleanup and tidy
psychedelicious Oct 30, 2024
c1562a8
feat(ui): support different labels for external drop targets (e.g. up…
psychedelicious Oct 31, 2024
99c3697
refactor(ui): dnd actions to image actions
psychedelicious Nov 1, 2024
03b50fa
feat(ui): use new image actions system for image menu
psychedelicious Nov 2, 2024
3ddd942
refactor(ui): image actions sep of concerns
psychedelicious Nov 5, 2024
dc5a1f1
fix(ui): scroll issue w/ boards list
psychedelicious Nov 5, 2024
c986190
fix(ui): ts issues
psychedelicious Nov 5, 2024
3147b83
feat(ui): rework image uploads (wip)
psychedelicious Nov 5, 2024
1f8d0f5
fix(ui): match new default controlnet behaviour
psychedelicious Nov 6, 2024
e4df19f
fix(ui): uploads initiated from canvas
psychedelicious Nov 6, 2024
34b6a99
feat(ui): remove SerializableObject, use type-fest's JsonObject
psychedelicious Nov 6, 2024
dd236a7
fix(ui): use revised uploader for CL empty state
psychedelicious Nov 6, 2024
6c63aec
feat(ui): restore missing upload buttons
psychedelicious Nov 7, 2024
49892d4
feat(ui): DndDropOverlay supports react node for label
psychedelicious Nov 7, 2024
d93bccc
feat(ui): migrate fullscreen drop zone to pdnd
psychedelicious Nov 7, 2024
3c2b169
chore(ui): lint
psychedelicious Nov 7, 2024
c0c5997
fix(ui): workflow field sorting doesn't use unique identifier for fields
psychedelicious Nov 7, 2024
093b6d1
fix(ui): dnd autoscroll on elements w/ custom scrollbar
psychedelicious Nov 7, 2024
7df8e29
tweak(ui): workflow linear field styling
psychedelicious Nov 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions invokeai/frontend/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@
}
},
"dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^1.4.0",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
"@dagrejs/dagre": "^1.1.4",
"@dagrejs/graphlib": "^2.2.4",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@fontsource-variable/inter": "^5.1.0",
"@invoke-ai/ui-library": "^0.0.43",
"@nanostores/react": "^0.7.3",
Expand Down
91 changes: 39 additions & 52 deletions invokeai/frontend/web/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 3 additions & 16 deletions invokeai/frontend/web/src/app/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@ import { useSyncLoggingConfig } from 'app/logging/useSyncLoggingConfig';
import { appStarted } from 'app/store/middleware/listenerMiddleware/listeners/appStarted';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import type { PartialAppConfig } from 'app/types/invokeai';
import ImageUploadOverlay from 'common/components/ImageUploadOverlay';
import { useFocusRegionWatcher } from 'common/hooks/focus';
import { useClearStorage } from 'common/hooks/useClearStorage';
import { useFullscreenDropzone } from 'common/hooks/useFullscreenDropzone';
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
import ChangeBoardModal from 'features/changeBoardModal/components/ChangeBoardModal';
import {
NewCanvasSessionDialog,
NewGallerySessionDialog,
} from 'features/controlLayers/components/NewSessionConfirmationAlertDialog';
import DeleteImageModal from 'features/deleteImageModal/components/DeleteImageModal';
import { FullscreenDropzone } from 'features/dnd/FullscreenDropzone';
import { DynamicPromptsModal } from 'features/dynamicPrompts/components/DynamicPromptsPreviewModal';
import DeleteBoardModal from 'features/gallery/components/Boards/DeleteBoardModal';
import { ImageContextMenu } from 'features/gallery/components/ImageContextMenu/ImageContextMenu';
Expand Down Expand Up @@ -62,8 +61,6 @@ const App = ({ config = DEFAULT_CONFIG, studioInitAction }: Props) => {
useGetOpenAPISchemaQuery();
useSyncLoggingConfig();

const { dropzone, isHandlingUpload, setIsHandlingUpload } = useFullscreenDropzone();

const handleReset = useCallback(() => {
clearStorage();
location.reload();
Expand Down Expand Up @@ -92,19 +89,8 @@ const App = ({ config = DEFAULT_CONFIG, studioInitAction }: Props) => {

return (
<ErrorBoundary onReset={handleReset} FallbackComponent={AppErrorBoundaryFallback}>
<Box
id="invoke-app-wrapper"
w="100dvw"
h="100dvh"
position="relative"
overflow="hidden"
{...dropzone.getRootProps()}
>
<input {...dropzone.getInputProps()} />
<Box id="invoke-app-wrapper" w="100dvw" h="100dvh" position="relative" overflow="hidden">
<AppContent />
{dropzone.isDragActive && isHandlingUpload && (
<ImageUploadOverlay dropzone={dropzone} setIsHandlingUpload={setIsHandlingUpload} />
)}
</Box>
<DeleteImageModal />
<ChangeBoardModal />
Expand All @@ -121,6 +107,7 @@ const App = ({ config = DEFAULT_CONFIG, studioInitAction }: Props) => {
<NewGallerySessionDialog />
<NewCanvasSessionDialog />
<ImageContextMenu />
<FullscreenDropzone />
</ErrorBoundary>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { skipToken } from '@reduxjs/toolkit/query';
import { useAppSelector } from 'app/store/storeHooks';
import { useIsRegionFocused } from 'common/hooks/focus';
import { useAssertSingleton } from 'common/hooks/useAssertSingleton';
Expand All @@ -8,13 +7,11 @@ import { selectLastSelectedImage } from 'features/gallery/store/gallerySelectors
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { memo } from 'react';
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
import type { ImageDTO } from 'services/api/types';

export const GlobalImageHotkeys = memo(() => {
useAssertSingleton('GlobalImageHotkeys');
const lastSelectedImage = useAppSelector(selectLastSelectedImage);
const { currentData: imageDTO } = useGetImageDTOQuery(lastSelectedImage?.image_name ?? skipToken);
const imageDTO = useAppSelector(selectLastSelectedImage);

if (!imageDTO) {
return null;
Expand Down
5 changes: 1 addition & 4 deletions invokeai/frontend/web/src/app/components/InvokeAIUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { $workflowCategories } from 'app/store/nanostores/workflowCategories';
import { createStore } from 'app/store/store';
import type { PartialAppConfig } from 'app/types/invokeai';
import Loading from 'common/components/Loading/Loading';
import AppDndContext from 'features/dnd/components/AppDndContext';
import type { WorkflowCategory } from 'features/nodes/types/workflow';
import type { PropsWithChildren, ReactNode } from 'react';
import React, { lazy, memo, useEffect, useLayoutEffect, useMemo } from 'react';
Expand Down Expand Up @@ -237,9 +236,7 @@ const InvokeAIUI = ({
<Provider store={store}>
<React.Suspense fallback={<Loading />}>
<ThemeLocaleProvider>
<AppDndContext>
<App config={config} studioInitAction={studioInitAction} />
</AppDndContext>
<App config={config} studioInitAction={studioInitAction} />
</ThemeLocaleProvider>
</React.Suspense>
</Provider>
Expand Down
1 change: 1 addition & 0 deletions invokeai/frontend/web/src/app/logging/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const $logger = atom<Logger>(Roarr.child(BASE_CONTEXT));
export const zLogNamespace = z.enum([
'canvas',
'config',
'dnd',
'events',
'gallery',
'generation',
Expand Down
1 change: 0 additions & 1 deletion invokeai/frontend/web/src/app/store/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export const STORAGE_PREFIX = '@@invokeai-';
export const EMPTY_ARRAY = [];
/** @knipignore */
export const EMPTY_OBJECT = {};
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { addGalleryOffsetChangedListener } from 'app/store/middleware/listenerMi
import { addGetOpenAPISchemaListener } from 'app/store/middleware/listenerMiddleware/listeners/getOpenAPISchema';
import { addImageAddedToBoardFulfilledListener } from 'app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard';
import { addImageDeletionListeners } from 'app/store/middleware/listenerMiddleware/listeners/imageDeletionListeners';
import { addImageDroppedListener } from 'app/store/middleware/listenerMiddleware/listeners/imageDropped';
import { addImageRemovedFromBoardFulfilledListener } from 'app/store/middleware/listenerMiddleware/listeners/imageRemovedFromBoard';
import { addImagesStarredListener } from 'app/store/middleware/listenerMiddleware/listeners/imagesStarred';
import { addImagesUnstarredListener } from 'app/store/middleware/listenerMiddleware/listeners/imagesUnstarred';
Expand Down Expand Up @@ -93,9 +92,6 @@ addGetOpenAPISchemaListener(startAppListening);
addWorkflowLoadRequestedListener(startAppListening);
addUpdateAllNodesRequestedListener(startAppListening);

// DND
addImageDroppedListener(startAppListening);

// Models
addModelSelectedListener(startAppListening);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { createAction } from '@reduxjs/toolkit';
import { logger } from 'app/logging/logger';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import type { SerializableObject } from 'common/types';
import { buildAdHocPostProcessingGraph } from 'features/nodes/util/graph/buildAdHocPostProcessingGraph';
import { toast } from 'features/toast/toast';
import { t } from 'i18next';
import { queueApi } from 'services/api/endpoints/queue';
import type { BatchConfig, ImageDTO } from 'services/api/types';
import type { JsonObject } from 'type-fest';

const log = logger('queue');

Expand Down Expand Up @@ -39,9 +39,9 @@ export const addAdHocPostProcessingRequestedListener = (startAppListening: AppSt

const enqueueResult = await req.unwrap();
req.reset();
log.debug({ enqueueResult } as SerializableObject, t('queue.graphQueued'));
log.debug({ enqueueResult } as JsonObject, t('queue.graphQueued'));
} catch (error) {
log.error({ enqueueBatchArg } as SerializableObject, t('queue.graphFailedToQueue'));
log.error({ enqueueBatchArg } as JsonObject, t('queue.graphFailedToQueue'));

if (error instanceof Object && 'status' in error && error.status === 403) {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { logger } from 'app/logging/logger';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import type { SerializableObject } from 'common/types';
import { zPydanticValidationError } from 'features/system/store/zodSchemas';
import { toast } from 'features/toast/toast';
import { t } from 'i18next';
import { truncate, upperFirst } from 'lodash-es';
import { serializeError } from 'serialize-error';
import { queueApi } from 'services/api/endpoints/queue';
import type { JsonObject } from 'type-fest';

const log = logger('queue');

Expand All @@ -17,7 +17,7 @@ export const addBatchEnqueuedListener = (startAppListening: AppStartListening) =
effect: (action) => {
const enqueueResult = action.payload;
const arg = action.meta.arg.originalArgs;
log.debug({ enqueueResult } as SerializableObject, 'Batch enqueued');
log.debug({ enqueueResult } as JsonObject, 'Batch enqueued');

toast({
id: 'QUEUE_BATCH_SUCCEEDED',
Expand Down Expand Up @@ -45,7 +45,7 @@ export const addBatchEnqueuedListener = (startAppListening: AppStartListening) =
status: 'error',
description: t('common.unknownError'),
});
log.error({ batchConfig } as SerializableObject, t('queue.batchFailedToQueue'));
log.error({ batchConfig } as JsonObject, t('queue.batchFailedToQueue'));
return;
}

Expand All @@ -71,7 +71,7 @@ export const addBatchEnqueuedListener = (startAppListening: AppStartListening) =
description: t('common.unknownError'),
});
}
log.error({ batchConfig, error: serializeError(response) } as SerializableObject, t('queue.batchFailedToQueue'));
log.error({ batchConfig, error: serializeError(response) } as JsonObject, t('queue.batchFailedToQueue'));
},
});
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { logger } from 'app/logging/logger';
import { enqueueRequested } from 'app/store/actions';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import type { SerializableObject } from 'common/types';
import type { Result } from 'common/util/result';
import { withResult, withResultAsync } from 'common/util/result';
import { $canvasManager } from 'features/controlLayers/store/ephemeral';
Expand All @@ -14,6 +13,7 @@ import { serializeError } from 'serialize-error';
import { queueApi } from 'services/api/endpoints/queue';
import type { Invocation } from 'services/api/types';
import { assert } from 'tsafe';
import type { JsonObject } from 'type-fest';

const log = logger('generation');

Expand Down Expand Up @@ -88,7 +88,7 @@ export const addEnqueueRequestedLinear = (startAppListening: AppStartListening)
return;
}

log.debug({ batchConfig: prepareBatchResult.value } as SerializableObject, 'Enqueued batch');
log.debug({ batchConfig: prepareBatchResult.value } as JsonObject, 'Enqueued batch');
},
});
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { logger } from 'app/logging/logger';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import type { SerializableObject } from 'common/types';
import { parseify } from 'common/util/serialize';
import { $templates } from 'features/nodes/store/nodesSlice';
import { parseSchema } from 'features/nodes/util/schema/parseSchema';
import { size } from 'lodash-es';
import { serializeError } from 'serialize-error';
import { appInfoApi } from 'services/api/endpoints/appInfo';
import type { JsonObject } from 'type-fest';

const log = logger('system');

Expand All @@ -16,12 +16,12 @@ export const addGetOpenAPISchemaListener = (startAppListening: AppStartListening
effect: (action, { getState }) => {
const schemaJSON = action.payload;

log.debug({ schemaJSON: parseify(schemaJSON) } as SerializableObject, 'Received OpenAPI schema');
log.debug({ schemaJSON: parseify(schemaJSON) } as JsonObject, 'Received OpenAPI schema');
const { nodesAllowlist, nodesDenylist } = getState().config;

const nodeTemplates = parseSchema(schemaJSON, nodesAllowlist, nodesDenylist);

log.debug({ nodeTemplates } as SerializableObject, `Built ${size(nodeTemplates)} node templates`);
log.debug({ nodeTemplates } as JsonObject, `Built ${size(nodeTemplates)} node templates`);

$templates.set(nodeTemplates);
},
Expand Down
Loading
Loading