fix(editor): exisiting slice import should be move instead of add (#9616)

Closes: [BS-2339](https://linear.app/affine-design/issue/BS-2339/%E6%8B%96%E6%8B%BD%E9%87%8A%E6%94%BE%E5%90%8E%E7%9A%84%E4%BD%8D%E7%BD%AE%E4%B8%8D%E5%AF%B9)
This commit is contained in:
Saul-Mirone
2025-01-09 12:14:53 +00:00
parent 126ab18967
commit 6feb4def2f
2 changed files with 53 additions and 61 deletions

View File

@@ -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<string>;
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

View File

@@ -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))