mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-21 20:16:26 +08:00
129 lines
4.0 KiB
TypeScript
129 lines
4.0 KiB
TypeScript
import { AttachmentBlockSchema } from '@blocksuite/affine-model';
|
|
import {
|
|
DragHandleConfigExtension,
|
|
TelemetryProvider,
|
|
} from '@blocksuite/affine-shared/services';
|
|
import {
|
|
captureEventTarget,
|
|
convertDragPreviewDocToEdgeless,
|
|
convertDragPreviewEdgelessToDoc,
|
|
isInsideEdgelessEditor,
|
|
matchFlavours,
|
|
} from '@blocksuite/affine-shared/utils';
|
|
import { BlockService } from '@blocksuite/block-std';
|
|
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
|
|
|
import {
|
|
FileDropManager,
|
|
type FileDropOptions,
|
|
} from '../_common/components/file-drop-manager.js';
|
|
import { EMBED_CARD_HEIGHT, EMBED_CARD_WIDTH } from '../_common/consts.js';
|
|
import { addAttachments } from '../root-block/edgeless/utils/common.js';
|
|
import type { AttachmentBlockComponent } from './attachment-block.js';
|
|
import { AttachmentEdgelessBlockComponent } from './attachment-edgeless-block.js';
|
|
import { addSiblingAttachmentBlocks } from './utils.js';
|
|
|
|
export class AttachmentBlockService extends BlockService {
|
|
static override readonly flavour = AttachmentBlockSchema.model.flavour;
|
|
|
|
private readonly _fileDropOptions: FileDropOptions = {
|
|
flavour: this.flavour,
|
|
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/')
|
|
);
|
|
|
|
if (targetModel && !matchFlavours(targetModel, ['affine:surface'])) {
|
|
await addSiblingAttachmentBlocks(
|
|
this.host,
|
|
attachmentFiles,
|
|
this.maxFileSize,
|
|
targetModel,
|
|
place
|
|
);
|
|
} else if (isInsideEdgelessEditor(this.host)) {
|
|
const gfx = this.std.get(GfxControllerIdentifier);
|
|
point = gfx.viewport.toViewCoordFromClientCoord(point);
|
|
await addAttachments(this.std, attachmentFiles, point);
|
|
|
|
this.std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
|
|
control: 'canvas:drop',
|
|
page: 'whiteboard editor',
|
|
module: 'toolbar',
|
|
segment: 'toolbar',
|
|
type: 'attachment',
|
|
});
|
|
}
|
|
|
|
return true;
|
|
},
|
|
};
|
|
|
|
fileDropManager!: FileDropManager;
|
|
|
|
maxFileSize = 10 * 1000 * 1000; // 10MB (default)
|
|
|
|
override mounted(): void {
|
|
super.mounted();
|
|
|
|
this.fileDropManager = new FileDropManager(this, this._fileDropOptions);
|
|
}
|
|
}
|
|
|
|
export const AttachmentDragHandleOption = DragHandleConfigExtension({
|
|
flavour: AttachmentBlockSchema.model.flavour,
|
|
edgeless: true,
|
|
onDragEnd: props => {
|
|
const { state, draggingElements, editorHost } = props;
|
|
if (
|
|
draggingElements.length !== 1 ||
|
|
!matchFlavours(draggingElements[0].model, [
|
|
AttachmentBlockSchema.model.flavour,
|
|
])
|
|
)
|
|
return false;
|
|
|
|
const blockComponent = draggingElements[0] as
|
|
| AttachmentBlockComponent
|
|
| AttachmentEdgelessBlockComponent;
|
|
const isInSurface =
|
|
blockComponent instanceof AttachmentEdgelessBlockComponent;
|
|
const target = captureEventTarget(state.raw.target);
|
|
const isTargetEdgelessContainer =
|
|
target?.classList.contains('edgeless-container');
|
|
|
|
if (isInSurface) {
|
|
const style = blockComponent.model.style;
|
|
const targetStyle = style === 'cubeThick' ? 'horizontalThin' : style;
|
|
return convertDragPreviewEdgelessToDoc({
|
|
blockComponent,
|
|
style: targetStyle,
|
|
...props,
|
|
});
|
|
} else if (isTargetEdgelessContainer) {
|
|
let style = blockComponent.model.style ?? 'cubeThick';
|
|
const embed = blockComponent.model.embed;
|
|
if (embed) {
|
|
style = 'cubeThick';
|
|
editorHost.doc.updateBlock(blockComponent.model, {
|
|
style,
|
|
embed: false,
|
|
});
|
|
}
|
|
|
|
return convertDragPreviewDocToEdgeless({
|
|
blockComponent,
|
|
cssSelector: '.affine-attachment-container',
|
|
width: EMBED_CARD_WIDTH[style],
|
|
height: EMBED_CARD_HEIGHT[style],
|
|
...props,
|
|
});
|
|
}
|
|
|
|
return false;
|
|
},
|
|
});
|