mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 12:28:42 +00:00
refactor(editor): replace-id middlware (#12250)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Improved the internal structure and clarity of ID handling during import processes, leading to more maintainable and modular code. No changes to user-facing functionality. - **Chores** - Enhanced type definitions for import events to improve code readability and maintainability. No impact on end-user experience. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -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<string, string>();
|
||||
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 =
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user