Skip to content

Commit

Permalink
feat(blocks): file drop manager supports files from other apps
Browse files Browse the repository at this point in the history
  • Loading branch information
fundon committed May 14, 2024
1 parent aa6f0b7 commit cad688e
Show file tree
Hide file tree
Showing 11 changed files with 442 additions and 123 deletions.
68 changes: 16 additions & 52 deletions packages/blocks/src/_common/adapters/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,19 +131,6 @@ export class HtmlAdapter extends BaseAdapter<Html> {
): Promise<DocSnapshot> {
const htmlAst = this._htmlToAst(payload.file);
const titleAst = hastQuerySelector(htmlAst, 'title');
const blockSnapshotRoot = {
type: 'block',
id: nanoid(),
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: '--affine-background-secondary-color',
index: 'a0',
hidden: false,
displayMode: NoteDisplayMode.DocAndEdgeless,
},
children: [],
};
return {
type: 'page',
meta: {
Expand Down Expand Up @@ -177,11 +164,7 @@ export class HtmlAdapter extends BaseAdapter<Html> {
},
children: [],
},
await this._traverseHtml(
htmlAst,
blockSnapshotRoot as BlockSnapshot,
payload.assets
),
await this._traverseHtml(htmlAst, payload.assets),
],
},
};
Expand All @@ -190,45 +173,14 @@ export class HtmlAdapter extends BaseAdapter<Html> {
payload: ToBlockSnapshotPayload<string>
): Promise<BlockSnapshot> {
const htmlAst = this._htmlToAst(payload.file);
const blockSnapshotRoot = {
type: 'block',
id: nanoid(),
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: '--affine-background-secondary-color',
index: 'a0',
hidden: false,
displayMode: NoteDisplayMode.DocAndEdgeless,
},
children: [],
};
return this._traverseHtml(
htmlAst,
blockSnapshotRoot as BlockSnapshot,
payload.assets
);
return this._traverseHtml(htmlAst, payload.assets);
}
override async toSliceSnapshot(
payload: HtmlToSliceSnapshotPayload
): Promise<SliceSnapshot | null> {
const htmlAst = this._htmlToAst(payload.file);
const blockSnapshotRoot = {
type: 'block',
id: nanoid(),
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: '--affine-background-secondary-color',
index: 'a0',
hidden: false,
displayMode: NoteDisplayMode.DocAndEdgeless,
},
children: [],
};
const contentSlice = (await this._traverseHtml(
htmlAst,
blockSnapshotRoot as BlockSnapshot,
payload.assets
)) as BlockSnapshot;
if (contentSlice.children.length === 0) {
Expand Down Expand Up @@ -684,8 +636,20 @@ export class HtmlAdapter extends BaseAdapter<Html> {

private _traverseHtml = async (
html: HtmlAST,
snapshot: BlockSnapshot,
assets?: AssetsManager
assets?: AssetsManager,
snapshot: BlockSnapshot = {
type: 'block',
id: nanoid(),
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: '--affine-background-secondary-color',
index: 'a0',
hidden: false,
displayMode: NoteDisplayMode.DocAndEdgeless,
},
children: [],
}
) => {
const walker = new ASTWalker<HtmlAST, BlockSnapshot>();
walker.setONodeTypeGuard(
Expand Down
1 change: 1 addition & 0 deletions packages/blocks/src/_common/adapters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export * from './markdown.js';
export * from './mix-text.js';
export * from './notion-html.js';
export * from './plain-text.js';
export * from './uri-list.js';
export { fetchable, fetchImage } from './utils.js';
60 changes: 60 additions & 0 deletions packages/blocks/src/_common/adapters/uri-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type {
BlockSnapshot,
DocSnapshot,
FromBlockSnapshotPayload,
FromBlockSnapshotResult,
FromDocSnapshotPayload,
FromDocSnapshotResult,
FromSliceSnapshotPayload,
FromSliceSnapshotResult,
SliceSnapshot,
ToBlockSnapshotPayload,
ToDocSnapshotPayload,
ToSliceSnapshotPayload,
} from '@blocksuite/store';
import { BaseAdapter } from '@blocksuite/store';

export type UriList = string;

// https://www.iana.org/assignments/media-types/text/uri-list
export class UriListAdapter extends BaseAdapter<UriList> {
override fromDocSnapshot(
_payload: FromDocSnapshotPayload
): Promise<FromDocSnapshotResult<UriList>> {
throw new Error('Method not implemented.');
}
override fromBlockSnapshot(
_payload: FromBlockSnapshotPayload
): Promise<FromBlockSnapshotResult<UriList>> {
throw new Error('Method not implemented.');
}
override fromSliceSnapshot(
_payload: FromSliceSnapshotPayload
): Promise<FromSliceSnapshotResult<UriList>> {
throw new Error('Method not implemented.');
}
override toDocSnapshot(
_payload: ToDocSnapshotPayload<UriList>
): Promise<DocSnapshot> {
throw new Error('Method not implemented.');
}
override toSliceSnapshot(
_payload: ToSliceSnapshotPayload<UriList>
): SliceSnapshot | Promise<SliceSnapshot | null> | null {
throw new Error('Method not implemented.');
}
override toBlockSnapshot(
_payload: ToBlockSnapshotPayload<UriList>
): BlockSnapshot {
throw new Error('Method not implemented.');
}

parse(input: UriList) {
return input
.split('\n')
.map(line => line.trim())
.filter(line => line.length >= 3)
.filter(line => line.at(0) !== '#')
.filter(line => URL.canParse(line));
}
}
52 changes: 31 additions & 21 deletions packages/blocks/src/_common/components/file-drop-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import type { DragIndicator } from './drag-indicator.js';

export type onDropProps = {
files: File[];
html?: string;
uriList?: string;
targetModel: BlockModel | null;
place: 'before' | 'after';
point: IPoint;
Expand All @@ -26,6 +28,8 @@ export type FileDropOptions = {
flavour: string;
onDrop?: ({
files,
html,
uriList,
targetModel,
place,
point,
Expand Down Expand Up @@ -113,11 +117,12 @@ export class FileDropManager {
onDragOver = (event: DragEvent) => {
event.preventDefault();

const dataTransfer = event.dataTransfer;
if (!dataTransfer) return;

// allow only external drag-and-drop files
const effectAllowed = event.dataTransfer?.effectAllowed ?? 'none';
if (effectAllowed !== 'all') {
return;
}
const effectAllowed = dataTransfer.effectAllowed;
if (effectAllowed === 'none') return;

const { clientX, clientY } = event;
const point = new Point(clientX, clientY);
Expand Down Expand Up @@ -149,36 +154,41 @@ export class FileDropManager {
this._indicator.rect = null;

const { onDrop } = this._fileDropOptions;
if (!onDrop) {
return;
}
if (!onDrop) return;

event.preventDefault();
const dataTransfer = event.dataTransfer;
if (!dataTransfer) return;

// allow only external drag-and-drop files
const effectAllowed = event.dataTransfer?.effectAllowed ?? 'none';
if (effectAllowed !== 'all') {
return;
const effectAllowed = dataTransfer.effectAllowed;
if (effectAllowed === 'none') return;

const types = dataTransfer.types;
if (!types.length) return;

event.preventDefault();

let uriList: string | undefined;
if (types.includes('text/uri-list')) {
uriList = dataTransfer.getData('text/uri-list');
}

const droppedFiles = event.dataTransfer?.files;
if (!droppedFiles || !droppedFiles.length) {
return;
let html;
if (!uriList?.length && types.includes('text/html')) {
html = dataTransfer.getData('text/html');
}

const targetModel = this.targetModel;
const place = this.type;

const { clientX, clientY } = event;
const point = { x: event.clientX, y: event.clientY };

onDrop({
files: [...droppedFiles],
files: Array.from(dataTransfer.files),
html,
uriList,
targetModel,
place,
point: {
x: clientX,
y: clientY,
},
point,
})?.catch(console.error);
};
}

0 comments on commit cad688e

Please sign in to comment.