diff --git a/blocksuite/affine/all/src/__tests__/adapters/notion-text.unit.spec.ts b/blocksuite/affine/all/src/__tests__/adapters/notion-text.unit.spec.ts index 17bf524166..f998133522 100644 --- a/blocksuite/affine/all/src/__tests__/adapters/notion-text.unit.spec.ts +++ b/blocksuite/affine/all/src/__tests__/adapters/notion-text.unit.spec.ts @@ -7,7 +7,7 @@ import { createJob } from '../utils/create-job.js'; import { getProvider } from '../utils/get-provider.js'; import { nanoidReplacement } from '../utils/nanoid-replacement.js'; -getProvider(); +const provider = getProvider(); describe('notion-text to snapshot', () => { test('basic', () => { @@ -98,7 +98,7 @@ describe('notion-text to snapshot', () => { pageId: '', }; - const ntAdapter = new NotionTextAdapter(createJob()); + const ntAdapter = new NotionTextAdapter(createJob(), provider); const target = ntAdapter.toSliceSnapshot({ file: notionText, workspaceId: '', diff --git a/blocksuite/affine/blocks/block-root/src/clipboard/page-clipboard.ts b/blocksuite/affine/blocks/block-root/src/clipboard/page-clipboard.ts index 57a4afe77a..3f5c336c7e 100644 --- a/blocksuite/affine/blocks/block-root/src/clipboard/page-clipboard.ts +++ b/blocksuite/affine/blocks/block-root/src/clipboard/page-clipboard.ts @@ -165,5 +165,3 @@ export class PageClipboard extends ReadOnlyClipboard { } } } - -export { pasteMiddleware }; diff --git a/blocksuite/affine/blocks/block-root/src/clipboard/readonly-clipboard.ts b/blocksuite/affine/blocks/block-root/src/clipboard/readonly-clipboard.ts index e69da3daaf..3fbf46392c 100644 --- a/blocksuite/affine/blocks/block-root/src/clipboard/readonly-clipboard.ts +++ b/blocksuite/affine/blocks/block-root/src/clipboard/readonly-clipboard.ts @@ -1,6 +1,7 @@ import { defaultImageProxyMiddleware } from '@blocksuite/affine-block-image'; import { AttachmentAdapter, + ClipboardAdapter, copyMiddleware, HtmlAdapter, ImageAdapter, @@ -16,8 +17,6 @@ import { import type { BlockComponent, UIEventHandler } from '@blocksuite/block-std'; import { DisposableGroup } from '@blocksuite/global/disposable'; -import { ClipboardAdapter } from './adapter.js'; - /** * ReadOnlyClipboard is a class that provides a read-only clipboard for the root block. * It is supported to copy models in the root block. diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/clipboard/clipboard.ts b/blocksuite/affine/blocks/block-root/src/edgeless/clipboard/clipboard.ts index b72f2fa35a..8da2887eef 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/clipboard/clipboard.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/clipboard/clipboard.ts @@ -19,6 +19,11 @@ import { FrameBlockModel, MAX_IMAGE_WIDTH, } from '@blocksuite/affine-model'; +import { + ClipboardAdapter, + decodeClipboardBlobs, + encodeClipboardBlobs, +} from '@blocksuite/affine-shared/adapters'; import { CANVAS_EXPORT_IGNORE_TAGS, EMBED_CARD_HEIGHT, @@ -72,12 +77,7 @@ import { import DOMPurify from 'dompurify'; import * as Y from 'yjs'; -import { ClipboardAdapter } from '../../clipboard/adapter.js'; import { PageClipboard } from '../../clipboard/index.js'; -import { - decodeClipboardBlobs, - encodeClipboardBlobs, -} from '../../clipboard/utils.js'; import { edgelessElementsBoundFromRawData } from '../utils/bound-utils.js'; import { createNewPresentationIndexes } from '../utils/clipboard-utils.js'; import { diff --git a/blocksuite/affine/shared/src/adapters/attachment.ts b/blocksuite/affine/shared/src/adapters/attachment.ts index cc2f1d88ea..2be93c7b12 100644 --- a/blocksuite/affine/shared/src/adapters/attachment.ts +++ b/blocksuite/affine/shared/src/adapters/attachment.ts @@ -131,8 +131,8 @@ export const AttachmentAdapterFactoryIdentifier = export const AttachmentAdapterFactoryExtension: ExtensionType = { setup: di => { - di.addImpl(AttachmentAdapterFactoryIdentifier, () => ({ - get: (job: Transformer) => new AttachmentAdapter(job), + di.addImpl(AttachmentAdapterFactoryIdentifier, provider => ({ + get: (job: Transformer) => new AttachmentAdapter(job, provider), })); }, }; diff --git a/blocksuite/affine/blocks/block-root/src/clipboard/adapter.ts b/blocksuite/affine/shared/src/adapters/clipboard/clipboard.ts similarity index 88% rename from blocksuite/affine/blocks/block-root/src/clipboard/adapter.ts rename to blocksuite/affine/shared/src/adapters/clipboard/clipboard.ts index f7ec271205..57b594b145 100644 --- a/blocksuite/affine/blocks/block-root/src/clipboard/adapter.ts +++ b/blocksuite/affine/shared/src/adapters/clipboard/clipboard.ts @@ -15,6 +15,7 @@ import type { } from '@blocksuite/store'; import { BaseAdapter } from '@blocksuite/store'; +import { NotificationProvider } from '../../services/notification-service.js'; import { decodeClipboardBlobs, encodeClipboardBlobs } from './utils.js'; export type FileSnapshot = { @@ -26,6 +27,13 @@ export type FileSnapshot = { export class ClipboardAdapter extends BaseAdapter { static MIME = 'BLOCKSUITE/SNAPSHOT'; + private readonly _onError = (message: string) => { + const notification = this.provider.getOptional(NotificationProvider); + if (!notification) return; + + notification.toast(message); + }; + override fromBlockSnapshot( _payload: FromBlockSnapshotPayload ): Promise> { @@ -56,7 +64,10 @@ export class ClipboardAdapter extends BaseAdapter { ); } const map = assets.getAssets(); - const blobs: Record = await encodeClipboardBlobs(map); + const blobs: Record = await encodeClipboardBlobs( + map, + this._onError + ); return { file: JSON.stringify({ snapshot, diff --git a/blocksuite/affine/shared/src/adapters/clipboard/index.ts b/blocksuite/affine/shared/src/adapters/clipboard/index.ts new file mode 100644 index 0000000000..f0d5f97452 --- /dev/null +++ b/blocksuite/affine/shared/src/adapters/clipboard/index.ts @@ -0,0 +1,2 @@ +export * from './clipboard'; +export * from './utils'; diff --git a/blocksuite/affine/blocks/block-root/src/clipboard/utils.ts b/blocksuite/affine/shared/src/adapters/clipboard/utils.ts similarity index 84% rename from blocksuite/affine/blocks/block-root/src/clipboard/utils.ts rename to blocksuite/affine/shared/src/adapters/clipboard/utils.ts index 5fb4fad4e4..c56d15b4c8 100644 --- a/blocksuite/affine/blocks/block-root/src/clipboard/utils.ts +++ b/blocksuite/affine/shared/src/adapters/clipboard/utils.ts @@ -1,6 +1,4 @@ -import { toast } from '@blocksuite/affine-components/toast'; - -import type { FileSnapshot } from './adapter.js'; +import type { FileSnapshot } from './clipboard.js'; const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; @@ -67,30 +65,21 @@ export const decode = (base64: string): ArrayBuffer => { return arraybuffer; }; -export async function encodeClipboardBlobs(map: Map) { +export async function encodeClipboardBlobs( + map: Map, + onError?: (message: string) => void +) { const blobs: Record = {}; let sumSize = 0; await Promise.all( Array.from(map.entries()).map(async ([id, blob]) => { if (blob.size > 4 * 1024 * 1024) { - const host = document.querySelector('editor-host'); - if (!host) { - return; - } - toast( - host, - (blob as File).name ?? 'File' + ' is too large to be copied' - ); + onError?.((blob as File).name ?? 'File' + ' is too large to be copied'); return; } sumSize += blob.size; if (sumSize > 6 * 1024 * 1024) { - const host = document.querySelector('editor-host'); - if (!host) { - return; - } - toast( - host, + onError?.( (blob as File).name ?? 'File' + ' cannot be copied due to the clipboard size limit' ); diff --git a/blocksuite/affine/shared/src/adapters/html/html.ts b/blocksuite/affine/shared/src/adapters/html/html.ts index 49a4bb393b..3a3b61da05 100644 --- a/blocksuite/affine/shared/src/adapters/html/html.ts +++ b/blocksuite/affine/shared/src/adapters/html/html.ts @@ -174,11 +174,8 @@ export class HtmlAdapter extends BaseAdapter { readonly blockMatchers: BlockHtmlAdapterMatcher[]; - constructor( - job: Transformer, - readonly provider: ServiceProvider - ) { - super(job); + constructor(job: Transformer, provider: ServiceProvider) { + super(job, provider); const blockMatchers = Array.from( provider.getAll(BlockHtmlAdapterMatcherIdentifier).values() ); diff --git a/blocksuite/affine/shared/src/adapters/image.ts b/blocksuite/affine/shared/src/adapters/image.ts index 73997b1b4a..885a636b10 100644 --- a/blocksuite/affine/shared/src/adapters/image.ts +++ b/blocksuite/affine/shared/src/adapters/image.ts @@ -122,8 +122,8 @@ export const ImageAdapterFactoryIdentifier = AdapterFactoryIdentifier('Image'); export const ImageAdapterFactoryExtension: ExtensionType = { setup: di => { - di.addImpl(ImageAdapterFactoryIdentifier, () => ({ - get: (job: Transformer) => new ImageAdapter(job), + di.addImpl(ImageAdapterFactoryIdentifier, provider => ({ + get: (job: Transformer) => new ImageAdapter(job, provider), })); }, }; diff --git a/blocksuite/affine/shared/src/adapters/index.ts b/blocksuite/affine/shared/src/adapters/index.ts index 0a7e8ac743..5b50f4a972 100644 --- a/blocksuite/affine/shared/src/adapters/index.ts +++ b/blocksuite/affine/shared/src/adapters/index.ts @@ -1,4 +1,5 @@ export * from './attachment'; +export * from './clipboard'; export { BlockHtmlAdapterExtension, type BlockHtmlAdapterMatcher, diff --git a/blocksuite/affine/shared/src/adapters/markdown/markdown.ts b/blocksuite/affine/shared/src/adapters/markdown/markdown.ts index a58a2c6816..895dceec94 100644 --- a/blocksuite/affine/shared/src/adapters/markdown/markdown.ts +++ b/blocksuite/affine/shared/src/adapters/markdown/markdown.ts @@ -170,11 +170,8 @@ export class MarkdownAdapter extends BaseAdapter { readonly blockMatchers: BlockMarkdownAdapterMatcher[]; - constructor( - job: Transformer, - readonly provider: ServiceProvider - ) { - super(job); + constructor(job: Transformer, provider: ServiceProvider) { + super(job, provider); const blockMatchers = Array.from( provider.getAll(BlockMarkdownAdapterMatcherIdentifier).values() ); diff --git a/blocksuite/affine/shared/src/adapters/mix-text.ts b/blocksuite/affine/shared/src/adapters/mix-text.ts index 481023e23a..393017fed9 100644 --- a/blocksuite/affine/shared/src/adapters/mix-text.ts +++ b/blocksuite/affine/shared/src/adapters/mix-text.ts @@ -38,7 +38,7 @@ export class MixTextAdapter extends BaseAdapter { private readonly _markdownAdapter: MarkdownAdapter; constructor(job: Transformer, provider: ServiceProvider) { - super(job); + super(job, provider); this._markdownAdapter = new MarkdownAdapter(job, provider); } diff --git a/blocksuite/affine/shared/src/adapters/notion-html/notion-html.ts b/blocksuite/affine/shared/src/adapters/notion-html/notion-html.ts index 7d8d2ca53d..50ab639313 100644 --- a/blocksuite/affine/shared/src/adapters/notion-html/notion-html.ts +++ b/blocksuite/affine/shared/src/adapters/notion-html/notion-html.ts @@ -116,7 +116,7 @@ export class NotionHtmlAdapter extends BaseAdapter { readonly blockMatchers: BlockNotionHtmlAdapterMatcher[]; constructor(job: Transformer, provider: ServiceProvider) { - super(job); + super(job, provider); const blockMatchers = Array.from( provider.getAll(BlockNotionHtmlAdapterMatcherIdentifier).values() ); diff --git a/blocksuite/affine/shared/src/adapters/notion-text.ts b/blocksuite/affine/shared/src/adapters/notion-text.ts index 2443af7b86..fd11bdc0ea 100644 --- a/blocksuite/affine/shared/src/adapters/notion-text.ts +++ b/blocksuite/affine/shared/src/adapters/notion-text.ts @@ -163,8 +163,8 @@ export const NotionTextAdapterFactoryIdentifier = export const NotionTextAdapterFactoryExtension: ExtensionType = { setup: di => { - di.addImpl(NotionTextAdapterFactoryIdentifier, () => ({ - get: (job: Transformer) => new NotionTextAdapter(job), + di.addImpl(NotionTextAdapterFactoryIdentifier, provider => ({ + get: (job: Transformer) => new NotionTextAdapter(job, provider), })); }, }; diff --git a/blocksuite/affine/shared/src/adapters/plain-text/plain-text.ts b/blocksuite/affine/shared/src/adapters/plain-text/plain-text.ts index 79eaae76d9..828d3039a9 100644 --- a/blocksuite/affine/shared/src/adapters/plain-text/plain-text.ts +++ b/blocksuite/affine/shared/src/adapters/plain-text/plain-text.ts @@ -49,11 +49,8 @@ export class PlainTextAdapter extends BaseAdapter { readonly blockMatchers: BlockPlainTextAdapterMatcher[]; - constructor( - job: Transformer, - readonly provider: ServiceProvider - ) { - super(job); + constructor(job: Transformer, provider: ServiceProvider) { + super(job, provider); const blockMatchers = Array.from( provider.getAll(BlockPlainTextAdapterMatcherIdentifier).values() ); diff --git a/blocksuite/framework/store/src/adapter/base.ts b/blocksuite/framework/store/src/adapter/base.ts index e48a5b3f91..fe808375c2 100644 --- a/blocksuite/framework/store/src/adapter/base.ts +++ b/blocksuite/framework/store/src/adapter/base.ts @@ -1,3 +1,4 @@ +import type { ServiceProvider } from '@blocksuite/global/di'; import { BlockSuiteError } from '@blocksuite/global/exceptions'; import { @@ -73,7 +74,10 @@ export abstract class BaseAdapter<AdapterTarget = unknown> { return this.job.adapterConfigs; } - constructor(job: Transformer) { + constructor( + job: Transformer, + readonly provider: ServiceProvider + ) { this.job = job; } diff --git a/packages/frontend/core/src/blocksuite/utils/markdown-utils.ts b/packages/frontend/core/src/blocksuite/utils/markdown-utils.ts index 9fec76f37c..bf48455998 100644 --- a/packages/frontend/core/src/blocksuite/utils/markdown-utils.ts +++ b/packages/frontend/core/src/blocksuite/utils/markdown-utils.ts @@ -5,12 +5,12 @@ import { TextSelection, } from '@blocksuite/affine/block-std'; import { defaultImageProxyMiddleware } from '@blocksuite/affine/blocks/image'; -import { pasteMiddleware } from '@blocksuite/affine/blocks/root'; import type { ServiceProvider } from '@blocksuite/affine/global/di'; import { embedSyncedDocMiddleware, MarkdownAdapter, MixTextAdapter, + pasteMiddleware, PlainTextAdapter, titleMiddleware, } from '@blocksuite/affine/shared/adapters';