From ebd97752bf9ef22924c6e0adeaf0fa2c8d4bcc3b Mon Sep 17 00:00:00 2001 From: Saul-Mirone Date: Wed, 25 Dec 2024 12:19:58 +0000 Subject: [PATCH] refactor(editor): extract attachment block (#9308) --- .../affine/block-attachment/package.json | 44 ++++++++++ .../src}/adapters/notion-html.ts | 0 .../block-attachment/src}/attachment-block.ts | 0 .../src}/attachment-edgeless-block.ts | 14 ++- .../src}/attachment-service.ts | 8 +- .../block-attachment/src}/attachment-spec.ts | 0 .../src}/components/config.ts | 0 .../src}/components/context.ts | 0 .../src}/components/options.ts | 0 .../src}/components/rename-model.ts | 0 .../src}/components/styles.ts | 0 .../affine/block-attachment/src/effects.ts | 19 ++++ .../block-attachment/src}/embed.ts | 0 .../affine/block-attachment/src/index.ts | 11 +++ .../block-attachment/src}/styles.ts | 0 .../block-attachment/src}/utils.ts | 85 +++++++++++++++++- .../affine/block-attachment/tsconfig.json | 35 ++++++++ blocksuite/blocks/package.json | 1 + .../adapters/notion-html/block-matcher.ts | 2 +- blocksuite/blocks/src/_specs/common.ts | 2 +- blocksuite/blocks/src/_specs/group/common.ts | 2 +- .../blocks/src/attachment-block/index.ts | 8 -- blocksuite/blocks/src/effects.ts | 13 +-- blocksuite/blocks/src/index.ts | 2 +- .../edgeless/clipboard/clipboard.ts | 3 +- .../components/toolbar/note/note-menu.ts | 3 +- .../src/root-block/edgeless/utils/common.ts | 87 ------------------- .../change-attachment-button.ts | 6 +- .../element-toolbar/more-menu/config.ts | 2 +- .../widgets/keyboard-toolbar/config.ts | 2 +- .../root-block/widgets/slash-menu/config.ts | 2 +- blocksuite/blocks/tsconfig.json | 3 + tools/utils/src/workspace.gen.ts | 16 ++++ tsconfig.project.json | 2 + yarn.lock | 25 ++++++ 35 files changed, 272 insertions(+), 125 deletions(-) create mode 100644 blocksuite/affine/block-attachment/package.json rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/adapters/notion-html.ts (100%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/attachment-block.ts (100%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/attachment-edgeless-block.ts (80%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/attachment-service.ts (89%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/attachment-spec.ts (100%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/components/config.ts (100%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/components/context.ts (100%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/components/options.ts (100%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/components/rename-model.ts (100%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/components/styles.ts (100%) create mode 100644 blocksuite/affine/block-attachment/src/effects.ts rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/embed.ts (100%) create mode 100644 blocksuite/affine/block-attachment/src/index.ts rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/styles.ts (100%) rename blocksuite/{blocks/src/attachment-block => affine/block-attachment/src}/utils.ts (73%) create mode 100644 blocksuite/affine/block-attachment/tsconfig.json delete mode 100644 blocksuite/blocks/src/attachment-block/index.ts diff --git a/blocksuite/affine/block-attachment/package.json b/blocksuite/affine/block-attachment/package.json new file mode 100644 index 0000000000..227341f621 --- /dev/null +++ b/blocksuite/affine/block-attachment/package.json @@ -0,0 +1,44 @@ +{ + "name": "@blocksuite/affine-block-attachment", + "description": "Attachment block for BlockSuite.", + "type": "module", + "scripts": { + "build": "tsc", + "test:unit": "nx vite:test --run --passWithNoTests", + "test:unit:coverage": "nx vite:test --run --coverage", + "test:e2e": "playwright test" + }, + "sideEffects": false, + "keywords": [], + "author": "toeverything", + "license": "MIT", + "dependencies": { + "@blocksuite/affine-block-embed": "workspace:*", + "@blocksuite/affine-components": "workspace:*", + "@blocksuite/affine-model": "workspace:*", + "@blocksuite/affine-shared": "workspace:*", + "@blocksuite/block-std": "workspace:*", + "@blocksuite/global": "workspace:*", + "@blocksuite/icons": "^2.1.75", + "@blocksuite/inline": "workspace:*", + "@blocksuite/store": "workspace:*", + "@floating-ui/dom": "^1.6.10", + "@lit/context": "^1.1.2", + "@preact/signals-core": "^1.8.0", + "@toeverything/theme": "^1.1.1", + "file-type": "^19.5.0", + "lit": "^3.2.0", + "minimatch": "^10.0.1", + "zod": "^3.23.8" + }, + "exports": { + ".": "./src/index.ts", + "./effects": "./src/effects.ts" + }, + "files": [ + "src", + "dist", + "!src/__tests__", + "!dist/__tests__" + ] +} diff --git a/blocksuite/blocks/src/attachment-block/adapters/notion-html.ts b/blocksuite/affine/block-attachment/src/adapters/notion-html.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/adapters/notion-html.ts rename to blocksuite/affine/block-attachment/src/adapters/notion-html.ts diff --git a/blocksuite/blocks/src/attachment-block/attachment-block.ts b/blocksuite/affine/block-attachment/src/attachment-block.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/attachment-block.ts rename to blocksuite/affine/block-attachment/src/attachment-block.ts diff --git a/blocksuite/blocks/src/attachment-block/attachment-edgeless-block.ts b/blocksuite/affine/block-attachment/src/attachment-edgeless-block.ts similarity index 80% rename from blocksuite/blocks/src/attachment-block/attachment-edgeless-block.ts rename to blocksuite/affine/block-attachment/src/attachment-edgeless-block.ts index d6914cfa5f..72614b2dea 100644 --- a/blocksuite/blocks/src/attachment-block/attachment-edgeless-block.ts +++ b/blocksuite/affine/block-attachment/src/attachment-edgeless-block.ts @@ -4,10 +4,10 @@ import { EMBED_CARD_HEIGHT, EMBED_CARD_WIDTH, } from '@blocksuite/affine-shared/consts'; -import { toGfxBlockComponent } from '@blocksuite/block-std'; +import { type BlockService, toGfxBlockComponent } from '@blocksuite/block-std'; +import type { Slot } from '@blocksuite/store'; import { styleMap } from 'lit/directives/style-map.js'; -import type { EdgelessRootService } from '../root-block/index.js'; import { AttachmentBlockComponent } from './attachment-block.js'; export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent( @@ -17,15 +17,20 @@ export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent( override blockDraggable = false; - get rootService() { - return this.std.getService('affine:page') as EdgelessRootService; + get rootService(): null | (BlockService & { slots: Record }) { + return this.std.getService('affine:page'); } override connectedCallback(): void { super.connectedCallback(); const rootService = this.rootService; + if (!rootService) { + console.warn('rootService is not found'); + return; + } + // TODO: move root service slots to extension this._disposables.add( rootService.slots.elementResizeStart.on(() => { this._isResizing = true; @@ -33,6 +38,7 @@ export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent( }) ); + // TODO: move root service slots to extension this._disposables.add( rootService.slots.elementResizeEnd.on(() => { this._isResizing = false; diff --git a/blocksuite/blocks/src/attachment-block/attachment-service.ts b/blocksuite/affine/block-attachment/src/attachment-service.ts similarity index 89% rename from blocksuite/blocks/src/attachment-block/attachment-service.ts rename to blocksuite/affine/block-attachment/src/attachment-service.ts index 4667900751..c81c9c559c 100644 --- a/blocksuite/blocks/src/attachment-block/attachment-service.ts +++ b/blocksuite/affine/block-attachment/src/attachment-service.ts @@ -8,8 +8,7 @@ import { import { BlockService } from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; -import { addAttachments } from '../root-block/edgeless/utils/common.js'; -import { addSiblingAttachmentBlocks } from './utils.js'; +import { addAttachments, addSiblingAttachmentBlocks } from './utils.js'; // bytes.parse('2GB') const maxFileSize = 2147483648; @@ -30,7 +29,10 @@ export const AttachmentDropOption = FileDropConfigExtension({ if (!attachmentFiles.length) return false; - if (targetModel && !matchFlavours(targetModel, ['affine:surface'])) { + if ( + targetModel && + !matchFlavours(targetModel, ['affine:surface' as BlockSuite.Flavour]) + ) { addSiblingAttachmentBlocks( std.host, attachmentFiles, diff --git a/blocksuite/blocks/src/attachment-block/attachment-spec.ts b/blocksuite/affine/block-attachment/src/attachment-spec.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/attachment-spec.ts rename to blocksuite/affine/block-attachment/src/attachment-spec.ts diff --git a/blocksuite/blocks/src/attachment-block/components/config.ts b/blocksuite/affine/block-attachment/src/components/config.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/components/config.ts rename to blocksuite/affine/block-attachment/src/components/config.ts diff --git a/blocksuite/blocks/src/attachment-block/components/context.ts b/blocksuite/affine/block-attachment/src/components/context.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/components/context.ts rename to blocksuite/affine/block-attachment/src/components/context.ts diff --git a/blocksuite/blocks/src/attachment-block/components/options.ts b/blocksuite/affine/block-attachment/src/components/options.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/components/options.ts rename to blocksuite/affine/block-attachment/src/components/options.ts diff --git a/blocksuite/blocks/src/attachment-block/components/rename-model.ts b/blocksuite/affine/block-attachment/src/components/rename-model.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/components/rename-model.ts rename to blocksuite/affine/block-attachment/src/components/rename-model.ts diff --git a/blocksuite/blocks/src/attachment-block/components/styles.ts b/blocksuite/affine/block-attachment/src/components/styles.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/components/styles.ts rename to blocksuite/affine/block-attachment/src/components/styles.ts diff --git a/blocksuite/affine/block-attachment/src/effects.ts b/blocksuite/affine/block-attachment/src/effects.ts new file mode 100644 index 0000000000..ee4fdb0350 --- /dev/null +++ b/blocksuite/affine/block-attachment/src/effects.ts @@ -0,0 +1,19 @@ +import { AttachmentBlockComponent } from './attachment-block'; +import { AttachmentEdgelessBlockComponent } from './attachment-edgeless-block'; +import type { AttachmentBlockService } from './attachment-service'; + +export function effects() { + customElements.define( + 'affine-edgeless-attachment', + AttachmentEdgelessBlockComponent + ); + customElements.define('affine-attachment', AttachmentBlockComponent); +} + +declare global { + namespace BlockSuite { + interface BlockServices { + 'affine:attachment': AttachmentBlockService; + } + } +} diff --git a/blocksuite/blocks/src/attachment-block/embed.ts b/blocksuite/affine/block-attachment/src/embed.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/embed.ts rename to blocksuite/affine/block-attachment/src/embed.ts diff --git a/blocksuite/affine/block-attachment/src/index.ts b/blocksuite/affine/block-attachment/src/index.ts new file mode 100644 index 0000000000..4298e7a67f --- /dev/null +++ b/blocksuite/affine/block-attachment/src/index.ts @@ -0,0 +1,11 @@ +export * from './adapters/notion-html'; +export * from './attachment-block'; +export * from './attachment-service'; +export * from './attachment-spec'; +export { attachmentViewToggleMenu } from './components/options'; +export { + type AttachmentEmbedConfig, + AttachmentEmbedConfigIdentifier, + AttachmentEmbedProvider, +} from './embed'; +export { addAttachments, addSiblingAttachmentBlocks } from './utils'; diff --git a/blocksuite/blocks/src/attachment-block/styles.ts b/blocksuite/affine/block-attachment/src/styles.ts similarity index 100% rename from blocksuite/blocks/src/attachment-block/styles.ts rename to blocksuite/affine/block-attachment/src/styles.ts diff --git a/blocksuite/blocks/src/attachment-block/utils.ts b/blocksuite/affine/block-attachment/src/utils.ts similarity index 73% rename from blocksuite/blocks/src/attachment-block/utils.ts rename to blocksuite/affine/block-attachment/src/utils.ts index 84b0f1551d..5ed02be23b 100644 --- a/blocksuite/blocks/src/attachment-block/utils.ts +++ b/blocksuite/affine/block-attachment/src/utils.ts @@ -4,9 +4,15 @@ import type { AttachmentBlockProps, } from '@blocksuite/affine-model'; import { defaultAttachmentProps } from '@blocksuite/affine-model'; +import { + EMBED_CARD_HEIGHT, + EMBED_CARD_WIDTH, +} from '@blocksuite/affine-shared/consts'; import { TelemetryProvider } from '@blocksuite/affine-shared/services'; import { humanFileSize } from '@blocksuite/affine-shared/utils'; -import type { EditorHost } from '@blocksuite/block-std'; +import type { BlockStdScope, EditorHost } from '@blocksuite/block-std'; +import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; +import { Bound, type IVec, Point, Vec } from '@blocksuite/global/utils'; import type { BlockModel } from '@blocksuite/store'; import type { AttachmentBlockComponent } from './attachment-block.js'; @@ -251,3 +257,80 @@ export async function addSiblingAttachmentBlocks( return blockIds; } + +export async function addAttachments( + std: BlockStdScope, + files: File[], + point?: IVec +): Promise { + if (!files.length) return []; + + const attachmentService = std.getService('affine:attachment'); + const gfx = std.get(GfxControllerIdentifier); + + if (!attachmentService) { + console.error('Attachment service not found'); + return []; + } + const maxFileSize = attachmentService.maxFileSize; + const isSizeExceeded = files.some(file => file.size > maxFileSize); + if (isSizeExceeded) { + toast( + std.host, + `You can only upload files less than ${humanFileSize( + maxFileSize, + true, + 0 + )}` + ); + return []; + } + + let { x, y } = gfx.viewport.center; + if (point) [x, y] = gfx.viewport.toModelCoord(...point); + + const CARD_STACK_GAP = 32; + + const dropInfos: { blockId: string; file: File }[] = files.map( + (file, index) => { + const point = new Point( + x + index * CARD_STACK_GAP, + y + index * CARD_STACK_GAP + ); + const center = Vec.toVec(point); + const bound = Bound.fromCenter( + center, + EMBED_CARD_WIDTH.cubeThick, + EMBED_CARD_HEIGHT.cubeThick + ); + const blockId = std.doc.addBlock( + 'affine:attachment', + { + name: file.name, + size: file.size, + type: file.type, + style: 'cubeThick', + xywh: bound.serialize(), + } satisfies Partial, + gfx.surface + ); + + return { blockId, file }; + } + ); + + // upload file and update the attachment model + const uploadPromises = dropInfos.map(async ({ blockId, file }) => { + const filetype = await getFileType(file); + await uploadAttachmentBlob(std.host, blockId, file, filetype, true); + return blockId; + }); + const blockIds = await Promise.all(uploadPromises); + + gfx.selection.set({ + elements: blockIds, + editing: false, + }); + + return blockIds; +} diff --git a/blocksuite/affine/block-attachment/tsconfig.json b/blocksuite/affine/block-attachment/tsconfig.json new file mode 100644 index 0000000000..54b5d3348b --- /dev/null +++ b/blocksuite/affine/block-attachment/tsconfig.json @@ -0,0 +1,35 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src/", + "outDir": "./dist/", + "noEmit": false + }, + "include": ["./src"], + "references": [ + { + "path": "../../framework/global" + }, + { + "path": "../../framework/store" + }, + { + "path": "../../framework/block-std" + }, + { + "path": "../../framework/inline" + }, + { + "path": "../model" + }, + { + "path": "../components" + }, + { + "path": "../shared" + }, + { + "path": "../block-embed" + } + ] +} diff --git a/blocksuite/blocks/package.json b/blocksuite/blocks/package.json index 54bafdeefb..6892f262e5 100644 --- a/blocksuite/blocks/package.json +++ b/blocksuite/blocks/package.json @@ -14,6 +14,7 @@ "author": "toeverything", "license": "MIT", "dependencies": { + "@blocksuite/affine-block-attachment": "workspace:*", "@blocksuite/affine-block-bookmark": "workspace:*", "@blocksuite/affine-block-embed": "workspace:*", "@blocksuite/affine-block-list": "workspace:*", diff --git a/blocksuite/blocks/src/_common/adapters/notion-html/block-matcher.ts b/blocksuite/blocks/src/_common/adapters/notion-html/block-matcher.ts index dd63e6ef94..1e0a81db55 100644 --- a/blocksuite/blocks/src/_common/adapters/notion-html/block-matcher.ts +++ b/blocksuite/blocks/src/_common/adapters/notion-html/block-matcher.ts @@ -1,3 +1,4 @@ +import { attachmentBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-attachment'; import { bookmarkBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-bookmark'; import { embedFigmaBlockNotionHtmlAdapterMatcher, @@ -9,7 +10,6 @@ import { listBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-list import { paragraphBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-paragraph'; import type { BlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-shared/adapters'; -import { attachmentBlockNotionHtmlAdapterMatcher } from '../../../attachment-block/adapters/notion-html.js'; import { codeBlockNotionHtmlAdapterMatcher } from '../../../code-block/adapters/notion-html.js'; import { databaseBlockNotionHtmlAdapterMatcher } from '../../../database-block/adapters/notion-html.js'; import { dividerBlockNotionHtmlAdapterMatcher } from '../../../divider-block/adapters/notion-html.js'; diff --git a/blocksuite/blocks/src/_specs/common.ts b/blocksuite/blocks/src/_specs/common.ts index de39829fdf..adbdb3fd37 100644 --- a/blocksuite/blocks/src/_specs/common.ts +++ b/blocksuite/blocks/src/_specs/common.ts @@ -1,3 +1,4 @@ +import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment'; import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark'; import { EmbedExtensions } from '@blocksuite/affine-block-embed'; import { ListBlockSpec } from '@blocksuite/affine-block-list'; @@ -7,7 +8,6 @@ import { EditPropsStore } from '@blocksuite/affine-shared/services'; import type { ExtensionType } from '@blocksuite/block-std'; import { AdapterFactoryExtensions } from '../_common/adapters/extension.js'; -import { AttachmentBlockSpec } from '../attachment-block/attachment-spec.js'; import { CodeBlockSpec } from '../code-block/code-block-spec.js'; import { DataViewBlockSpec } from '../data-view-block/data-view-spec.js'; import { DatabaseBlockSpec } from '../database-block/database-spec.js'; diff --git a/blocksuite/blocks/src/_specs/group/common.ts b/blocksuite/blocks/src/_specs/group/common.ts index d70dc2ba58..1a60cb811d 100644 --- a/blocksuite/blocks/src/_specs/group/common.ts +++ b/blocksuite/blocks/src/_specs/group/common.ts @@ -1,3 +1,4 @@ +import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment'; import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark'; import { EmbedFigmaBlockSpec, @@ -11,7 +12,6 @@ import { import { ListBlockSpec } from '@blocksuite/affine-block-list'; import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph'; -import { AttachmentBlockSpec } from '../../attachment-block/attachment-spec.js'; import { CodeBlockSpec } from '../../code-block/code-block-spec.js'; import { DataViewBlockSpec } from '../../data-view-block/data-view-spec.js'; import { DatabaseBlockSpec } from '../../database-block/database-spec.js'; diff --git a/blocksuite/blocks/src/attachment-block/index.ts b/blocksuite/blocks/src/attachment-block/index.ts deleted file mode 100644 index fddf77a8c5..0000000000 --- a/blocksuite/blocks/src/attachment-block/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './attachment-block.js'; -export * from './attachment-service.js'; -export { attachmentViewToggleMenu } from './components/options.js'; -export { - type AttachmentEmbedConfig, - AttachmentEmbedConfigIdentifier, - AttachmentEmbedProvider, -} from './embed.js'; diff --git a/blocksuite/blocks/src/effects.ts b/blocksuite/blocks/src/effects.ts index ec1a1352b6..040f7db3d8 100644 --- a/blocksuite/blocks/src/effects.ts +++ b/blocksuite/blocks/src/effects.ts @@ -1,3 +1,4 @@ +import { effects as blockAttachmentEffects } from '@blocksuite/affine-block-attachment/effects'; import { effects as blockBookmarkEffects } from '@blocksuite/affine-block-bookmark/effects'; import { effects as blockEmbedEffects } from '@blocksuite/affine-block-embed/effects'; import { effects as blockListEffects } from '@blocksuite/affine-block-list/effects'; @@ -29,11 +30,6 @@ import { EmbedCardEditCaptionEditModal } from './_common/components/embed-card/m import { EmbedCardCreateModal } from './_common/components/embed-card/modal/embed-card-create-modal.js'; import { EmbedCardEditModal } from './_common/components/embed-card/modal/embed-card-edit-modal.js'; import { registerSpecs } from './_specs/register-specs.js'; -import { AttachmentEdgelessBlockComponent } from './attachment-block/attachment-edgeless-block.js'; -import { - AttachmentBlockComponent, - type AttachmentBlockService, -} from './attachment-block/index.js'; import { AffineCodeUnit } from './code-block/highlight/affine-code-unit.js'; import { CodeBlockComponent, @@ -275,6 +271,7 @@ export function effects() { stdEffects(); inlineEffects(); + blockAttachmentEffects(); blockBookmarkEffects(); blockListEffects(); blockParagraphEffects(); @@ -322,13 +319,8 @@ export function effects() { ); customElements.define('affine-edgeless-text', EdgelessTextBlockComponent); customElements.define('center-peek', CenterPeek); - customElements.define( - 'affine-edgeless-attachment', - AttachmentEdgelessBlockComponent - ); customElements.define('database-datasource-note-renderer', NoteRenderer); customElements.define('database-datasource-block-renderer', BlockRenderer); - customElements.define('affine-attachment', AttachmentBlockComponent); customElements.define('affine-latex', LatexBlockComponent); customElements.define('affine-page-root', PageRootBlockComponent); customElements.define('edgeless-note-mask', EdgelessNoteMask); @@ -594,7 +586,6 @@ declare global { interface BlockServices { 'affine:note': NoteBlockService; 'affine:page': RootService; - 'affine:attachment': AttachmentBlockService; 'affine:database': DatabaseBlockService; 'affine:image': ImageBlockService; } diff --git a/blocksuite/blocks/src/index.ts b/blocksuite/blocks/src/index.ts index ee31346ac0..6e3fe8b345 100644 --- a/blocksuite/blocks/src/index.ts +++ b/blocksuite/blocks/src/index.ts @@ -16,7 +16,6 @@ export * from './_common/test-utils/test-utils.js'; export * from './_common/transformers/index.js'; export { type AbstractEditor } from './_common/types.js'; export * from './_specs/index.js'; -export * from './attachment-block/index.js'; export * from './code-block/index.js'; export * from './data-view-block/index.js'; export * from './database-block/index.js'; @@ -49,6 +48,7 @@ export { MiniMindmapPreview, } from './surface-block/mini-mindmap/index.js'; export * from './surface-ref-block/index.js'; +export * from '@blocksuite/affine-block-attachment'; export * from '@blocksuite/affine-block-bookmark'; export * from '@blocksuite/affine-block-embed'; export * from '@blocksuite/affine-block-list'; diff --git a/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts b/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts index a31509663d..b6c70e9e2e 100644 --- a/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts +++ b/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts @@ -1,3 +1,4 @@ +import { addAttachments } from '@blocksuite/affine-block-attachment'; import { CanvasElementType, SurfaceGroupLikeModel, @@ -75,7 +76,7 @@ import { getSortedCloneElements, serializeElement, } from '../utils/clone-utils.js'; -import { addAttachments, addImages } from '../utils/common.js'; +import { addImages } from '../utils/common.js'; import { deleteElements } from '../utils/crud.js'; import { isAttachmentBlock, diff --git a/blocksuite/blocks/src/root-block/edgeless/components/toolbar/note/note-menu.ts b/blocksuite/blocks/src/root-block/edgeless/components/toolbar/note/note-menu.ts index dd1e5f5b1a..40c8ebc45a 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/toolbar/note/note-menu.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/toolbar/note/note-menu.ts @@ -1,3 +1,4 @@ +import { addAttachments } from '@blocksuite/affine-block-attachment'; import { AttachmentIcon, LinkIcon } from '@blocksuite/affine-components/icons'; import { MAX_IMAGE_WIDTH } from '@blocksuite/affine-model'; import { TelemetryProvider } from '@blocksuite/affine-shared/services'; @@ -14,7 +15,7 @@ import { } from '../../../../../_common/utils/index.js'; import { ImageIcon } from '../../../../../image-block/styles.js'; import type { NoteToolOption } from '../../../gfx-tool/note-tool.js'; -import { addAttachments, addImages } from '../../../utils/common.js'; +import { addImages } from '../../../utils/common.js'; import { getTooltipWithShortcut } from '../../utils.js'; import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js'; import { NOTE_MENU_ITEMS } from './note-menu-config.js'; diff --git a/blocksuite/blocks/src/root-block/edgeless/utils/common.ts b/blocksuite/blocks/src/root-block/edgeless/utils/common.ts index 235d226690..ec7bdafdd3 100644 --- a/blocksuite/blocks/src/root-block/edgeless/utils/common.ts +++ b/blocksuite/blocks/src/root-block/edgeless/utils/common.ts @@ -1,7 +1,6 @@ import { focusTextModel } from '@blocksuite/affine-components/rich-text'; import { toast } from '@blocksuite/affine-components/toast'; import { - type AttachmentBlockProps, DEFAULT_NOTE_HEIGHT, DEFAULT_NOTE_WIDTH, type ImageBlockProps, @@ -9,10 +8,6 @@ import { type NoteBlockModel, NoteDisplayMode, } from '@blocksuite/affine-model'; -import { - EMBED_CARD_HEIGHT, - EMBED_CARD_WIDTH, -} from '@blocksuite/affine-shared/consts'; import { TelemetryProvider } from '@blocksuite/affine-shared/services'; import type { NoteChildrenFlavour } from '@blocksuite/affine-shared/types'; import { @@ -22,7 +17,6 @@ import { import type { BlockStdScope } from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; import { - Bound, type IPoint, type IVec, Point, @@ -30,91 +24,10 @@ import { Vec, } from '@blocksuite/global/utils'; -import { - getFileType, - uploadAttachmentBlob, -} from '../../../attachment-block/utils.js'; import { calcBoundByOrigin, readImageSize } from '../components/utils.js'; import { DEFAULT_NOTE_OFFSET_X, DEFAULT_NOTE_OFFSET_Y } from './consts.js'; import { addBlock } from './crud.js'; -export async function addAttachments( - std: BlockStdScope, - files: File[], - point?: IVec -): Promise { - if (!files.length) return []; - - const attachmentService = std.getService('affine:attachment'); - const gfx = std.get(GfxControllerIdentifier); - - if (!attachmentService) { - console.error('Attachment service not found'); - return []; - } - const maxFileSize = attachmentService.maxFileSize; - const isSizeExceeded = files.some(file => file.size > maxFileSize); - if (isSizeExceeded) { - toast( - std.host, - `You can only upload files less than ${humanFileSize( - maxFileSize, - true, - 0 - )}` - ); - return []; - } - - let { x, y } = gfx.viewport.center; - if (point) [x, y] = gfx.viewport.toModelCoord(...point); - - const CARD_STACK_GAP = 32; - - const dropInfos: { blockId: string; file: File }[] = files.map( - (file, index) => { - const point = new Point( - x + index * CARD_STACK_GAP, - y + index * CARD_STACK_GAP - ); - const center = Vec.toVec(point); - const bound = Bound.fromCenter( - center, - EMBED_CARD_WIDTH.cubeThick, - EMBED_CARD_HEIGHT.cubeThick - ); - const blockId = std.doc.addBlock( - 'affine:attachment', - { - name: file.name, - size: file.size, - type: file.type, - style: 'cubeThick', - xywh: bound.serialize(), - } satisfies Partial, - gfx.surface - ); - - return { blockId, file }; - } - ); - - // upload file and update the attachment model - const uploadPromises = dropInfos.map(async ({ blockId, file }) => { - const filetype = await getFileType(file); - await uploadAttachmentBlob(std.host, blockId, file, filetype, true); - return blockId; - }); - const blockIds = await Promise.all(uploadPromises); - - gfx.selection.set({ - elements: blockIds, - editing: false, - }); - - return blockIds; -} - export async function addImages( std: BlockStdScope, files: File[], diff --git a/blocksuite/blocks/src/root-block/widgets/element-toolbar/change-attachment-button.ts b/blocksuite/blocks/src/root-block/widgets/element-toolbar/change-attachment-button.ts index 244b7f578a..88da0234df 100644 --- a/blocksuite/blocks/src/root-block/widgets/element-toolbar/change-attachment-button.ts +++ b/blocksuite/blocks/src/root-block/widgets/element-toolbar/change-attachment-button.ts @@ -1,3 +1,7 @@ +import { + type AttachmentBlockComponent, + attachmentViewToggleMenu, +} from '@blocksuite/affine-block-attachment'; import { getEmbedCardIcons } from '@blocksuite/affine-block-embed'; import { CaptionIcon, @@ -18,8 +22,6 @@ import { property } from 'lit/decorators.js'; import { join } from 'lit/directives/join.js'; import type { EmbedCardStyle } from '../../../_common/types.js'; -import type { AttachmentBlockComponent } from '../../../attachment-block/index.js'; -import { attachmentViewToggleMenu } from '../../../attachment-block/index.js'; import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js'; export class EdgelessChangeAttachmentButton extends WithDisposable(LitElement) { diff --git a/blocksuite/blocks/src/root-block/widgets/element-toolbar/more-menu/config.ts b/blocksuite/blocks/src/root-block/widgets/element-toolbar/more-menu/config.ts index 619f967b30..59bc904bcd 100644 --- a/blocksuite/blocks/src/root-block/widgets/element-toolbar/more-menu/config.ts +++ b/blocksuite/blocks/src/root-block/widgets/element-toolbar/more-menu/config.ts @@ -1,3 +1,4 @@ +import type { AttachmentBlockComponent } from '@blocksuite/affine-block-attachment'; import type { BookmarkBlockComponent } from '@blocksuite/affine-block-bookmark'; import type { EmbedFigmaBlockComponent, @@ -31,7 +32,6 @@ import { notifyDocCreated, promptDocTitle, } from '../../../../_common/utils/render-linked-doc.js'; -import type { AttachmentBlockComponent } from '../../../../attachment-block/attachment-block.js'; import type { ImageBlockComponent } from '../../../../image-block/image-block.js'; import { duplicate } from '../../../edgeless/utils/clipboard-utils.js'; import { getSortedCloneElements } from '../../../edgeless/utils/clone-utils.js'; diff --git a/blocksuite/blocks/src/root-block/widgets/keyboard-toolbar/config.ts b/blocksuite/blocks/src/root-block/widgets/keyboard-toolbar/config.ts index 3f7fafae81..e79898795d 100644 --- a/blocksuite/blocks/src/root-block/widgets/keyboard-toolbar/config.ts +++ b/blocksuite/blocks/src/root-block/widgets/keyboard-toolbar/config.ts @@ -1,3 +1,4 @@ +import { addSiblingAttachmentBlocks } from '@blocksuite/affine-block-attachment'; import { getInlineEditorByModel, insertContent, @@ -60,7 +61,6 @@ import { cssVarV2 } from '@toeverything/theme/v2'; import type { TemplateResult } from 'lit'; import { toggleEmbedCardCreateModal } from '../../../_common/components/embed-card/modal/embed-card-create-modal.js'; -import { addSiblingAttachmentBlocks } from '../../../attachment-block/utils.js'; import { getSurfaceBlock } from '../../../surface-ref-block/utils.js'; import type { PageRootBlockComponent } from '../../page/page-root-block.js'; import { formatDate, formatTime } from '../../utils/misc.js'; diff --git a/blocksuite/blocks/src/root-block/widgets/slash-menu/config.ts b/blocksuite/blocks/src/root-block/widgets/slash-menu/config.ts index 2fb9a43e88..3768e94af4 100644 --- a/blocksuite/blocks/src/root-block/widgets/slash-menu/config.ts +++ b/blocksuite/blocks/src/root-block/widgets/slash-menu/config.ts @@ -1,3 +1,4 @@ +import { addSiblingAttachmentBlocks } from '@blocksuite/affine-block-attachment'; import { FigmaIcon, GithubIcon, @@ -49,7 +50,6 @@ import type { TemplateResult } from 'lit'; import { toggleEmbedCardCreateModal } from '../../../_common/components/embed-card/modal/embed-card-create-modal.js'; import { textConversionConfigs } from '../../../_common/configs/text-conversion.js'; -import { addSiblingAttachmentBlocks } from '../../../attachment-block/utils.js'; import type { DataViewBlockComponent } from '../../../data-view-block/index.js'; import { getSurfaceBlock } from '../../../surface-ref-block/utils.js'; import type { RootBlockComponent } from '../../types.js'; diff --git a/blocksuite/blocks/tsconfig.json b/blocksuite/blocks/tsconfig.json index ff77206180..e489f45465 100644 --- a/blocksuite/blocks/tsconfig.json +++ b/blocksuite/blocks/tsconfig.json @@ -40,6 +40,9 @@ { "path": "../affine/block-bookmark" }, + { + "path": "../affine/block-attachment" + }, { "path": "../affine/data-view" }, diff --git a/tools/utils/src/workspace.gen.ts b/tools/utils/src/workspace.gen.ts index 5e7f88b16a..7664bf16bd 100644 --- a/tools/utils/src/workspace.gen.ts +++ b/tools/utils/src/workspace.gen.ts @@ -13,6 +13,20 @@ export const PackageList = [ 'blocksuite/framework/store', ], }, + { + location: 'blocksuite/affine/block-attachment', + name: '@blocksuite/affine-block-attachment', + workspaceDependencies: [ + 'blocksuite/affine/block-embed', + 'blocksuite/affine/components', + 'blocksuite/affine/model', + 'blocksuite/affine/shared', + 'blocksuite/framework/block-std', + 'blocksuite/framework/global', + 'blocksuite/framework/inline', + 'blocksuite/framework/store', + ], + }, { location: 'blocksuite/affine/block-bookmark', name: '@blocksuite/affine-block-bookmark', @@ -138,6 +152,7 @@ export const PackageList = [ location: 'blocksuite/blocks', name: '@blocksuite/blocks', workspaceDependencies: [ + 'blocksuite/affine/block-attachment', 'blocksuite/affine/block-bookmark', 'blocksuite/affine/block-embed', 'blocksuite/affine/block-list', @@ -472,6 +487,7 @@ export const PackageList = [ export type PackageName = | '@blocksuite/affine' + | '@blocksuite/affine-block-attachment' | '@blocksuite/affine-block-bookmark' | '@blocksuite/affine-block-embed' | '@blocksuite/affine-block-list' diff --git a/tsconfig.project.json b/tsconfig.project.json index 61e8105a69..8e05cf14c5 100644 --- a/tsconfig.project.json +++ b/tsconfig.project.json @@ -7,6 +7,8 @@ "include": [], "references": [ { "path": "./blocksuite/affine/all" }, + { "path": "./blocksuite/affine/block-attachment" }, + { "path": "./blocksuite/affine/block-bookmark" }, { "path": "./blocksuite/affine/block-embed" }, { "path": "./blocksuite/affine/block-list" }, { "path": "./blocksuite/affine/block-paragraph" }, diff --git a/yarn.lock b/yarn.lock index b7738d159e..7168e59d4b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3224,6 +3224,30 @@ __metadata: languageName: node linkType: hard +"@blocksuite/affine-block-attachment@workspace:*, @blocksuite/affine-block-attachment@workspace:blocksuite/affine/block-attachment": + version: 0.0.0-use.local + resolution: "@blocksuite/affine-block-attachment@workspace:blocksuite/affine/block-attachment" + dependencies: + "@blocksuite/affine-block-embed": "workspace:*" + "@blocksuite/affine-components": "workspace:*" + "@blocksuite/affine-model": "workspace:*" + "@blocksuite/affine-shared": "workspace:*" + "@blocksuite/block-std": "workspace:*" + "@blocksuite/global": "workspace:*" + "@blocksuite/icons": "npm:^2.1.75" + "@blocksuite/inline": "workspace:*" + "@blocksuite/store": "workspace:*" + "@floating-ui/dom": "npm:^1.6.10" + "@lit/context": "npm:^1.1.2" + "@preact/signals-core": "npm:^1.8.0" + "@toeverything/theme": "npm:^1.1.1" + file-type: "npm:^19.5.0" + lit: "npm:^3.2.0" + minimatch: "npm:^10.0.1" + zod: "npm:^3.23.8" + languageName: unknown + linkType: soft + "@blocksuite/affine-block-bookmark@workspace:*, @blocksuite/affine-block-bookmark@workspace:blocksuite/affine/block-bookmark": version: 0.0.0-use.local resolution: "@blocksuite/affine-block-bookmark@workspace:blocksuite/affine/block-bookmark" @@ -3458,6 +3482,7 @@ __metadata: version: 0.0.0-use.local resolution: "@blocksuite/blocks@workspace:blocksuite/blocks" dependencies: + "@blocksuite/affine-block-attachment": "workspace:*" "@blocksuite/affine-block-bookmark": "workspace:*" "@blocksuite/affine-block-embed": "workspace:*" "@blocksuite/affine-block-list": "workspace:*"