Skip to content

Commit

Permalink
feat: add from entity api for dnd (#8946)
Browse files Browse the repository at this point in the history
  • Loading branch information
Saul-Mirone committed Dec 12, 2024
1 parent 1876df2 commit 78634b8
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 50 deletions.
111 changes: 63 additions & 48 deletions packages/affine/shared/src/services/drag-handle-config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import type {
BlockComponent,
DndEventState,
EditorHost,
ExtensionType,
} from '@blocksuite/block-std';
import type { Point } from '@blocksuite/global/utils';

import { createIdentifier } from '@blocksuite/global/di';
import {
type BlockComponent,
type BlockStdScope,
type DndEventState,
type EditorHost,
Extension,
type ExtensionType,
StdIdentifier,
} from '@blocksuite/block-std';
import { type Container, createIdentifier } from '@blocksuite/global/di';
import {
type BlockModel,
Job,
Slice,
type SliceSnapshot,
} from '@blocksuite/store';

export type DropType = 'before' | 'after' | 'in';
export type OnDragStartProps = {
Expand Down Expand Up @@ -62,48 +71,54 @@ export function DragHandleConfigExtension(
};
}

export type DndApi = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
decodeSnapshot: (dataTransfer: DataTransfer) => any | null;
encodeSnapshot: (
json: Record<string, unknown>,
dataTransfer: DataTransfer,
html?: string
) => void;
};

export const DndApiExtensionIdentifier = createIdentifier<DndApi>(
export const DndApiExtensionIdentifier = createIdentifier<DNDAPIExtension>(
'AffineDndApiIdentifier'
);

export function DNDAPIExtension(): ExtensionType {
return {
setup: di => {
di.addImpl(DndApiExtensionIdentifier, () => ({
decodeSnapshot: dataTransfer => {
const html = dataTransfer.getData('text/html');
if (!html) return null;

const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const dom = doc.querySelector<HTMLDivElement>(
'[data-blocksuite-snapshot]'
);
if (!dom) return null;

const json = JSON.parse(
decodeURIComponent(dom.dataset.blocksuiteSnapshot as string)
);
return json;
},
encodeSnapshot: (json, dataTransfer, htmlBody = '') => {
const snapshot = JSON.stringify(json);
dataTransfer.setData(
'text/html',
`<div data-blocksuite-snapshot="${encodeURIComponent(snapshot)}">${htmlBody}</div>`
);
},
}));
},
};
export class DNDAPIExtension extends Extension {
mimeType = 'application/x-blocksuite-dnd';

constructor(readonly std: BlockStdScope) {
super();
}

static override setup(di: Container) {
di.add(this, [StdIdentifier]);

di.addImpl(DndApiExtensionIdentifier, provider => provider.get(this));
}

decodeSnapshot(dataTransfer: DataTransfer): SliceSnapshot {
const data = dataTransfer.getData(this.mimeType);

return JSON.parse(decodeURIComponent(data));
}

encodeSnapshot(json: SliceSnapshot, dataTransfer: DataTransfer) {
const snapshot = JSON.stringify(json);
dataTransfer.setData(this.mimeType, encodeURIComponent(snapshot));
}

fromEntity(docId: string, blockId?: string): SliceSnapshot | null {
const doc = this.std.collection.getDoc(docId);
if (!doc) {
console.error(`Doc ${docId} not found`);
return null;
}
const blocks: BlockModel[] = [];
if (blockId) {
const model = doc.getBlock(blockId)?.model;
if (model) {
blocks.push(model);
}
}
const slice = Slice.fromModels(doc, blocks);
const job = new Job({ collection: this.std.collection });
const snapshot = job.sliceToSnapshot(slice);
if (!snapshot) {
console.error('Failed to convert slice to snapshot');
return null;
}
return snapshot;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const EdgelessCommonExtension: ExtensionType[] = [
CommandExtension(commands),
ExportManagerExtension,
ToolController,
DNDAPIExtension(),
DNDAPIExtension,
];

export const EdgelessRootBlockSpec: ExtensionType[] = [
Expand Down
2 changes: 1 addition & 1 deletion packages/blocks/src/root-block/page/page-root-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,5 @@ export const PageRootBlockSpec: ExtensionType[] = [
BlockViewExtension('affine:page', literal`affine-page-root`),
WidgetViewMapExtension('affine:page', pageRootWidgetViewMap),
ExportManagerExtension,
DNDAPIExtension(),
DNDAPIExtension,
];

0 comments on commit 78634b8

Please sign in to comment.