fix(core): canDrop check for external (#9058)
This commit is contained in:
13
packages/frontend/component/src/ui/dnd/context.ts
Normal file
13
packages/frontend/component/src/ui/dnd/context.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
import type { DNDData, ExternalDataAdapter } from './types';
|
||||||
|
|
||||||
|
export const DNDContext = createContext<{
|
||||||
|
/**
|
||||||
|
* external data adapter.
|
||||||
|
* if this is provided, the drop target will handle external elements as well.
|
||||||
|
*
|
||||||
|
* @default undefined
|
||||||
|
*/
|
||||||
|
externalDataAdapter?: ExternalDataAdapter<DNDData>;
|
||||||
|
}>({});
|
||||||
@@ -17,9 +17,10 @@ import {
|
|||||||
type Instruction,
|
type Instruction,
|
||||||
type ItemMode,
|
type ItemMode,
|
||||||
} from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
|
} from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
|
||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
|
||||||
import type { DNDData } from './types';
|
import { DNDContext } from './context';
|
||||||
|
import type { DNDData, ExternalDataAdapter } from './types';
|
||||||
|
|
||||||
export type DropTargetDropEvent<D extends DNDData> = {
|
export type DropTargetDropEvent<D extends DNDData> = {
|
||||||
treeInstruction: Instruction | null;
|
treeInstruction: Instruction | null;
|
||||||
@@ -58,25 +59,27 @@ type DropTargetGet<T, D extends DNDData> =
|
|||||||
| T
|
| T
|
||||||
| ((data: DropTargetGetFeedback<D>) => T);
|
| ((data: DropTargetGetFeedback<D>) => T);
|
||||||
|
|
||||||
export type ExternalGetDataFeedbackArgs = Parameters<
|
const isExternalDrag = <D extends DNDData>(
|
||||||
NonNullable<Parameters<typeof dropTargetForExternal>[0]['getData']>
|
args: Pick<DropTargetGetFeedback<D>, 'source'>
|
||||||
>[0];
|
) => {
|
||||||
|
return !args.source['data'];
|
||||||
export type ExternalDataAdapter<D extends DNDData> = (
|
};
|
||||||
args: ExternalGetDataFeedbackArgs
|
|
||||||
) => D['draggable'];
|
|
||||||
|
|
||||||
const getAdaptedEventArgs = <
|
const getAdaptedEventArgs = <
|
||||||
D extends DNDData,
|
D extends DNDData,
|
||||||
Args extends Pick<DropTargetGetFeedback<D>, 'source'>,
|
Args extends Pick<DropTargetGetFeedback<D>, 'source'>,
|
||||||
>(
|
>(
|
||||||
options: DropTargetOptions<D>,
|
options: DropTargetOptions<D>,
|
||||||
args: Args
|
args: Args,
|
||||||
|
isDropEvent = false
|
||||||
): Args => {
|
): Args => {
|
||||||
const data =
|
const data =
|
||||||
!args.source['data'] && options.externalDataAdapter
|
isExternalDrag(args) && options.externalDataAdapter
|
||||||
? // @ts-expect-error hack for external data adapter (source has no data field)
|
? options.externalDataAdapter(
|
||||||
options.externalDataAdapter(args as ExternalGetDataFeedbackArgs)
|
// @ts-expect-error hack for external data adapter (source has no data field)
|
||||||
|
args as ExternalGetDataFeedbackArgs,
|
||||||
|
isDropEvent
|
||||||
|
)
|
||||||
: args.source['data'];
|
: args.source['data'];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -167,11 +170,16 @@ export interface DropTargetOptions<D extends DNDData = DNDData> {
|
|||||||
onDrag?: (data: DropTargetDragEvent<D>) => void;
|
onDrag?: (data: DropTargetDragEvent<D>) => void;
|
||||||
/**
|
/**
|
||||||
* external data adapter.
|
* external data adapter.
|
||||||
* if this is provided, the drop target will handle external elements as well.
|
* Will use the external data adapter from the context if not provided.
|
||||||
|
*/
|
||||||
|
externalDataAdapter?: ExternalDataAdapter<D>;
|
||||||
|
/**
|
||||||
|
* Make the drop target allow external data.
|
||||||
|
* If this is undefined, it will be set to true if externalDataAdapter is provided.
|
||||||
*
|
*
|
||||||
* @default undefined
|
* @default undefined
|
||||||
*/
|
*/
|
||||||
externalDataAdapter?: ExternalDataAdapter<D>;
|
allowExternal?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useDropTarget = <D extends DNDData = DNDData>(
|
export const useDropTarget = <D extends DNDData = DNDData>(
|
||||||
@@ -205,19 +213,56 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
|||||||
const enableDraggedOverPosition = useRef(false);
|
const enableDraggedOverPosition = useRef(false);
|
||||||
const enableDropEffect = useRef(false);
|
const enableDropEffect = useRef(false);
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
const dropTargetContext = useContext(DNDContext);
|
||||||
const options = useMemo(getOptions, deps);
|
|
||||||
|
const options = useMemo(() => {
|
||||||
|
const opts = getOptions();
|
||||||
|
const allowExternal = opts.allowExternal ?? !!opts.externalDataAdapter;
|
||||||
|
return {
|
||||||
|
...opts,
|
||||||
|
allowExternal,
|
||||||
|
externalDataAdapter: allowExternal
|
||||||
|
? (opts.externalDataAdapter ??
|
||||||
|
(dropTargetContext.externalDataAdapter as ExternalDataAdapter<D>))
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [...deps, dropTargetContext.externalDataAdapter]);
|
||||||
|
|
||||||
const dropTargetOptions = useMemo(() => {
|
const dropTargetOptions = useMemo(() => {
|
||||||
|
const wrappedCanDrop = dropTargetGet(options.canDrop, options);
|
||||||
return {
|
return {
|
||||||
get element() {
|
get element() {
|
||||||
return dropTargetRef.current;
|
return dropTargetRef.current;
|
||||||
},
|
},
|
||||||
canDrop: dropTargetGet(options.canDrop, options),
|
canDrop: wrappedCanDrop
|
||||||
|
? (args: DropTargetGetFeedback<D>) => {
|
||||||
|
// check if args has data. if not, it's an external drag
|
||||||
|
// we always allow external drag since the data is only
|
||||||
|
// available in drop event
|
||||||
|
if (isExternalDrag(args) && options.externalDataAdapter) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return wrappedCanDrop(args);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
getDropEffect: dropTargetGet(options.dropEffect, options),
|
getDropEffect: dropTargetGet(options.dropEffect, options),
|
||||||
getIsSticky: dropTargetGet(options.isSticky, options),
|
getIsSticky: dropTargetGet(options.isSticky, options),
|
||||||
onDrop: (args: DropTargetDropEvent<D>) => {
|
onDrop: (_args: DropTargetDropEvent<D>) => {
|
||||||
args = getAdaptedEventArgs(options, args);
|
// external data is only available in drop event thus
|
||||||
|
// this is the only case for getAdaptedEventArgs
|
||||||
|
const args = getAdaptedEventArgs(options, _args, true);
|
||||||
|
if (
|
||||||
|
isExternalDrag(_args) &&
|
||||||
|
options.externalDataAdapter &&
|
||||||
|
typeof options.canDrop === 'function' &&
|
||||||
|
// there is a small flaw that canDrop called in onDrop misses
|
||||||
|
// `input and `element` arguments
|
||||||
|
!options.canDrop(args as any)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (enableDraggedOver.current) {
|
if (enableDraggedOver.current) {
|
||||||
setDraggedOver(false);
|
setDraggedOver(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export * from './context';
|
||||||
export * from './draggable';
|
export * from './draggable';
|
||||||
export * from './drop-indicator';
|
export * from './drop-indicator';
|
||||||
export * from './drop-target';
|
export * from './drop-target';
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import type { dropTargetForExternal } from '@atlaskit/pragmatic-drag-and-drop/external/adapter';
|
||||||
|
|
||||||
export interface DNDData<
|
export interface DNDData<
|
||||||
Draggable extends Record<string, unknown> = Record<string, unknown>,
|
Draggable extends Record<string, unknown> = Record<string, unknown>,
|
||||||
DropTarget extends Record<string, unknown> = Record<string, unknown>,
|
DropTarget extends Record<string, unknown> = Record<string, unknown>,
|
||||||
@@ -5,3 +7,12 @@ export interface DNDData<
|
|||||||
draggable: Draggable;
|
draggable: Draggable;
|
||||||
dropTarget: DropTarget;
|
dropTarget: DropTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ExternalGetDataFeedbackArgs = Parameters<
|
||||||
|
NonNullable<Parameters<typeof dropTargetForExternal>[0]['getData']>
|
||||||
|
>[0];
|
||||||
|
|
||||||
|
export type ExternalDataAdapter<D extends DNDData> = (
|
||||||
|
args: ExternalGetDataFeedbackArgs,
|
||||||
|
isDropEvent?: boolean
|
||||||
|
) => D['draggable'];
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
|
import { DNDContext } from '@affine/component';
|
||||||
import { AffineOtherPageLayout } from '@affine/component/affine-other-page-layout';
|
import { AffineOtherPageLayout } from '@affine/component/affine-other-page-layout';
|
||||||
import { workbenchRoutes } from '@affine/core/desktop/workbench-router';
|
import { workbenchRoutes } from '@affine/core/desktop/workbench-router';
|
||||||
import {
|
import {
|
||||||
DefaultServerService,
|
DefaultServerService,
|
||||||
WorkspaceServerService,
|
WorkspaceServerService,
|
||||||
} from '@affine/core/modules/cloud';
|
} from '@affine/core/modules/cloud';
|
||||||
|
import { DndService } from '@affine/core/modules/dnd/services';
|
||||||
import { ZipTransformer } from '@blocksuite/affine/blocks';
|
import { ZipTransformer } from '@blocksuite/affine/blocks';
|
||||||
import type { Workspace, WorkspaceMetadata } from '@toeverything/infra';
|
import type { Workspace, WorkspaceMetadata } from '@toeverything/infra';
|
||||||
import {
|
import {
|
||||||
FrameworkScope,
|
FrameworkScope,
|
||||||
GlobalContextService,
|
GlobalContextService,
|
||||||
useLiveData,
|
useLiveData,
|
||||||
|
useService,
|
||||||
useServices,
|
useServices,
|
||||||
WorkspacesService,
|
WorkspacesService,
|
||||||
} from '@toeverything/infra';
|
} from '@toeverything/infra';
|
||||||
import type { ReactElement } from 'react';
|
import type { PropsWithChildren, ReactElement } from 'react';
|
||||||
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { matchPath, useLocation, useParams } from 'react-router-dom';
|
import { matchPath, useLocation, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
@@ -128,6 +131,18 @@ export const Component = (): ReactElement => {
|
|||||||
return <WorkspacePage meta={meta} />;
|
return <WorkspacePage meta={meta} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const DNDContextProvider = ({ children }: PropsWithChildren) => {
|
||||||
|
const dndService = useService(DndService);
|
||||||
|
const contextValue = useMemo(() => {
|
||||||
|
return {
|
||||||
|
externalDataAdapter: dndService.externalDataAdapter,
|
||||||
|
};
|
||||||
|
}, [dndService.externalDataAdapter]);
|
||||||
|
return (
|
||||||
|
<DNDContext.Provider value={contextValue}>{children}</DNDContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const WorkspacePage = ({ meta }: { meta: WorkspaceMetadata }) => {
|
const WorkspacePage = ({ meta }: { meta: WorkspaceMetadata }) => {
|
||||||
const { workspacesService, globalContextService, defaultServerService } =
|
const { workspacesService, globalContextService, defaultServerService } =
|
||||||
useServices({
|
useServices({
|
||||||
@@ -229,7 +244,9 @@ const WorkspacePage = ({ meta }: { meta: WorkspaceMetadata }) => {
|
|||||||
return (
|
return (
|
||||||
<FrameworkScope scope={workspaceServer?.scope}>
|
<FrameworkScope scope={workspaceServer?.scope}>
|
||||||
<FrameworkScope scope={workspace.scope}>
|
<FrameworkScope scope={workspace.scope}>
|
||||||
<AppContainer fallback />
|
<DNDContextProvider>
|
||||||
|
<AppContainer fallback />
|
||||||
|
</DNDContextProvider>
|
||||||
</FrameworkScope>
|
</FrameworkScope>
|
||||||
</FrameworkScope>
|
</FrameworkScope>
|
||||||
);
|
);
|
||||||
@@ -238,11 +255,13 @@ const WorkspacePage = ({ meta }: { meta: WorkspaceMetadata }) => {
|
|||||||
return (
|
return (
|
||||||
<FrameworkScope scope={workspaceServer?.scope}>
|
<FrameworkScope scope={workspaceServer?.scope}>
|
||||||
<FrameworkScope scope={workspace.scope}>
|
<FrameworkScope scope={workspace.scope}>
|
||||||
<AffineErrorBoundary height="100vh">
|
<DNDContextProvider>
|
||||||
<WorkspaceLayout>
|
<AffineErrorBoundary height="100vh">
|
||||||
<WorkbenchRoot />
|
<WorkspaceLayout>
|
||||||
</WorkspaceLayout>
|
<WorkbenchRoot />
|
||||||
</AffineErrorBoundary>
|
</WorkspaceLayout>
|
||||||
|
</AffineErrorBoundary>
|
||||||
|
</DNDContextProvider>
|
||||||
</FrameworkScope>
|
</FrameworkScope>
|
||||||
</FrameworkScope>
|
</FrameworkScope>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import type { ExternalGetDataFeedbackArgs } from '@affine/component';
|
import type {
|
||||||
|
ExternalDataAdapter,
|
||||||
|
ExternalGetDataFeedbackArgs,
|
||||||
|
} from '@affine/component';
|
||||||
import type { AffineDNDData } from '@affine/core/types/dnd';
|
import type { AffineDNDData } from '@affine/core/types/dnd';
|
||||||
import type { DocsService, WorkspaceService } from '@toeverything/infra';
|
import type { DocsService, WorkspaceService } from '@toeverything/infra';
|
||||||
import { Service } from '@toeverything/infra';
|
import { Service } from '@toeverything/infra';
|
||||||
@@ -23,7 +26,13 @@ export class DndService extends Service {
|
|||||||
|
|
||||||
private readonly resolvers = new Map<string, EntityResolver>();
|
private readonly resolvers = new Map<string, EntityResolver>();
|
||||||
|
|
||||||
externalDataAdapter = (args: ExternalGetDataFeedbackArgs) => {
|
externalDataAdapter: ExternalDataAdapter<AffineDNDData> = (
|
||||||
|
args: ExternalGetDataFeedbackArgs,
|
||||||
|
isDropEvent?: boolean
|
||||||
|
) => {
|
||||||
|
if (!isDropEvent) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
const from: AffineDNDData['draggable']['from'] = {
|
const from: AffineDNDData['draggable']['from'] = {
|
||||||
at: 'external',
|
at: 'external',
|
||||||
};
|
};
|
||||||
@@ -43,6 +52,10 @@ export class DndService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!entity) {
|
||||||
|
return {}; // no resolver can handle this data
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
from,
|
from,
|
||||||
entity,
|
entity,
|
||||||
|
|||||||
@@ -189,10 +189,9 @@ export const ExplorerCollectionNode = ({
|
|||||||
const handleCanDrop = useMemo<DropTargetOptions<AffineDNDData>['canDrop']>(
|
const handleCanDrop = useMemo<DropTargetOptions<AffineDNDData>['canDrop']>(
|
||||||
() => args => {
|
() => args => {
|
||||||
const entityType = args.source.data.entity?.type;
|
const entityType = args.source.data.entity?.type;
|
||||||
const isExternalDrop = args.source.data.from?.at === 'external';
|
|
||||||
return args.treeInstruction?.type !== 'make-child'
|
return args.treeInstruction?.type !== 'make-child'
|
||||||
? ((typeof canDrop === 'function' ? canDrop(args) : canDrop) ?? true)
|
? ((typeof canDrop === 'function' ? canDrop(args) : canDrop) ?? true)
|
||||||
: entityType === 'doc' || isExternalDrop;
|
: entityType === 'doc';
|
||||||
},
|
},
|
||||||
[canDrop]
|
[canDrop]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -180,10 +180,9 @@ export const ExplorerDocNode = ({
|
|||||||
const handleCanDrop = useMemo<DropTargetOptions<AffineDNDData>['canDrop']>(
|
const handleCanDrop = useMemo<DropTargetOptions<AffineDNDData>['canDrop']>(
|
||||||
() => args => {
|
() => args => {
|
||||||
const entityType = args.source.data.entity?.type;
|
const entityType = args.source.data.entity?.type;
|
||||||
const isExternalDrop = args.source.data.from?.at === 'external';
|
|
||||||
return args.treeInstruction?.type !== 'make-child'
|
return args.treeInstruction?.type !== 'make-child'
|
||||||
? ((typeof canDrop === 'function' ? canDrop(args) : canDrop) ?? true)
|
? ((typeof canDrop === 'function' ? canDrop(args) : canDrop) ?? true)
|
||||||
: entityType === 'doc' || isExternalDrop;
|
: entityType === 'doc';
|
||||||
},
|
},
|
||||||
[canDrop]
|
[canDrop]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,10 +16,8 @@ export const favoriteChildrenDropEffect: ExplorerTreeNodeDropEffect = data => {
|
|||||||
) {
|
) {
|
||||||
return 'move';
|
return 'move';
|
||||||
} else if (
|
} else if (
|
||||||
(data.source.data.entity?.type &&
|
data.source.data.entity?.type &&
|
||||||
isFavoriteSupportType(data.source.data.entity.type)) ||
|
isFavoriteSupportType(data.source.data.entity.type)
|
||||||
// always allow external drop
|
|
||||||
data.source.data.from?.at === 'external'
|
|
||||||
) {
|
) {
|
||||||
return 'link';
|
return 'link';
|
||||||
}
|
}
|
||||||
@@ -39,7 +37,7 @@ export const favoriteRootCanDrop: DropTargetOptions<AffineDNDData>['canDrop'] =
|
|||||||
data => {
|
data => {
|
||||||
return data.source.data.entity?.type
|
return data.source.data.entity?.type
|
||||||
? isFavoriteSupportType(data.source.data.entity.type)
|
? isFavoriteSupportType(data.source.data.entity.type)
|
||||||
: data.source.data.from?.at === 'external'; // always allow external drop
|
: false;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const favoriteChildrenCanDrop: DropTargetOptions<AffineDNDData>['canDrop'] =
|
export const favoriteChildrenCanDrop: DropTargetOptions<AffineDNDData>['canDrop'] =
|
||||||
|
|||||||
@@ -3,11 +3,9 @@ import {
|
|||||||
Skeleton,
|
Skeleton,
|
||||||
useDropTarget,
|
useDropTarget,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { DndService } from '@affine/core/modules/dnd/services';
|
|
||||||
import type { AffineDNDData } from '@affine/core/types/dnd';
|
import type { AffineDNDData } from '@affine/core/types/dnd';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { FavoriteIcon } from '@blocksuite/icons/rc';
|
import { FavoriteIcon } from '@blocksuite/icons/rc';
|
||||||
import { useService } from '@toeverything/infra';
|
|
||||||
|
|
||||||
import { ExplorerEmptySection } from '../../layouts/empty-section';
|
import { ExplorerEmptySection } from '../../layouts/empty-section';
|
||||||
import { DropEffect } from '../../tree';
|
import { DropEffect } from '../../tree';
|
||||||
@@ -23,7 +21,6 @@ const RootEmptyLoading = () => {
|
|||||||
};
|
};
|
||||||
const RootEmptyReady = ({ onDrop }: Omit<RootEmptyProps, 'isLoading'>) => {
|
const RootEmptyReady = ({ onDrop }: Omit<RootEmptyProps, 'isLoading'>) => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const dndService = useService(DndService);
|
|
||||||
|
|
||||||
const { dropTargetRef, draggedOverDraggable, draggedOverPosition } =
|
const { dropTargetRef, draggedOverDraggable, draggedOverPosition } =
|
||||||
useDropTarget<AffineDNDData>(
|
useDropTarget<AffineDNDData>(
|
||||||
@@ -33,9 +30,9 @@ const RootEmptyReady = ({ onDrop }: Omit<RootEmptyProps, 'isLoading'>) => {
|
|||||||
},
|
},
|
||||||
onDrop: onDrop,
|
onDrop: onDrop,
|
||||||
canDrop: favoriteRootCanDrop,
|
canDrop: favoriteRootCanDrop,
|
||||||
externalDataAdapter: dndService.externalDataAdapter,
|
allowExternal: true,
|
||||||
}),
|
}),
|
||||||
[dndService.externalDataAdapter, onDrop]
|
[onDrop]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
useDropTarget,
|
useDropTarget,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { usePageHelper } from '@affine/core/components/blocksuite/block-suite-page-list/utils';
|
import { usePageHelper } from '@affine/core/components/blocksuite/block-suite-page-list/utils';
|
||||||
import { DndService } from '@affine/core/modules/dnd/services';
|
|
||||||
import {
|
import {
|
||||||
DropEffect,
|
DropEffect,
|
||||||
ExplorerTreeRoot,
|
ExplorerTreeRoot,
|
||||||
@@ -21,7 +20,6 @@ import { track } from '@affine/track';
|
|||||||
import { PlusIcon } from '@blocksuite/icons/rc';
|
import { PlusIcon } from '@blocksuite/icons/rc';
|
||||||
import {
|
import {
|
||||||
useLiveData,
|
useLiveData,
|
||||||
useService,
|
|
||||||
useServices,
|
useServices,
|
||||||
WorkspaceService,
|
WorkspaceService,
|
||||||
} from '@toeverything/infra';
|
} from '@toeverything/infra';
|
||||||
@@ -151,8 +149,6 @@ export const ExplorerFavorites = () => {
|
|||||||
[favoriteService]
|
[favoriteService]
|
||||||
);
|
);
|
||||||
|
|
||||||
const dndService = useService(DndService);
|
|
||||||
|
|
||||||
const { dropTargetRef, draggedOverDraggable, draggedOverPosition } =
|
const { dropTargetRef, draggedOverDraggable, draggedOverPosition } =
|
||||||
useDropTarget<AffineDNDData>(
|
useDropTarget<AffineDNDData>(
|
||||||
() => ({
|
() => ({
|
||||||
@@ -161,9 +157,9 @@ export const ExplorerFavorites = () => {
|
|||||||
},
|
},
|
||||||
onDrop: handleDrop,
|
onDrop: handleDrop,
|
||||||
canDrop: favoriteRootCanDrop,
|
canDrop: favoriteRootCanDrop,
|
||||||
externalDataAdapter: dndService.externalDataAdapter,
|
allowExternal: true,
|
||||||
}),
|
}),
|
||||||
[dndService.externalDataAdapter, handleDrop]
|
[handleDrop]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { RenameModal } from '@affine/component/rename-modal';
|
import { RenameModal } from '@affine/component/rename-modal';
|
||||||
import { AppSidebarService } from '@affine/core/modules/app-sidebar';
|
import { AppSidebarService } from '@affine/core/modules/app-sidebar';
|
||||||
import { DndService } from '@affine/core/modules/dnd/services';
|
|
||||||
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
||||||
import type { AffineDNDData } from '@affine/core/types/dnd';
|
import type { AffineDNDData } from '@affine/core/types/dnd';
|
||||||
import { extractEmojiIcon } from '@affine/core/utils';
|
import { extractEmojiIcon } from '@affine/core/utils';
|
||||||
@@ -186,7 +185,6 @@ export const ExplorerTreeNode = ({
|
|||||||
},
|
},
|
||||||
[canDrop, reorderable]
|
[canDrop, reorderable]
|
||||||
);
|
);
|
||||||
const dndService = useService(DndService);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
dropTargetRef,
|
dropTargetRef,
|
||||||
@@ -224,9 +222,7 @@ export const ExplorerTreeNode = ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
canDrop: handleCanDrop,
|
canDrop: handleCanDrop,
|
||||||
externalDataAdapter(args) {
|
allowExternal: true,
|
||||||
return dndService.externalDataAdapter(args) as any;
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
dndData?.dropTarget,
|
dndData?.dropTarget,
|
||||||
@@ -238,7 +234,6 @@ export const ExplorerTreeNode = ({
|
|||||||
cid,
|
cid,
|
||||||
onDrop,
|
onDrop,
|
||||||
setCollapsed,
|
setCollapsed,
|
||||||
dndService,
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
const isSelfDraggedOver = draggedOverDraggable?.data.__cid === cid;
|
const isSelfDraggedOver = draggedOverDraggable?.data.__cid === cid;
|
||||||
|
|||||||
Reference in New Issue
Block a user