feat(editor): affine to blocksuite doc dnd with prefered card view (#11748)

Close [BS-3070](https://linear.app/affine-design/issue/BS-3070/文档拖动进入edgeless,形成引用时,默认形成embeded的引用,但是记录上次选择)
This commit is contained in:
L-Sun
2025-04-17 04:06:50 +00:00
parent 50b3f5f7df
commit 98899b4eea
13 changed files with 199 additions and 22 deletions

View File

@@ -1,11 +1,12 @@
import { type Framework } from '@toeverything/infra';
import { DocsService } from '../doc';
import { EditorSettingService } from '../editor-setting';
import { WorkspaceScope, WorkspaceService } from '../workspace';
import { DndService } from './services';
export function configureDndModule(framework: Framework) {
framework
.scope(WorkspaceScope)
.service(DndService, [DocsService, WorkspaceService]);
.service(DndService, [DocsService, WorkspaceService, EditorSettingService]);
}

View File

@@ -1,6 +1,7 @@
import {
type ExternalGetDataFeedbackArgs,
type fromExternalData,
type MonitorDragEvent,
monitorForElements,
type MonitorGetFeedback,
type toExternalData,
@@ -16,6 +17,7 @@ import type { DragBlockPayload } from '@blocksuite/affine/widgets/drag-handle';
import { Service } from '@toeverything/infra';
import type { DocsService } from '../../doc';
import type { EditorSettingService } from '../../editor-setting';
import { resolveLinkToDoc } from '../../navigation';
import type { WorkspaceService } from '../../workspace';
@@ -31,7 +33,8 @@ type MixedDNDData = AffineDNDData & {
export class DndService extends Service {
constructor(
private readonly docsService: DocsService,
private readonly workspaceService: WorkspaceService
private readonly workspaceService: WorkspaceService,
private readonly editorSettingService: EditorSettingService
) {
super();
@@ -130,6 +133,43 @@ export class DndService extends Service {
);
}
function getBSDropTarget(args: MonitorDragEvent<MixedDNDData>) {
for (const target of args.location.current.dropTargets) {
const { tagName } = target.element;
if (['AFFINE-EDGELESS-NOTE', 'AFFINE-NOTE'].includes(tagName))
return 'note';
if (tagName === 'AFFINE-EDGELESS-ROOT') return 'canvas';
}
return 'other';
}
const changeDocCardView = (args: MonitorDragEvent<MixedDNDData>) => {
if (args.source.data.from?.at === 'blocksuite-editor') return;
const dropTarget = getBSDropTarget(args);
if (dropTarget === 'other') return;
const flavour =
dropTarget === 'canvas'
? this.editorSettingService.editorSetting.docDropCanvasPreferView
.value
: 'affine:embed-linked-doc';
const { entity, bsEntity } = args.source.data;
if (!entity || !bsEntity) return;
const dndAPI = this.getBlocksuiteDndAPI();
if (!dndAPI) return;
const snapshotSlice = dndAPI.fromEntity({
docId: entity.id,
flavour,
});
if (!snapshotSlice) return;
bsEntity.snapshot = snapshotSlice;
};
this.disposables.push(
monitorForElements({
canMonitor: (args: MonitorGetFeedback<MixedDNDData>) => {
@@ -144,6 +184,9 @@ export class DndService extends Service {
}
return false;
},
onDropTargetChange: (args: MonitorDragEvent<MixedDNDData>) => {
changeDocCardView(args);
},
})
);
}