mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 14:27:02 +08:00
refactor(editor): extract attachment block (#9308)
This commit is contained in:
44
blocksuite/affine/block-attachment/package.json
Normal file
44
blocksuite/affine/block-attachment/package.json
Normal file
@@ -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__"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -4,10 +4,10 @@ import {
|
|||||||
EMBED_CARD_HEIGHT,
|
EMBED_CARD_HEIGHT,
|
||||||
EMBED_CARD_WIDTH,
|
EMBED_CARD_WIDTH,
|
||||||
} from '@blocksuite/affine-shared/consts';
|
} 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 { styleMap } from 'lit/directives/style-map.js';
|
||||||
|
|
||||||
import type { EdgelessRootService } from '../root-block/index.js';
|
|
||||||
import { AttachmentBlockComponent } from './attachment-block.js';
|
import { AttachmentBlockComponent } from './attachment-block.js';
|
||||||
|
|
||||||
export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent(
|
export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent(
|
||||||
@@ -17,15 +17,20 @@ export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent(
|
|||||||
|
|
||||||
override blockDraggable = false;
|
override blockDraggable = false;
|
||||||
|
|
||||||
get rootService() {
|
get rootService(): null | (BlockService & { slots: Record<string, Slot> }) {
|
||||||
return this.std.getService('affine:page') as EdgelessRootService;
|
return this.std.getService('affine:page');
|
||||||
}
|
}
|
||||||
|
|
||||||
override connectedCallback(): void {
|
override connectedCallback(): void {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
|
|
||||||
const rootService = this.rootService;
|
const rootService = this.rootService;
|
||||||
|
if (!rootService) {
|
||||||
|
console.warn('rootService is not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: move root service slots to extension
|
||||||
this._disposables.add(
|
this._disposables.add(
|
||||||
rootService.slots.elementResizeStart.on(() => {
|
rootService.slots.elementResizeStart.on(() => {
|
||||||
this._isResizing = true;
|
this._isResizing = true;
|
||||||
@@ -33,6 +38,7 @@ export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: move root service slots to extension
|
||||||
this._disposables.add(
|
this._disposables.add(
|
||||||
rootService.slots.elementResizeEnd.on(() => {
|
rootService.slots.elementResizeEnd.on(() => {
|
||||||
this._isResizing = false;
|
this._isResizing = false;
|
||||||
@@ -8,8 +8,7 @@ import {
|
|||||||
import { BlockService } from '@blocksuite/block-std';
|
import { BlockService } from '@blocksuite/block-std';
|
||||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||||
|
|
||||||
import { addAttachments } from '../root-block/edgeless/utils/common.js';
|
import { addAttachments, addSiblingAttachmentBlocks } from './utils.js';
|
||||||
import { addSiblingAttachmentBlocks } from './utils.js';
|
|
||||||
|
|
||||||
// bytes.parse('2GB')
|
// bytes.parse('2GB')
|
||||||
const maxFileSize = 2147483648;
|
const maxFileSize = 2147483648;
|
||||||
@@ -30,7 +29,10 @@ export const AttachmentDropOption = FileDropConfigExtension({
|
|||||||
|
|
||||||
if (!attachmentFiles.length) return false;
|
if (!attachmentFiles.length) return false;
|
||||||
|
|
||||||
if (targetModel && !matchFlavours(targetModel, ['affine:surface'])) {
|
if (
|
||||||
|
targetModel &&
|
||||||
|
!matchFlavours(targetModel, ['affine:surface' as BlockSuite.Flavour])
|
||||||
|
) {
|
||||||
addSiblingAttachmentBlocks(
|
addSiblingAttachmentBlocks(
|
||||||
std.host,
|
std.host,
|
||||||
attachmentFiles,
|
attachmentFiles,
|
||||||
19
blocksuite/affine/block-attachment/src/effects.ts
Normal file
19
blocksuite/affine/block-attachment/src/effects.ts
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
blocksuite/affine/block-attachment/src/index.ts
Normal file
11
blocksuite/affine/block-attachment/src/index.ts
Normal file
@@ -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';
|
||||||
@@ -4,9 +4,15 @@ import type {
|
|||||||
AttachmentBlockProps,
|
AttachmentBlockProps,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import { defaultAttachmentProps } 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 { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
||||||
import { humanFileSize } from '@blocksuite/affine-shared/utils';
|
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 { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
import type { AttachmentBlockComponent } from './attachment-block.js';
|
import type { AttachmentBlockComponent } from './attachment-block.js';
|
||||||
@@ -251,3 +257,80 @@ export async function addSiblingAttachmentBlocks(
|
|||||||
|
|
||||||
return blockIds;
|
return blockIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function addAttachments(
|
||||||
|
std: BlockStdScope,
|
||||||
|
files: File[],
|
||||||
|
point?: IVec
|
||||||
|
): Promise<string[]> {
|
||||||
|
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<AttachmentBlockProps>,
|
||||||
|
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;
|
||||||
|
}
|
||||||
35
blocksuite/affine/block-attachment/tsconfig.json
Normal file
35
blocksuite/affine/block-attachment/tsconfig.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
"author": "toeverything",
|
"author": "toeverything",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@blocksuite/affine-block-attachment": "workspace:*",
|
||||||
"@blocksuite/affine-block-bookmark": "workspace:*",
|
"@blocksuite/affine-block-bookmark": "workspace:*",
|
||||||
"@blocksuite/affine-block-embed": "workspace:*",
|
"@blocksuite/affine-block-embed": "workspace:*",
|
||||||
"@blocksuite/affine-block-list": "workspace:*",
|
"@blocksuite/affine-block-list": "workspace:*",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { attachmentBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-attachment';
|
||||||
import { bookmarkBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-bookmark';
|
import { bookmarkBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-bookmark';
|
||||||
import {
|
import {
|
||||||
embedFigmaBlockNotionHtmlAdapterMatcher,
|
embedFigmaBlockNotionHtmlAdapterMatcher,
|
||||||
@@ -9,7 +10,6 @@ import { listBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-list
|
|||||||
import { paragraphBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-paragraph';
|
import { paragraphBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-paragraph';
|
||||||
import type { BlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-shared/adapters';
|
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 { codeBlockNotionHtmlAdapterMatcher } from '../../../code-block/adapters/notion-html.js';
|
||||||
import { databaseBlockNotionHtmlAdapterMatcher } from '../../../database-block/adapters/notion-html.js';
|
import { databaseBlockNotionHtmlAdapterMatcher } from '../../../database-block/adapters/notion-html.js';
|
||||||
import { dividerBlockNotionHtmlAdapterMatcher } from '../../../divider-block/adapters/notion-html.js';
|
import { dividerBlockNotionHtmlAdapterMatcher } from '../../../divider-block/adapters/notion-html.js';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment';
|
||||||
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
|
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
|
||||||
import { EmbedExtensions } from '@blocksuite/affine-block-embed';
|
import { EmbedExtensions } from '@blocksuite/affine-block-embed';
|
||||||
import { ListBlockSpec } from '@blocksuite/affine-block-list';
|
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 type { ExtensionType } from '@blocksuite/block-std';
|
||||||
|
|
||||||
import { AdapterFactoryExtensions } from '../_common/adapters/extension.js';
|
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 { CodeBlockSpec } from '../code-block/code-block-spec.js';
|
||||||
import { DataViewBlockSpec } from '../data-view-block/data-view-spec.js';
|
import { DataViewBlockSpec } from '../data-view-block/data-view-spec.js';
|
||||||
import { DatabaseBlockSpec } from '../database-block/database-spec.js';
|
import { DatabaseBlockSpec } from '../database-block/database-spec.js';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment';
|
||||||
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
|
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
|
||||||
import {
|
import {
|
||||||
EmbedFigmaBlockSpec,
|
EmbedFigmaBlockSpec,
|
||||||
@@ -11,7 +12,6 @@ import {
|
|||||||
import { ListBlockSpec } from '@blocksuite/affine-block-list';
|
import { ListBlockSpec } from '@blocksuite/affine-block-list';
|
||||||
import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph';
|
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 { CodeBlockSpec } from '../../code-block/code-block-spec.js';
|
||||||
import { DataViewBlockSpec } from '../../data-view-block/data-view-spec.js';
|
import { DataViewBlockSpec } from '../../data-view-block/data-view-spec.js';
|
||||||
import { DatabaseBlockSpec } from '../../database-block/database-spec.js';
|
import { DatabaseBlockSpec } from '../../database-block/database-spec.js';
|
||||||
|
|||||||
@@ -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';
|
|
||||||
@@ -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 blockBookmarkEffects } from '@blocksuite/affine-block-bookmark/effects';
|
||||||
import { effects as blockEmbedEffects } from '@blocksuite/affine-block-embed/effects';
|
import { effects as blockEmbedEffects } from '@blocksuite/affine-block-embed/effects';
|
||||||
import { effects as blockListEffects } from '@blocksuite/affine-block-list/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 { 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 { EmbedCardEditModal } from './_common/components/embed-card/modal/embed-card-edit-modal.js';
|
||||||
import { registerSpecs } from './_specs/register-specs.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 { AffineCodeUnit } from './code-block/highlight/affine-code-unit.js';
|
||||||
import {
|
import {
|
||||||
CodeBlockComponent,
|
CodeBlockComponent,
|
||||||
@@ -275,6 +271,7 @@ export function effects() {
|
|||||||
stdEffects();
|
stdEffects();
|
||||||
inlineEffects();
|
inlineEffects();
|
||||||
|
|
||||||
|
blockAttachmentEffects();
|
||||||
blockBookmarkEffects();
|
blockBookmarkEffects();
|
||||||
blockListEffects();
|
blockListEffects();
|
||||||
blockParagraphEffects();
|
blockParagraphEffects();
|
||||||
@@ -322,13 +319,8 @@ export function effects() {
|
|||||||
);
|
);
|
||||||
customElements.define('affine-edgeless-text', EdgelessTextBlockComponent);
|
customElements.define('affine-edgeless-text', EdgelessTextBlockComponent);
|
||||||
customElements.define('center-peek', CenterPeek);
|
customElements.define('center-peek', CenterPeek);
|
||||||
customElements.define(
|
|
||||||
'affine-edgeless-attachment',
|
|
||||||
AttachmentEdgelessBlockComponent
|
|
||||||
);
|
|
||||||
customElements.define('database-datasource-note-renderer', NoteRenderer);
|
customElements.define('database-datasource-note-renderer', NoteRenderer);
|
||||||
customElements.define('database-datasource-block-renderer', BlockRenderer);
|
customElements.define('database-datasource-block-renderer', BlockRenderer);
|
||||||
customElements.define('affine-attachment', AttachmentBlockComponent);
|
|
||||||
customElements.define('affine-latex', LatexBlockComponent);
|
customElements.define('affine-latex', LatexBlockComponent);
|
||||||
customElements.define('affine-page-root', PageRootBlockComponent);
|
customElements.define('affine-page-root', PageRootBlockComponent);
|
||||||
customElements.define('edgeless-note-mask', EdgelessNoteMask);
|
customElements.define('edgeless-note-mask', EdgelessNoteMask);
|
||||||
@@ -594,7 +586,6 @@ declare global {
|
|||||||
interface BlockServices {
|
interface BlockServices {
|
||||||
'affine:note': NoteBlockService;
|
'affine:note': NoteBlockService;
|
||||||
'affine:page': RootService;
|
'affine:page': RootService;
|
||||||
'affine:attachment': AttachmentBlockService;
|
|
||||||
'affine:database': DatabaseBlockService;
|
'affine:database': DatabaseBlockService;
|
||||||
'affine:image': ImageBlockService;
|
'affine:image': ImageBlockService;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ export * from './_common/test-utils/test-utils.js';
|
|||||||
export * from './_common/transformers/index.js';
|
export * from './_common/transformers/index.js';
|
||||||
export { type AbstractEditor } from './_common/types.js';
|
export { type AbstractEditor } from './_common/types.js';
|
||||||
export * from './_specs/index.js';
|
export * from './_specs/index.js';
|
||||||
export * from './attachment-block/index.js';
|
|
||||||
export * from './code-block/index.js';
|
export * from './code-block/index.js';
|
||||||
export * from './data-view-block/index.js';
|
export * from './data-view-block/index.js';
|
||||||
export * from './database-block/index.js';
|
export * from './database-block/index.js';
|
||||||
@@ -49,6 +48,7 @@ export {
|
|||||||
MiniMindmapPreview,
|
MiniMindmapPreview,
|
||||||
} from './surface-block/mini-mindmap/index.js';
|
} from './surface-block/mini-mindmap/index.js';
|
||||||
export * from './surface-ref-block/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-bookmark';
|
||||||
export * from '@blocksuite/affine-block-embed';
|
export * from '@blocksuite/affine-block-embed';
|
||||||
export * from '@blocksuite/affine-block-list';
|
export * from '@blocksuite/affine-block-list';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { addAttachments } from '@blocksuite/affine-block-attachment';
|
||||||
import {
|
import {
|
||||||
CanvasElementType,
|
CanvasElementType,
|
||||||
SurfaceGroupLikeModel,
|
SurfaceGroupLikeModel,
|
||||||
@@ -75,7 +76,7 @@ import {
|
|||||||
getSortedCloneElements,
|
getSortedCloneElements,
|
||||||
serializeElement,
|
serializeElement,
|
||||||
} from '../utils/clone-utils.js';
|
} 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 { deleteElements } from '../utils/crud.js';
|
||||||
import {
|
import {
|
||||||
isAttachmentBlock,
|
isAttachmentBlock,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { addAttachments } from '@blocksuite/affine-block-attachment';
|
||||||
import { AttachmentIcon, LinkIcon } from '@blocksuite/affine-components/icons';
|
import { AttachmentIcon, LinkIcon } from '@blocksuite/affine-components/icons';
|
||||||
import { MAX_IMAGE_WIDTH } from '@blocksuite/affine-model';
|
import { MAX_IMAGE_WIDTH } from '@blocksuite/affine-model';
|
||||||
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
||||||
@@ -14,7 +15,7 @@ import {
|
|||||||
} from '../../../../../_common/utils/index.js';
|
} from '../../../../../_common/utils/index.js';
|
||||||
import { ImageIcon } from '../../../../../image-block/styles.js';
|
import { ImageIcon } from '../../../../../image-block/styles.js';
|
||||||
import type { NoteToolOption } from '../../../gfx-tool/note-tool.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 { getTooltipWithShortcut } from '../../utils.js';
|
||||||
import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js';
|
import { EdgelessToolbarToolMixin } from '../mixins/tool.mixin.js';
|
||||||
import { NOTE_MENU_ITEMS } from './note-menu-config.js';
|
import { NOTE_MENU_ITEMS } from './note-menu-config.js';
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
|
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
|
||||||
import { toast } from '@blocksuite/affine-components/toast';
|
import { toast } from '@blocksuite/affine-components/toast';
|
||||||
import {
|
import {
|
||||||
type AttachmentBlockProps,
|
|
||||||
DEFAULT_NOTE_HEIGHT,
|
DEFAULT_NOTE_HEIGHT,
|
||||||
DEFAULT_NOTE_WIDTH,
|
DEFAULT_NOTE_WIDTH,
|
||||||
type ImageBlockProps,
|
type ImageBlockProps,
|
||||||
@@ -9,10 +8,6 @@ import {
|
|||||||
type NoteBlockModel,
|
type NoteBlockModel,
|
||||||
NoteDisplayMode,
|
NoteDisplayMode,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import {
|
|
||||||
EMBED_CARD_HEIGHT,
|
|
||||||
EMBED_CARD_WIDTH,
|
|
||||||
} from '@blocksuite/affine-shared/consts';
|
|
||||||
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
||||||
import type { NoteChildrenFlavour } from '@blocksuite/affine-shared/types';
|
import type { NoteChildrenFlavour } from '@blocksuite/affine-shared/types';
|
||||||
import {
|
import {
|
||||||
@@ -22,7 +17,6 @@ import {
|
|||||||
import type { BlockStdScope } from '@blocksuite/block-std';
|
import type { BlockStdScope } from '@blocksuite/block-std';
|
||||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||||
import {
|
import {
|
||||||
Bound,
|
|
||||||
type IPoint,
|
type IPoint,
|
||||||
type IVec,
|
type IVec,
|
||||||
Point,
|
Point,
|
||||||
@@ -30,91 +24,10 @@ import {
|
|||||||
Vec,
|
Vec,
|
||||||
} from '@blocksuite/global/utils';
|
} from '@blocksuite/global/utils';
|
||||||
|
|
||||||
import {
|
|
||||||
getFileType,
|
|
||||||
uploadAttachmentBlob,
|
|
||||||
} from '../../../attachment-block/utils.js';
|
|
||||||
import { calcBoundByOrigin, readImageSize } from '../components/utils.js';
|
import { calcBoundByOrigin, readImageSize } from '../components/utils.js';
|
||||||
import { DEFAULT_NOTE_OFFSET_X, DEFAULT_NOTE_OFFSET_Y } from './consts.js';
|
import { DEFAULT_NOTE_OFFSET_X, DEFAULT_NOTE_OFFSET_Y } from './consts.js';
|
||||||
import { addBlock } from './crud.js';
|
import { addBlock } from './crud.js';
|
||||||
|
|
||||||
export async function addAttachments(
|
|
||||||
std: BlockStdScope,
|
|
||||||
files: File[],
|
|
||||||
point?: IVec
|
|
||||||
): Promise<string[]> {
|
|
||||||
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<AttachmentBlockProps>,
|
|
||||||
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(
|
export async function addImages(
|
||||||
std: BlockStdScope,
|
std: BlockStdScope,
|
||||||
files: File[],
|
files: File[],
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
import {
|
||||||
|
type AttachmentBlockComponent,
|
||||||
|
attachmentViewToggleMenu,
|
||||||
|
} from '@blocksuite/affine-block-attachment';
|
||||||
import { getEmbedCardIcons } from '@blocksuite/affine-block-embed';
|
import { getEmbedCardIcons } from '@blocksuite/affine-block-embed';
|
||||||
import {
|
import {
|
||||||
CaptionIcon,
|
CaptionIcon,
|
||||||
@@ -18,8 +22,6 @@ import { property } from 'lit/decorators.js';
|
|||||||
import { join } from 'lit/directives/join.js';
|
import { join } from 'lit/directives/join.js';
|
||||||
|
|
||||||
import type { EmbedCardStyle } from '../../../_common/types.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';
|
import type { EdgelessRootBlockComponent } from '../../edgeless/edgeless-root-block.js';
|
||||||
|
|
||||||
export class EdgelessChangeAttachmentButton extends WithDisposable(LitElement) {
|
export class EdgelessChangeAttachmentButton extends WithDisposable(LitElement) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { AttachmentBlockComponent } from '@blocksuite/affine-block-attachment';
|
||||||
import type { BookmarkBlockComponent } from '@blocksuite/affine-block-bookmark';
|
import type { BookmarkBlockComponent } from '@blocksuite/affine-block-bookmark';
|
||||||
import type {
|
import type {
|
||||||
EmbedFigmaBlockComponent,
|
EmbedFigmaBlockComponent,
|
||||||
@@ -31,7 +32,6 @@ import {
|
|||||||
notifyDocCreated,
|
notifyDocCreated,
|
||||||
promptDocTitle,
|
promptDocTitle,
|
||||||
} from '../../../../_common/utils/render-linked-doc.js';
|
} 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 type { ImageBlockComponent } from '../../../../image-block/image-block.js';
|
||||||
import { duplicate } from '../../../edgeless/utils/clipboard-utils.js';
|
import { duplicate } from '../../../edgeless/utils/clipboard-utils.js';
|
||||||
import { getSortedCloneElements } from '../../../edgeless/utils/clone-utils.js';
|
import { getSortedCloneElements } from '../../../edgeless/utils/clone-utils.js';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { addSiblingAttachmentBlocks } from '@blocksuite/affine-block-attachment';
|
||||||
import {
|
import {
|
||||||
getInlineEditorByModel,
|
getInlineEditorByModel,
|
||||||
insertContent,
|
insertContent,
|
||||||
@@ -60,7 +61,6 @@ import { cssVarV2 } from '@toeverything/theme/v2';
|
|||||||
import type { TemplateResult } from 'lit';
|
import type { TemplateResult } from 'lit';
|
||||||
|
|
||||||
import { toggleEmbedCardCreateModal } from '../../../_common/components/embed-card/modal/embed-card-create-modal.js';
|
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 { getSurfaceBlock } from '../../../surface-ref-block/utils.js';
|
||||||
import type { PageRootBlockComponent } from '../../page/page-root-block.js';
|
import type { PageRootBlockComponent } from '../../page/page-root-block.js';
|
||||||
import { formatDate, formatTime } from '../../utils/misc.js';
|
import { formatDate, formatTime } from '../../utils/misc.js';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { addSiblingAttachmentBlocks } from '@blocksuite/affine-block-attachment';
|
||||||
import {
|
import {
|
||||||
FigmaIcon,
|
FigmaIcon,
|
||||||
GithubIcon,
|
GithubIcon,
|
||||||
@@ -49,7 +50,6 @@ import type { TemplateResult } from 'lit';
|
|||||||
|
|
||||||
import { toggleEmbedCardCreateModal } from '../../../_common/components/embed-card/modal/embed-card-create-modal.js';
|
import { toggleEmbedCardCreateModal } from '../../../_common/components/embed-card/modal/embed-card-create-modal.js';
|
||||||
import { textConversionConfigs } from '../../../_common/configs/text-conversion.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 type { DataViewBlockComponent } from '../../../data-view-block/index.js';
|
||||||
import { getSurfaceBlock } from '../../../surface-ref-block/utils.js';
|
import { getSurfaceBlock } from '../../../surface-ref-block/utils.js';
|
||||||
import type { RootBlockComponent } from '../../types.js';
|
import type { RootBlockComponent } from '../../types.js';
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
{
|
{
|
||||||
"path": "../affine/block-bookmark"
|
"path": "../affine/block-bookmark"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "../affine/block-attachment"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "../affine/data-view"
|
"path": "../affine/data-view"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,6 +13,20 @@ export const PackageList = [
|
|||||||
'blocksuite/framework/store',
|
'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',
|
location: 'blocksuite/affine/block-bookmark',
|
||||||
name: '@blocksuite/affine-block-bookmark',
|
name: '@blocksuite/affine-block-bookmark',
|
||||||
@@ -138,6 +152,7 @@ export const PackageList = [
|
|||||||
location: 'blocksuite/blocks',
|
location: 'blocksuite/blocks',
|
||||||
name: '@blocksuite/blocks',
|
name: '@blocksuite/blocks',
|
||||||
workspaceDependencies: [
|
workspaceDependencies: [
|
||||||
|
'blocksuite/affine/block-attachment',
|
||||||
'blocksuite/affine/block-bookmark',
|
'blocksuite/affine/block-bookmark',
|
||||||
'blocksuite/affine/block-embed',
|
'blocksuite/affine/block-embed',
|
||||||
'blocksuite/affine/block-list',
|
'blocksuite/affine/block-list',
|
||||||
@@ -472,6 +487,7 @@ export const PackageList = [
|
|||||||
|
|
||||||
export type PackageName =
|
export type PackageName =
|
||||||
| '@blocksuite/affine'
|
| '@blocksuite/affine'
|
||||||
|
| '@blocksuite/affine-block-attachment'
|
||||||
| '@blocksuite/affine-block-bookmark'
|
| '@blocksuite/affine-block-bookmark'
|
||||||
| '@blocksuite/affine-block-embed'
|
| '@blocksuite/affine-block-embed'
|
||||||
| '@blocksuite/affine-block-list'
|
| '@blocksuite/affine-block-list'
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
"include": [],
|
"include": [],
|
||||||
"references": [
|
"references": [
|
||||||
{ "path": "./blocksuite/affine/all" },
|
{ "path": "./blocksuite/affine/all" },
|
||||||
|
{ "path": "./blocksuite/affine/block-attachment" },
|
||||||
|
{ "path": "./blocksuite/affine/block-bookmark" },
|
||||||
{ "path": "./blocksuite/affine/block-embed" },
|
{ "path": "./blocksuite/affine/block-embed" },
|
||||||
{ "path": "./blocksuite/affine/block-list" },
|
{ "path": "./blocksuite/affine/block-list" },
|
||||||
{ "path": "./blocksuite/affine/block-paragraph" },
|
{ "path": "./blocksuite/affine/block-paragraph" },
|
||||||
|
|||||||
25
yarn.lock
25
yarn.lock
@@ -3224,6 +3224,30 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
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":
|
"@blocksuite/affine-block-bookmark@workspace:*, @blocksuite/affine-block-bookmark@workspace:blocksuite/affine/block-bookmark":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@blocksuite/affine-block-bookmark@workspace:blocksuite/affine/block-bookmark"
|
resolution: "@blocksuite/affine-block-bookmark@workspace:blocksuite/affine/block-bookmark"
|
||||||
@@ -3458,6 +3482,7 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@blocksuite/blocks@workspace:blocksuite/blocks"
|
resolution: "@blocksuite/blocks@workspace:blocksuite/blocks"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@blocksuite/affine-block-attachment": "workspace:*"
|
||||||
"@blocksuite/affine-block-bookmark": "workspace:*"
|
"@blocksuite/affine-block-bookmark": "workspace:*"
|
||||||
"@blocksuite/affine-block-embed": "workspace:*"
|
"@blocksuite/affine-block-embed": "workspace:*"
|
||||||
"@blocksuite/affine-block-list": "workspace:*"
|
"@blocksuite/affine-block-list": "workspace:*"
|
||||||
|
|||||||
Reference in New Issue
Block a user