diff --git a/blocksuite/framework/store/src/model/store/crud.ts b/blocksuite/framework/store/src/model/store/crud.ts index 99abe93f87..a895ad0595 100644 --- a/blocksuite/framework/store/src/model/store/crud.ts +++ b/blocksuite/framework/store/src/model/store/crud.ts @@ -58,73 +58,48 @@ export class DocCRUD { ); } + const hasBlock = this._yBlocks.has(id); + if (hasBlock) { + throw new BlockSuiteError( + ErrorCode.ModelCRUDError, + `Should not add existing block: ${id}` + ); + } + const parentFlavour = parent ? this._yBlocks.get(parent)?.get('sys:flavour') : undefined; this._schema.validate(flavour, parentFlavour as string); - const hasBlock = this._yBlocks.has(id); + const yBlock = new Y.Map() as YBlock; + this._yBlocks.set(id, yBlock); - if (hasBlock) { - const yBlock = this._yBlocks.get(id); - const existedParent = this.getParent(id); - if (yBlock && existedParent) { - const yParent = this._yBlocks.get(existedParent) as YBlock; - const yParentChildren = yParent.get('sys:children') as Y.Array; - const index = yParentChildren.toArray().indexOf(id); - yParentChildren.delete(index, 1); - if ( - parentIndex != null && - index != null && - existedParent === parent && - index < parentIndex - ) { - parentIndex--; - } - const props = { - ...initialProps, - }; - delete props.id; - delete props.flavour; - delete props.children; + const version = schema.version; + const children = ( + initialProps.children as undefined | (string | BlockModel)[] + )?.map(child => (typeof child === 'string' ? child : child.id)); - Object.entries(props).forEach(([key, value]) => { - if (value === undefined) return; + yBlock.set('sys:id', id); + yBlock.set('sys:flavour', flavour); + yBlock.set('sys:version', version); + yBlock.set('sys:children', Y.Array.from(children ?? [])); - yBlock.set(`prop:${key}`, native2Y(value)); - }); - } - } else { - const yBlock = new Y.Map() as YBlock; - this._yBlocks.set(id, yBlock); + const defaultProps = schema.model.props?.(internalPrimitives) ?? {}; + const props = { + ...defaultProps, + ...initialProps, + }; - const version = schema.version; - const children = ( - initialProps.children as undefined | (string | BlockModel)[] - )?.map(child => (typeof child === 'string' ? child : child.id)); + delete props.id; + delete props.flavour; + delete props.children; - yBlock.set('sys:id', id); - yBlock.set('sys:flavour', flavour); - yBlock.set('sys:version', version); - yBlock.set('sys:children', Y.Array.from(children ?? [])); + Object.entries(props).forEach(([key, value]) => { + if (value === undefined) return; - const defaultProps = schema.model.props?.(internalPrimitives) ?? {}; - const props = { - ...defaultProps, - ...initialProps, - }; - - delete props.id; - delete props.flavour; - delete props.children; - - Object.entries(props).forEach(([key, value]) => { - if (value === undefined) return; - - yBlock.set(`prop:${key}`, native2Y(value)); - }); - } + yBlock.set(`prop:${key}`, native2Y(value)); + }); const parentId = parent ?? (schema.model.role === 'root' ? null : this.root); @@ -355,14 +330,12 @@ export class DocCRUD { return; } - const targetIndex = targetParentChildren + let targetIndex = targetParentChildren .toArray() .findIndex(id => id === targetSibling); if (targetIndex === -1) { - throw new BlockSuiteError( - ErrorCode.ModelCRUDError, - 'Target sibling not found' - ); + console.error('Target sibling not found, just insert to the end'); + targetIndex = targetParentChildren.length; } insertIndex = shouldInsertBeforeSibling ? targetIndex diff --git a/blocksuite/framework/store/src/transformer/job.ts b/blocksuite/framework/store/src/transformer/job.ts index 1a9d497a20..404db0818d 100644 --- a/blocksuite/framework/store/src/transformer/job.ts +++ b/blocksuite/framework/store/src/transformer/job.ts @@ -256,7 +256,26 @@ export class Job { const blockTree = await this._convertFlatSnapshots(flatSnapshots); - await this._insertBlockTree(blockTree.children, doc, parent, index); + const first = content[0]; + // check if the slice is already in the doc + if (first && doc.hasBlock(first.id)) { + // if the slice is already in the doc, we need to move the blocks instead of adding them + const models = flatSnapshots + .map(flat => doc.getBlock(flat.snapshot.id)?.model) + .filter(Boolean) as BlockModel[]; + const parentModel = parent ? doc.getBlock(parent)?.model : undefined; + if (!parentModel) { + throw new BlockSuiteError( + ErrorCode.TransformerError, + 'Parent block not found in doc when moving slice' + ); + } + const targetSibling = + index !== undefined ? parentModel.children[index] : null; + doc.moveBlocks(models, parentModel, targetSibling); + } else { + await this._insertBlockTree(blockTree.children, doc, parent, index); + } const contentBlocks = blockTree.children .map(tree => doc.getBlockById(tree.draft.id))