mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 05:14:54 +00:00
refactor(editor): query methods in edgeless api (#9407)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
})
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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' });
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<K extends keyof BlockSuite.SurfaceElementModelMap>(
|
||||
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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { GroupElementModel } from '@blocksuite/affine-model';
|
||||
export function getElementsWithoutGroup(elements: BlockSuite.EdgelessModel[]) {
|
||||
const set = new Set<BlockSuite.EdgelessModel>();
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<RootBlockModel> {
|
||||
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;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<RootBlockModel> {
|
||||
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(),
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -452,7 +452,8 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
||||
const edgelessService = this.std.get(EdgelessRootService);
|
||||
const { _disposable } = this;
|
||||
|
||||
const referenceElement = edgelessService.getElementById(referenceId);
|
||||
const referenceElement =
|
||||
edgelessService.crud.getElementById(referenceId);
|
||||
if (!referenceElement) {
|
||||
throw new BlockSuiteError(
|
||||
ErrorCode.MissingViewModelError,
|
||||
|
||||
Reference in New Issue
Block a user