From 1e4b1807be6cf62182a8d0f5f9f1ff2a84e395c0 Mon Sep 17 00:00:00 2001 From: Saul-Mirone Date: Sat, 28 Dec 2024 07:48:41 +0000 Subject: [PATCH] refactor(editor): query methods in edgeless api (#9407) --- .../src/extensions/crud-extension.ts | 22 ++++ .../affine/shared/src/utils/edgeless.ts | 79 +++++++++++++ blocksuite/affine/shared/src/utils/index.ts | 1 + .../edgeless/clipboard/clipboard.ts | 6 +- .../auto-complete/auto-complete-panel.ts | 18 ++- .../auto-complete/edgeless-auto-complete.ts | 30 ++--- .../components/auto-complete/utils.ts | 11 +- .../rects/edgeless-selected-rect.ts | 4 +- .../text/edgeless-shape-text-editor.ts | 2 +- .../components/text/edgeless-text-editor.ts | 2 +- .../toolbar/mindmap/basket-elements.ts | 2 +- .../toolbar/mindmap/mindmap-tool-button.ts | 4 +- .../root-block/edgeless/edgeless-keyboard.ts | 4 +- .../edgeless/edgeless-root-preview-block.ts | 2 +- .../edgeless/edgeless-root-service.ts | 15 +-- .../edgeless/gfx-tool/eraser-tool.ts | 3 +- .../edgeless/utils/clipboard-utils.ts | 2 +- .../src/root-block/edgeless/utils/group.ts | 15 --- .../src/root-block/edgeless/utils/query.ts | 70 +----------- .../src/root-block/edgeless/utils/text.ts | 4 +- .../widgets/drag-handle/drag-handle.ts | 8 +- .../drag-handle/watchers/edgeless-watcher.ts | 8 +- .../edgeless-auto-connect.ts | 2 +- .../edgeless-remote-selection/index.ts | 48 ++++---- .../widgets/element-toolbar/lock-button.ts | 4 +- .../widgets/surface-ref-toolbar/utils.ts | 2 +- .../surface-ref-block/surface-ref-block.ts | 3 +- .../src/__tests__/edgeless/group.spec.ts | 12 +- .../src/__tests__/edgeless/last-props.spec.ts | 54 +++++---- .../src/__tests__/edgeless/layer.spec.ts | 106 +++++++++--------- .../__tests__/edgeless/surface-ref.spec.ts | 2 +- .../src/__tests__/edgeless/tools.spec.ts | 4 +- .../tests-legacy/edgeless/linked-doc.spec.ts | 8 +- .../tests-legacy/utils/actions/edgeless.ts | 12 +- .../blocksuite/presets/ai/peek-view/utils.ts | 2 +- 35 files changed, 296 insertions(+), 275 deletions(-) create mode 100644 blocksuite/affine/shared/src/utils/edgeless.ts delete mode 100644 blocksuite/blocks/src/root-block/edgeless/utils/group.ts diff --git a/blocksuite/affine/block-surface/src/extensions/crud-extension.ts b/blocksuite/affine/block-surface/src/extensions/crud-extension.ts index 39f5266209..5119dc7013 100644 --- a/blocksuite/affine/block-surface/src/extensions/crud-extension.ts +++ b/blocksuite/affine/block-surface/src/extensions/crud-extension.ts @@ -137,4 +137,26 @@ export class EdgelessCRUDExtension extends Extension { this.std.doc.updateBlock(block, props); } }; + + getElementById(id: string): BlockSuite.EdgelessModel | null { + const surface = this._surface; + if (!surface) { + return null; + } + const el = + surface.getElementById(id) ?? + (this.std.doc.getBlockById( + id + ) as BlockSuite.EdgelessBlockModelType | null); + return el; + } + + getElementsByType( + type: K + ): BlockSuite.SurfaceElementModelMap[K][] { + if (!this._surface) { + return []; + } + return this._surface.getElementsByType(type); + } } diff --git a/blocksuite/affine/shared/src/utils/edgeless.ts b/blocksuite/affine/shared/src/utils/edgeless.ts new file mode 100644 index 0000000000..3daf5775a5 --- /dev/null +++ b/blocksuite/affine/shared/src/utils/edgeless.ts @@ -0,0 +1,79 @@ +import { FrameBlockModel, GroupElementModel } from '@blocksuite/affine-model'; +import type { GfxBlockElementModel } from '@blocksuite/block-std/gfx'; +import { + deserializeXYWH, + getQuadBoundWithRotation, +} from '@blocksuite/global/utils'; +import type { BlockModel } from '@blocksuite/store'; + +export function getSelectedRect(selected: BlockSuite.EdgelessModel[]): DOMRect { + if (selected.length === 0) { + return new DOMRect(); + } + + const lockedElementsByFrame = selected + .map(selectable => { + if (selectable instanceof FrameBlockModel && selectable.isLocked()) { + return selectable.descendantElements; + } + return []; + }) + .flat(); + + selected = [...new Set([...selected, ...lockedElementsByFrame])]; + + if (selected.length === 1) { + const [x, y, w, h] = deserializeXYWH(selected[0].xywh); + return new DOMRect(x, y, w, h); + } + + return getElementsWithoutGroup(selected).reduce( + (bounds, selectable, index) => { + const rotate = isTopLevelBlock(selectable) ? 0 : selectable.rotate; + const [x, y, w, h] = deserializeXYWH(selectable.xywh); + let { left, top, right, bottom } = getQuadBoundWithRotation({ + x, + y, + w, + h, + rotate, + }); + + if (index !== 0) { + left = Math.min(left, bounds.left); + top = Math.min(top, bounds.top); + right = Math.max(right, bounds.right); + bottom = Math.max(bottom, bounds.bottom); + } + + bounds.x = left; + bounds.y = top; + bounds.width = right - left; + bounds.height = bottom - top; + + return bounds; + }, + new DOMRect() + ); +} + +export function getElementsWithoutGroup(elements: BlockSuite.EdgelessModel[]) { + const set = new Set(); + + elements.forEach(element => { + if (element instanceof GroupElementModel) { + element.descendantElements + .filter(descendant => !(descendant instanceof GroupElementModel)) + .forEach(descendant => set.add(descendant)); + } else { + set.add(element); + } + }); + return Array.from(set); +} + +export function isTopLevelBlock( + selectable: BlockModel | BlockSuite.EdgelessModel | null +): selectable is GfxBlockElementModel { + return !!selectable && 'flavour' in selectable; +} diff --git a/blocksuite/affine/shared/src/utils/index.ts b/blocksuite/affine/shared/src/utils/index.ts index 516293823b..85150e8403 100644 --- a/blocksuite/affine/shared/src/utils/index.ts +++ b/blocksuite/affine/shared/src/utils/index.ts @@ -2,6 +2,7 @@ export * from './button-popper.js'; export * from './collapsed/index.js'; export * from './dnd/index.js'; export * from './dom/index.js'; +export * from './edgeless.js'; export * from './event.js'; export * from './file/index.js'; export * from './insert.js'; diff --git a/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts b/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts index 781eebe5e1..0c8ad53712 100644 --- a/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts +++ b/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts @@ -26,6 +26,7 @@ import { } from '@blocksuite/affine-shared/services'; import { isInsidePageEditor, + isTopLevelBlock, isUrlInClipboard, matchFlavours, referenceToNode, @@ -83,7 +84,6 @@ import { isAttachmentBlock, isCanvasElementWithText, isImageBlock, - isTopLevelBlock, } from '../utils/query.js'; const BLOCKSUITE_SURFACE = 'blocksuite/surface'; @@ -595,9 +595,7 @@ export class EdgelessClipboardController extends PageClipboard { segment: 'toolbar', type: clipboardData.type as string, }); - const element = this.host.service.getElementById( - id - ) as BlockSuite.SurfaceModel; + const element = this.crud.getElementById(id) as BlockSuite.SurfaceModel; assertExists(element); return element; } diff --git a/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/auto-complete-panel.ts b/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/auto-complete-panel.ts index f81a94e1f8..77c38e8646 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/auto-complete-panel.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/auto-complete-panel.ts @@ -167,7 +167,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { surfaceBlockModel ); edgeless.doc.captureSync(); - const frame = service.getElementById(id); + const frame = this.crud.getElementById(id); if (!frame) return; this.connector.target = { @@ -225,7 +225,6 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { const currentSource = this.currentSource; const { nextBound, position } = result; - const { service } = edgeless; const id = createShapeElement(edgeless, currentSource, targetType); if (!id) return; @@ -235,10 +234,10 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { }); mountShapeTextEditor( - service.getElementById(id) as ShapeElementModel, + this.crud.getElementById(id) as ShapeElementModel, this.edgeless ); - edgeless.service.selection.set({ + this.gfx.selection.set({ elements: [id], editing: true, }); @@ -250,7 +249,6 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { if (!target) return; const { xywh, position } = target; const bound = Bound.fromXYWH(xywh); - const edgelessService = this.edgeless.service; const textFlag = this.edgeless.doc.awarenessStore.getFlag( 'enable_edgeless_text' @@ -262,7 +260,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { }); if (!textId) return; - const textElement = edgelessService.getElementById(textId); + const textElement = this.crud.getElementById(textId); if (!textElement) return; this.crud.updateElement(this.connector.id, { @@ -272,7 +270,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { this.currentSource.group.addChild(textElement); } - this.edgeless.service.selection.set({ + this.gfx.selection.set({ elements: [textId], editing: false, }); @@ -289,7 +287,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { fontStyle: FontStyle.Normal, }); if (!textId) return; - const textElement = edgelessService.getElementById(textId); + const textElement = this.crud.getElementById(textId); assertInstanceOf(textElement, TextElementModel); this.crud.updateElement(this.connector.id, { @@ -299,7 +297,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { this.currentSource.group.addChild(textElement); } - this.edgeless.service.selection.set({ + this.gfx.selection.set({ elements: [textId], editing: false, }); @@ -331,7 +329,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { } private _connectorExist() { - return !!this.edgeless.service.getElementById(this.connector.id); + return !!this.crud.getElementById(this.connector.id); } private _generateTarget(connector: ConnectorElementModel) { diff --git a/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/edgeless-auto-complete.ts b/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/edgeless-auto-complete.ts index c06c80c171..9febe37d46 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/edgeless-auto-complete.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/edgeless-auto-complete.ts @@ -164,9 +164,8 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { private _autoCompleteOverlay!: AutoCompleteOverlay; private readonly _onPointerDown = (e: PointerEvent, type: Direction) => { - const { service } = this.edgeless; - const viewportRect = service.viewport.boundingClientRect; - const start = service.viewport.toModelCoord( + const viewportRect = this.gfx.viewport.boundingClientRect; + const start = this.gfx.viewport.toModelCoord( e.clientX - viewportRect.left, e.clientY - viewportRect.top ); @@ -176,7 +175,7 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { let connector: ConnectorElementModel | null; this._disposables.addFromEvent(document, 'pointermove', e => { - const point = service.viewport.toModelCoord( + const point = this.gfx.viewport.toModelCoord( e.clientX - viewportRect.left, e.clientY - viewportRect.top ); @@ -237,14 +236,17 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { return this.std.get(EdgelessCRUDIdentifier); } + get gfx() { + return this.std.get(GfxControllerIdentifier); + } + private _addConnector(source: Connection, target: Connection) { - const { edgeless } = this; const id = this.crud.addElement(CanvasElementType.CONNECTOR, { source, target, }); if (!id) return null; - return edgeless.service.getElementById(id) as ConnectorElementModel; + return this.crud.getElementById(id) as ConnectorElementModel; } private _addMindmapNode(target: 'sibling' | 'child') { @@ -274,7 +276,7 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { requestAnimationFrame(() => { mountShapeTextEditor( - this.edgeless.service.getElementById(newNode) as ShapeElementModel, + this.crud.getElementById(newNode) as ShapeElementModel, this.edgeless ); }); @@ -375,7 +377,7 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { ); mountShapeTextEditor( - service.getElementById(id) as ShapeElementModel, + this.crud.getElementById(id) as ShapeElementModel, this.edgeless ); } else { @@ -403,12 +405,12 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { return service.getConnectors(element.id).reduce((prev, current) => { if (current.target.id === element.id && current.source.id) { prev.push( - service.getElementById(current.source.id) as ShapeElementModel + this.crud.getElementById(current.source.id) as ShapeElementModel ); } if (current.source.id === element.id && current.target.id) { prev.push( - service.getElementById(current.target.id) as ShapeElementModel + this.crud.getElementById(current.target.id) as ShapeElementModel ); } @@ -467,9 +469,7 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { private _initOverlay() { const { surface } = this.edgeless; - this._autoCompleteOverlay = new AutoCompleteOverlay( - this.std.get(GfxControllerIdentifier) - ); + this._autoCompleteOverlay = new AutoCompleteOverlay(this.gfx); surface.renderer.addOverlay(this._autoCompleteOverlay); } @@ -656,7 +656,7 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { override connectedCallback(): void { super.connectedCallback(); this._pathGenerator = new ConnectorPathGenerator({ - getElementById: id => this.edgeless.service.getElementById(id), + getElementById: id => this.crud.getElementById(id), }); this._initOverlay(); } @@ -665,7 +665,7 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { const { _disposables, edgeless } = this; _disposables.add( - this.edgeless.service.selection.slots.updated.on(() => { + this.gfx.selection.slots.updated.on(() => { this._autoCompleteOverlay.linePoints = []; this._autoCompleteOverlay.renderShape = null; }) diff --git a/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/utils.ts b/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/utils.ts index ceada16dc0..0a0ab17265 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/utils.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/auto-complete/utils.ts @@ -277,17 +277,18 @@ export function createEdgelessElement( ) { let id; const { service } = edgeless; + const { crud } = service; let element: GfxModel | null = null; if (isShape(current)) { - id = service.crud.addElement(current.type, { + id = crud.addElement(current.type, { ...current.serialize(), text: new DocCollection.Y.Text(), xywh: bound.serialize(), }); if (!id) return null; - element = service.getElementById(id); + element = crud.getElementById(id); } else { const { doc } = edgeless; id = doc.addBlock( @@ -335,14 +336,14 @@ export function createShapeElement( current: ShapeElementModel | NoteBlockModel, targetType: TARGET_SHAPE_TYPE ) { - const service = edgeless.service; - const id = service.crud.addElement('shape', { + const { crud } = edgeless.service; + const id = crud.addElement('shape', { shapeType: getShapeType(targetType), radius: getShapeRadius(targetType), text: new DocCollection.Y.Text(), }); if (!id) return null; - const element = service.getElementById(id); + const element = crud.getElementById(id); const group = current.group; if (group instanceof GroupElementModel && element) { group.addChild(element); diff --git a/blocksuite/blocks/src/root-block/edgeless/components/rects/edgeless-selected-rect.ts b/blocksuite/blocks/src/root-block/edgeless/components/rects/edgeless-selected-rect.ts index b52213f7ff..8b35c531b3 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/rects/edgeless-selected-rect.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/rects/edgeless-selected-rect.ts @@ -31,6 +31,8 @@ import { EMBED_CARD_HEIGHT } from '@blocksuite/affine-shared/consts'; import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme'; import { clamp, + getElementsWithoutGroup, + getSelectedRect, requestThrottledConnectedFrame, stopPropagation, } from '@blocksuite/affine-shared/utils'; @@ -72,10 +74,8 @@ import { AI_CHAT_BLOCK_MIN_HEIGHT, AI_CHAT_BLOCK_MIN_WIDTH, } from '../../utils/consts.js'; -import { getElementsWithoutGroup } from '../../utils/group.js'; import { getSelectableBounds, - getSelectedRect, isAIChatBlock, isAttachmentBlock, isBookmarkBlock, diff --git a/blocksuite/blocks/src/root-block/edgeless/components/text/edgeless-shape-text-editor.ts b/blocksuite/blocks/src/root-block/edgeless/components/text/edgeless-shape-text-editor.ts index dc1fbaf705..1fb63c0670 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/text/edgeless-shape-text-editor.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/text/edgeless-shape-text-editor.ts @@ -7,6 +7,7 @@ import type { RichText } from '@blocksuite/affine-components/rich-text'; import type { ShapeElementModel } from '@blocksuite/affine-model'; import { MindmapElementModel, TextResizing } from '@blocksuite/affine-model'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; +import { getSelectedRect } from '@blocksuite/affine-shared/utils'; import { RANGE_SYNC_EXCLUDE_ATTR, ShadowlessElement, @@ -23,7 +24,6 @@ import { property, query } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; import type { EdgelessRootBlockComponent } from '../../edgeless-root-block.js'; -import { getSelectedRect } from '../../utils/query.js'; const { toRadian } = CommonUtils; diff --git a/blocksuite/blocks/src/root-block/edgeless/components/text/edgeless-text-editor.ts b/blocksuite/blocks/src/root-block/edgeless/components/text/edgeless-text-editor.ts index 8e2df13dfd..1d2cf89fb8 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/text/edgeless-text-editor.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/text/edgeless-text-editor.ts @@ -6,6 +6,7 @@ import { import type { RichText } from '@blocksuite/affine-components/rich-text'; import type { TextElementModel } from '@blocksuite/affine-model'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; +import { getSelectedRect } from '@blocksuite/affine-shared/utils'; import { RANGE_SYNC_EXCLUDE_ATTR, ShadowlessElement, @@ -22,7 +23,6 @@ import { styleMap } from 'lit/directives/style-map.js'; import type { EdgelessRootBlockComponent } from '../../edgeless-root-block.js'; import { deleteElements } from '../../utils/crud.js'; -import { getSelectedRect } from '../../utils/query.js'; const { toRadian } = CommonUtils; diff --git a/blocksuite/blocks/src/root-block/edgeless/components/toolbar/mindmap/basket-elements.ts b/blocksuite/blocks/src/root-block/edgeless/components/toolbar/mindmap/basket-elements.ts index cf42b93f81..b2c8445cc8 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/toolbar/mindmap/basket-elements.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/toolbar/mindmap/basket-elements.ts @@ -118,7 +118,7 @@ export const textRender: DraggableTool['render'] = ( }) as string; edgeless.doc.captureSync(); - const textElement = edgeless.service.getElementById(id); + const textElement = edgeless.service.crud.getElementById(id); assertInstanceOf(textElement, TextElementModel); mountTextElementEditor(textElement, edgeless); } diff --git a/blocksuite/blocks/src/root-block/edgeless/components/toolbar/mindmap/mindmap-tool-button.ts b/blocksuite/blocks/src/root-block/edgeless/components/toolbar/mindmap/mindmap-tool-button.ts index 6ffde40aff..1e5ab15b70 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/toolbar/mindmap/mindmap-tool-button.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/toolbar/mindmap/mindmap-tool-button.ts @@ -186,9 +186,7 @@ export class EdgelessMindmapToolButton extends EdgelessToolbarToolMixin( layoutType: mindmap?.layoutType === 'left' ? 1 : 0, }); if (!id) return; - const element = this.edgeless.service.getElementById( - id - ) as MindmapElementModel; + const element = this.crud.getElementById(id) as MindmapElementModel; this.tryDisposePopper(); this.setEdgelessTool({ type: 'default' }); diff --git a/blocksuite/blocks/src/root-block/edgeless/edgeless-keyboard.ts b/blocksuite/blocks/src/root-block/edgeless/edgeless-keyboard.ts index 4d15853802..7127a3ec2d 100644 --- a/blocksuite/blocks/src/root-block/edgeless/edgeless-keyboard.ts +++ b/blocksuite/blocks/src/root-block/edgeless/edgeless-keyboard.ts @@ -372,7 +372,7 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { const node = mindmap.getNode(elements[0].id)!; const parent = mindmap.getParentNode(node.id) ?? node; const id = mindmap.addNode(parent.id, currentNode.id, 'after'); - const target = service.getElementById(id) as ShapeElementModel; + const target = service.crud.getElementById(id) as ShapeElementModel; requestAnimationFrame(() => { mountShapeTextEditor(target, rootComponent); @@ -403,7 +403,7 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { const node = mindmap.getNode(elements[0].id)!; const id = mindmap.addNode(node.id); - const target = service.getElementById(id) as ShapeElementModel; + const target = service.crud.getElementById(id) as ShapeElementModel; if (node.detail.collapsed) { mindmap.toggleCollapse(node, { layout: true }); diff --git a/blocksuite/blocks/src/root-block/edgeless/edgeless-root-preview-block.ts b/blocksuite/blocks/src/root-block/edgeless/edgeless-root-preview-block.ts index 8991394046..999e550ca9 100644 --- a/blocksuite/blocks/src/root-block/edgeless/edgeless-root-preview-block.ts +++ b/blocksuite/blocks/src/root-block/edgeless/edgeless-root-preview-block.ts @@ -181,7 +181,7 @@ export class EdgelessRootPreviewBlockComponent extends BlockComponent< ); if (!surface) return; - const el = this.service.getElementById(surface.elements[0]); + const el = this.service.crud.getElementById(surface.elements[0]); if (isCanvasElement(el)) { return true; } diff --git a/blocksuite/blocks/src/root-block/edgeless/edgeless-root-service.ts b/blocksuite/blocks/src/root-block/edgeless/edgeless-root-service.ts index 68e2655c7f..a58dac6de2 100644 --- a/blocksuite/blocks/src/root-block/edgeless/edgeless-root-service.ts +++ b/blocksuite/blocks/src/root-block/edgeless/edgeless-root-service.ts @@ -288,19 +288,6 @@ export class EdgelessRootService extends RootService implements SurfaceContext { return this.surface.getConnectors(id) as ConnectorElementModel[]; } - getElementById(id: string): BlockSuite.EdgelessModel | null { - const el = - this._surface.getElementById(id) ?? - (this.doc.getBlockById(id) as BlockSuite.EdgelessBlockModelType | null); - return el; - } - - getElementsByType( - type: K - ): BlockSuite.SurfaceElementModelMap[K][] { - return this.surface.getElementsByType(type); - } - getFitToScreenData( padding: [number, number, number, number] = [0, 0, 0, 0], inputBounds?: Bound[] @@ -351,7 +338,7 @@ export class EdgelessRootService extends RootService implements SurfaceContext { removeElement(id: string | BlockSuite.EdgelessModel) { id = typeof id === 'string' ? id : id.id; - const el = this.getElementById(id); + const el = this.crud.getElementById(id); if (isGfxGroupCompatibleModel(el)) { el.childIds.forEach(childId => { this.removeElement(childId); diff --git a/blocksuite/blocks/src/root-block/edgeless/gfx-tool/eraser-tool.ts b/blocksuite/blocks/src/root-block/edgeless/gfx-tool/eraser-tool.ts index c730c6bde6..a8498c8941 100644 --- a/blocksuite/blocks/src/root-block/edgeless/gfx-tool/eraser-tool.ts +++ b/blocksuite/blocks/src/root-block/edgeless/gfx-tool/eraser-tool.ts @@ -4,12 +4,11 @@ import { Overlay, type SurfaceBlockComponent, } from '@blocksuite/affine-block-surface'; +import { isTopLevelBlock } from '@blocksuite/affine-shared/utils'; import type { PointerEventState } from '@blocksuite/block-std'; import { BaseTool } from '@blocksuite/block-std/gfx'; import { Bound, type IVec } from '@blocksuite/global/utils'; -import { isTopLevelBlock } from '../utils/query.js'; - const { getSvgPathFromStroke, getStroke, linePolygonIntersects } = CommonUtils; class EraserOverlay extends Overlay { diff --git a/blocksuite/blocks/src/root-block/edgeless/utils/clipboard-utils.ts b/blocksuite/blocks/src/root-block/edgeless/utils/clipboard-utils.ts index e6beab304d..6af0a91c7f 100644 --- a/blocksuite/blocks/src/root-block/edgeless/utils/clipboard-utils.ts +++ b/blocksuite/blocks/src/root-block/edgeless/utils/clipboard-utils.ts @@ -6,6 +6,7 @@ import type { ImageBlockModel, NoteBlockModel, } from '@blocksuite/affine-model'; +import { getElementsWithoutGroup } from '@blocksuite/affine-shared/utils'; import { generateKeyBetweenV2, type SerializedElement, @@ -16,7 +17,6 @@ import { type BlockSnapshot, BlockSnapshotSchema } from '@blocksuite/store'; import type { EdgelessRootBlockComponent } from '../edgeless-root-block.js'; import { EdgelessFrameManager } from '../frame-manager.js'; import { getSortedCloneElements, prepareCloneData } from './clone-utils.js'; -import { getElementsWithoutGroup } from './group.js'; import { isEdgelessTextBlock, isEmbedSyncedDocBlock, diff --git a/blocksuite/blocks/src/root-block/edgeless/utils/group.ts b/blocksuite/blocks/src/root-block/edgeless/utils/group.ts deleted file mode 100644 index 3dd461da70..0000000000 --- a/blocksuite/blocks/src/root-block/edgeless/utils/group.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { GroupElementModel } from '@blocksuite/affine-model'; -export function getElementsWithoutGroup(elements: BlockSuite.EdgelessModel[]) { - const set = new Set(); - - elements.forEach(element => { - if (element instanceof GroupElementModel) { - element.descendantElements - .filter(descendant => !(descendant instanceof GroupElementModel)) - .forEach(descendant => set.add(descendant)); - } else { - set.add(element); - } - }); - return Array.from(set); -} diff --git a/blocksuite/blocks/src/root-block/edgeless/utils/query.ts b/blocksuite/blocks/src/root-block/edgeless/utils/query.ts index 7ed78c2670..5326ed9f4c 100644 --- a/blocksuite/blocks/src/root-block/edgeless/utils/query.ts +++ b/blocksuite/blocks/src/root-block/edgeless/utils/query.ts @@ -17,13 +17,17 @@ import { type EmbedLoomModel, type EmbedSyncedDocModel, type EmbedYoutubeModel, - FrameBlockModel, + type FrameBlockModel, type ImageBlockModel, MindmapElementModel, type NoteBlockModel, ShapeElementModel, TextElementModel, } from '@blocksuite/affine-model'; +import { + getElementsWithoutGroup, + isTopLevelBlock, +} from '@blocksuite/affine-shared/utils'; import type { GfxBlockElementModel, GfxModel, @@ -32,15 +36,10 @@ import type { Viewport, } from '@blocksuite/block-std/gfx'; import type { PointLocation } from '@blocksuite/global/utils'; -import { - Bound, - deserializeXYWH, - getQuadBoundWithRotation, -} from '@blocksuite/global/utils'; +import { Bound } from '@blocksuite/global/utils'; import type { BlockModel } from '@blocksuite/store'; import type { Connectable } from '../../../_common/utils/index.js'; -import { getElementsWithoutGroup } from './group.js'; const { clamp } = CommonUtils; @@ -50,12 +49,6 @@ export function isMindmapNode( return element?.group instanceof MindmapElementModel; } -export function isTopLevelBlock( - selectable: BlockModel | BlockSuite.EdgelessModel | null -): selectable is GfxBlockElementModel { - return !!selectable && 'flavour' in selectable; -} - export function isNoteBlock( element: BlockModel | BlockSuite.EdgelessModel | null ): element is NoteBlockModel { @@ -263,57 +256,6 @@ export function getBackgroundGrid(zoom: number, showGrid: boolean) { }; } -export function getSelectedRect(selected: BlockSuite.EdgelessModel[]): DOMRect { - if (selected.length === 0) { - return new DOMRect(); - } - - const lockedElementsByFrame = selected - .map(selectable => { - if (selectable instanceof FrameBlockModel && selectable.isLocked()) { - return selectable.descendantElements; - } - return []; - }) - .flat(); - - selected = [...new Set([...selected, ...lockedElementsByFrame])]; - - if (selected.length === 1) { - const [x, y, w, h] = deserializeXYWH(selected[0].xywh); - return new DOMRect(x, y, w, h); - } - - return getElementsWithoutGroup(selected).reduce( - (bounds, selectable, index) => { - const rotate = isTopLevelBlock(selectable) ? 0 : selectable.rotate; - const [x, y, w, h] = deserializeXYWH(selectable.xywh); - let { left, top, right, bottom } = getQuadBoundWithRotation({ - x, - y, - w, - h, - rotate, - }); - - if (index !== 0) { - left = Math.min(left, bounds.left); - top = Math.min(top, bounds.top); - right = Math.max(right, bounds.right); - bottom = Math.max(bottom, bounds.bottom); - } - - bounds.x = left; - bounds.y = top; - bounds.width = right - left; - bounds.height = bottom - top; - - return bounds; - }, - new DOMRect() - ); -} - export type SelectableProps = { bound: Bound; rotate: number; diff --git a/blocksuite/blocks/src/root-block/edgeless/utils/text.ts b/blocksuite/blocks/src/root-block/edgeless/utils/text.ts index c8c1a9e63c..cd6b1c8fca 100644 --- a/blocksuite/blocks/src/root-block/edgeless/utils/text.ts +++ b/blocksuite/blocks/src/root-block/edgeless/utils/text.ts @@ -79,7 +79,7 @@ export function mountShapeTextEditor( .updateElement(shapeElement.id, { text }); } - const updatedElement = edgeless.service.getElementById(shapeElement.id); + const updatedElement = edgeless.service.crud.getElementById(shapeElement.id); assertInstanceOf( updatedElement, @@ -171,7 +171,7 @@ export function addText( }); if (!id) return; edgeless.doc.captureSync(); - const textElement = edgeless.service.getElementById(id); + const textElement = edgeless.service.crud.getElementById(id); if (!textElement) return; if (textElement instanceof TextElementModel) { mountTextElementEditor(textElement, edgeless); diff --git a/blocksuite/blocks/src/root-block/widgets/drag-handle/drag-handle.ts b/blocksuite/blocks/src/root-block/widgets/drag-handle/drag-handle.ts index 40ae22bb5f..6e8f834013 100644 --- a/blocksuite/blocks/src/root-block/widgets/drag-handle/drag-handle.ts +++ b/blocksuite/blocks/src/root-block/widgets/drag-handle/drag-handle.ts @@ -1,3 +1,4 @@ +import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface'; import type { RootBlockModel } from '@blocksuite/affine-model'; import { DocModeProvider } from '@blocksuite/affine-shared/services'; import { @@ -7,6 +8,7 @@ import { getScrollContainer, isInsideEdgelessEditor, isInsidePageEditor, + isTopLevelBlock, matchFlavours, } from '@blocksuite/affine-shared/utils'; import { @@ -22,9 +24,7 @@ import { html } from 'lit'; import { query, state } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; -import { isTopLevelBlock } from '../../../root-block/edgeless/utils/query.js'; import { autoScroll } from '../../../root-block/text-selection/utils.js'; -import type { EdgelessRootService } from '../../edgeless/index.js'; import type { DragPreview } from './components/drag-preview.js'; import type { DropIndicator } from './components/drop-indicator.js'; import type { AFFINE_DRAG_HANDLE_WIDGET } from './consts.js'; @@ -196,8 +196,8 @@ export class AffineDragHandleWidget extends WidgetComponent { if (!this.anchorBlockId.value) return null; if (this.mode === 'page') return null; - const service = this.std.getService('affine:page') as EdgelessRootService; - const edgelessElement = service.getElementById(this.anchorBlockId.value); + const crud = this.std.get(EdgelessCRUDIdentifier); + const edgelessElement = crud.getElementById(this.anchorBlockId.value); return isTopLevelBlock(edgelessElement) ? edgelessElement : null; } ); diff --git a/blocksuite/blocks/src/root-block/widgets/drag-handle/watchers/edgeless-watcher.ts b/blocksuite/blocks/src/root-block/widgets/drag-handle/watchers/edgeless-watcher.ts index 0867bebb8f..b447fdf8ca 100644 --- a/blocksuite/blocks/src/root-block/widgets/drag-handle/watchers/edgeless-watcher.ts +++ b/blocksuite/blocks/src/root-block/widgets/drag-handle/watchers/edgeless-watcher.ts @@ -2,6 +2,10 @@ import { EdgelessLegacySlotIdentifier, type SurfaceBlockComponent, } from '@blocksuite/affine-block-surface'; +import { + getSelectedRect, + isTopLevelBlock, +} from '@blocksuite/affine-shared/utils'; import type { DndEventState } from '@blocksuite/block-std'; import { GfxControllerIdentifier, @@ -10,10 +14,6 @@ import { import { type IVec, Rect } from '@blocksuite/global/utils'; import { effect } from '@preact/signals-core'; -import { - getSelectedRect, - isTopLevelBlock, -} from '../../../edgeless/utils/query.js'; import { DRAG_HANDLE_CONTAINER_OFFSET_LEFT_TOP_LEVEL, DRAG_HANDLE_CONTAINER_WIDTH_TOP_LEVEL, diff --git a/blocksuite/blocks/src/root-block/widgets/edgeless-auto-connect/edgeless-auto-connect.ts b/blocksuite/blocks/src/root-block/widgets/edgeless-auto-connect/edgeless-auto-connect.ts index dbbd9184fa..115db07dfe 100644 --- a/blocksuite/blocks/src/root-block/widgets/edgeless-auto-connect/edgeless-auto-connect.ts +++ b/blocksuite/blocks/src/root-block/widgets/edgeless-auto-connect/edgeless-auto-connect.ts @@ -194,7 +194,7 @@ export class EdgelessAutoConnectWidget extends WidgetComponent< note.children.forEach(model => { if (matchFlavours(model, ['affine:surface-ref'])) { - const reference = service.getElementById(model.reference); + const reference = service.crud.getElementById(model.reference); if (!isAutoConnectElement(reference)) return; diff --git a/blocksuite/blocks/src/root-block/widgets/edgeless-remote-selection/index.ts b/blocksuite/blocks/src/root-block/widgets/edgeless-remote-selection/index.ts index 1232667bf1..f0fd1b58c0 100644 --- a/blocksuite/blocks/src/root-block/widgets/edgeless-remote-selection/index.ts +++ b/blocksuite/blocks/src/root-block/widgets/edgeless-remote-selection/index.ts @@ -1,28 +1,26 @@ +import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface'; import { RemoteCursor } from '@blocksuite/affine-components/icons'; import type { RootBlockModel } from '@blocksuite/affine-model'; -import { requestThrottledConnectedFrame } from '@blocksuite/affine-shared/utils'; +import { + getSelectedRect, + isTopLevelBlock, + requestThrottledConnectedFrame, +} from '@blocksuite/affine-shared/utils'; import { WidgetComponent } from '@blocksuite/block-std'; -import { assertExists, pickValues } from '@blocksuite/global/utils'; +import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; +import { pickValues } from '@blocksuite/global/utils'; import type { UserInfo } from '@blocksuite/store'; -import { css, html } from 'lit'; +import { css, html, nothing } from 'lit'; import { state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; import { styleMap } from 'lit/directives/style-map.js'; -import type { EdgelessRootBlockComponent } from '../../../root-block/edgeless/edgeless-root-block.js'; -import { - getSelectedRect, - isTopLevelBlock, -} from '../../../root-block/edgeless/utils/query.js'; import { RemoteColorManager } from '../../../root-block/remote-color-manager/remote-color-manager.js'; export const AFFINE_EDGELESS_REMOTE_SELECTION_WIDGET = 'affine-edgeless-remote-selection-widget'; -export class EdgelessRemoteSelectionWidget extends WidgetComponent< - RootBlockModel, - EdgelessRootBlockComponent -> { +export class EdgelessRemoteSelectionWidget extends WidgetComponent { static override styles = css` :host { pointer-events: none; @@ -109,7 +107,7 @@ export class EdgelessRemoteSelectionWidget extends WidgetComponent< }; private readonly _updateRemoteRects = () => { - const { selection, block } = this; + const { selection } = this; const remoteSelectionsMap = selection.remoteSurfaceSelectionsMap; const remoteRects: EdgelessRemoteSelectionWidget['_remoteRects'] = new Map(); @@ -119,7 +117,7 @@ export class EdgelessRemoteSelectionWidget extends WidgetComponent< if (selection.elements.length === 0) return; const elements = selection.elements - .map(id => block.service.getElementById(id)) + .map(id => this.crud.getElementById(id)) .filter(element => element) as BlockSuite.EdgelessModel[]; const rect = getSelectedRect(elements); @@ -151,7 +149,7 @@ export class EdgelessRemoteSelectionWidget extends WidgetComponent< }; private readonly _updateTransform = requestThrottledConnectedFrame(() => { - const { translateX, translateY, zoom } = this.edgeless.service.viewport; + const { translateX, translateY, zoom } = this.gfx.viewport; this.style.setProperty('--v-zoom', `${zoom}`); @@ -161,24 +159,28 @@ export class EdgelessRemoteSelectionWidget extends WidgetComponent< ); }, this); - get edgeless() { - return this.block; + get gfx() { + return this.std.get(GfxControllerIdentifier); + } + + get crud() { + return this.std.get(EdgelessCRUDIdentifier); } get selection() { - return this.edgeless.service.selection; + return this.gfx.selection; } get surface() { - return this.edgeless.surface; + return this.gfx.surface; } override connectedCallback() { super.connectedCallback(); - const { _disposables, doc, edgeless } = this; + const { _disposables, doc } = this; - pickValues(edgeless.service.surface, [ + pickValues(this.surface!, [ 'elementAdded', 'elementRemoved', 'elementUpdated', @@ -196,7 +198,7 @@ export class EdgelessRemoteSelectionWidget extends WidgetComponent< ); _disposables.add( - edgeless.service.viewport.viewportUpdated.on(() => { + this.gfx.viewport.viewportUpdated.on(() => { this._updateTransform(); }) ); @@ -209,7 +211,7 @@ export class EdgelessRemoteSelectionWidget extends WidgetComponent< override render() { const { _remoteRects, _remoteCursors, _remoteColorManager } = this; - assertExists(_remoteColorManager); + if (!_remoteColorManager) return nothing; const rects = repeat( _remoteRects.entries(), diff --git a/blocksuite/blocks/src/root-block/widgets/element-toolbar/lock-button.ts b/blocksuite/blocks/src/root-block/widgets/element-toolbar/lock-button.ts index 63abd49e20..2b8a65d719 100644 --- a/blocksuite/blocks/src/root-block/widgets/element-toolbar/lock-button.ts +++ b/blocksuite/blocks/src/root-block/widgets/element-toolbar/lock-button.ts @@ -54,7 +54,7 @@ export class EdgelessLockButton extends SignalWatcher( // release other elements from their groups and group with top element otherElements.forEach(element => { - // eslint-disable-next-line + // oxlint-disable-next-line unicorn/prefer-dom-node-remove element.group?.removeChild(element); topElement.group?.addChild(element); }); @@ -72,7 +72,7 @@ export class EdgelessLockButton extends SignalWatcher( const groupId = service.createGroup([topElement, ...otherElements]); if (groupId) { - const group = service.getElementById(groupId); + const group = service.crud.getElementById(groupId); if (group) { group.lock(); this.edgeless.gfx.selection.set({ diff --git a/blocksuite/blocks/src/root-block/widgets/surface-ref-toolbar/utils.ts b/blocksuite/blocks/src/root-block/widgets/surface-ref-toolbar/utils.ts index 9361ca6ce2..ed070b1c13 100644 --- a/blocksuite/blocks/src/root-block/widgets/surface-ref-toolbar/utils.ts +++ b/blocksuite/blocks/src/root-block/widgets/surface-ref-toolbar/utils.ts @@ -1,9 +1,9 @@ import type { CanvasRenderer } from '@blocksuite/affine-block-surface'; +import { isTopLevelBlock } from '@blocksuite/affine-shared/utils'; import type { EditorHost } from '@blocksuite/block-std'; import { assertExists, Bound } from '@blocksuite/global/utils'; import { ExportManager } from '../../../_common/export-manager/export-manager.js'; -import { isTopLevelBlock } from '../../../root-block/edgeless/utils/query.js'; import type { SurfaceRefBlockComponent } from '../../../surface-ref-block/surface-ref-block.js'; export const edgelessToBlob = async ( diff --git a/blocksuite/blocks/src/surface-ref-block/surface-ref-block.ts b/blocksuite/blocks/src/surface-ref-block/surface-ref-block.ts index 813881ba2a..5a24f781af 100644 --- a/blocksuite/blocks/src/surface-ref-block/surface-ref-block.ts +++ b/blocksuite/blocks/src/surface-ref-block/surface-ref-block.ts @@ -452,7 +452,8 @@ export class SurfaceRefBlockComponent extends BlockComponent { const groupId = service.crud.addElement('group', { children }); assertExists(groupId); - const group = service.getElementById(groupId) as GroupElementModel; + const group = service.crud.getElementById(groupId) as GroupElementModel; const assertInitial = () => { expect(group.x).toBe(0); expect(group.y).toBe(0); @@ -190,7 +190,7 @@ describe('group', () => { const map = new DocCollection.Y.Map(); const groupId = service.crud.addElement('group', { children: map }); assertExists(groupId); - const group = service.getElementById(groupId) as GroupElementModel; + const group = service.crud.getElementById(groupId) as GroupElementModel; expect(group.x).toBe(0); expect(group.y).toBe(0); @@ -205,7 +205,7 @@ describe('group', () => { }) as string; }); const groups = groupIds.map( - id => service.getElementById(id) as GroupElementModel + id => service.crud.getElementById(id) as GroupElementModel ); groups.forEach(group => { @@ -255,7 +255,7 @@ describe('mindmap', () => { const mindmapId = service.crud.addElement('mindmap', { children: tree }); assertExists(mindmapId); const mindmap = () => - service.getElementById(mindmapId) as MindmapElementModel; + service.crud.getElementById(mindmapId) as MindmapElementModel; expect(service.surface.elementModels.length).toBe(6); doc.captureSync(); @@ -306,7 +306,7 @@ describe('mindmap', () => { }); assertExists(mindmapId); const mindmap = () => - service.getElementById(mindmapId) as MindmapElementModel; + service.crud.getElementById(mindmapId) as MindmapElementModel; doc.captureSync(); await wait(); @@ -351,7 +351,7 @@ describe('mindmap', () => { }); assertExists(mindmapId); const mindmap = () => - service.getElementById(mindmapId) as MindmapElementModel; + service.crud.getElementById(mindmapId) as MindmapElementModel; doc.captureSync(); await wait(); diff --git a/blocksuite/presets/src/__tests__/edgeless/last-props.spec.ts b/blocksuite/presets/src/__tests__/edgeless/last-props.spec.ts index ae62d6884e..58f091cbc8 100644 --- a/blocksuite/presets/src/__tests__/edgeless/last-props.spec.ts +++ b/blocksuite/presets/src/__tests__/edgeless/last-props.spec.ts @@ -50,7 +50,7 @@ describe('apply last props', () => { shapeType: ShapeType.Rect, }); assertExists(rectId); - const rectShape = service.getElementById(rectId) as ShapeElementModel; + const rectShape = service.crud.getElementById(rectId) as ShapeElementModel; expect(rectShape.fillColor).toBe(ShapeFillColor.Yellow); service.crud.updateElement(rectId, { fillColor: ShapeFillColor.Orange, @@ -65,7 +65,9 @@ describe('apply last props', () => { shapeType: ShapeType.Diamond, }); assertExists(diamondId); - const diamondShape = service.getElementById(diamondId) as ShapeElementModel; + const diamondShape = service.crud.getElementById( + diamondId + ) as ShapeElementModel; expect(diamondShape.fillColor).toBe(ShapeFillColor.Yellow); service.crud.updateElement(diamondId, { fillColor: ShapeFillColor.Blue, @@ -81,7 +83,7 @@ describe('apply last props', () => { radius: 0.1, }); assertExists(roundedRectId); - const roundedRectShape = service.getElementById( + const roundedRectShape = service.crud.getElementById( roundedRectId ) as ShapeElementModel; expect(roundedRectShape.fillColor).toBe(ShapeFillColor.Yellow); @@ -97,14 +99,16 @@ describe('apply last props', () => { shapeType: ShapeType.Rect, }); assertExists(rectId2); - const rectShape2 = service.getElementById(rectId2) as ShapeElementModel; + const rectShape2 = service.crud.getElementById( + rectId2 + ) as ShapeElementModel; expect(rectShape2.fillColor).toBe(ShapeFillColor.Orange); const diamondId2 = service.crud.addElement('shape', { shapeType: ShapeType.Diamond, }); assertExists(diamondId2); - const diamondShape2 = service.getElementById( + const diamondShape2 = service.crud.getElementById( diamondId2 ) as ShapeElementModel; expect(diamondShape2.fillColor).toBe(ShapeFillColor.Blue); @@ -114,7 +118,7 @@ describe('apply last props', () => { radius: 0.1, }); assertExists(roundedRectId2); - const roundedRectShape2 = service.getElementById( + const roundedRectShape2 = service.crud.getElementById( roundedRectId2 ) as ShapeElementModel; expect(roundedRectShape2.fillColor).toBe(ShapeFillColor.Green); @@ -123,7 +127,7 @@ describe('apply last props', () => { test('connector', () => { const id = service.crud.addElement('connector', { mode: 0 }); assertExists(id); - const connector = service.getElementById(id) as ConnectorElementModel; + const connector = service.crud.getElementById(id) as ConnectorElementModel; expect(connector.stroke).toBe(LineColor.Grey); expect(connector.strokeWidth).toBe(2); expect(connector.strokeStyle).toBe('solid'); @@ -133,7 +137,9 @@ describe('apply last props', () => { const id2 = service.crud.addElement('connector', { mode: 1 }); assertExists(id2); - const connector2 = service.getElementById(id2) as ConnectorElementModel; + const connector2 = service.crud.getElementById( + id2 + ) as ConnectorElementModel; expect(connector2.strokeWidth).toBe(10); service.crud.updateElement(id2, { labelStyle: { @@ -144,7 +150,9 @@ describe('apply last props', () => { const id3 = service.crud.addElement('connector', { mode: 1 }); assertExists(id3); - const connector3 = service.getElementById(id3) as ConnectorElementModel; + const connector3 = service.crud.getElementById( + id3 + ) as ConnectorElementModel; expect(connector3.strokeWidth).toBe(10); expect(connector3.labelStyle.color).toBe(LineColor.Magenta); expect(connector3.labelStyle.fontFamily).toBe(FontFamily.Kalam); @@ -153,14 +161,14 @@ describe('apply last props', () => { test('brush', () => { const id = service.crud.addElement('brush', {}); assertExists(id); - const brush = service.getElementById(id) as BrushElementModel; + const brush = service.crud.getElementById(id) as BrushElementModel; expect(brush.color).toEqual({ dark: LineColor.White, light: LineColor.Black, }); expect(brush.lineWidth).toBe(4); service.crud.updateElement(id, { lineWidth: 10 }); - const secondBrush = service.getElementById( + const secondBrush = service.crud.getElementById( service.crud.addElement('brush', {}) as string ) as BrushElementModel; expect(secondBrush.lineWidth).toBe(10); @@ -169,10 +177,10 @@ describe('apply last props', () => { test('text', () => { const id = service.crud.addElement('text', {}); assertExists(id); - const text = service.getElementById(id) as TextElementModel; + const text = service.crud.getElementById(id) as TextElementModel; expect(text.fontSize).toBe(24); service.crud.updateElement(id, { fontSize: 36 }); - const secondText = service.getElementById( + const secondText = service.crud.getElementById( service.crud.addElement('text', {}) as string ) as TextElementModel; expect(secondText.fontSize).toBe(36); @@ -181,7 +189,7 @@ describe('apply last props', () => { test('mindmap', () => { const id = service.crud.addElement('mindmap', {}); assertExists(id); - const mindmap = service.getElementById(id) as MindmapElementModel; + const mindmap = service.crud.getElementById(id) as MindmapElementModel; expect(mindmap.layoutType).toBe(LayoutType.RIGHT); expect(mindmap.style).toBe(MindmapStyle.ONE); service.crud.updateElement(id, { @@ -191,7 +199,7 @@ describe('apply last props', () => { const id2 = service.crud.addElement('mindmap', {}); assertExists(id2); - const mindmap2 = service.getElementById(id2) as MindmapElementModel; + const mindmap2 = service.crud.getElementById(id2) as MindmapElementModel; expect(mindmap2.layoutType).toBe(LayoutType.BALANCE); expect(mindmap2.style).toBe(MindmapStyle.THREE); }); @@ -200,7 +208,7 @@ describe('apply last props', () => { const surface = getSurfaceBlock(doc); const id = service.crud.addBlock('affine:edgeless-text', {}, surface!.id); assertExists(id); - const text = service.getElementById(id) as EdgelessTextBlockModel; + const text = service.crud.getElementById(id) as EdgelessTextBlockModel; expect(text.color).toBe(DEFAULT_TEXT_COLOR); expect(text.fontFamily).toBe(FontFamily.Inter); service.crud.updateElement(id, { @@ -210,7 +218,7 @@ describe('apply last props', () => { const id2 = service.crud.addBlock('affine:edgeless-text', {}, surface!.id); assertExists(id2); - const text2 = service.getElementById(id2) as EdgelessTextBlockModel; + const text2 = service.crud.getElementById(id2) as EdgelessTextBlockModel; expect(text2.color).toBe(LineColor.Green); expect(text2.fontFamily).toBe(FontFamily.OrelegaOne); }); @@ -218,7 +226,7 @@ describe('apply last props', () => { test('note', () => { const id = service.crud.addBlock('affine:note', {}, doc.root!.id); assertExists(id); - const note = service.getElementById(id) as NoteBlockModel; + const note = service.crud.getElementById(id) as NoteBlockModel; expect(note.background).toBe(DEFAULT_NOTE_BACKGROUND_COLOR); expect(note.edgeless.style.shadowType).toBe(DEFAULT_NOTE_SHADOW); service.crud.updateElement(id, { @@ -232,7 +240,7 @@ describe('apply last props', () => { const id2 = service.crud.addBlock('affine:note', {}, doc.root!.id); assertExists(id2); - const note2 = service.getElementById(id2) as NoteBlockModel; + const note2 = service.crud.getElementById(id2) as NoteBlockModel; expect(note2.background).toBe(NoteBackgroundColor.Purple); expect(note2.edgeless.style.shadowType).toBe(NoteShadow.Film); }); @@ -241,7 +249,7 @@ describe('apply last props', () => { const surface = getSurfaceBlock(doc); const id = service.crud.addBlock('affine:frame', {}, surface!.id); assertExists(id); - const note = service.getElementById(id) as FrameBlockModel; + const note = service.crud.getElementById(id) as FrameBlockModel; expect(note.background).toBe('--affine-palette-transparent'); service.crud.updateElement(id, { background: FrameBackgroundColor.Purple, @@ -249,7 +257,7 @@ describe('apply last props', () => { const id2 = service.crud.addBlock('affine:frame', {}, surface!.id); assertExists(id2); - const frame2 = service.getElementById(id2) as FrameBlockModel; + const frame2 = service.crud.getElementById(id2) as FrameBlockModel; expect(frame2.background).toBe(FrameBackgroundColor.Purple); service.crud.updateElement(id2, { background: { normal: '#def4e740' }, @@ -257,7 +265,7 @@ describe('apply last props', () => { const id3 = service.crud.addBlock('affine:frame', {}, surface!.id); assertExists(id3); - const frame3 = service.getElementById(id3) as FrameBlockModel; + const frame3 = service.crud.getElementById(id3) as FrameBlockModel; expect(frame3.background).toEqual({ normal: '#def4e740' }); service.crud.updateElement(id3, { background: { light: '#a381aa23', dark: '#6e907452' }, @@ -265,7 +273,7 @@ describe('apply last props', () => { const id4 = service.crud.addBlock('affine:frame', {}, surface!.id); assertExists(id4); - const frame4 = service.getElementById(id4) as FrameBlockModel; + const frame4 = service.crud.getElementById(id4) as FrameBlockModel; expect(frame4.background).toEqual({ light: '#a381aa23', dark: '#6e907452', diff --git a/blocksuite/presets/src/__tests__/edgeless/layer.spec.ts b/blocksuite/presets/src/__tests__/edgeless/layer.spec.ts index 8e0f69847b..c250fb4a77 100644 --- a/blocksuite/presets/src/__tests__/edgeless/layer.spec.ts +++ b/blocksuite/presets/src/__tests__/edgeless/layer.spec.ts @@ -91,7 +91,7 @@ test('change element should update layer automatically', async () => { service.crud.updateElement(id, { index: service.layer.getReorderedIndex( - service.getElementById(id)!, + service.crud.getElementById(id)!, 'forward' ), }); @@ -101,7 +101,7 @@ test('change element should update layer automatically', async () => { service.crud.updateElement(canvasElId!, { index: service.layer.getReorderedIndex( - service.getElementById(canvasElId!)!, + service.crud.getElementById(canvasElId!)!, 'forward' ), }); @@ -160,7 +160,7 @@ test('a new layer should be created in canvasLayers prop when the topmost layer test('layer zindex should update correctly when elements changed', async () => { addNote(doc); const noteId = addNote(doc); - const note = service.getElementById(noteId); + const note = service.crud.getElementById(noteId); addNote(doc); service.crud.addElement('shape', { shapeType: 'rect', @@ -168,7 +168,7 @@ test('layer zindex should update correctly when elements changed', async () => { const topShapeId = service.crud.addElement('shape', { shapeType: 'rect', }); - const topShape = service.getElementById(topShapeId!)!; + const topShape = service.crud.getElementById(topShapeId!)!; await wait(); @@ -238,8 +238,8 @@ test('blocks should rerender when their z-index changed', async () => { service.crud.addElement('shape', { shapeType: 'rect', index: CommonUtils.generateKeyBetween( - service.getElementById(blocks[1])!.index, - service.getElementById(blocks[2])!.index + service.crud.getElementById(blocks[1])!.index, + service.crud.getElementById(blocks[2])!.index ), }); @@ -266,19 +266,19 @@ describe('layer reorder functionality', () => { test('forward', async () => { service.crud.updateElement(ids[0], { index: service.layer.getReorderedIndex( - service.getElementById(ids[0])!, + service.crud.getElementById(ids[0])!, 'forward' ), }); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[0]) as any) + layer.set.has(service.crud.getElementById(ids[0]) as any) ) ).toBe(1); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[1]) as any) + layer.set.has(service.crud.getElementById(ids[1]) as any) ) ).toBe(0); @@ -286,19 +286,19 @@ describe('layer reorder functionality', () => { service.crud.updateElement(ids[1], { index: service.layer.getReorderedIndex( - service.getElementById(ids[1])!, + service.crud.getElementById(ids[1])!, 'forward' ), }); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[0]) as any) + layer.set.has(service.crud.getElementById(ids[0]) as any) ) ).toBe(0); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[1]) as any) + layer.set.has(service.crud.getElementById(ids[1]) as any) ) ).toBe(1); }); @@ -306,7 +306,7 @@ describe('layer reorder functionality', () => { test('front', async () => { service.crud.updateElement(ids[0], { index: service.layer.getReorderedIndex( - service.getElementById(ids[0])!, + service.crud.getElementById(ids[0])!, 'front' ), }); @@ -315,20 +315,20 @@ describe('layer reorder functionality', () => { expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[0]) as any) + layer.set.has(service.crud.getElementById(ids[0]) as any) ) ).toBe(3); service.crud.updateElement(ids[1], { index: service.layer.getReorderedIndex( - service.getElementById(ids[1])!, + service.crud.getElementById(ids[1])!, 'front' ), }); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[1]) as any) + layer.set.has(service.crud.getElementById(ids[1]) as any) ) ).toBe(3); }); @@ -336,19 +336,19 @@ describe('layer reorder functionality', () => { test('backward', async () => { service.crud.updateElement(ids[3], { index: service.layer.getReorderedIndex( - service.getElementById(ids[3])!, + service.crud.getElementById(ids[3])!, 'backward' ), }); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[3]) as any) + layer.set.has(service.crud.getElementById(ids[3]) as any) ) ).toBe(1); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[2]) as any) + layer.set.has(service.crud.getElementById(ids[2]) as any) ) ).toBe(2); @@ -356,19 +356,19 @@ describe('layer reorder functionality', () => { service.crud.updateElement(ids[2], { index: service.layer.getReorderedIndex( - service.getElementById(ids[2])!, + service.crud.getElementById(ids[2])!, 'backward' ), }); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[3]) as any) + layer.set.has(service.crud.getElementById(ids[3]) as any) ) ).toBe(3); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[2]) as any) + layer.set.has(service.crud.getElementById(ids[2]) as any) ) ).toBe(2); }); @@ -376,14 +376,14 @@ describe('layer reorder functionality', () => { test('back', async () => { service.crud.updateElement(ids[3], { index: service.layer.getReorderedIndex( - service.getElementById(ids[3])!, + service.crud.getElementById(ids[3])!, 'back' ), }); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[3]) as any) + layer.set.has(service.crud.getElementById(ids[3]) as any) ) ).toBe(0); @@ -391,14 +391,14 @@ describe('layer reorder functionality', () => { service.crud.updateElement(ids[2], { index: service.layer.getReorderedIndex( - service.getElementById(ids[2])!, + service.crud.getElementById(ids[2])!, 'back' ), }); expect( service.layer.layers.findIndex(layer => - layer.set.has(service.getElementById(ids[2]) as any) + layer.set.has(service.crud.getElementById(ids[2]) as any) ) ).toBe(0); }); @@ -507,7 +507,7 @@ describe('group related functionality', () => { service, elements.filter((_, idx) => idx !== 1 && idx !== 3) )!; - const group = service.getElementById(groupId)!; + const group = service.crud.getElementById(groupId)!; expect(service.layer.layers.length).toBe(2); @@ -538,7 +538,7 @@ describe('group related functionality', () => { })!, ]; service.doc.captureSync(); - const elements = elementIds.map(id => service.getElementById(id)!); + const elements = elementIds.map(id => service.crud.getElementById(id)!); const isKeptRelativeOrder = () => { return elements.every((element, idx) => { @@ -552,7 +552,7 @@ describe('group related functionality', () => { const groupId = createGroup(edgeless.service, elementIds)!; expect(isKeptRelativeOrder()).toBeTruthy(); - service.ungroup(service.getElementById(groupId) as GroupElementModel); + service.ungroup(service.crud.getElementById(groupId) as GroupElementModel); expect(isKeptRelativeOrder()).toBeTruthy(); service.doc.undo(); @@ -586,15 +586,15 @@ describe('compare function', () => { const shapeId = service.crud.addElement('shape', { shapeType: 'rect', })!; - const shapeEl = service.getElementById(shapeId)!; + const shapeEl = service.crud.getElementById(shapeId)!; expect(service.layer.compare(shapeEl, shapeEl)).toBe(SORT_ORDER.SAME); const groupId = createGroup(service, [shapeId])!; - const groupEl = service.getElementById(groupId)!; + const groupEl = service.crud.getElementById(groupId)!; expect(service.layer.compare(groupEl, groupEl)).toBe(SORT_ORDER.SAME); const noteId = addNote(doc); - const note = service.getElementById(noteId)! as NoteBlockModel; + const note = service.crud.getElementById(noteId)! as NoteBlockModel; expect(service.layer.compare(note, note)).toBe(SORT_ORDER.SAME); }); @@ -602,11 +602,11 @@ describe('compare function', () => { const shapeId = service.crud.addElement('shape', { shapeType: 'rect', })!; - const shapeEl = service.getElementById(shapeId)!; + const shapeEl = service.crud.getElementById(shapeId)!; const noteId = addNote(doc); - const note = service.getElementById(noteId)! as NoteBlockModel; + const note = service.crud.getElementById(noteId)! as NoteBlockModel; const groupId = createGroup(service, [shapeId, noteId])!; - const groupEl = service.getElementById(groupId)!; + const groupEl = service.crud.getElementById(groupId)!; expect(service.layer.compare(groupEl, shapeEl)).toBe(SORT_ORDER.BEFORE); expect(service.layer.compare(shapeEl, groupEl)).toBe(SORT_ORDER.AFTER); @@ -618,16 +618,16 @@ describe('compare function', () => { const shape1Id = service.crud.addElement('shape', { shapeType: 'rect', })!; - const shape1 = service.getElementById(shape1Id)!; + const shape1 = service.crud.getElementById(shape1Id)!; const shape2Id = service.crud.addElement('shape', { shapeType: 'rect', })!; - const shape2 = service.getElementById(shape2Id)!; + const shape2 = service.crud.getElementById(shape2Id)!; const note1Id = addNote(doc); - const note1 = service.getElementById(note1Id)! as NoteBlockModel; + const note1 = service.crud.getElementById(note1Id)! as NoteBlockModel; const note2Id = addNote(doc); - const note2 = service.getElementById(note2Id)! as NoteBlockModel; + const note2 = service.crud.getElementById(note2Id)! as NoteBlockModel; expect(service.layer.compare(shape1, shape2)).toBe(SORT_ORDER.BEFORE); expect(service.layer.compare(shape2, shape1)).toBe(SORT_ORDER.AFTER); @@ -659,12 +659,12 @@ describe('compare function', () => { ])!; const group2Id = createGroup(service, [group1Id])!; - const shape1 = service.getElementById(shape1Id)!; - const shape2 = service.getElementById(shape2Id)!; - const note1 = service.getElementById(note1Id)! as NoteBlockModel; - const note2 = service.getElementById(note2Id)! as NoteBlockModel; - const group1 = service.getElementById(group1Id)!; - const group2 = service.getElementById(group2Id)!; + const shape1 = service.crud.getElementById(shape1Id)!; + const shape2 = service.crud.getElementById(shape2Id)!; + const note1 = service.crud.getElementById(note1Id)! as NoteBlockModel; + const note2 = service.crud.getElementById(note2Id)! as NoteBlockModel; + const group1 = service.crud.getElementById(group1Id)!; + const group2 = service.crud.getElementById(group2Id)!; // assert nested group to group expect(service.layer.compare(group2, group1)).toBe(SORT_ORDER.BEFORE); @@ -695,9 +695,9 @@ describe('compare function', () => { const groupAId = createGroup(service, [ createGroup(service, [groupAShapeId, groupANoteId])!, ])!; - const groupAShape = service.getElementById(groupAShapeId)!; - const groupANote = service.getElementById(groupANoteId)!; - const groupA = service.getElementById(groupAId)!; + const groupAShape = service.crud.getElementById(groupAShapeId)!; + const groupANote = service.crud.getElementById(groupANoteId)!; + const groupA = service.crud.getElementById(groupAId)!; const groupBShapeId = service.crud.addElement('shape', { shapeType: 'rect', @@ -706,9 +706,9 @@ describe('compare function', () => { const groupBId = createGroup(service, [ createGroup(service, [groupBShapeId, groupBNoteId])!, ])!; - const groupBShape = service.getElementById(groupBShapeId)!; - const groupBNote = service.getElementById(groupBNoteId)!; - const groupB = service.getElementById(groupBId)!; + const groupBShape = service.crud.getElementById(groupBShapeId)!; + const groupBNote = service.crud.getElementById(groupBNoteId)!; + const groupB = service.crud.getElementById(groupBId)!; expect(service.layer.compare(groupAShape, groupBShape)).toBe( SORT_ORDER.BEFORE @@ -860,10 +860,10 @@ describe('index generator', () => { })!; const noteId = addNote(doc); - preinsertedShape = service.getElementById( + preinsertedShape = service.crud.getElementById( shapeId )! as BlockSuite.SurfaceElementModel; - preinsertedNote = service.getElementById(noteId)! as NoteBlockModel; + preinsertedNote = service.crud.getElementById(noteId)! as NoteBlockModel; }); test('generator should remember the index it generated', () => { diff --git a/blocksuite/presets/src/__tests__/edgeless/surface-ref.spec.ts b/blocksuite/presets/src/__tests__/edgeless/surface-ref.spec.ts index b6040e9ed0..0de75804d7 100644 --- a/blocksuite/presets/src/__tests__/edgeless/surface-ref.spec.ts +++ b/blocksuite/presets/src/__tests__/edgeless/surface-ref.spec.ts @@ -211,7 +211,7 @@ describe('basic', () => { const edgeless = surfaceRef.previewEditor!.std.get(EdgelessRootService); - const group = edgeless.getElementById(groupId)!; + const group = edgeless.crud.getElementById(groupId)!; expect(edgeless.viewport.isInViewport(group.elementBound)).toBeTruthy(); }); diff --git a/blocksuite/presets/src/__tests__/edgeless/tools.spec.ts b/blocksuite/presets/src/__tests__/edgeless/tools.spec.ts index aab77dfc14..f7322b1cb0 100644 --- a/blocksuite/presets/src/__tests__/edgeless/tools.spec.ts +++ b/blocksuite/presets/src/__tests__/edgeless/tools.spec.ts @@ -64,7 +64,7 @@ describe('default tool', () => { drag(edgeless.host, { x: 0, y: 50 }, { x: 0, y: 150 }); await wait(); - const element = service.getElementById(id!)!; + const element = service.crud.getElementById(id!)!; expect(element.xywh).toEqual(`[0,100,100,100]`); }); @@ -86,7 +86,7 @@ describe('default tool', () => { drag(edgeless.host, { x: 50, y: 50 }, { x: 150, y: 150 }); await wait(); - const element = service.getElementById(noteId)!; + const element = service.crud.getElementById(noteId)!; const [x, y] = JSON.parse(element.xywh); expect(x).toEqual(100); diff --git a/blocksuite/tests-legacy/edgeless/linked-doc.spec.ts b/blocksuite/tests-legacy/edgeless/linked-doc.spec.ts index 5215ff760b..2ae9ba391e 100644 --- a/blocksuite/tests-legacy/edgeless/linked-doc.spec.ts +++ b/blocksuite/tests-legacy/edgeless/linked-doc.spec.ts @@ -124,7 +124,7 @@ test.describe('single edgeless element to linked doc', () => { const shapes = await page.evaluate(() => { const container = document.querySelector('affine-edgeless-root'); - return container!.service + return container!.service.crud .getElementsByType('shape') .map(s => ({ type: s.type, xywh: s.xywh })); }); @@ -163,7 +163,7 @@ test.describe('single edgeless element to linked doc', () => { await waitNextFrame(page, 200); const brushes = await page.evaluate(() => { const container = document.querySelector('affine-edgeless-root'); - return container!.service + return container!.service.crud .getElementsByType('brush') .map(s => ({ type: s.type, xywh: s.xywh })); }); @@ -191,9 +191,9 @@ test.describe('single edgeless element to linked doc', () => { await waitNextFrame(page, 200); const groups = await page.evaluate(() => { const container = document.querySelector('affine-edgeless-root'); - return container!.service.getElementsByType('group').map(s => ({ + return container!.service.crud.getElementsByType('group').map(s => ({ type: s.type, - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // oxlint-disable-next-line @typescript-eslint/no-explicit-any children: s.childElements.map((c: any) => c.type || c.flavour), })); }); diff --git a/blocksuite/tests-legacy/utils/actions/edgeless.ts b/blocksuite/tests-legacy/utils/actions/edgeless.ts index 51a318a955..f3a733b5d9 100644 --- a/blocksuite/tests-legacy/utils/actions/edgeless.ts +++ b/blocksuite/tests-legacy/utils/actions/edgeless.ts @@ -1005,7 +1005,7 @@ export async function deleteAllConnectors(page: Page) { return page.evaluate(() => { const container = document.querySelector('affine-edgeless-root'); if (!container) throw new Error('container not found'); - container.service.getElementsByType('connector').forEach(c => { + container.service.crud.getElementsByType('connector').forEach(c => { container.service.removeElement(c.id); }); }); @@ -1604,7 +1604,7 @@ export async function getConnectorSourceConnection(page: Page) { return page.evaluate(() => { const container = document.querySelector('affine-edgeless-root'); if (!container) throw new Error('container not found'); - return container.service.getElementsByType('connector')[0].source; + return container.service.crud.getElementsByType('connector')[0].source; }); } @@ -1613,7 +1613,7 @@ export async function getConnectorPath(page: Page, index = 0): Promise { ([index]) => { const container = document.querySelector('affine-edgeless-root'); if (!container) throw new Error('container not found'); - const connectors = container.service.getElementsByType('connector'); + const connectors = container.service.crud.getElementsByType('connector'); return connectors[index].absolutePath; }, [index] @@ -1628,7 +1628,7 @@ export async function getEdgelessElementBound( ([elementId]) => { const container = document.querySelector('affine-edgeless-root'); if (!container) throw new Error('container not found'); - const element = container.service.getElementById(elementId); + const element = container.service.crud.getElementById(elementId); if (!element) throw new Error(`element not found: ${elementId}`); return JSON.parse(element.xywh); }, @@ -1692,7 +1692,7 @@ export async function getContainerChildIds(page: Page, id: string) { ([id]) => { const container = document.querySelector('affine-edgeless-root'); if (!container) throw new Error('container not found'); - const gfxModel = container.service.getElementById(id); + const gfxModel = container.service.crud.getElementById(id); return gfxModel && container.service.surface.isGroup(gfxModel) ? gfxModel.childIds @@ -1731,7 +1731,7 @@ export async function getTypeById(page: Page, id: string) { ([id]) => { const container = document.querySelector('affine-edgeless-root'); if (!container) throw new Error('container not found'); - const element = container.service.getElementById(id)!; + const element = container.service.crud.getElementById(id)!; return 'flavour' in element ? element.flavour : element.type; }, [id] diff --git a/packages/frontend/core/src/blocksuite/presets/ai/peek-view/utils.ts b/packages/frontend/core/src/blocksuite/presets/ai/peek-view/utils.ts index ce0d5f65eb..1384d299d8 100644 --- a/packages/frontend/core/src/blocksuite/presets/ai/peek-view/utils.ts +++ b/packages/frontend/core/src/blocksuite/presets/ai/peek-view/utils.ts @@ -41,7 +41,7 @@ export function calcChildBound( const targetBlocks = childConnectors .map(connector => connector.target.id) .filter(id => id !== undefined) - .map(id => service.getElementById(id)) + .map(id => service.crud.getElementById(id)) .filter(block => !!block); if (targetBlocks.length) {