mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-12 23:56:36 +08:00
feat(editor): add provider for base adapter (#11169)
This commit is contained in:
@@ -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: '',
|
||||
|
||||
@@ -165,5 +165,3 @@ export class PageClipboard extends ReadOnlyClipboard {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { pasteMiddleware };
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
+12
-1
@@ -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<string> {
|
||||
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<FromBlockSnapshotResult<string>> {
|
||||
@@ -56,7 +64,10 @@ export class ClipboardAdapter extends BaseAdapter<string> {
|
||||
);
|
||||
}
|
||||
const map = assets.getAssets();
|
||||
const blobs: Record<string, FileSnapshot> = await encodeClipboardBlobs(map);
|
||||
const blobs: Record<string, FileSnapshot> = await encodeClipboardBlobs(
|
||||
map,
|
||||
this._onError
|
||||
);
|
||||
return {
|
||||
file: JSON.stringify({
|
||||
snapshot,
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './clipboard';
|
||||
export * from './utils';
|
||||
+7
-18
@@ -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<string, Blob>) {
|
||||
export async function encodeClipboardBlobs(
|
||||
map: Map<string, Blob>,
|
||||
onError?: (message: string) => void
|
||||
) {
|
||||
const blobs: Record<string, FileSnapshot> = {};
|
||||
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'
|
||||
);
|
||||
@@ -174,11 +174,8 @@ export class HtmlAdapter extends BaseAdapter<Html> {
|
||||
|
||||
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()
|
||||
);
|
||||
|
||||
@@ -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),
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './attachment';
|
||||
export * from './clipboard';
|
||||
export {
|
||||
BlockHtmlAdapterExtension,
|
||||
type BlockHtmlAdapterMatcher,
|
||||
|
||||
@@ -170,11 +170,8 @@ export class MarkdownAdapter extends BaseAdapter<Markdown> {
|
||||
|
||||
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()
|
||||
);
|
||||
|
||||
@@ -38,7 +38,7 @@ export class MixTextAdapter extends BaseAdapter<MixText> {
|
||||
private readonly _markdownAdapter: MarkdownAdapter;
|
||||
|
||||
constructor(job: Transformer, provider: ServiceProvider) {
|
||||
super(job);
|
||||
super(job, provider);
|
||||
this._markdownAdapter = new MarkdownAdapter(job, provider);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ export class NotionHtmlAdapter extends BaseAdapter<NotionHtml> {
|
||||
readonly blockMatchers: BlockNotionHtmlAdapterMatcher[];
|
||||
|
||||
constructor(job: Transformer, provider: ServiceProvider) {
|
||||
super(job);
|
||||
super(job, provider);
|
||||
const blockMatchers = Array.from(
|
||||
provider.getAll(BlockNotionHtmlAdapterMatcherIdentifier).values()
|
||||
);
|
||||
|
||||
@@ -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),
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -49,11 +49,8 @@ export class PlainTextAdapter extends BaseAdapter<PlainText> {
|
||||
|
||||
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()
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user