diff --git a/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts b/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts index 849528d55c..b2648206de 100644 --- a/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts +++ b/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts @@ -1,4 +1,4 @@ -import type { +import { DatabaseBlockModel, EmbedLinkedDocModel, EmbedSyncedDocModel, @@ -7,32 +7,50 @@ import type { SurfaceRefBlockModel, } from '@blocksuite/affine-model'; import { BlockSuiteError } from '@blocksuite/global/exceptions'; -import type { DeltaOperation, TransformerMiddleware } from '@blocksuite/store'; +import type { + AfterImportBlockPayload, + BeforeImportBlockPayload, + DeltaOperation, + TransformerMiddleware, +} from '@blocksuite/store'; +import { filter, map } from 'rxjs'; + +import { matchModels } from '../../utils'; export const replaceIdMiddleware = (idGenerator: () => string): TransformerMiddleware => ({ slots, docCRUD }) => { const idMap = new Map(); - slots.afterImport.subscribe(payload => { - if ( - payload.type === 'block' && - payload.snapshot.flavour === 'affine:database' - ) { - const model = payload.model as DatabaseBlockModel; + + // After Import + + const afterImportBlock$ = slots.afterImport.pipe( + filter( + (payload): payload is AfterImportBlockPayload => + payload.type === 'block' + ), + map(({ model }) => model) + ); + + afterImportBlock$ + .pipe(filter(model => matchModels(model, [DatabaseBlockModel]))) + .subscribe(model => { Object.keys(model.props.cells).forEach(cellId => { if (idMap.has(cellId)) { model.props.cells[idMap.get(cellId)!] = model.props.cells[cellId]; delete model.props.cells[cellId]; } }); - } + }); - // replace LinkedPage pageId with new id in paragraph blocks - if ( - payload.type === 'block' && - ['affine:list', 'affine:paragraph'].includes(payload.snapshot.flavour) - ) { - const model = payload.model as ParagraphBlockModel | ListBlockModel; + // replace LinkedPage pageId with new id in paragraph blocks + afterImportBlock$ + .pipe( + filter(model => + matchModels(model, [ParagraphBlockModel, ListBlockModel]) + ) + ) + .subscribe(model => { let prev = 0; const delta: DeltaOperation[] = []; for (const d of model.props.text.toDelta()) { @@ -64,13 +82,11 @@ export const replaceIdMiddleware = if (delta.length > 0) { model.props.text.applyDelta(delta); } - } + }); - if ( - payload.type === 'block' && - payload.snapshot.flavour === 'affine:surface-ref' - ) { - const model = payload.model as SurfaceRefBlockModel; + afterImportBlock$ + .pipe(filter(model => matchModels(model, [SurfaceRefBlockModel]))) + .subscribe(model => { const original = model.props.reference; // If there exists a replacement, replace the reference with the new id. // Otherwise, @@ -86,18 +102,16 @@ export const replaceIdMiddleware = idMap.set(original, newId); model.props.reference = newId; } - } + }); - // TODO(@fundon): process linked block/element - if ( - payload.type === 'block' && - ['affine:embed-linked-doc', 'affine:embed-synced-doc'].includes( - payload.snapshot.flavour + // TODO(@fundon): process linked block/element + afterImportBlock$ + .pipe( + filter(model => + matchModels(model, [EmbedLinkedDocModel, EmbedSyncedDocModel]) ) - ) { - const model = payload.model as - | EmbedLinkedDocModel - | EmbedSyncedDocModel; + ) + .subscribe(model => { const original = model.props.pageId; // If the pageId is not in the doc, generate a new id. // If we already have a replacement, use it. @@ -110,10 +124,13 @@ export const replaceIdMiddleware = model.props.pageId = newId; } } - } - }); - slots.beforeImport.subscribe(payload => { - if (payload.type === 'page') { + }); + + // Before Import + + slots.beforeImport + .pipe(filter(payload => payload.type === 'page')) + .subscribe(payload => { if (idMap.has(payload.snapshot.meta.id)) { payload.snapshot.meta.id = idMap.get(payload.snapshot.meta.id)!; return; @@ -121,10 +138,16 @@ export const replaceIdMiddleware = const newId = idGenerator(); idMap.set(payload.snapshot.meta.id, newId); payload.snapshot.meta.id = newId; - return; - } + }); - if (payload.type === 'block') { + slots.beforeImport + .pipe( + filter( + (payload): payload is BeforeImportBlockPayload => + payload.type === 'block' + ) + ) + .subscribe(payload => { const { snapshot } = payload; if (snapshot.flavour === 'affine:page') { const index = snapshot.children.findIndex( @@ -210,6 +233,5 @@ export const replaceIdMiddleware = } }); } - } - }); + }); }; diff --git a/blocksuite/framework/store/src/transformer/middleware.ts b/blocksuite/framework/store/src/transformer/middleware.ts index 7a288ec687..5fbf6006c9 100644 --- a/blocksuite/framework/store/src/transformer/middleware.ts +++ b/blocksuite/framework/store/src/transformer/middleware.ts @@ -11,13 +11,15 @@ import type { SliceSnapshot, } from './type.js'; +export type BeforeImportBlockPayload = { + snapshot: BlockSnapshot; + type: 'block'; + parent?: string; + index?: number; +}; + export type BeforeImportPayload = - | { - snapshot: BlockSnapshot; - type: 'block'; - parent?: string; - index?: number; - } + | BeforeImportBlockPayload | { snapshot: SliceSnapshot; type: 'slice'; @@ -71,14 +73,16 @@ export type AfterExportPayload = type: 'info'; }; +export type AfterImportBlockPayload = { + snapshot: BlockSnapshot; + type: 'block'; + model: BlockModel; + parent?: string; + index?: number; +}; + export type AfterImportPayload = - | { - snapshot: BlockSnapshot; - type: 'block'; - model: BlockModel; - parent?: string; - index?: number; - } + | AfterImportBlockPayload | { snapshot: DocSnapshot; type: 'page';