Skip to content

Commit

Permalink
fix: file drop on edgeless
Browse files Browse the repository at this point in the history
  • Loading branch information
AyushAgrawal-A2 committed Jan 23, 2024
1 parent 8ed50fd commit 35f3875
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 69 deletions.
6 changes: 2 additions & 4 deletions packages/blocks/src/_common/components/file-drop-manager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BlockService } from '@blocksuite/block-std';
import { assertExists, throttle } from '@blocksuite/global/utils';
import { assertExists } from '@blocksuite/global/utils';
import type { EditorHost } from '@blocksuite/lit';
import type { BlockModel } from '@blocksuite/store';

Expand Down Expand Up @@ -89,7 +89,7 @@ export class FileDropManager {
return targetModel;
}

private _onDragOver = (event: DragEvent) => {
onDragOver = (event: DragEvent) => {
event.preventDefault();

// allow only external drag-and-drop files
Expand All @@ -114,8 +114,6 @@ export class FileDropManager {
}
};

onDragOver = throttle(this._onDragOver, 1000 / 60);

private _onDrop = (event: DragEvent) => {
const { onDrop } = this._fileDropOptions;
if (!onDrop) return;
Expand Down
33 changes: 26 additions & 7 deletions packages/blocks/src/attachment-block/attachment-service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BlockService } from '@blocksuite/block-std';
import { assertExists } from '@blocksuite/global/utils';
import type { EditorHost } from '@blocksuite/lit';
import { Slot } from '@blocksuite/store';

Expand All @@ -7,10 +8,24 @@ import {
type FileDropOptions,
} from '../_common/components/file-drop-manager.js';
import { matchFlavours } from '../_common/utils/model.js';
import { isInsideEdgelessEditor } from '../_common/utils/query.js';
import type { EdgelessPageBlockComponent } from '../page-block/edgeless/edgeless-page-block.js';
import type { PageBlockComponent } from '../page-block/types.js';
import type { AttachmentBlockModel } from './attachment-model.js';
import { addSiblingAttachmentBlock } from './utils.js';

export class AttachmentService extends BlockService<AttachmentBlockModel> {
get pageBlockComponent(): PageBlockComponent {
const pageBlock = this.page.root;
assertExists(pageBlock);

const pageElement = this.std.view.viewFromPath('block', [
pageBlock.id,
]) as PageBlockComponent | null;
assertExists(pageElement);
return pageElement;
}

maxFileSize = 10 * 1000 * 1000; // 10MB (default)

slots = {
Expand All @@ -19,24 +34,28 @@ export class AttachmentService extends BlockService<AttachmentBlockModel> {

private _fileDropOptions: FileDropOptions = {
flavour: this.flavour,
onDrop: async ({ files, targetModel, place }) => {
if (!files.length || !targetModel) return false;
if (matchFlavours(targetModel, ['affine:surface'])) return false;
onDrop: async ({ files, targetModel, place, point }) => {
if (!files.length) return false;

// generic attachment block for all files except images
const attachmentFiles = files.filter(
file => !file.type.startsWith('image/')
);

attachmentFiles.forEach(file => {
if (targetModel && !matchFlavours(targetModel, ['affine:surface'])) {
addSiblingAttachmentBlock(
this.std.host as EditorHost,
file,
attachmentFiles,
this.maxFileSize,
targetModel,
place
).catch(console.error);
});
);
} else if (isInsideEdgelessEditor(this.std.host as EditorHost)) {
const edgelessPage = this
.pageBlockComponent as EdgelessPageBlockComponent;
await edgelessPage.addFiles(attachmentFiles, point);
}

this.slots.onFilesDropped.emit(attachmentFiles);
return true;
},
Expand Down
83 changes: 40 additions & 43 deletions packages/blocks/src/attachment-block/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import type { BlockModel } from '@blocksuite/store';

import { toast } from '../_common/components/toast.js';
import { humanFileSize } from '../_common/utils/math.js';
import { buildPath } from '../_common/utils/query.js';
import type { PageBlockComponent } from '../page-block/types.js';
import type { AttachmentBlockComponent } from './attachment-block.js';
import type {
AttachmentBlockModel,
Expand All @@ -27,10 +25,10 @@ export function cloneAttachmentProperties(model: AttachmentBlockModel) {
}

const attachmentUploads = new Set<string>();
function setAttachmentUploading(blockId: string) {
export function setAttachmentUploading(blockId: string) {
attachmentUploads.add(blockId);
}
function setAttachmentUploaded(blockId: string) {
export function setAttachmentUploaded(blockId: string) {
attachmentUploads.delete(blockId);
}
function isAttachmentUploading(blockId: string) {
Expand All @@ -44,26 +42,17 @@ async function uploadAttachmentBlob(
editorHost: EditorHost,
blockId: string,
blob: Blob
): Promise<string> {
): Promise<void> {
if (isAttachmentUploading(blockId)) {
throw new Error('The attachment is already uploading!');
}

setAttachmentUploading(blockId);

const page = editorHost.page;
const attachmentModel = page.getBlockById(
blockId
) as AttachmentBlockModel | null;
assertExists(attachmentModel);
let sourceId: string | undefined;

try {
const sourceId = await page.blob.set(blob);
page.withoutTransact(() => {
page.updateBlock(attachmentModel, {
sourceId,
} satisfies Partial<AttachmentBlockProps>);
});
setAttachmentUploading(blockId);
sourceId = await page.blob.set(blob);
} catch (error) {
console.error(error);
if (error instanceof Error) {
Expand All @@ -75,22 +64,17 @@ async function uploadAttachmentBlob(
} finally {
setAttachmentUploaded(blockId);

const pageElement = editorHost.view.viewFromPath('block', [
page.root?.id ?? '',
]) as PageBlockComponent | null;
assertExists(pageElement);

await pageElement.updateComplete;
const attachmentModel = page.getBlockById(
blockId
) as AttachmentBlockModel | null;
assertExists(attachmentModel);

const attachmentElement = editorHost.view.viewFromPath(
'block',
buildPath(attachmentModel)
) as AttachmentBlockComponent | null;
assertExists(attachmentElement);

attachmentElement.refreshData();
page.withoutTransact(() => {
page.updateBlock(attachmentModel, {
sourceId,
} satisfies Partial<AttachmentBlockProps>);
});
}
return blockId;
}

export async function getAttachmentBlob(model: AttachmentBlockModel) {
Expand Down Expand Up @@ -184,14 +168,17 @@ export async function downloadAttachmentBlob(block: AttachmentBlockComponent) {
/**
* Add a new attachment block before / after the specified block.
*/
export async function addSiblingAttachmentBlock(
export function addSiblingAttachmentBlock(
editorHost: EditorHost,
file: File,
files: File[],
maxFileSize: number,
model: BlockModel,
targetModel: BlockModel,
place: 'before' | 'after' = 'after'
): Promise<string | null> {
if (file.size > maxFileSize) {
) {
if (!files.length) return;

const isSizeExceeded = files.some(file => file.size > maxFileSize);
if (isSizeExceeded) {
toast(
editorHost,
`You can only upload files less than ${humanFileSize(
Expand All @@ -200,19 +187,29 @@ export async function addSiblingAttachmentBlock(
0
)}`
);
return null;
return;
}

const page = model.page;
const props: Partial<AttachmentBlockProps> & {
const page = targetModel.page;
const attachmentBlockProps: (Partial<AttachmentBlockProps> & {
flavour: 'affine:attachment';
} = {
})[] = files.map(file => ({
flavour: 'affine:attachment',
name: file.name,
size: file.size,
type: file.type,
};
const [blockId] = page.addSiblingBlocks(model, [props], place);
}));

const blockIds = page.addSiblingBlocks(
targetModel,
attachmentBlockProps,
place
);

blockIds.map(
(blockId, index) =>
void uploadAttachmentBlob(editorHost, blockId, files[index])
);

return uploadAttachmentBlob(editorHost, blockId, file);
return blockIds;
}
12 changes: 6 additions & 6 deletions packages/blocks/src/image-block/image-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,20 @@ import {
isInsideEdgelessEditor,
matchFlavours,
} from '../_common/utils/index.js';
import type { DocPageBlockComponent } from '../page-block/doc/doc-page-block.js';
import type { EdgelessPageBlockComponent } from '../page-block/edgeless/edgeless-page-block.js';
import type { PageBlockComponent } from '../page-block/types.js';
import type { ImageBlockModel } from './image-model.js';
import { ImageSelection } from './image-selection.js';
import { addSiblingImageBlock } from './utils.js';

export class ImageService extends BlockService<ImageBlockModel> {
get pageBlockComponent(): DocPageBlockComponent | EdgelessPageBlockComponent {
get pageBlockComponent(): PageBlockComponent {
const pageBlock = this.page.root;
assertExists(pageBlock);

const pageElement = this.std.view.viewFromPath('block', [pageBlock.id]) as
| DocPageBlockComponent
| EdgelessPageBlockComponent
| null;
const pageElement = this.std.view.viewFromPath('block', [
pageBlock.id,
]) as PageBlockComponent | null;
assertExists(pageElement);
return pageElement;
}
Expand All @@ -36,6 +35,7 @@ export class ImageService extends BlockService<ImageBlockModel> {
flavour: this.flavour,
onDrop: async ({ files, targetModel, place, point }) => {
const imageFiles = files.filter(file => file.type.startsWith('image/'));
if (!imageFiles.length) return false;

if (targetModel && !matchFlavours(targetModel, ['affine:surface'])) {
addSiblingImageBlock(
Expand Down
10 changes: 6 additions & 4 deletions packages/blocks/src/image-block/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ export function shouldResizeImage(node: Node, target: EventTarget | null) {

export async function uploadBlobForImage(
editorHost: EditorHost,
page: Page,
blockId: string,
blob: Blob
): Promise<string> {
Expand All @@ -140,6 +139,7 @@ export async function uploadBlobForImage(
throw new Error('the image is already uploading!');
}
setImageLoading(blockId, true);
const page = editorHost.page;
const storage = page.blob;
let sourceId = '';
let imageBlock: BlockModel | null = null;
Expand Down Expand Up @@ -195,6 +195,8 @@ export function addSiblingImageBlock(
place: 'after' | 'before' = 'after'
) {
const imageFiles = files.filter(file => file.type.startsWith('image/'));
if (!imageFiles.length) return;

const isSizeExceeded = imageFiles.some(file => file.size > maxFileSize);
if (isSizeExceeded) {
toast(
Expand All @@ -205,7 +207,7 @@ export function addSiblingImageBlock(
0
)}`
);
return [];
return;
}

const imageBlockProps: Partial<ImageBlockProps> &
Expand All @@ -220,7 +222,7 @@ export function addSiblingImageBlock(
const blockIds = page.addSiblingBlocks(targetModel, imageBlockProps, place);
blockIds.map(
(blockId, index) =>
void uploadBlobForImage(editorHost, page, blockId, imageFiles[index])
void uploadBlobForImage(editorHost, blockId, imageFiles[index])
);
return blockIds;
}
Expand Down Expand Up @@ -257,7 +259,7 @@ export function addImageBlocks(
);
blockIds.map(
(blockId, index) =>
void uploadBlobForImage(editorHost, page, blockId, imageFiles[index])
void uploadBlobForImage(editorHost, blockId, imageFiles[index])
);
return blockIds;
}
Loading

0 comments on commit 35f3875

Please sign in to comment.