feat(editor): add edgeless crud extension (#9335)
This commit is contained in:
@@ -5,7 +5,10 @@ import {
|
|||||||
MindmapElementModel,
|
MindmapElementModel,
|
||||||
NoteBlockModel,
|
NoteBlockModel,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import type { GfxModel } from '@blocksuite/block-std/gfx';
|
import {
|
||||||
|
GfxControllerIdentifier,
|
||||||
|
type GfxModel,
|
||||||
|
} from '@blocksuite/block-std/gfx';
|
||||||
import { Bound } from '@blocksuite/global/utils';
|
import { Bound } from '@blocksuite/global/utils';
|
||||||
import chunk from 'lodash.chunk';
|
import chunk from 'lodash.chunk';
|
||||||
|
|
||||||
@@ -15,6 +18,7 @@ const ALIGN_PADDING = 20;
|
|||||||
import type { Command } from '@blocksuite/block-std';
|
import type { Command } from '@blocksuite/block-std';
|
||||||
import type { BlockModel, BlockProps } from '@blocksuite/store';
|
import type { BlockModel, BlockProps } from '@blocksuite/store';
|
||||||
|
|
||||||
|
import { EdgelessCRUDIdentifier } from '../extensions/crud-extension.js';
|
||||||
import { updateXYWH } from '../utils/update-xywh.js';
|
import { updateXYWH } from '../utils/update-xywh.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,11 +29,10 @@ export const autoArrangeElementsCommand: Command<never, never, {}> = (
|
|||||||
next
|
next
|
||||||
) => {
|
) => {
|
||||||
const { updateBlock } = ctx.std.doc;
|
const { updateBlock } = ctx.std.doc;
|
||||||
const rootService = ctx.std.getService('affine:page');
|
const gfx = ctx.std.get(GfxControllerIdentifier);
|
||||||
// @ts-expect-error TODO: fix after edgeless refactor
|
|
||||||
const elements = rootService?.selection.selectedElements;
|
const elements = gfx.selection.selectedElements;
|
||||||
// @ts-expect-error TODO: fix after edgeless refactor
|
const { updateElement } = ctx.std.get(EdgelessCRUDIdentifier);
|
||||||
const updateElement = rootService?.updateElement;
|
|
||||||
if (elements && updateElement) {
|
if (elements && updateElement) {
|
||||||
autoArrangeElements(elements, updateElement, updateBlock);
|
autoArrangeElements(elements, updateElement, updateBlock);
|
||||||
}
|
}
|
||||||
@@ -44,11 +47,10 @@ export const autoResizeElementsCommand: Command<never, never, {}> = (
|
|||||||
next
|
next
|
||||||
) => {
|
) => {
|
||||||
const { updateBlock } = ctx.std.doc;
|
const { updateBlock } = ctx.std.doc;
|
||||||
const rootService = ctx.std.getService('affine:page');
|
const gfx = ctx.std.get(GfxControllerIdentifier);
|
||||||
// @ts-expect-error TODO: fix after edgeless refactor
|
|
||||||
const elements = rootService?.selection.selectedElements;
|
const elements = gfx.selection.selectedElements;
|
||||||
// @ts-expect-error TODO: fix after edgeless refactor
|
const { updateElement } = ctx.std.get(EdgelessCRUDIdentifier);
|
||||||
const updateElement = rootService?.updateElement;
|
|
||||||
if (elements && updateElement) {
|
if (elements && updateElement) {
|
||||||
autoResizeElements(elements, updateElement, updateBlock);
|
autoResizeElements(elements, updateElement, updateBlock);
|
||||||
}
|
}
|
||||||
|
|||||||
140
blocksuite/affine/block-surface/src/extensions/crud-extension.ts
Normal file
140
blocksuite/affine/block-surface/src/extensions/crud-extension.ts
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
||||||
|
import {
|
||||||
|
type BlockStdScope,
|
||||||
|
Extension,
|
||||||
|
StdIdentifier,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
|
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||||
|
import { type Container, createIdentifier } from '@blocksuite/global/di';
|
||||||
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
|
import type { SurfaceBlockModel } from '../surface-model';
|
||||||
|
import { getLastPropsKey } from '../utils/get-last-props-key';
|
||||||
|
import { isConnectable, isNoteBlock } from './query';
|
||||||
|
|
||||||
|
export const EdgelessCRUDIdentifier = createIdentifier<EdgelessCRUDExtension>(
|
||||||
|
'AffineEdgelessCrudService'
|
||||||
|
);
|
||||||
|
|
||||||
|
export class EdgelessCRUDExtension extends Extension {
|
||||||
|
constructor(readonly std: BlockStdScope) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
static override setup(di: Container) {
|
||||||
|
di.add(this, [StdIdentifier]);
|
||||||
|
di.addImpl(EdgelessCRUDIdentifier, provider => provider.get(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _gfx() {
|
||||||
|
return this.std.get(GfxControllerIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _surface() {
|
||||||
|
return this._gfx.surface as SurfaceBlockModel | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteElements(elements: BlockSuite.EdgelessModel[]) {
|
||||||
|
const surface = this._surface;
|
||||||
|
if (!surface) {
|
||||||
|
console.error('surface is not initialized');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gfx = this.std.get(GfxControllerIdentifier);
|
||||||
|
const set = new Set(elements);
|
||||||
|
elements.forEach(element => {
|
||||||
|
if (isConnectable(element)) {
|
||||||
|
const connectors = surface.getConnectors(element.id);
|
||||||
|
connectors.forEach(connector => set.add(connector));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
set.forEach(element => {
|
||||||
|
if (isNoteBlock(element)) {
|
||||||
|
const children = gfx.doc.root?.children ?? [];
|
||||||
|
if (children.length > 1) {
|
||||||
|
gfx.doc.deleteBlock(element);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gfx.deleteElement(element.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addBlock(
|
||||||
|
flavour: BlockSuite.EdgelessModelKeys | string,
|
||||||
|
props: Record<string, unknown>,
|
||||||
|
parentId?: string | BlockModel,
|
||||||
|
parentIndex?: number
|
||||||
|
) {
|
||||||
|
const gfx = this.std.get(GfxControllerIdentifier);
|
||||||
|
const key = getLastPropsKey(flavour as BlockSuite.EdgelessModelKeys, props);
|
||||||
|
if (key) {
|
||||||
|
props = this.std.get(EditPropsStore).applyLastProps(key, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nProps = {
|
||||||
|
...props,
|
||||||
|
index: gfx.layer.generateIndex(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.std.doc.addBlock(
|
||||||
|
flavour as never,
|
||||||
|
nProps,
|
||||||
|
parentId,
|
||||||
|
parentIndex
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
addElement<T extends Record<string, unknown>>(type: string, props: T) {
|
||||||
|
const surface = this._surface;
|
||||||
|
if (!surface) {
|
||||||
|
console.error('surface is not initialized');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gfx = this.std.get(GfxControllerIdentifier);
|
||||||
|
const key = getLastPropsKey(type as BlockSuite.EdgelessModelKeys, props);
|
||||||
|
if (key) {
|
||||||
|
props = this.std.get(EditPropsStore).applyLastProps(key, props) as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nProps = {
|
||||||
|
...props,
|
||||||
|
type,
|
||||||
|
index: props.index ?? gfx.layer.generateIndex(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return surface.addElement(nProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateElement = (id: string, props: Record<string, unknown>) => {
|
||||||
|
const surface = this._surface;
|
||||||
|
if (!surface) {
|
||||||
|
console.error('surface is not initialized');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const element = this._surface.getElementById(id);
|
||||||
|
if (element) {
|
||||||
|
const key = getLastPropsKey(
|
||||||
|
element.type as BlockSuite.EdgelessModelKeys,
|
||||||
|
{ ...element.yMap.toJSON(), ...props }
|
||||||
|
);
|
||||||
|
key && this.std.get(EditPropsStore).recordLastProps(key, props);
|
||||||
|
this._surface.updateElement(id, props);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const block = this.std.doc.getBlockById(id);
|
||||||
|
if (block) {
|
||||||
|
const key = getLastPropsKey(
|
||||||
|
block.flavour as BlockSuite.EdgelessModelKeys,
|
||||||
|
{ ...block.yBlock.toJSON(), ...props }
|
||||||
|
);
|
||||||
|
key && this.std.get(EditPropsStore).recordLastProps(key, props);
|
||||||
|
this.std.doc.updateBlock(block, props);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
1
blocksuite/affine/block-surface/src/extensions/index.ts
Normal file
1
blocksuite/affine/block-surface/src/extensions/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './crud-extension';
|
||||||
16
blocksuite/affine/block-surface/src/extensions/query.ts
Normal file
16
blocksuite/affine/block-surface/src/extensions/query.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import type { NoteBlockModel } from '@blocksuite/affine-model';
|
||||||
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
|
import type { Connectable } from '../managers/connector-manager';
|
||||||
|
|
||||||
|
export function isConnectable(
|
||||||
|
element: BlockSuite.EdgelessModel | null
|
||||||
|
): element is Connectable {
|
||||||
|
return !!element && element.connectable;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isNoteBlock(
|
||||||
|
element: BlockModel | BlockSuite.EdgelessModel | null
|
||||||
|
): element is NoteBlockModel {
|
||||||
|
return !!element && 'flavour' in element && element.flavour === 'affine:note';
|
||||||
|
}
|
||||||
@@ -88,7 +88,11 @@ import {
|
|||||||
} from '@blocksuite/global/utils';
|
} from '@blocksuite/global/utils';
|
||||||
import { generateKeyBetween } from 'fractional-indexing';
|
import { generateKeyBetween } from 'fractional-indexing';
|
||||||
|
|
||||||
import { generateElementId, normalizeWheelDeltaY } from './utils/index.js';
|
import {
|
||||||
|
generateElementId,
|
||||||
|
getLastPropsKey,
|
||||||
|
normalizeWheelDeltaY,
|
||||||
|
} from './utils';
|
||||||
import {
|
import {
|
||||||
addTree,
|
addTree,
|
||||||
containsNode,
|
containsNode,
|
||||||
@@ -98,9 +102,11 @@ import {
|
|||||||
hideNodeConnector,
|
hideNodeConnector,
|
||||||
moveNode,
|
moveNode,
|
||||||
tryMoveNode,
|
tryMoveNode,
|
||||||
} from './utils/mindmap/utils.js';
|
} from './utils/mindmap/utils';
|
||||||
export type { Options } from './utils/rough/core.js';
|
export * from './extensions';
|
||||||
export { sortIndex } from './utils/sort.js';
|
export { getLastPropsKey } from './utils/get-last-props-key';
|
||||||
|
export type { Options } from './utils/rough/core';
|
||||||
|
export { sortIndex } from './utils/sort';
|
||||||
export { updateXYWH } from './utils/update-xywh.js';
|
export { updateXYWH } from './utils/update-xywh.js';
|
||||||
|
|
||||||
export const ConnectorUtils = {
|
export const ConnectorUtils = {
|
||||||
@@ -129,6 +135,7 @@ export const CommonUtils = {
|
|||||||
getPointFromBoundsWithRotation,
|
getPointFromBoundsWithRotation,
|
||||||
getStroke,
|
getStroke,
|
||||||
getSvgPathFromStroke,
|
getSvgPathFromStroke,
|
||||||
|
getLastPropsKey,
|
||||||
intersects,
|
intersects,
|
||||||
isOverlap,
|
isOverlap,
|
||||||
isPointIn,
|
isPointIn,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
SurfaceBlockAdapterExtensions,
|
SurfaceBlockAdapterExtensions,
|
||||||
} from './adapters/extension.js';
|
} from './adapters/extension.js';
|
||||||
import { commands } from './commands/index.js';
|
import { commands } from './commands/index.js';
|
||||||
|
import { EdgelessCRUDExtension } from './extensions/crud-extension.js';
|
||||||
import { SurfaceBlockService } from './surface-service.js';
|
import { SurfaceBlockService } from './surface-service.js';
|
||||||
import { MindMapView } from './view/mindmap.js';
|
import { MindMapView } from './view/mindmap.js';
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ const CommonSurfaceBlockSpec: ExtensionType[] = [
|
|||||||
CommandExtension(commands),
|
CommandExtension(commands),
|
||||||
HighlightSelectionExtension,
|
HighlightSelectionExtension,
|
||||||
MindMapView,
|
MindMapView,
|
||||||
|
EdgelessCRUDExtension,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const PageSurfaceBlockSpec: ExtensionType[] = [
|
export const PageSurfaceBlockSpec: ExtensionType[] = [
|
||||||
|
|||||||
@@ -32,3 +32,5 @@ export function normalizeWheelDeltaY(delta: number, zoom = 1) {
|
|||||||
Math.min(1, abs / 20);
|
Math.min(1, abs / 20);
|
||||||
return newZoom;
|
return newZoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { getLastPropsKey } from './get-last-props-key';
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import { toast } from '@blocksuite/affine-components/toast';
|
import { toast } from '@blocksuite/affine-components/toast';
|
||||||
import type { EmbedCardStyle } from '@blocksuite/affine-model';
|
import type { EmbedCardStyle } from '@blocksuite/affine-model';
|
||||||
import {
|
import {
|
||||||
@@ -71,6 +72,7 @@ export class EmbedCardCreateModal extends WithDisposable(ShadowlessElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const gfx = this.host.std.get(GfxControllerIdentifier);
|
const gfx = this.host.std.get(GfxControllerIdentifier);
|
||||||
|
const crud = this.host.std.get(EdgelessCRUDIdentifier);
|
||||||
|
|
||||||
const viewport = gfx.viewport;
|
const viewport = gfx.viewport;
|
||||||
const surfaceModel = gfx.surface;
|
const surfaceModel = gfx.surface;
|
||||||
@@ -79,7 +81,7 @@ export class EmbedCardCreateModal extends WithDisposable(ShadowlessElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const center = Vec.toVec(viewport.center);
|
const center = Vec.toVec(viewport.center);
|
||||||
edgelessRoot.service.addBlock(
|
crud.addBlock(
|
||||||
flavour,
|
flavour,
|
||||||
{
|
{
|
||||||
url,
|
url,
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
|
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
|
||||||
import type { Command } from '@blocksuite/block-std';
|
import type { Command } from '@blocksuite/block-std';
|
||||||
|
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||||
import { Bound } from '@blocksuite/global/utils';
|
import { Bound } from '@blocksuite/global/utils';
|
||||||
|
|
||||||
import { EdgelessRootService } from '../../root-block/edgeless/edgeless-root-service.js';
|
|
||||||
import { getSurfaceBlock } from '../../surface-ref-block/utils.js';
|
import { getSurfaceBlock } from '../../surface-ref-block/utils.js';
|
||||||
import {
|
import {
|
||||||
EDGELESS_TEXT_BLOCK_MIN_HEIGHT,
|
EDGELESS_TEXT_BLOCK_MIN_HEIGHT,
|
||||||
@@ -21,15 +22,16 @@ export const insertEdgelessTextCommand: Command<
|
|||||||
const { std, x, y } = ctx;
|
const { std, x, y } = ctx;
|
||||||
const host = std.host;
|
const host = std.host;
|
||||||
const doc = host.doc;
|
const doc = host.doc;
|
||||||
const edgelessService = std.getService('affine:page');
|
|
||||||
const surface = getSurfaceBlock(doc);
|
const surface = getSurfaceBlock(doc);
|
||||||
if (!(edgelessService instanceof EdgelessRootService) || !surface) {
|
if (!surface) {
|
||||||
next();
|
next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const gfx = std.get(GfxControllerIdentifier);
|
||||||
|
const zoom = gfx.viewport.zoom;
|
||||||
|
const selection = gfx.selection;
|
||||||
|
|
||||||
const zoom = edgelessService.zoom;
|
const textId = std.get(EdgelessCRUDIdentifier).addBlock(
|
||||||
const textId = edgelessService.addBlock(
|
|
||||||
'affine:edgeless-text',
|
'affine:edgeless-text',
|
||||||
{
|
{
|
||||||
xywh: new Bound(
|
xywh: new Bound(
|
||||||
@@ -45,13 +47,13 @@ export const insertEdgelessTextCommand: Command<
|
|||||||
const blockId = doc.addBlock('affine:paragraph', { type: 'text' }, textId);
|
const blockId = doc.addBlock('affine:paragraph', { type: 'text' }, textId);
|
||||||
host.updateComplete
|
host.updateComplete
|
||||||
.then(() => {
|
.then(() => {
|
||||||
edgelessService.selection.set({
|
selection.set({
|
||||||
elements: [textId],
|
elements: [textId],
|
||||||
editing: true,
|
editing: true,
|
||||||
});
|
});
|
||||||
const disposable = edgelessService.selection.slots.updated.on(() => {
|
const disposable = selection.slots.updated.on(() => {
|
||||||
const editing = edgelessService.selection.editing;
|
const editing = selection.editing;
|
||||||
const id = edgelessService.selection.selectedIds[0];
|
const id = selection.selectedIds[0];
|
||||||
if (!editing || id !== textId) {
|
if (!editing || id !== textId) {
|
||||||
const textBlock = host.view.getBlock(textId);
|
const textBlock = host.view.getBlock(textId);
|
||||||
if (textBlock instanceof EdgelessTextBlockComponent) {
|
if (textBlock instanceof EdgelessTextBlockComponent) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { addAttachments } from '@blocksuite/affine-block-attachment';
|
|||||||
import { addImages } from '@blocksuite/affine-block-image';
|
import { addImages } from '@blocksuite/affine-block-image';
|
||||||
import {
|
import {
|
||||||
CanvasElementType,
|
CanvasElementType,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
SurfaceGroupLikeModel,
|
SurfaceGroupLikeModel,
|
||||||
TextUtils,
|
TextUtils,
|
||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
@@ -329,11 +330,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
).serialize();
|
).serialize();
|
||||||
options.style = style;
|
options.style = style;
|
||||||
|
|
||||||
const id = this.host.service.addBlock(
|
const id = this.crud.addBlock(flavour, options, this.surface.model.id);
|
||||||
flavour,
|
|
||||||
options,
|
|
||||||
this.surface.model.id
|
|
||||||
);
|
|
||||||
|
|
||||||
this.std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
|
this.std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
|
||||||
control: 'canvas:paste',
|
control: 'canvas:paste',
|
||||||
@@ -418,6 +415,10 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
return this.host.surface;
|
return this.host.surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get crud() {
|
||||||
|
return this.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private get toolManager() {
|
private get toolManager() {
|
||||||
return this.host.gfx.tool;
|
return this.host.gfx.tool;
|
||||||
}
|
}
|
||||||
@@ -470,7 +471,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
if (!(await this.host.std.collection.blobSync.get(sourceId as string))) {
|
if (!(await this.host.std.collection.blobSync.get(sourceId as string))) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const attachmentId = this.host.service.addBlock(
|
const attachmentId = this.crud.addBlock(
|
||||||
'affine:attachment',
|
'affine:attachment',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -491,7 +492,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
const { xywh, style, url, caption, description, icon, image, title } =
|
const { xywh, style, url, caption, description, icon, image, title } =
|
||||||
bookmark.props;
|
bookmark.props;
|
||||||
|
|
||||||
const bookmarkId = this.host.service.addBlock(
|
const bookmarkId = this.crud.addBlock(
|
||||||
'affine:bookmark',
|
'affine:bookmark',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -581,10 +582,13 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
|
|
||||||
clipboardData.lockedBySelf = false;
|
clipboardData.lockedBySelf = false;
|
||||||
|
|
||||||
const id = this.host.service.addElement(
|
const id = this.crud.addElement(
|
||||||
clipboardData.type as CanvasElementType,
|
clipboardData.type as CanvasElementType,
|
||||||
clipboardData
|
clipboardData
|
||||||
);
|
);
|
||||||
|
if (!id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
this.std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
|
this.std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
|
||||||
control: 'canvas:paste',
|
control: 'canvas:paste',
|
||||||
page: 'whiteboard editor',
|
page: 'whiteboard editor',
|
||||||
@@ -624,7 +628,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
private _createFigmaEmbedBlock(figmaEmbed: BlockSnapshot) {
|
private _createFigmaEmbedBlock(figmaEmbed: BlockSnapshot) {
|
||||||
const { xywh, style, url, caption, title, description } = figmaEmbed.props;
|
const { xywh, style, url, caption, title, description } = figmaEmbed.props;
|
||||||
|
|
||||||
const embedFigmaId = this.host.service.addBlock(
|
const embedFigmaId = this.crud.addBlock(
|
||||||
'affine:embed-figma',
|
'affine:embed-figma',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -654,7 +658,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const frameId = this.host.service.addBlock(
|
const frameId = this.crud.addBlock(
|
||||||
'affine:frame',
|
'affine:frame',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -687,7 +691,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
assignees,
|
assignees,
|
||||||
} = githubEmbed.props;
|
} = githubEmbed.props;
|
||||||
|
|
||||||
const embedGithubId = this.host.service.addBlock(
|
const embedGithubId = this.crud.addBlock(
|
||||||
'affine:embed-github',
|
'affine:embed-github',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -714,7 +718,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
private _createHtmlEmbedBlock(htmlEmbed: BlockSnapshot) {
|
private _createHtmlEmbedBlock(htmlEmbed: BlockSnapshot) {
|
||||||
const { xywh, style, caption, html, design } = htmlEmbed.props;
|
const { xywh, style, caption, html, design } = htmlEmbed.props;
|
||||||
|
|
||||||
const embedHtmlId = this.host.service.addBlock(
|
const embedHtmlId = this.crud.addBlock(
|
||||||
'affine:embed-html',
|
'affine:embed-html',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -735,7 +739,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
if (!(await this.host.std.collection.blobSync.get(sourceId as string))) {
|
if (!(await this.host.std.collection.blobSync.get(sourceId as string))) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.host.service.addBlock(
|
return this.crud.addBlock(
|
||||||
'affine:image',
|
'affine:image',
|
||||||
{
|
{
|
||||||
caption,
|
caption,
|
||||||
@@ -760,7 +764,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
description,
|
description,
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.host.service.addBlock(
|
return this.crud.addBlock(
|
||||||
'affine:embed-linked-doc',
|
'affine:embed-linked-doc',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -776,7 +780,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
const { xywh, style, url, caption, videoId, image, title, description } =
|
const { xywh, style, url, caption, videoId, image, title, description } =
|
||||||
loomEmbed.props;
|
loomEmbed.props;
|
||||||
|
|
||||||
const embedLoomId = this.host.service.addBlock(
|
const embedLoomId = this.crud.addBlock(
|
||||||
'affine:embed-loom',
|
'affine:embed-loom',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -820,7 +824,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
syncedDocEmbed.props;
|
syncedDocEmbed.props;
|
||||||
const referenceInfo = ReferenceInfoSchema.parse({ pageId, params });
|
const referenceInfo = ReferenceInfoSchema.parse({ pageId, params });
|
||||||
|
|
||||||
return this.host.service.addBlock(
|
return this.crud.addBlock(
|
||||||
'affine:embed-synced-doc',
|
'affine:embed-synced-doc',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -848,7 +852,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
creatorImage,
|
creatorImage,
|
||||||
} = youtubeEmbed.props;
|
} = youtubeEmbed.props;
|
||||||
|
|
||||||
const embedYoutubeId = this.host.service.addBlock(
|
const embedYoutubeId = this.crud.addBlock(
|
||||||
'affine:embed-youtube',
|
'affine:embed-youtube',
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
@@ -1085,7 +1089,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
).serialize(),
|
).serialize(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const noteId = edgeless.service.addBlock(
|
const noteId = this.crud.addBlock(
|
||||||
'affine:note',
|
'affine:note',
|
||||||
noteProps,
|
noteProps,
|
||||||
this.doc.root!.id
|
this.doc.root!.id
|
||||||
@@ -1101,7 +1105,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
|
|
||||||
if (typeof content === 'string') {
|
if (typeof content === 'string') {
|
||||||
TextUtils.splitIntoLines(content).forEach((line, idx) => {
|
TextUtils.splitIntoLines(content).forEach((line, idx) => {
|
||||||
edgeless.service.addBlock(
|
this.crud.addBlock(
|
||||||
'affine:paragraph',
|
'affine:paragraph',
|
||||||
{ text: new DocCollection.Y.Text(line) },
|
{ text: new DocCollection.Y.Text(line) },
|
||||||
noteId,
|
noteId,
|
||||||
@@ -1181,7 +1185,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
sortedElements.forEach(ele => {
|
sortedElements.forEach(ele => {
|
||||||
const newIndex = idxGenerator();
|
const newIndex = idxGenerator();
|
||||||
|
|
||||||
this.edgeless.service.updateElement(ele.id, {
|
this.crud.updateElement(ele.id, {
|
||||||
index: newIndex,
|
index: newIndex,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1323,6 +1327,8 @@ export class EdgelessClipboardController extends PageClipboard {
|
|||||||
getNewXYWH(data.xywh)
|
getNewXYWH(data.xywh)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!element) continue;
|
||||||
|
|
||||||
canvasElements.push(element);
|
canvasElements.push(element);
|
||||||
allElements.push(element);
|
allElements.push(element);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
CanvasElementType,
|
CanvasElementType,
|
||||||
CommonUtils,
|
CommonUtils,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
FontFamilyIcon,
|
FontFamilyIcon,
|
||||||
@@ -137,6 +138,10 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
|
|||||||
this.connector = connector;
|
this.connector = connector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private _addFrame() {
|
private _addFrame() {
|
||||||
const bound = this._generateTarget(this.connector)?.nextBound;
|
const bound = this._generateTarget(this.connector)?.nextBound;
|
||||||
if (!bound) return;
|
if (!bound) return;
|
||||||
@@ -152,7 +157,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
|
|||||||
const { service, surfaceBlockModel } = edgeless;
|
const { service, surfaceBlockModel } = edgeless;
|
||||||
const frameMgr = service.frame;
|
const frameMgr = service.frame;
|
||||||
const frameIndex = service.frames.length + 1;
|
const frameIndex = service.frames.length + 1;
|
||||||
const id = service.addBlock(
|
const id = this.crud.addBlock(
|
||||||
'affine:frame',
|
'affine:frame',
|
||||||
{
|
{
|
||||||
title: new DocCollection.Y.Text(`Frame ${frameIndex}`),
|
title: new DocCollection.Y.Text(`Frame ${frameIndex}`),
|
||||||
@@ -178,7 +183,6 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
|
|||||||
|
|
||||||
private _addNote() {
|
private _addNote() {
|
||||||
const { doc } = this.edgeless;
|
const { doc } = this.edgeless;
|
||||||
const service = this.edgeless.service;
|
|
||||||
const target = this._getTargetXYWH(
|
const target = this._getTargetXYWH(
|
||||||
DEFAULT_NOTE_WIDTH,
|
DEFAULT_NOTE_WIDTH,
|
||||||
DEFAULT_NOTE_OVERLAY_HEIGHT
|
DEFAULT_NOTE_OVERLAY_HEIGHT
|
||||||
@@ -186,7 +190,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
|
|||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
const { xywh, position } = target;
|
const { xywh, position } = target;
|
||||||
const id = service.addBlock(
|
const id = this.crud.addBlock(
|
||||||
'affine:note',
|
'affine:note',
|
||||||
{
|
{
|
||||||
xywh: serializeXYWH(...xywh),
|
xywh: serializeXYWH(...xywh),
|
||||||
@@ -205,7 +209,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
|
|||||||
id,
|
id,
|
||||||
position: position as [number, number],
|
position: position as [number, number],
|
||||||
};
|
};
|
||||||
service.updateElement(this.connector.id, {
|
this.crud.updateElement(this.connector.id, {
|
||||||
target: { id, position },
|
target: { id, position },
|
||||||
});
|
});
|
||||||
this.edgeless.service.selection.set({
|
this.edgeless.service.selection.set({
|
||||||
@@ -223,9 +227,10 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
|
|||||||
const { nextBound, position } = result;
|
const { nextBound, position } = result;
|
||||||
const { service } = edgeless;
|
const { service } = edgeless;
|
||||||
const id = createShapeElement(edgeless, currentSource, targetType);
|
const id = createShapeElement(edgeless, currentSource, targetType);
|
||||||
|
if (!id) return;
|
||||||
|
|
||||||
service.updateElement(id, { xywh: nextBound.serialize() });
|
this.crud.updateElement(id, { xywh: nextBound.serialize() });
|
||||||
service.updateElement(this.connector.id, {
|
this.crud.updateElement(this.connector.id, {
|
||||||
target: { id, position },
|
target: { id, position },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -260,7 +265,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
|
|||||||
const textElement = edgelessService.getElementById(textId);
|
const textElement = edgelessService.getElementById(textId);
|
||||||
if (!textElement) return;
|
if (!textElement) return;
|
||||||
|
|
||||||
edgelessService.updateElement(this.connector.id, {
|
this.crud.updateElement(this.connector.id, {
|
||||||
target: { id: textId, position },
|
target: { id: textId, position },
|
||||||
});
|
});
|
||||||
if (this.currentSource.group instanceof GroupElementModel) {
|
if (this.currentSource.group instanceof GroupElementModel) {
|
||||||
@@ -273,7 +278,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
|
|||||||
});
|
});
|
||||||
this.edgeless.doc.captureSync();
|
this.edgeless.doc.captureSync();
|
||||||
} else {
|
} else {
|
||||||
const textId = edgelessService.addElement(CanvasElementType.TEXT, {
|
const textId = this.crud.addElement(CanvasElementType.TEXT, {
|
||||||
xywh: bound.serialize(),
|
xywh: bound.serialize(),
|
||||||
text: new DocCollection.Y.Text(),
|
text: new DocCollection.Y.Text(),
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
@@ -283,10 +288,11 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) {
|
|||||||
fontWeight: FontWeight.Regular,
|
fontWeight: FontWeight.Regular,
|
||||||
fontStyle: FontStyle.Normal,
|
fontStyle: FontStyle.Normal,
|
||||||
});
|
});
|
||||||
|
if (!textId) return;
|
||||||
const textElement = edgelessService.getElementById(textId);
|
const textElement = edgelessService.getElementById(textId);
|
||||||
assertInstanceOf(textElement, TextElementModel);
|
assertInstanceOf(textElement, TextElementModel);
|
||||||
|
|
||||||
edgelessService.updateElement(this.connector.id, {
|
this.crud.updateElement(this.connector.id, {
|
||||||
target: { id: textId, position },
|
target: { id: textId, position },
|
||||||
});
|
});
|
||||||
if (this.currentSource.group instanceof GroupElementModel) {
|
if (this.currentSource.group instanceof GroupElementModel) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
CanvasElementType,
|
CanvasElementType,
|
||||||
type ConnectionOverlay,
|
type ConnectionOverlay,
|
||||||
ConnectorPathGenerator,
|
ConnectorPathGenerator,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
Overlay,
|
Overlay,
|
||||||
OverlayIdentifier,
|
OverlayIdentifier,
|
||||||
type RoughCanvas,
|
type RoughCanvas,
|
||||||
@@ -232,12 +233,17 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) {
|
|||||||
return this.std.get(OverlayIdentifier('connection')) as ConnectionOverlay;
|
return this.std.get(OverlayIdentifier('connection')) as ConnectionOverlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private _addConnector(source: Connection, target: Connection) {
|
private _addConnector(source: Connection, target: Connection) {
|
||||||
const { edgeless } = this;
|
const { edgeless } = this;
|
||||||
const id = edgeless.service.addElement(CanvasElementType.CONNECTOR, {
|
const id = this.crud.addElement(CanvasElementType.CONNECTOR, {
|
||||||
source,
|
source,
|
||||||
target,
|
target,
|
||||||
});
|
});
|
||||||
|
if (!id) return null;
|
||||||
return edgeless.service.getElementById(id) as ConnectorElementModel;
|
return edgeless.service.getElementById(id) as ConnectorElementModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,6 +360,7 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) {
|
|||||||
const { doc, service } = this.edgeless;
|
const { doc, service } = this.edgeless;
|
||||||
const bound = this._computeNextBound(type);
|
const bound = this._computeNextBound(type);
|
||||||
const id = createEdgelessElement(this.edgeless, this.current, bound);
|
const id = createEdgelessElement(this.edgeless, this.current, bound);
|
||||||
|
if (!id) return;
|
||||||
if (isShape(this.current)) {
|
if (isShape(this.current)) {
|
||||||
const { startPosition, endPosition } = getPosition(type);
|
const { startPosition, endPosition } = getPosition(type);
|
||||||
this._addConnector(
|
this._addConnector(
|
||||||
|
|||||||
@@ -281,11 +281,12 @@ export function createEdgelessElement(
|
|||||||
let element: GfxModel | null = null;
|
let element: GfxModel | null = null;
|
||||||
|
|
||||||
if (isShape(current)) {
|
if (isShape(current)) {
|
||||||
id = service.addElement(current.type, {
|
id = service.crud.addElement(current.type, {
|
||||||
...current.serialize(),
|
...current.serialize(),
|
||||||
text: new DocCollection.Y.Text(),
|
text: new DocCollection.Y.Text(),
|
||||||
xywh: bound.serialize(),
|
xywh: bound.serialize(),
|
||||||
});
|
});
|
||||||
|
if (!id) return null;
|
||||||
element = service.getElementById(id);
|
element = service.getElementById(id);
|
||||||
} else {
|
} else {
|
||||||
const { doc } = edgeless;
|
const { doc } = edgeless;
|
||||||
@@ -335,11 +336,12 @@ export function createShapeElement(
|
|||||||
targetType: TARGET_SHAPE_TYPE
|
targetType: TARGET_SHAPE_TYPE
|
||||||
) {
|
) {
|
||||||
const service = edgeless.service;
|
const service = edgeless.service;
|
||||||
const id = service.addElement('shape', {
|
const id = service.crud.addElement('shape', {
|
||||||
shapeType: getShapeType(targetType),
|
shapeType: getShapeType(targetType),
|
||||||
radius: getShapeRadius(targetType),
|
radius: getShapeRadius(targetType),
|
||||||
text: new DocCollection.Y.Text(),
|
text: new DocCollection.Y.Text(),
|
||||||
});
|
});
|
||||||
|
if (!id) return null;
|
||||||
const element = service.getElementById(id);
|
const element = service.getElementById(id);
|
||||||
const group = current.group;
|
const group = current.group;
|
||||||
if (group instanceof GroupElementModel && element) {
|
if (group instanceof GroupElementModel && element) {
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { TextUtils } from '@blocksuite/affine-block-surface';
|
import {
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
|
TextUtils,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
import type { RichText } from '@blocksuite/affine-components/rich-text';
|
import type { RichText } from '@blocksuite/affine-components/rich-text';
|
||||||
import type { ConnectorElementModel } from '@blocksuite/affine-model';
|
import type { ConnectorElementModel } from '@blocksuite/affine-model';
|
||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||||
@@ -60,6 +63,10 @@ export class EdgelessConnectorLabelEditor extends WithDisposable(
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private _isComposition = false;
|
private _isComposition = false;
|
||||||
|
|
||||||
private _keeping = false;
|
private _keeping = false;
|
||||||
@@ -84,7 +91,7 @@ export class EdgelessConnectorLabelEditor extends WithDisposable(
|
|||||||
!connector.labelXYWH ||
|
!connector.labelXYWH ||
|
||||||
labelXYWH.some((p, i) => !almostEqual(p, connector.labelXYWH![i]))
|
labelXYWH.some((p, i) => !almostEqual(p, connector.labelXYWH![i]))
|
||||||
) {
|
) {
|
||||||
edgeless.service.updateElement(connector.id, {
|
this.crud.updateElement(connector.id, {
|
||||||
labelXYWH,
|
labelXYWH,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -172,13 +179,13 @@ export class EdgelessConnectorLabelEditor extends WithDisposable(
|
|||||||
const len = trimed.length;
|
const len = trimed.length;
|
||||||
if (len === 0) {
|
if (len === 0) {
|
||||||
// reset
|
// reset
|
||||||
edgeless.service.updateElement(connector.id, {
|
this.crud.updateElement(connector.id, {
|
||||||
text: undefined,
|
text: undefined,
|
||||||
labelXYWH: undefined,
|
labelXYWH: undefined,
|
||||||
labelOffset: undefined,
|
labelOffset: undefined,
|
||||||
});
|
});
|
||||||
} else if (len < text.length) {
|
} else if (len < text.length) {
|
||||||
edgeless.service.updateElement(connector.id, {
|
this.crud.updateElement(connector.id, {
|
||||||
// @TODO: trim in Y.Text?
|
// @TODO: trim in Y.Text?
|
||||||
text: new DocCollection.Y.Text(trimed),
|
text: new DocCollection.Y.Text(trimed),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { CommonUtils, TextUtils } from '@blocksuite/affine-block-surface';
|
import {
|
||||||
|
CommonUtils,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
|
TextUtils,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
import type { RichText } from '@blocksuite/affine-components/rich-text';
|
import type { RichText } from '@blocksuite/affine-components/rich-text';
|
||||||
import type { ShapeElementModel } from '@blocksuite/affine-model';
|
import type { ShapeElementModel } from '@blocksuite/affine-model';
|
||||||
import { MindmapElementModel, TextResizing } from '@blocksuite/affine-model';
|
import { MindmapElementModel, TextResizing } from '@blocksuite/affine-model';
|
||||||
@@ -24,6 +28,10 @@ import { getSelectedRect } from '../../utils/query.js';
|
|||||||
const { toRadian } = CommonUtils;
|
const { toRadian } = CommonUtils;
|
||||||
|
|
||||||
export class EdgelessShapeTextEditor extends WithDisposable(ShadowlessElement) {
|
export class EdgelessShapeTextEditor extends WithDisposable(ShadowlessElement) {
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private _keeping = false;
|
private _keeping = false;
|
||||||
|
|
||||||
private _lastXYWH = '';
|
private _lastXYWH = '';
|
||||||
@@ -137,7 +145,7 @@ export class EdgelessShapeTextEditor extends WithDisposable(ShadowlessElement) {
|
|||||||
const [modelLeftTopX, modelLeftTopY] =
|
const [modelLeftTopX, modelLeftTopY] =
|
||||||
this.edgeless.service.viewport.toModelCoord(leftTopX, leftTopY);
|
this.edgeless.service.viewport.toModelCoord(leftTopX, leftTopY);
|
||||||
|
|
||||||
this.edgeless.service.updateElement(this.element.id, {
|
this.crud.updateElement(this.element.id, {
|
||||||
xywh: new Bound(
|
xywh: new Bound(
|
||||||
modelLeftTopX,
|
modelLeftTopX,
|
||||||
modelLeftTopY,
|
modelLeftTopY,
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { CommonUtils, TextUtils } from '@blocksuite/affine-block-surface';
|
import {
|
||||||
|
CommonUtils,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
|
TextUtils,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
import type { RichText } from '@blocksuite/affine-components/rich-text';
|
import type { RichText } from '@blocksuite/affine-components/rich-text';
|
||||||
import type { TextElementModel } from '@blocksuite/affine-model';
|
import type { TextElementModel } from '@blocksuite/affine-model';
|
||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||||
@@ -23,6 +27,10 @@ import { getSelectedRect } from '../../utils/query.js';
|
|||||||
const { toRadian } = CommonUtils;
|
const { toRadian } = CommonUtils;
|
||||||
|
|
||||||
export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
static BORDER_WIDTH = 1;
|
static BORDER_WIDTH = 1;
|
||||||
|
|
||||||
static PADDING_HORIZONTAL = 10;
|
static PADDING_HORIZONTAL = 10;
|
||||||
@@ -137,7 +145,7 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
edgeless.service.updateElement(element.id, {
|
this.crud.updateElement(element.id, {
|
||||||
xywh: bound.serialize(),
|
xywh: bound.serialize(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
||||||
import { CanvasElementType } from '@blocksuite/affine-block-surface';
|
import { CanvasElementType } from '@blocksuite/affine-block-surface';
|
||||||
import { type MindmapStyle, TextElementModel } from '@blocksuite/affine-model';
|
import { type MindmapStyle, TextElementModel } from '@blocksuite/affine-model';
|
||||||
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
||||||
@@ -78,7 +77,7 @@ export const getMindmapRender =
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const mindmapId = edgelessService.addElement('mindmap', {
|
const mindmapId = edgelessService.crud.addElement('mindmap', {
|
||||||
style: mindmapStyle,
|
style: mindmapStyle,
|
||||||
children: root,
|
children: root,
|
||||||
}) as string;
|
}) as string;
|
||||||
@@ -113,10 +112,10 @@ export const textRender: DraggableTool['render'] = (
|
|||||||
});
|
});
|
||||||
id = textId!;
|
id = textId!;
|
||||||
} else {
|
} else {
|
||||||
id = service.addElement(CanvasElementType.TEXT, {
|
id = service.crud.addElement(CanvasElementType.TEXT, {
|
||||||
xywh: new Bound(bound.x, vCenter - h / 2, w, h).serialize(),
|
xywh: new Bound(bound.x, vCenter - h / 2, w, h).serialize(),
|
||||||
text: new DocCollection.Y.Text(),
|
text: new DocCollection.Y.Text(),
|
||||||
});
|
}) as string;
|
||||||
|
|
||||||
edgeless.doc.captureSync();
|
edgeless.doc.captureSync();
|
||||||
const textElement = edgeless.service.getElementById(id);
|
const textElement = edgeless.service.getElementById(id);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import type {
|
import type {
|
||||||
MindmapElementModel,
|
MindmapElementModel,
|
||||||
MindmapStyle,
|
MindmapStyle,
|
||||||
@@ -162,6 +163,10 @@ export class EdgelessMindmapToolButton extends EdgelessToolbarToolMixin(
|
|||||||
return getMindMaps(this.theme);
|
return getMindMaps(this.theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private _toggleMenu() {
|
private _toggleMenu() {
|
||||||
if (this.tryDisposePopper()) return;
|
if (this.tryDisposePopper()) return;
|
||||||
this.setEdgelessTool({ type: 'default' });
|
this.setEdgelessTool({ type: 'default' });
|
||||||
@@ -176,10 +181,11 @@ export class EdgelessMindmapToolButton extends EdgelessToolbarToolMixin(
|
|||||||
},
|
},
|
||||||
onImportMindMap: (bound: Bound) => {
|
onImportMindMap: (bound: Bound) => {
|
||||||
return importMindmap(bound).then(mindmap => {
|
return importMindmap(bound).then(mindmap => {
|
||||||
const id = this.edgeless.service.addElement('mindmap', {
|
const id = this.crud.addElement('mindmap', {
|
||||||
children: mindmap,
|
children: mindmap,
|
||||||
layoutType: mindmap?.layoutType === 'left' ? 1 : 0,
|
layoutType: mindmap?.layoutType === 'left' ? 1 : 0,
|
||||||
});
|
});
|
||||||
|
if (!id) return;
|
||||||
const element = this.edgeless.service.getElementById(
|
const element = this.edgeless.service.getElementById(
|
||||||
id
|
id
|
||||||
) as MindmapElementModel;
|
) as MindmapElementModel;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import { generateKeyBetweenV2 } from '@blocksuite/block-std/gfx';
|
import { generateKeyBetweenV2 } from '@blocksuite/block-std/gfx';
|
||||||
import {
|
import {
|
||||||
DisposableGroup,
|
DisposableGroup,
|
||||||
@@ -98,6 +99,10 @@ export class EdgelessFrameOrderMenu extends SignalWatcher(
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private get _frames() {
|
private get _frames() {
|
||||||
return this.edgeless.service.frames;
|
return this.edgeless.service.frames;
|
||||||
}
|
}
|
||||||
@@ -182,7 +187,7 @@ export class EdgelessFrameOrderMenu extends SignalWatcher(
|
|||||||
|
|
||||||
const frame = this._frames[index];
|
const frame = this._frames[index];
|
||||||
|
|
||||||
this.edgeless.service.updateElement(frame.id, {
|
this.crud.updateElement(frame.id, {
|
||||||
presentationIndex: generateKeyBetweenV2(before, after),
|
presentationIndex: generateKeyBetweenV2(before, after),
|
||||||
});
|
});
|
||||||
this.edgeless.doc.captureSync();
|
this.edgeless.doc.captureSync();
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { CanvasElementType } from '@blocksuite/affine-block-surface';
|
import {
|
||||||
|
CanvasElementType,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
ellipseSvg,
|
ellipseSvg,
|
||||||
roundedSvg,
|
roundedSvg,
|
||||||
@@ -137,6 +140,10 @@ export class EdgelessToolbarShapeDraggable extends EdgelessToolbarToolMixin(
|
|||||||
|
|
||||||
override type = 'shape' as const;
|
override type = 'shape' as const;
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
get shapeShadow() {
|
get shapeShadow() {
|
||||||
return this.theme === 'dark'
|
return this.theme === 'dark'
|
||||||
? '0 0 7px rgba(0, 0, 0, .22)'
|
? '0 0 7px rgba(0, 0, 0, .22)'
|
||||||
@@ -179,12 +186,12 @@ export class EdgelessToolbarShapeDraggable extends EdgelessToolbarToolMixin(
|
|||||||
onDrop: (el, bound) => {
|
onDrop: (el, bound) => {
|
||||||
const xywh = bound.serialize();
|
const xywh = bound.serialize();
|
||||||
const shape = el.data;
|
const shape = el.data;
|
||||||
const id = this.edgeless.service.addElement(CanvasElementType.SHAPE, {
|
const id = this.crud.addElement(CanvasElementType.SHAPE, {
|
||||||
shapeType: getShapeType(shape.name),
|
shapeType: getShapeType(shape.name),
|
||||||
xywh,
|
xywh,
|
||||||
radius: getShapeRadius(shape.name),
|
radius: getShapeRadius(shape.name),
|
||||||
});
|
});
|
||||||
|
if (!id) return;
|
||||||
this.edgeless.std
|
this.edgeless.std
|
||||||
.getOptional(TelemetryProvider)
|
.getOptional(TelemetryProvider)
|
||||||
?.track('CanvasElementAdded', {
|
?.track('CanvasElementAdded', {
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { CanvasElementType } from '@blocksuite/affine-block-surface';
|
import {
|
||||||
|
CanvasElementType,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
getShapeRadius,
|
getShapeRadius,
|
||||||
getShapeType,
|
getShapeType,
|
||||||
@@ -67,6 +70,10 @@ export class EdgelessShapeToolElement extends WithDisposable(LitElement) {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly _addShape = (coord: Coord, padding: Coord) => {
|
private readonly _addShape = (coord: Coord, padding: Coord) => {
|
||||||
const width = 100;
|
const width = 100;
|
||||||
const height = 100;
|
const height = 100;
|
||||||
@@ -78,7 +85,7 @@ export class EdgelessShapeToolElement extends WithDisposable(LitElement) {
|
|||||||
coord.y - edgelessY - height * padding.y * zoom
|
coord.y - edgelessY - height * padding.y * zoom
|
||||||
);
|
);
|
||||||
const xywh = new Bound(modelX, modelY, width, height).serialize();
|
const xywh = new Bound(modelX, modelY, width, height).serialize();
|
||||||
this.edgeless.service.addElement(CanvasElementType.SHAPE, {
|
this.crud.addElement(CanvasElementType.SHAPE, {
|
||||||
shapeType: getShapeType(this.shape.name),
|
shapeType: getShapeType(this.shape.name),
|
||||||
xywh: xywh,
|
xywh: xywh,
|
||||||
radius: getShapeRadius(this.shape.name),
|
radius: getShapeRadius(this.shape.name),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
type ElementRenderer,
|
type ElementRenderer,
|
||||||
elementRenderers,
|
elementRenderers,
|
||||||
type SurfaceBlockModel,
|
type SurfaceBlockModel,
|
||||||
@@ -11,7 +12,6 @@ import {
|
|||||||
MindmapElementModel,
|
MindmapElementModel,
|
||||||
RootBlockSchema,
|
RootBlockSchema,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
|
||||||
import { clamp } from '@blocksuite/affine-shared/utils';
|
import { clamp } from '@blocksuite/affine-shared/utils';
|
||||||
import type { BlockStdScope } from '@blocksuite/block-std';
|
import type { BlockStdScope } from '@blocksuite/block-std';
|
||||||
import type {
|
import type {
|
||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
} from '@blocksuite/block-std/gfx';
|
} from '@blocksuite/block-std/gfx';
|
||||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||||
import { Bound, getCommonBound } from '@blocksuite/global/utils';
|
import { Bound, getCommonBound } from '@blocksuite/global/utils';
|
||||||
import { type BlockModel, Slot } from '@blocksuite/store';
|
import { Slot } from '@blocksuite/store';
|
||||||
import { effect } from '@preact/signals-core';
|
import { effect } from '@preact/signals-core';
|
||||||
|
|
||||||
import { getSurfaceBlock } from '../../surface-ref-block/utils.js';
|
import { getSurfaceBlock } from '../../surface-ref-block/utils.js';
|
||||||
@@ -43,7 +43,6 @@ import {
|
|||||||
replaceIdMiddleware,
|
replaceIdMiddleware,
|
||||||
} from './services/template-middlewares.js';
|
} from './services/template-middlewares.js';
|
||||||
import { FIT_TO_SCREEN_PADDING } from './utils/consts.js';
|
import { FIT_TO_SCREEN_PADDING } from './utils/consts.js';
|
||||||
import { getLastPropsKey } from './utils/get-last-props-key.js';
|
|
||||||
import { getCursorMode } from './utils/query.js';
|
import { getCursorMode } from './utils/query.js';
|
||||||
import {
|
import {
|
||||||
ZOOM_INITIAL,
|
ZOOM_INITIAL,
|
||||||
@@ -85,29 +84,6 @@ export class EdgelessRootService extends RootService implements SurfaceContext {
|
|||||||
|
|
||||||
TemplateJob = TemplateJob;
|
TemplateJob = TemplateJob;
|
||||||
|
|
||||||
updateElement = (id: string, props: Record<string, unknown>) => {
|
|
||||||
const element = this._surface.getElementById(id);
|
|
||||||
if (element) {
|
|
||||||
const key = getLastPropsKey(
|
|
||||||
element.type as BlockSuite.EdgelessModelKeys,
|
|
||||||
{ ...element.yMap.toJSON(), ...props }
|
|
||||||
);
|
|
||||||
key && this.std.get(EditPropsStore).recordLastProps(key, props);
|
|
||||||
this._surface.updateElement(id, props);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const block = this.doc.getBlockById(id);
|
|
||||||
if (block) {
|
|
||||||
const key = getLastPropsKey(
|
|
||||||
block.flavour as BlockSuite.EdgelessModelKeys,
|
|
||||||
{ ...block.yBlock.toJSON(), ...props }
|
|
||||||
);
|
|
||||||
key && this.std.get(EditPropsStore).recordLastProps(key, props);
|
|
||||||
this.doc.updateBlock(block, props);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
get blocks(): GfxBlockModel[] {
|
get blocks(): GfxBlockModel[] {
|
||||||
return this.layer.blocks;
|
return this.layer.blocks;
|
||||||
}
|
}
|
||||||
@@ -179,6 +155,10 @@ export class EdgelessRootService extends RootService implements SurfaceContext {
|
|||||||
return this.viewport.zoom;
|
return this.viewport.zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(std: BlockStdScope, flavourProvider: { flavour: string }) {
|
constructor(std: BlockStdScope, flavourProvider: { flavour: string }) {
|
||||||
super(std, flavourProvider);
|
super(std, flavourProvider);
|
||||||
const surface = getSurfaceBlock(this.doc);
|
const surface = getSurfaceBlock(this.doc);
|
||||||
@@ -216,44 +196,11 @@ export class EdgelessRootService extends RootService implements SurfaceContext {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addBlock(
|
|
||||||
flavour: string,
|
|
||||||
props: Record<string, unknown>,
|
|
||||||
parent?: string | BlockModel,
|
|
||||||
parentIndex?: number
|
|
||||||
) {
|
|
||||||
const key = getLastPropsKey(flavour as BlockSuite.EdgelessModelKeys, props);
|
|
||||||
if (key) {
|
|
||||||
props = this.std.get(EditPropsStore).applyLastProps(key, props);
|
|
||||||
}
|
|
||||||
|
|
||||||
const nProps = {
|
|
||||||
...props,
|
|
||||||
index: this.generateIndex(),
|
|
||||||
};
|
|
||||||
return this.doc.addBlock(flavour as never, nProps, parent, parentIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
addElement<T extends Record<string, unknown>>(type: string, props: T) {
|
|
||||||
const key = getLastPropsKey(type as BlockSuite.EdgelessModelKeys, props);
|
|
||||||
if (key) {
|
|
||||||
props = this.std.get(EditPropsStore).applyLastProps(key, props) as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nProps = {
|
|
||||||
...props,
|
|
||||||
type,
|
|
||||||
index: props.index ?? this.generateIndex(),
|
|
||||||
};
|
|
||||||
const id = this._surface.addElement(nProps);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
createGroup(elements: BlockSuite.EdgelessModel[] | string[]) {
|
createGroup(elements: BlockSuite.EdgelessModel[] | string[]) {
|
||||||
const groups = this.elements.filter(
|
const groups = this.elements.filter(
|
||||||
el => el.type === 'group'
|
el => el.type === 'group'
|
||||||
) as GroupElementModel[];
|
) as GroupElementModel[];
|
||||||
const groupId = this.addElement('group', {
|
const groupId = this.crud.addElement('group', {
|
||||||
children: elements.reduce(
|
children: elements.reduce(
|
||||||
(pre, el) => {
|
(pre, el) => {
|
||||||
const id = typeof el === 'string' ? el : el.id;
|
const id = typeof el === 'string' ? el : el.id;
|
||||||
@@ -290,12 +237,15 @@ export class EdgelessRootService extends RootService implements SurfaceContext {
|
|||||||
|
|
||||||
if (parent !== null) {
|
if (parent !== null) {
|
||||||
selection.selectedElements.forEach(element => {
|
selection.selectedElements.forEach(element => {
|
||||||
// eslint-disable-next-line unicorn/prefer-dom-node-remove
|
// oxlint-disable-next-line unicorn/prefer-dom-node-remove
|
||||||
parent.removeChild(element);
|
parent.removeChild(element);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupId = this.createGroup(selection.selectedElements);
|
const groupId = this.createGroup(selection.selectedElements);
|
||||||
|
if (!groupId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const group = this.surface.getElementById(groupId);
|
const group = this.surface.getElementById(groupId);
|
||||||
|
|
||||||
if (parent !== null && group) {
|
if (parent !== null && group) {
|
||||||
@@ -487,12 +437,12 @@ export class EdgelessRootService extends RootService implements SurfaceContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (parent !== null) {
|
if (parent !== null) {
|
||||||
// eslint-disable-next-line unicorn/prefer-dom-node-remove
|
// oxlint-disable-next-line unicorn/prefer-dom-node-remove
|
||||||
parent.removeChild(group);
|
parent.removeChild(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
elements.forEach(element => {
|
elements.forEach(element => {
|
||||||
// eslint-disable-next-line unicorn/prefer-dom-node-remove
|
// oxlint-disable-next-line unicorn/prefer-dom-node-remove
|
||||||
group.removeChild(element);
|
group.removeChild(element);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
CommonUtils,
|
CommonUtils,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
Overlay,
|
Overlay,
|
||||||
type SurfaceBlockComponent,
|
type SurfaceBlockComponent,
|
||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
@@ -7,7 +8,6 @@ import type { PointerEventState } from '@blocksuite/block-std';
|
|||||||
import { BaseTool } from '@blocksuite/block-std/gfx';
|
import { BaseTool } from '@blocksuite/block-std/gfx';
|
||||||
import { Bound, type IVec } from '@blocksuite/global/utils';
|
import { Bound, type IVec } from '@blocksuite/global/utils';
|
||||||
|
|
||||||
import { deleteElementsV2 } from '../utils/crud.js';
|
|
||||||
import { isTopLevelBlock } from '../utils/query.js';
|
import { isTopLevelBlock } from '../utils/query.js';
|
||||||
|
|
||||||
const { getSvgPathFromStroke, getStroke, linePolygonIntersects } = CommonUtils;
|
const { getSvgPathFromStroke, getStroke, linePolygonIntersects } = CommonUtils;
|
||||||
@@ -99,7 +99,9 @@ export class EraserTool extends BaseTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override dragEnd(_: PointerEventState): void {
|
override dragEnd(_: PointerEventState): void {
|
||||||
deleteElementsV2(this.gfx, Array.from(this._eraseTargets));
|
this.gfx.std
|
||||||
|
.get(EdgelessCRUDIdentifier)
|
||||||
|
.deleteElements(Array.from(this._eraseTargets));
|
||||||
this._reset();
|
this._reset();
|
||||||
this.doc.captureSync();
|
this.doc.captureSync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
|
import { getLastPropsKey } from '@blocksuite/affine-block-surface';
|
||||||
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
||||||
import {
|
import {
|
||||||
type SurfaceMiddleware,
|
type SurfaceMiddleware,
|
||||||
SurfaceMiddlewareBuilder,
|
SurfaceMiddlewareBuilder,
|
||||||
} from '@blocksuite/block-std/gfx';
|
} from '@blocksuite/block-std/gfx';
|
||||||
|
|
||||||
import { getLastPropsKey } from '../utils/get-last-props-key.js';
|
|
||||||
|
|
||||||
export class EditPropsMiddlewareBuilder extends SurfaceMiddlewareBuilder {
|
export class EditPropsMiddlewareBuilder extends SurfaceMiddlewareBuilder {
|
||||||
static override key = 'editProps';
|
static override key = 'editProps';
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
|
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
|
||||||
import {
|
import {
|
||||||
DEFAULT_NOTE_HEIGHT,
|
DEFAULT_NOTE_HEIGHT,
|
||||||
@@ -18,7 +19,6 @@ import {
|
|||||||
} from '@blocksuite/global/utils';
|
} from '@blocksuite/global/utils';
|
||||||
|
|
||||||
import { DEFAULT_NOTE_OFFSET_X, DEFAULT_NOTE_OFFSET_Y } from './consts.js';
|
import { DEFAULT_NOTE_OFFSET_X, DEFAULT_NOTE_OFFSET_Y } from './consts.js';
|
||||||
import { addBlock } from './crud.js';
|
|
||||||
|
|
||||||
export function addNoteAtPoint(
|
export function addNoteAtPoint(
|
||||||
std: BlockStdScope,
|
std: BlockStdScope,
|
||||||
@@ -37,6 +37,7 @@ export function addNoteAtPoint(
|
|||||||
} = {}
|
} = {}
|
||||||
) {
|
) {
|
||||||
const gfx = std.get(GfxControllerIdentifier);
|
const gfx = std.get(GfxControllerIdentifier);
|
||||||
|
const crud = std.get(EdgelessCRUDIdentifier);
|
||||||
const {
|
const {
|
||||||
width = DEFAULT_NOTE_WIDTH,
|
width = DEFAULT_NOTE_WIDTH,
|
||||||
height = DEFAULT_NOTE_HEIGHT,
|
height = DEFAULT_NOTE_HEIGHT,
|
||||||
@@ -47,8 +48,7 @@ export function addNoteAtPoint(
|
|||||||
scale = 1,
|
scale = 1,
|
||||||
} = options;
|
} = options;
|
||||||
const [x, y] = gfx.viewport.toModelCoord(point.x, point.y);
|
const [x, y] = gfx.viewport.toModelCoord(point.x, point.y);
|
||||||
const blockId = addBlock(
|
const blockId = crud.addBlock(
|
||||||
std,
|
|
||||||
'affine:note',
|
'affine:note',
|
||||||
{
|
{
|
||||||
xywh: serializeXYWH(
|
xywh: serializeXYWH(
|
||||||
@@ -63,7 +63,7 @@ export function addNoteAtPoint(
|
|||||||
noteIndex
|
noteIndex
|
||||||
);
|
);
|
||||||
|
|
||||||
gfx.std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
|
std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
|
||||||
control: 'canvas:draw',
|
control: 'canvas:draw',
|
||||||
page: 'whiteboard editor',
|
page: 'whiteboard editor',
|
||||||
module: 'toolbar',
|
module: 'toolbar',
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
|
|
||||||
import type { EdgelessRootService } from '../edgeless-root-service.js';
|
import type { EdgelessRootService } from '../edgeless-root-service.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,14 +14,15 @@ export function moveConnectors(
|
|||||||
service: EdgelessRootService
|
service: EdgelessRootService
|
||||||
) {
|
) {
|
||||||
const connectors = service.surface.getConnectors(originId);
|
const connectors = service.surface.getConnectors(originId);
|
||||||
|
const crud = service.std.get(EdgelessCRUDIdentifier);
|
||||||
connectors.forEach(connector => {
|
connectors.forEach(connector => {
|
||||||
if (connector.source.id === originId) {
|
if (connector.source.id === originId) {
|
||||||
service.updateElement(connector.id, {
|
crud.updateElement(connector.id, {
|
||||||
source: { ...connector.source, id: targetId },
|
source: { ...connector.source, id: targetId },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (connector.target.id === originId) {
|
if (connector.target.id === originId) {
|
||||||
service.updateElement(connector.id, {
|
crud.updateElement(connector.id, {
|
||||||
target: { ...connector.target, id: targetId },
|
target: { ...connector.target, id: targetId },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
import type { SurfaceBlockModel } from '@blocksuite/affine-block-surface';
|
|
||||||
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
|
||||||
import type { BlockStdScope } from '@blocksuite/block-std';
|
|
||||||
import {
|
|
||||||
type GfxController,
|
|
||||||
GfxControllerIdentifier,
|
|
||||||
} from '@blocksuite/block-std/gfx';
|
|
||||||
import type { BlockModel } from '@blocksuite/store';
|
|
||||||
|
|
||||||
import type { Connectable } from '../../../_common/utils/index.js';
|
import type { Connectable } from '../../../_common/utils/index.js';
|
||||||
import type { EdgelessRootBlockComponent } from '../index.js';
|
import type { EdgelessRootBlockComponent } from '../index.js';
|
||||||
import { getLastPropsKey } from './get-last-props-key.js';
|
|
||||||
import { isConnectable, isNoteBlock } from './query.js';
|
import { isConnectable, isNoteBlock } from './query.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,51 +32,3 @@ export function deleteElements(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteElementsV2(
|
|
||||||
gfx: GfxController,
|
|
||||||
elements: BlockSuite.EdgelessModel[]
|
|
||||||
) {
|
|
||||||
const set = new Set(elements);
|
|
||||||
|
|
||||||
elements.forEach(element => {
|
|
||||||
if (isConnectable(element)) {
|
|
||||||
const connectors = (gfx.surface as SurfaceBlockModel).getConnectors(
|
|
||||||
element.id
|
|
||||||
);
|
|
||||||
connectors.forEach(connector => set.add(connector));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
set.forEach(element => {
|
|
||||||
if (isNoteBlock(element)) {
|
|
||||||
const children = gfx.doc.root?.children ?? [];
|
|
||||||
if (children.length > 1) {
|
|
||||||
gfx.doc.deleteBlock(element);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gfx.deleteElement(element.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addBlock(
|
|
||||||
std: BlockStdScope,
|
|
||||||
flavour: BlockSuite.EdgelessModelKeys,
|
|
||||||
props: Record<string, unknown>,
|
|
||||||
parentId?: string | BlockModel,
|
|
||||||
parentIndex?: number
|
|
||||||
) {
|
|
||||||
const gfx = std.get(GfxControllerIdentifier);
|
|
||||||
const key = getLastPropsKey(flavour as BlockSuite.EdgelessModelKeys, props);
|
|
||||||
if (key) {
|
|
||||||
props = std.get(EditPropsStore).applyLastProps(key, props);
|
|
||||||
}
|
|
||||||
|
|
||||||
const nProps = {
|
|
||||||
...props,
|
|
||||||
index: gfx.layer.generateIndex(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return std.doc.addBlock(flavour as never, nProps, parentId, parentIndex);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
CanvasElementType,
|
CanvasElementType,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
type IModelCoord,
|
type IModelCoord,
|
||||||
TextUtils,
|
TextUtils,
|
||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
@@ -12,11 +13,7 @@ import { ShapeElementModel, TextElementModel } from '@blocksuite/affine-model';
|
|||||||
import type { PointerEventState } from '@blocksuite/block-std';
|
import type { PointerEventState } from '@blocksuite/block-std';
|
||||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||||
import type { IVec } from '@blocksuite/global/utils';
|
import type { IVec } from '@blocksuite/global/utils';
|
||||||
import {
|
import { assertInstanceOf, Bound } from '@blocksuite/global/utils';
|
||||||
assertExists,
|
|
||||||
assertInstanceOf,
|
|
||||||
Bound,
|
|
||||||
} from '@blocksuite/global/utils';
|
|
||||||
import { DocCollection } from '@blocksuite/store';
|
import { DocCollection } from '@blocksuite/store';
|
||||||
|
|
||||||
import { EdgelessConnectorLabelEditor } from '../components/text/edgeless-connector-label-editor.js';
|
import { EdgelessConnectorLabelEditor } from '../components/text/edgeless-connector-label-editor.js';
|
||||||
@@ -77,7 +74,9 @@ export function mountShapeTextEditor(
|
|||||||
|
|
||||||
if (!shapeElement.text) {
|
if (!shapeElement.text) {
|
||||||
const text = new DocCollection.Y.Text();
|
const text = new DocCollection.Y.Text();
|
||||||
edgeless.service.updateElement(shapeElement.id, { text });
|
edgeless.std
|
||||||
|
.get(EdgelessCRUDIdentifier)
|
||||||
|
.updateElement(shapeElement.id, { text });
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedElement = edgeless.service.getElementById(shapeElement.id);
|
const updatedElement = edgeless.service.getElementById(shapeElement.id);
|
||||||
@@ -164,13 +163,16 @@ export function addText(
|
|||||||
event.x,
|
event.x,
|
||||||
event.y
|
event.y
|
||||||
);
|
);
|
||||||
const id = edgeless.service.addElement(CanvasElementType.TEXT, {
|
const id = edgeless.std
|
||||||
|
.get(EdgelessCRUDIdentifier)
|
||||||
|
.addElement(CanvasElementType.TEXT, {
|
||||||
xywh: new Bound(modelX, modelY, 32, 32).serialize(),
|
xywh: new Bound(modelX, modelY, 32, 32).serialize(),
|
||||||
text: new DocCollection.Y.Text(),
|
text: new DocCollection.Y.Text(),
|
||||||
});
|
});
|
||||||
|
if (!id) return;
|
||||||
edgeless.doc.captureSync();
|
edgeless.doc.captureSync();
|
||||||
const textElement = edgeless.service.getElementById(id);
|
const textElement = edgeless.service.getElementById(id);
|
||||||
assertExists(textElement);
|
if (!textElement) return;
|
||||||
if (textElement instanceof TextElementModel) {
|
if (textElement instanceof TextElementModel) {
|
||||||
mountTextElementEditor(textElement, edgeless);
|
mountTextElementEditor(textElement, edgeless);
|
||||||
}
|
}
|
||||||
@@ -203,7 +205,7 @@ export function mountConnectorLabelEditor(
|
|||||||
labelXYWH = bounds.toXYWH();
|
labelXYWH = bounds.toXYWH();
|
||||||
}
|
}
|
||||||
|
|
||||||
edgeless.service.updateElement(connector.id, {
|
edgeless.std.get(EdgelessCRUDIdentifier).updateElement(connector.id, {
|
||||||
text,
|
text,
|
||||||
labelXYWH,
|
labelXYWH,
|
||||||
labelOffset: { ...labelOffset },
|
labelOffset: { ...labelOffset },
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { updateXYWH } from '@blocksuite/affine-block-surface';
|
import {
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
|
updateXYWH,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
AlignBottomIcon,
|
AlignBottomIcon,
|
||||||
AlignDistributeHorizontallyIcon,
|
AlignDistributeHorizontallyIcon,
|
||||||
@@ -267,7 +270,7 @@ export class EdgelessAlignButton extends WithDisposable(LitElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _updateXYWH(ele: BlockSuite.EdgelessModel, bound: Bound) {
|
private _updateXYWH(ele: BlockSuite.EdgelessModel, bound: Bound) {
|
||||||
const { updateElement } = this.edgeless.service;
|
const { updateElement } = this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
const { updateBlock } = this.edgeless.doc;
|
const { updateBlock } = this.edgeless.doc;
|
||||||
updateXYWH(ele, bound, updateElement, updateBlock);
|
updateXYWH(ele, bound, updateElement, updateBlock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import type {
|
import type {
|
||||||
BrushElementModel,
|
BrushElementModel,
|
||||||
BrushProps,
|
BrushProps,
|
||||||
@@ -57,10 +58,7 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) {
|
|||||||
pickColor = (event: PickColorEvent) => {
|
pickColor = (event: PickColorEvent) => {
|
||||||
if (event.type === 'pick') {
|
if (event.type === 'pick') {
|
||||||
this.elements.forEach(ele =>
|
this.elements.forEach(ele =>
|
||||||
this.service.updateElement(
|
this.crud.updateElement(ele.id, packColor('color', { ...event.detail }))
|
||||||
ele.id,
|
|
||||||
packColor('color', { ...event.detail })
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -93,6 +91,10 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) {
|
|||||||
return this.edgeless.surface;
|
return this.edgeless.surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private _setBrushProp<K extends keyof BrushProps>(
|
private _setBrushProp<K extends keyof BrushProps>(
|
||||||
key: K,
|
key: K,
|
||||||
value: BrushProps[K]
|
value: BrushProps[K]
|
||||||
@@ -101,7 +103,7 @@ export class EdgelessChangeBrushButton extends WithDisposable(LitElement) {
|
|||||||
this.elements
|
this.elements
|
||||||
.filter(notEqual(key, value))
|
.filter(notEqual(key, value))
|
||||||
.forEach(element =>
|
.forEach(element =>
|
||||||
this.service.updateElement(element.id, { [key]: value })
|
this.crud.updateElement(element.id, { [key]: value })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
AddTextIcon,
|
AddTextIcon,
|
||||||
ConnectorCWithArrowIcon,
|
ConnectorCWithArrowIcon,
|
||||||
@@ -222,10 +223,14 @@ const MODE_CHOOSE: [ConnectorMode, () => TemplateResult<1>][] = [
|
|||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) {
|
export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) {
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
pickColor = (event: PickColorEvent) => {
|
pickColor = (event: PickColorEvent) => {
|
||||||
if (event.type === 'pick') {
|
if (event.type === 'pick') {
|
||||||
this.elements.forEach(ele =>
|
this.elements.forEach(ele =>
|
||||||
this.service.updateElement(
|
this.crud.updateElement(
|
||||||
ele.id,
|
ele.id,
|
||||||
packColor('stroke', { ...event.detail })
|
packColor('stroke', { ...event.detail })
|
||||||
)
|
)
|
||||||
@@ -257,7 +262,7 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) {
|
|||||||
if (frontEndpointStyle === rearEndpointStyle) return;
|
if (frontEndpointStyle === rearEndpointStyle) return;
|
||||||
|
|
||||||
this.elements.forEach(element =>
|
this.elements.forEach(element =>
|
||||||
this.service.updateElement(element.id, {
|
this.crud.updateElement(element.id, {
|
||||||
frontEndpointStyle: rearEndpointStyle,
|
frontEndpointStyle: rearEndpointStyle,
|
||||||
rearEndpointStyle: frontEndpointStyle,
|
rearEndpointStyle: frontEndpointStyle,
|
||||||
})
|
})
|
||||||
@@ -286,7 +291,7 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) {
|
|||||||
: 'rearEndpointStyle']: style,
|
: 'rearEndpointStyle']: style,
|
||||||
};
|
};
|
||||||
this.elements.forEach(element =>
|
this.elements.forEach(element =>
|
||||||
this.service.updateElement(element.id, { ...props })
|
this.crud.updateElement(element.id, { ...props })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +302,7 @@ export class EdgelessChangeConnectorButton extends WithDisposable(LitElement) {
|
|||||||
this.elements
|
this.elements
|
||||||
.filter(notEqual(key, value))
|
.filter(notEqual(key, value))
|
||||||
.forEach(element =>
|
.forEach(element =>
|
||||||
this.service.updateElement(element.id, { [key]: value })
|
this.crud.updateElement(element.id, { [key]: value })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
getDocContentWithMaxLength,
|
getDocContentWithMaxLength,
|
||||||
getEmbedCardIcons,
|
getEmbedCardIcons,
|
||||||
} from '@blocksuite/affine-block-embed';
|
} from '@blocksuite/affine-block-embed';
|
||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
CaptionIcon,
|
CaptionIcon,
|
||||||
CenterPeekIcon,
|
CenterPeekIcon,
|
||||||
@@ -114,6 +115,10 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly _convertToCardView = () => {
|
private readonly _convertToCardView = () => {
|
||||||
if (this._isCardView) {
|
if (this._isCardView) {
|
||||||
return;
|
return;
|
||||||
@@ -146,7 +151,7 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
|
|||||||
bound.w = EMBED_CARD_WIDTH[targetStyle];
|
bound.w = EMBED_CARD_WIDTH[targetStyle];
|
||||||
bound.h = EMBED_CARD_HEIGHT[targetStyle];
|
bound.h = EMBED_CARD_HEIGHT[targetStyle];
|
||||||
|
|
||||||
const newId = this.edgeless.service.addBlock(
|
const newId = this.crud.addBlock(
|
||||||
targetFlavour,
|
targetFlavour,
|
||||||
{ url, xywh: bound.serialize(), style: targetStyle, caption },
|
{ url, xywh: bound.serialize(), style: targetStyle, caption },
|
||||||
this.edgeless.surface.model
|
this.edgeless.surface.model
|
||||||
@@ -197,7 +202,7 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
|
|||||||
bound.w = EMBED_CARD_WIDTH[targetStyle];
|
bound.w = EMBED_CARD_WIDTH[targetStyle];
|
||||||
bound.h = EMBED_CARD_HEIGHT[targetStyle];
|
bound.h = EMBED_CARD_HEIGHT[targetStyle];
|
||||||
|
|
||||||
const newId = this.edgeless.service.addBlock(
|
const newId = this.crud.addBlock(
|
||||||
flavour,
|
flavour,
|
||||||
{
|
{
|
||||||
url,
|
url,
|
||||||
@@ -206,6 +211,7 @@ export class EdgelessChangeEmbedCardButton extends WithDisposable(LitElement) {
|
|||||||
},
|
},
|
||||||
this.edgeless.surface.model
|
this.edgeless.surface.model
|
||||||
);
|
);
|
||||||
|
if (!newId) return;
|
||||||
|
|
||||||
this.std.command.exec('reassociateConnectors', {
|
this.std.command.exec('reassociateConnectors', {
|
||||||
oldId: id,
|
oldId: id,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
NoteIcon,
|
NoteIcon,
|
||||||
RenameIcon,
|
RenameIcon,
|
||||||
@@ -51,10 +52,14 @@ function getMostCommonColor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class EdgelessChangeFrameButton extends WithDisposable(LitElement) {
|
export class EdgelessChangeFrameButton extends WithDisposable(LitElement) {
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
pickColor = (event: PickColorEvent) => {
|
pickColor = (event: PickColorEvent) => {
|
||||||
if (event.type === 'pick') {
|
if (event.type === 'pick') {
|
||||||
this.frames.forEach(ele =>
|
this.frames.forEach(ele =>
|
||||||
this.service.updateElement(
|
this.crud.updateElement(
|
||||||
ele.id,
|
ele.id,
|
||||||
packColor('background', { ...event.detail })
|
packColor('background', { ...event.detail })
|
||||||
)
|
)
|
||||||
@@ -116,7 +121,7 @@ export class EdgelessChangeFrameButton extends WithDisposable(LitElement) {
|
|||||||
|
|
||||||
private _setFrameBackground(color: string) {
|
private _setFrameBackground(color: string) {
|
||||||
this.frames.forEach(frame => {
|
this.frames.forEach(frame => {
|
||||||
this.service.updateElement(frame.id, { background: color });
|
this.crud.updateElement(frame.id, { background: color });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
ExpandIcon,
|
ExpandIcon,
|
||||||
LineStyleIcon,
|
LineStyleIcon,
|
||||||
@@ -78,6 +79,10 @@ function getMostCommonBackground(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
|
export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly _setBorderRadius = (borderRadius: number) => {
|
private readonly _setBorderRadius = (borderRadius: number) => {
|
||||||
this.notes.forEach(note => {
|
this.notes.forEach(note => {
|
||||||
const props = {
|
const props = {
|
||||||
@@ -88,7 +93,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.edgeless.service.updateElement(note.id, props);
|
this.crud.updateElement(note.id, props);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,7 +116,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
|
|||||||
if (event.type === 'pick') {
|
if (event.type === 'pick') {
|
||||||
this.notes.forEach(element => {
|
this.notes.forEach(element => {
|
||||||
const props = packColor('background', { ...event.detail });
|
const props = packColor('background', { ...event.detail });
|
||||||
this.edgeless.service.updateElement(element.id, props);
|
this.crud.updateElement(element.id, props);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -142,7 +147,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
|
|||||||
|
|
||||||
private _setBackground(background: string) {
|
private _setBackground(background: string) {
|
||||||
this.notes.forEach(element => {
|
this.notes.forEach(element => {
|
||||||
this.edgeless.service.updateElement(element.id, { background });
|
this.crud.updateElement(element.id, { background });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +178,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.edgeless.service.updateElement(note.id, { displayMode: newMode });
|
this.crud.updateElement(note.id, { displayMode: newMode });
|
||||||
|
|
||||||
const noteParent = this.doc.getParent(note);
|
const noteParent = this.doc.getParent(note);
|
||||||
assertExists(noteParent);
|
assertExists(noteParent);
|
||||||
@@ -208,7 +213,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.edgeless.service.updateElement(note.id, props);
|
this.crud.updateElement(note.id, props);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +227,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.edgeless.service.updateElement(note.id, props);
|
this.crud.updateElement(note.id, props);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +241,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.edgeless.service.updateElement(note.id, props);
|
this.crud.updateElement(note.id, props);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
AddTextIcon,
|
AddTextIcon,
|
||||||
ChangeShapeIcon,
|
ChangeShapeIcon,
|
||||||
@@ -155,6 +156,10 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
|
|||||||
return this.edgeless.service;
|
return this.edgeless.service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
#pickColor<K extends keyof Pick<ShapeProps, 'fillColor' | 'strokeColor'>>(
|
#pickColor<K extends keyof Pick<ShapeProps, 'fillColor' | 'strokeColor'>>(
|
||||||
key: K
|
key: K
|
||||||
) {
|
) {
|
||||||
@@ -166,7 +171,7 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
|
|||||||
if (key === 'fillColor' && !ele.filled) {
|
if (key === 'fillColor' && !ele.filled) {
|
||||||
Object.assign(props, { filled: true });
|
Object.assign(props, { filled: true });
|
||||||
}
|
}
|
||||||
this.service.updateElement(ele.id, props);
|
this.crud.updateElement(ele.id, props);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -199,25 +204,25 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
|
|||||||
const filled = !isTransparent(fillColor);
|
const filled = !isTransparent(fillColor);
|
||||||
const color = this._getTextColor(fillColor);
|
const color = this._getTextColor(fillColor);
|
||||||
this.elements.forEach(ele =>
|
this.elements.forEach(ele =>
|
||||||
this.service.updateElement(ele.id, { filled, fillColor, color })
|
this.crud.updateElement(ele.id, { filled, fillColor, color })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setShapeStrokeColor(strokeColor: string) {
|
private _setShapeStrokeColor(strokeColor: string) {
|
||||||
this.elements.forEach(ele =>
|
this.elements.forEach(ele =>
|
||||||
this.service.updateElement(ele.id, { strokeColor })
|
this.crud.updateElement(ele.id, { strokeColor })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setShapeStrokeStyle(strokeStyle: StrokeStyle) {
|
private _setShapeStrokeStyle(strokeStyle: StrokeStyle) {
|
||||||
this.elements.forEach(ele =>
|
this.elements.forEach(ele =>
|
||||||
this.service.updateElement(ele.id, { strokeStyle })
|
this.crud.updateElement(ele.id, { strokeStyle })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setShapeStrokeWidth(strokeWidth: number) {
|
private _setShapeStrokeWidth(strokeWidth: number) {
|
||||||
this.elements.forEach(ele =>
|
this.elements.forEach(ele =>
|
||||||
this.service.updateElement(ele.id, { strokeWidth })
|
this.crud.updateElement(ele.id, { strokeWidth })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +231,7 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
|
|||||||
shapeStyle === ShapeStyle.General ? FontFamily.Inter : FontFamily.Kalam;
|
shapeStyle === ShapeStyle.General ? FontFamily.Inter : FontFamily.Kalam;
|
||||||
|
|
||||||
this.elements.forEach(ele => {
|
this.elements.forEach(ele => {
|
||||||
this.service.updateElement(ele.id, { shapeStyle, fontFamily });
|
this.crud.updateElement(ele.id, { shapeStyle, fontFamily });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +262,7 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) {
|
|||||||
this._shapePanel.slots.select.on(shapeName => {
|
this._shapePanel.slots.select.on(shapeName => {
|
||||||
this.edgeless.doc.captureSync();
|
this.edgeless.doc.captureSync();
|
||||||
this.elements.forEach(element => {
|
this.elements.forEach(element => {
|
||||||
this.service.updateElement(element.id, {
|
this.crud.updateElement(element.id, {
|
||||||
shapeType: getShapeType(shapeName),
|
shapeType: getShapeType(shapeName),
|
||||||
radius: getShapeRadius(shapeName),
|
radius: getShapeRadius(shapeName),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
||||||
import {
|
import {
|
||||||
ConnectorUtils,
|
ConnectorUtils,
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
normalizeShapeBound,
|
normalizeShapeBound,
|
||||||
TextUtils,
|
TextUtils,
|
||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
@@ -176,6 +176,10 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
get crud() {
|
||||||
|
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly _setFontFamily = (fontFamily: FontFamily) => {
|
private readonly _setFontFamily = (fontFamily: FontFamily) => {
|
||||||
const currentFontWeight = getMostCommonFontWeight(this.elements);
|
const currentFontWeight = getMostCommonFontWeight(this.elements);
|
||||||
const fontWeight = TextUtils.isFontWeightSupported(
|
const fontWeight = TextUtils.isFontWeightSupported(
|
||||||
@@ -194,7 +198,7 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
|
|||||||
|
|
||||||
const props = { fontFamily, fontWeight, fontStyle };
|
const props = { fontFamily, fontWeight, fontStyle };
|
||||||
this.elements.forEach(element => {
|
this.elements.forEach(element => {
|
||||||
this.service.updateElement(element.id, buildProps(element, props));
|
this.crud.updateElement(element.id, buildProps(element, props));
|
||||||
this._updateElementBound(element);
|
this._updateElementBound(element);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -202,7 +206,7 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
|
|||||||
private readonly _setFontSize = (fontSize: number) => {
|
private readonly _setFontSize = (fontSize: number) => {
|
||||||
const props = { fontSize };
|
const props = { fontSize };
|
||||||
this.elements.forEach(element => {
|
this.elements.forEach(element => {
|
||||||
this.service.updateElement(element.id, buildProps(element, props));
|
this.crud.updateElement(element.id, buildProps(element, props));
|
||||||
this._updateElementBound(element);
|
this._updateElementBound(element);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -213,7 +217,7 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
|
|||||||
) => {
|
) => {
|
||||||
const props = { fontWeight, fontStyle };
|
const props = { fontWeight, fontStyle };
|
||||||
this.elements.forEach(element => {
|
this.elements.forEach(element => {
|
||||||
this.service.updateElement(element.id, buildProps(element, props));
|
this.crud.updateElement(element.id, buildProps(element, props));
|
||||||
this._updateElementBound(element);
|
this._updateElementBound(element);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -221,14 +225,14 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
|
|||||||
private readonly _setTextAlign = (textAlign: TextAlign) => {
|
private readonly _setTextAlign = (textAlign: TextAlign) => {
|
||||||
const props = { textAlign };
|
const props = { textAlign };
|
||||||
this.elements.forEach(element => {
|
this.elements.forEach(element => {
|
||||||
this.service.updateElement(element.id, buildProps(element, props));
|
this.crud.updateElement(element.id, buildProps(element, props));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly _setTextColor = ({ detail: color }: ColorEvent) => {
|
private readonly _setTextColor = ({ detail: color }: ColorEvent) => {
|
||||||
const props = { color };
|
const props = { color };
|
||||||
this.elements.forEach(element => {
|
this.elements.forEach(element => {
|
||||||
this.service.updateElement(element.id, buildProps(element, props));
|
this.crud.updateElement(element.id, buildProps(element, props));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -257,7 +261,7 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
|
|||||||
},
|
},
|
||||||
Bound.fromXYWH(element.deserializedXYWH)
|
Bound.fromXYWH(element.deserializedXYWH)
|
||||||
);
|
);
|
||||||
this.service.updateElement(element.id, {
|
this.crud.updateElement(element.id, {
|
||||||
xywh: newBound.serialize(),
|
xywh: newBound.serialize(),
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
@@ -285,7 +289,7 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
|
|||||||
prevBounds
|
prevBounds
|
||||||
);
|
);
|
||||||
bounds.center = center;
|
bounds.center = center;
|
||||||
this.service.updateElement(element.id, {
|
this.crud.updateElement(element.id, {
|
||||||
labelXYWH: bounds.toXYWH(),
|
labelXYWH: bounds.toXYWH(),
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
@@ -296,7 +300,7 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
|
|||||||
element,
|
element,
|
||||||
Bound.fromXYWH(element.deserializedXYWH)
|
Bound.fromXYWH(element.deserializedXYWH)
|
||||||
);
|
);
|
||||||
this.service.updateElement(element.id, {
|
this.crud.updateElement(element.id, {
|
||||||
xywh: newBound.serialize(),
|
xywh: newBound.serialize(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -307,7 +311,7 @@ export class EdgelessChangeTextMenu extends WithDisposable(LitElement) {
|
|||||||
if (event.type === 'pick') {
|
if (event.type === 'pick') {
|
||||||
this.elements.forEach(element => {
|
this.elements.forEach(element => {
|
||||||
const props = packColor('color', { ...event.detail });
|
const props = packColor('color', { ...event.detail });
|
||||||
this.service.updateElement(element.id, buildProps(element, props));
|
this.crud.updateElement(element.id, buildProps(element, props));
|
||||||
this._updateElementBound(element);
|
this._updateElementBound(element);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
promptDocTitle,
|
promptDocTitle,
|
||||||
} from '@blocksuite/affine-block-embed';
|
} from '@blocksuite/affine-block-embed';
|
||||||
import type { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
import type { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
||||||
|
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||||
import { isPeekable, peek } from '@blocksuite/affine-components/peek';
|
import { isPeekable, peek } from '@blocksuite/affine-components/peek';
|
||||||
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
|
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
|
||||||
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
||||||
@@ -253,8 +254,9 @@ export const conversionsGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
|||||||
if (title === null) return;
|
if (title === null) return;
|
||||||
|
|
||||||
const linkedDoc = createLinkedDocFromNote(doc, element, title);
|
const linkedDoc = createLinkedDocFromNote(doc, element, title);
|
||||||
|
const crud = std.get(EdgelessCRUDIdentifier);
|
||||||
// insert linked doc card
|
// insert linked doc card
|
||||||
const cardId = service.addBlock(
|
const cardId = crud.addBlock(
|
||||||
'affine:embed-synced-doc',
|
'affine:embed-synced-doc',
|
||||||
{
|
{
|
||||||
xywh: element.xywh,
|
xywh: element.xywh,
|
||||||
@@ -300,15 +302,7 @@ export const conversionsGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
|||||||
icon: LinkedPageIcon({ width: '20', height: '20' }),
|
icon: LinkedPageIcon({ width: '20', height: '20' }),
|
||||||
label: 'Create linked doc',
|
label: 'Create linked doc',
|
||||||
type: 'create-linked-doc',
|
type: 'create-linked-doc',
|
||||||
action: async ({
|
action: async ({ doc, selection, surface, edgeless, host, std }) => {
|
||||||
doc,
|
|
||||||
selection,
|
|
||||||
service,
|
|
||||||
surface,
|
|
||||||
edgeless,
|
|
||||||
host,
|
|
||||||
std,
|
|
||||||
}) => {
|
|
||||||
const title = await promptDocTitle(std);
|
const title = await promptDocTitle(std);
|
||||||
if (title === null) return;
|
if (title === null) return;
|
||||||
|
|
||||||
@@ -318,6 +312,7 @@ export const conversionsGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
|||||||
elements,
|
elements,
|
||||||
title
|
title
|
||||||
);
|
);
|
||||||
|
const crud = std.get(EdgelessCRUDIdentifier);
|
||||||
// delete selected elements
|
// delete selected elements
|
||||||
doc.transact(() => {
|
doc.transact(() => {
|
||||||
deleteElements(edgeless, elements);
|
deleteElements(edgeless, elements);
|
||||||
@@ -326,7 +321,7 @@ export const conversionsGroup: MenuItemGroup<ElementToolbarMoreMenuContext> = {
|
|||||||
const width = 364;
|
const width = 364;
|
||||||
const height = 390;
|
const height = 390;
|
||||||
const bound = getCommonBoundWithRotation(elements);
|
const bound = getCommonBoundWithRotation(elements);
|
||||||
const cardId = service.addBlock(
|
const cardId = crud.addBlock(
|
||||||
'affine:embed-linked-doc',
|
'affine:embed-linked-doc',
|
||||||
{
|
{
|
||||||
xywh: `[${bound.center[0] - width / 2}, ${bound.center[1] - height / 2}, ${width}, ${height}]`,
|
xywh: `[${bound.center[0] - width / 2}, ${bound.center[1] - height / 2}, ${width}, ${height}]`,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
LayoutType,
|
LayoutType,
|
||||||
NoteDisplayMode,
|
NoteDisplayMode,
|
||||||
} from '@blocksuite/blocks';
|
} from '@blocksuite/blocks';
|
||||||
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import { DocCollection } from '@blocksuite/store';
|
import { DocCollection } from '@blocksuite/store';
|
||||||
import { beforeEach, describe, expect, test } from 'vitest';
|
import { beforeEach, describe, expect, test } from 'vitest';
|
||||||
|
|
||||||
@@ -26,9 +27,9 @@ describe('group', () => {
|
|||||||
const map = new DocCollection.Y.Map<boolean>();
|
const map = new DocCollection.Y.Map<boolean>();
|
||||||
const ids = Array.from({ length: 2 })
|
const ids = Array.from({ length: 2 })
|
||||||
.map(() => {
|
.map(() => {
|
||||||
const id = service.addElement('shape', {
|
const id = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
map.set(id, true);
|
map.set(id, true);
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
@@ -40,7 +41,7 @@ describe('group', () => {
|
|||||||
return id;
|
return id;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
service.addElement('group', { children: map });
|
service.crud.addElement('group', { children: map });
|
||||||
doc.captureSync();
|
doc.captureSync();
|
||||||
expect(service.elements.length).toBe(3);
|
expect(service.elements.length).toBe(3);
|
||||||
|
|
||||||
@@ -64,14 +65,15 @@ describe('group', () => {
|
|||||||
const map = new DocCollection.Y.Map<boolean>();
|
const map = new DocCollection.Y.Map<boolean>();
|
||||||
const doc = service.doc;
|
const doc = service.doc;
|
||||||
const noteId = addNote(doc);
|
const noteId = addNote(doc);
|
||||||
const shapeId = service.addElement('shape', {
|
const shapeId = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
|
assertExists(shapeId);
|
||||||
|
|
||||||
map.set(noteId, true);
|
map.set(noteId, true);
|
||||||
map.set(shapeId, true);
|
map.set(shapeId, true);
|
||||||
const groupId = service.addElement('group', { children: map });
|
const groupId = service.crud.addElement('group', { children: map });
|
||||||
|
assertExists(groupId);
|
||||||
expect(service.elements.length).toBe(2);
|
expect(service.elements.length).toBe(2);
|
||||||
expect(doc.getBlock(noteId)).toBeDefined();
|
expect(doc.getBlock(noteId)).toBeDefined();
|
||||||
doc.captureSync();
|
doc.captureSync();
|
||||||
@@ -86,14 +88,16 @@ describe('group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("group's xywh should update automatically when children change", async () => {
|
test("group's xywh should update automatically when children change", async () => {
|
||||||
const shape1 = service.addElement('shape', {
|
const shape1 = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
xywh: '[0,0,100,100]',
|
xywh: '[0,0,100,100]',
|
||||||
});
|
});
|
||||||
const shape2 = service.addElement('shape', {
|
assertExists(shape1);
|
||||||
|
const shape2 = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
xywh: '[100,100,100,100]',
|
xywh: '[100,100,100,100]',
|
||||||
});
|
});
|
||||||
|
assertExists(shape2);
|
||||||
const note1 = addNote(doc, {
|
const note1 = addNote(doc, {
|
||||||
displayMode: NoteDisplayMode.DocAndEdgeless,
|
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||||
xywh: '[200,200,800,100]',
|
xywh: '[200,200,800,100]',
|
||||||
@@ -114,7 +118,9 @@ describe('group', () => {
|
|||||||
children.set(shape2, true);
|
children.set(shape2, true);
|
||||||
children.set(note1, true);
|
children.set(note1, true);
|
||||||
|
|
||||||
const groupId = service.addElement('group', { children });
|
const groupId = service.crud.addElement('group', { children });
|
||||||
|
assertExists(groupId);
|
||||||
|
|
||||||
const group = service.getElementById(groupId) as GroupElementModel;
|
const group = service.getElementById(groupId) as GroupElementModel;
|
||||||
const assertInitial = () => {
|
const assertInitial = () => {
|
||||||
expect(group.x).toBe(0);
|
expect(group.x).toBe(0);
|
||||||
@@ -139,7 +145,7 @@ describe('group', () => {
|
|||||||
await wait();
|
await wait();
|
||||||
assertInitial();
|
assertInitial();
|
||||||
|
|
||||||
service.updateElement(note1, {
|
service.crud.updateElement(note1, {
|
||||||
xywh: '[300,300,800,100]',
|
xywh: '[300,300,800,100]',
|
||||||
});
|
});
|
||||||
await wait();
|
await wait();
|
||||||
@@ -165,7 +171,7 @@ describe('group', () => {
|
|||||||
await wait();
|
await wait();
|
||||||
assertInitial();
|
assertInitial();
|
||||||
|
|
||||||
service.updateElement(shape1, {
|
service.crud.updateElement(shape1, {
|
||||||
xywh: '[100,100,100,100]',
|
xywh: '[100,100,100,100]',
|
||||||
});
|
});
|
||||||
await wait();
|
await wait();
|
||||||
@@ -182,7 +188,8 @@ describe('group', () => {
|
|||||||
|
|
||||||
test('empty group should have all zero xywh', () => {
|
test('empty group should have all zero xywh', () => {
|
||||||
const map = new DocCollection.Y.Map<boolean>();
|
const map = new DocCollection.Y.Map<boolean>();
|
||||||
const groupId = service.addElement('group', { children: map });
|
const groupId = service.crud.addElement('group', { children: map });
|
||||||
|
assertExists(groupId);
|
||||||
const group = service.getElementById(groupId) as GroupElementModel;
|
const group = service.getElementById(groupId) as GroupElementModel;
|
||||||
|
|
||||||
expect(group.x).toBe(0);
|
expect(group.x).toBe(0);
|
||||||
@@ -193,9 +200,9 @@ describe('group', () => {
|
|||||||
|
|
||||||
test('descendant of group should not contain itself', () => {
|
test('descendant of group should not contain itself', () => {
|
||||||
const groupIds = [1, 2, 3].map(_ => {
|
const groupIds = [1, 2, 3].map(_ => {
|
||||||
return service.addElement('group', {
|
return service.crud.addElement('group', {
|
||||||
children: new DocCollection.Y.Map<boolean>(),
|
children: new DocCollection.Y.Map<boolean>(),
|
||||||
});
|
}) as string;
|
||||||
});
|
});
|
||||||
const groups = groupIds.map(
|
const groups = groupIds.map(
|
||||||
id => service.getElementById(id) as GroupElementModel
|
id => service.getElementById(id) as GroupElementModel
|
||||||
@@ -245,7 +252,8 @@ describe('mindmap', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
const mindmapId = service.addElement('mindmap', { children: tree });
|
const mindmapId = service.crud.addElement('mindmap', { children: tree });
|
||||||
|
assertExists(mindmapId);
|
||||||
const mindmap = () =>
|
const mindmap = () =>
|
||||||
service.getElementById(mindmapId) as MindmapElementModel;
|
service.getElementById(mindmapId) as MindmapElementModel;
|
||||||
|
|
||||||
@@ -292,10 +300,11 @@ describe('mindmap', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
const mindmapId = service.addElement('mindmap', {
|
const mindmapId = service.crud.addElement('mindmap', {
|
||||||
type: LayoutType.RIGHT,
|
type: LayoutType.RIGHT,
|
||||||
children: tree,
|
children: tree,
|
||||||
});
|
});
|
||||||
|
assertExists(mindmapId);
|
||||||
const mindmap = () =>
|
const mindmap = () =>
|
||||||
service.getElementById(mindmapId) as MindmapElementModel;
|
service.getElementById(mindmapId) as MindmapElementModel;
|
||||||
|
|
||||||
@@ -336,10 +345,11 @@ describe('mindmap', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
const mindmapId = service.addElement('mindmap', {
|
const mindmapId = service.crud.addElement('mindmap', {
|
||||||
type: LayoutType.RIGHT,
|
type: LayoutType.RIGHT,
|
||||||
children: tree,
|
children: tree,
|
||||||
});
|
});
|
||||||
|
assertExists(mindmapId);
|
||||||
const mindmap = () =>
|
const mindmap = () =>
|
||||||
service.getElementById(mindmapId) as MindmapElementModel;
|
service.getElementById(mindmapId) as MindmapElementModel;
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import {
|
|||||||
ShapeType,
|
ShapeType,
|
||||||
type TextElementModel,
|
type TextElementModel,
|
||||||
} from '@blocksuite/blocks';
|
} from '@blocksuite/blocks';
|
||||||
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import { beforeEach, describe, expect, test } from 'vitest';
|
import { beforeEach, describe, expect, test } from 'vitest';
|
||||||
|
|
||||||
import { getDocRootBlock } from '../utils/edgeless.js';
|
import { getDocRootBlock } from '../utils/edgeless.js';
|
||||||
@@ -45,10 +46,13 @@ describe('apply last props', () => {
|
|||||||
|
|
||||||
test('shapes', () => {
|
test('shapes', () => {
|
||||||
// rect shape
|
// rect shape
|
||||||
const rectId = service.addElement('shape', { shapeType: ShapeType.Rect });
|
const rectId = service.crud.addElement('shape', {
|
||||||
|
shapeType: ShapeType.Rect,
|
||||||
|
});
|
||||||
|
assertExists(rectId);
|
||||||
const rectShape = service.getElementById(rectId) as ShapeElementModel;
|
const rectShape = service.getElementById(rectId) as ShapeElementModel;
|
||||||
expect(rectShape.fillColor).toBe(ShapeFillColor.Yellow);
|
expect(rectShape.fillColor).toBe(ShapeFillColor.Yellow);
|
||||||
service.updateElement(rectId, {
|
service.crud.updateElement(rectId, {
|
||||||
fillColor: ShapeFillColor.Orange,
|
fillColor: ShapeFillColor.Orange,
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
@@ -57,12 +61,13 @@ describe('apply last props', () => {
|
|||||||
).toBe(ShapeFillColor.Orange);
|
).toBe(ShapeFillColor.Orange);
|
||||||
|
|
||||||
// diamond shape
|
// diamond shape
|
||||||
const diamondId = service.addElement('shape', {
|
const diamondId = service.crud.addElement('shape', {
|
||||||
shapeType: ShapeType.Diamond,
|
shapeType: ShapeType.Diamond,
|
||||||
});
|
});
|
||||||
|
assertExists(diamondId);
|
||||||
const diamondShape = service.getElementById(diamondId) as ShapeElementModel;
|
const diamondShape = service.getElementById(diamondId) as ShapeElementModel;
|
||||||
expect(diamondShape.fillColor).toBe(ShapeFillColor.Yellow);
|
expect(diamondShape.fillColor).toBe(ShapeFillColor.Yellow);
|
||||||
service.updateElement(diamondId, {
|
service.crud.updateElement(diamondId, {
|
||||||
fillColor: ShapeFillColor.Blue,
|
fillColor: ShapeFillColor.Blue,
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
@@ -71,15 +76,16 @@ describe('apply last props', () => {
|
|||||||
).toBe(ShapeFillColor.Blue);
|
).toBe(ShapeFillColor.Blue);
|
||||||
|
|
||||||
// rounded rect shape
|
// rounded rect shape
|
||||||
const roundedRectId = service.addElement('shape', {
|
const roundedRectId = service.crud.addElement('shape', {
|
||||||
shapeType: ShapeType.Rect,
|
shapeType: ShapeType.Rect,
|
||||||
radius: 0.1,
|
radius: 0.1,
|
||||||
});
|
});
|
||||||
|
assertExists(roundedRectId);
|
||||||
const roundedRectShape = service.getElementById(
|
const roundedRectShape = service.getElementById(
|
||||||
roundedRectId
|
roundedRectId
|
||||||
) as ShapeElementModel;
|
) as ShapeElementModel;
|
||||||
expect(roundedRectShape.fillColor).toBe(ShapeFillColor.Yellow);
|
expect(roundedRectShape.fillColor).toBe(ShapeFillColor.Yellow);
|
||||||
service.updateElement(roundedRectId, {
|
service.crud.updateElement(roundedRectId, {
|
||||||
fillColor: ShapeFillColor.Green,
|
fillColor: ShapeFillColor.Green,
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
@@ -87,22 +93,27 @@ describe('apply last props', () => {
|
|||||||
).toBe(ShapeFillColor.Green);
|
).toBe(ShapeFillColor.Green);
|
||||||
|
|
||||||
// apply last props
|
// apply last props
|
||||||
const rectId2 = service.addElement('shape', { shapeType: ShapeType.Rect });
|
const rectId2 = service.crud.addElement('shape', {
|
||||||
|
shapeType: ShapeType.Rect,
|
||||||
|
});
|
||||||
|
assertExists(rectId2);
|
||||||
const rectShape2 = service.getElementById(rectId2) as ShapeElementModel;
|
const rectShape2 = service.getElementById(rectId2) as ShapeElementModel;
|
||||||
expect(rectShape2.fillColor).toBe(ShapeFillColor.Orange);
|
expect(rectShape2.fillColor).toBe(ShapeFillColor.Orange);
|
||||||
|
|
||||||
const diamondId2 = service.addElement('shape', {
|
const diamondId2 = service.crud.addElement('shape', {
|
||||||
shapeType: ShapeType.Diamond,
|
shapeType: ShapeType.Diamond,
|
||||||
});
|
});
|
||||||
|
assertExists(diamondId2);
|
||||||
const diamondShape2 = service.getElementById(
|
const diamondShape2 = service.getElementById(
|
||||||
diamondId2
|
diamondId2
|
||||||
) as ShapeElementModel;
|
) as ShapeElementModel;
|
||||||
expect(diamondShape2.fillColor).toBe(ShapeFillColor.Blue);
|
expect(diamondShape2.fillColor).toBe(ShapeFillColor.Blue);
|
||||||
|
|
||||||
const roundedRectId2 = service.addElement('shape', {
|
const roundedRectId2 = service.crud.addElement('shape', {
|
||||||
shapeType: ShapeType.Rect,
|
shapeType: ShapeType.Rect,
|
||||||
radius: 0.1,
|
radius: 0.1,
|
||||||
});
|
});
|
||||||
|
assertExists(roundedRectId2);
|
||||||
const roundedRectShape2 = service.getElementById(
|
const roundedRectShape2 = service.getElementById(
|
||||||
roundedRectId2
|
roundedRectId2
|
||||||
) as ShapeElementModel;
|
) as ShapeElementModel;
|
||||||
@@ -110,26 +121,29 @@ describe('apply last props', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('connector', () => {
|
test('connector', () => {
|
||||||
const id = service.addElement('connector', { mode: 0 });
|
const id = service.crud.addElement('connector', { mode: 0 });
|
||||||
|
assertExists(id);
|
||||||
const connector = service.getElementById(id) as ConnectorElementModel;
|
const connector = service.getElementById(id) as ConnectorElementModel;
|
||||||
expect(connector.stroke).toBe(LineColor.Grey);
|
expect(connector.stroke).toBe(LineColor.Grey);
|
||||||
expect(connector.strokeWidth).toBe(2);
|
expect(connector.strokeWidth).toBe(2);
|
||||||
expect(connector.strokeStyle).toBe('solid');
|
expect(connector.strokeStyle).toBe('solid');
|
||||||
expect(connector.frontEndpointStyle).toBe('None');
|
expect(connector.frontEndpointStyle).toBe('None');
|
||||||
expect(connector.rearEndpointStyle).toBe('Arrow');
|
expect(connector.rearEndpointStyle).toBe('Arrow');
|
||||||
service.updateElement(id, { strokeWidth: 10 });
|
service.crud.updateElement(id, { strokeWidth: 10 });
|
||||||
|
|
||||||
const id2 = service.addElement('connector', { mode: 1 });
|
const id2 = service.crud.addElement('connector', { mode: 1 });
|
||||||
|
assertExists(id2);
|
||||||
const connector2 = service.getElementById(id2) as ConnectorElementModel;
|
const connector2 = service.getElementById(id2) as ConnectorElementModel;
|
||||||
expect(connector2.strokeWidth).toBe(10);
|
expect(connector2.strokeWidth).toBe(10);
|
||||||
service.updateElement(id2, {
|
service.crud.updateElement(id2, {
|
||||||
labelStyle: {
|
labelStyle: {
|
||||||
color: LineColor.Magenta,
|
color: LineColor.Magenta,
|
||||||
fontFamily: FontFamily.Kalam,
|
fontFamily: FontFamily.Kalam,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const id3 = service.addElement('connector', { mode: 1 });
|
const id3 = service.crud.addElement('connector', { mode: 1 });
|
||||||
|
assertExists(id3);
|
||||||
const connector3 = service.getElementById(id3) as ConnectorElementModel;
|
const connector3 = service.getElementById(id3) as ConnectorElementModel;
|
||||||
expect(connector3.strokeWidth).toBe(10);
|
expect(connector3.strokeWidth).toBe(10);
|
||||||
expect(connector3.labelStyle.color).toBe(LineColor.Magenta);
|
expect(connector3.labelStyle.color).toBe(LineColor.Magenta);
|
||||||
@@ -137,42 +151,46 @@ describe('apply last props', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('brush', () => {
|
test('brush', () => {
|
||||||
const id = service.addElement('brush', {});
|
const id = service.crud.addElement('brush', {});
|
||||||
|
assertExists(id);
|
||||||
const brush = service.getElementById(id) as BrushElementModel;
|
const brush = service.getElementById(id) as BrushElementModel;
|
||||||
expect(brush.color).toEqual({
|
expect(brush.color).toEqual({
|
||||||
dark: LineColor.White,
|
dark: LineColor.White,
|
||||||
light: LineColor.Black,
|
light: LineColor.Black,
|
||||||
});
|
});
|
||||||
expect(brush.lineWidth).toBe(4);
|
expect(brush.lineWidth).toBe(4);
|
||||||
service.updateElement(id, { lineWidth: 10 });
|
service.crud.updateElement(id, { lineWidth: 10 });
|
||||||
const secondBrush = service.getElementById(
|
const secondBrush = service.getElementById(
|
||||||
service.addElement('brush', {})
|
service.crud.addElement('brush', {}) as string
|
||||||
) as BrushElementModel;
|
) as BrushElementModel;
|
||||||
expect(secondBrush.lineWidth).toBe(10);
|
expect(secondBrush.lineWidth).toBe(10);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('text', () => {
|
test('text', () => {
|
||||||
const id = service.addElement('text', {});
|
const id = service.crud.addElement('text', {});
|
||||||
|
assertExists(id);
|
||||||
const text = service.getElementById(id) as TextElementModel;
|
const text = service.getElementById(id) as TextElementModel;
|
||||||
expect(text.fontSize).toBe(24);
|
expect(text.fontSize).toBe(24);
|
||||||
service.updateElement(id, { fontSize: 36 });
|
service.crud.updateElement(id, { fontSize: 36 });
|
||||||
const secondText = service.getElementById(
|
const secondText = service.getElementById(
|
||||||
service.addElement('text', {})
|
service.crud.addElement('text', {}) as string
|
||||||
) as TextElementModel;
|
) as TextElementModel;
|
||||||
expect(secondText.fontSize).toBe(36);
|
expect(secondText.fontSize).toBe(36);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('mindmap', () => {
|
test('mindmap', () => {
|
||||||
const id = service.addElement('mindmap', {});
|
const id = service.crud.addElement('mindmap', {});
|
||||||
|
assertExists(id);
|
||||||
const mindmap = service.getElementById(id) as MindmapElementModel;
|
const mindmap = service.getElementById(id) as MindmapElementModel;
|
||||||
expect(mindmap.layoutType).toBe(LayoutType.RIGHT);
|
expect(mindmap.layoutType).toBe(LayoutType.RIGHT);
|
||||||
expect(mindmap.style).toBe(MindmapStyle.ONE);
|
expect(mindmap.style).toBe(MindmapStyle.ONE);
|
||||||
service.updateElement(id, {
|
service.crud.updateElement(id, {
|
||||||
layoutType: LayoutType.BALANCE,
|
layoutType: LayoutType.BALANCE,
|
||||||
style: MindmapStyle.THREE,
|
style: MindmapStyle.THREE,
|
||||||
});
|
});
|
||||||
|
|
||||||
const id2 = service.addElement('mindmap', {});
|
const id2 = service.crud.addElement('mindmap', {});
|
||||||
|
assertExists(id2);
|
||||||
const mindmap2 = service.getElementById(id2) as MindmapElementModel;
|
const mindmap2 = service.getElementById(id2) as MindmapElementModel;
|
||||||
expect(mindmap2.layoutType).toBe(LayoutType.BALANCE);
|
expect(mindmap2.layoutType).toBe(LayoutType.BALANCE);
|
||||||
expect(mindmap2.style).toBe(MindmapStyle.THREE);
|
expect(mindmap2.style).toBe(MindmapStyle.THREE);
|
||||||
@@ -180,27 +198,30 @@ describe('apply last props', () => {
|
|||||||
|
|
||||||
test('edgeless-text', () => {
|
test('edgeless-text', () => {
|
||||||
const surface = getSurfaceBlock(doc);
|
const surface = getSurfaceBlock(doc);
|
||||||
const id = service.addBlock('affine:edgeless-text', {}, surface!.id);
|
const id = service.crud.addBlock('affine:edgeless-text', {}, surface!.id);
|
||||||
|
assertExists(id);
|
||||||
const text = service.getElementById(id) as EdgelessTextBlockModel;
|
const text = service.getElementById(id) as EdgelessTextBlockModel;
|
||||||
expect(text.color).toBe(DEFAULT_TEXT_COLOR);
|
expect(text.color).toBe(DEFAULT_TEXT_COLOR);
|
||||||
expect(text.fontFamily).toBe(FontFamily.Inter);
|
expect(text.fontFamily).toBe(FontFamily.Inter);
|
||||||
service.updateElement(id, {
|
service.crud.updateElement(id, {
|
||||||
color: LineColor.Green,
|
color: LineColor.Green,
|
||||||
fontFamily: FontFamily.OrelegaOne,
|
fontFamily: FontFamily.OrelegaOne,
|
||||||
});
|
});
|
||||||
|
|
||||||
const id2 = service.addBlock('affine:edgeless-text', {}, surface!.id);
|
const id2 = service.crud.addBlock('affine:edgeless-text', {}, surface!.id);
|
||||||
|
assertExists(id2);
|
||||||
const text2 = service.getElementById(id2) as EdgelessTextBlockModel;
|
const text2 = service.getElementById(id2) as EdgelessTextBlockModel;
|
||||||
expect(text2.color).toBe(LineColor.Green);
|
expect(text2.color).toBe(LineColor.Green);
|
||||||
expect(text2.fontFamily).toBe(FontFamily.OrelegaOne);
|
expect(text2.fontFamily).toBe(FontFamily.OrelegaOne);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('note', () => {
|
test('note', () => {
|
||||||
const id = service.addBlock('affine:note', {}, doc.root!.id);
|
const id = service.crud.addBlock('affine:note', {}, doc.root!.id);
|
||||||
|
assertExists(id);
|
||||||
const note = service.getElementById(id) as NoteBlockModel;
|
const note = service.getElementById(id) as NoteBlockModel;
|
||||||
expect(note.background).toBe(DEFAULT_NOTE_BACKGROUND_COLOR);
|
expect(note.background).toBe(DEFAULT_NOTE_BACKGROUND_COLOR);
|
||||||
expect(note.edgeless.style.shadowType).toBe(DEFAULT_NOTE_SHADOW);
|
expect(note.edgeless.style.shadowType).toBe(DEFAULT_NOTE_SHADOW);
|
||||||
service.updateElement(id, {
|
service.crud.updateElement(id, {
|
||||||
background: NoteBackgroundColor.Purple,
|
background: NoteBackgroundColor.Purple,
|
||||||
edgeless: {
|
edgeless: {
|
||||||
style: {
|
style: {
|
||||||
@@ -209,7 +230,8 @@ describe('apply last props', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const id2 = service.addBlock('affine:note', {}, doc.root!.id);
|
const id2 = service.crud.addBlock('affine:note', {}, doc.root!.id);
|
||||||
|
assertExists(id2);
|
||||||
const note2 = service.getElementById(id2) as NoteBlockModel;
|
const note2 = service.getElementById(id2) as NoteBlockModel;
|
||||||
expect(note2.background).toBe(NoteBackgroundColor.Purple);
|
expect(note2.background).toBe(NoteBackgroundColor.Purple);
|
||||||
expect(note2.edgeless.style.shadowType).toBe(NoteShadow.Film);
|
expect(note2.edgeless.style.shadowType).toBe(NoteShadow.Film);
|
||||||
@@ -217,28 +239,32 @@ describe('apply last props', () => {
|
|||||||
|
|
||||||
test('frame', () => {
|
test('frame', () => {
|
||||||
const surface = getSurfaceBlock(doc);
|
const surface = getSurfaceBlock(doc);
|
||||||
const id = service.addBlock('affine:frame', {}, surface!.id);
|
const id = service.crud.addBlock('affine:frame', {}, surface!.id);
|
||||||
|
assertExists(id);
|
||||||
const note = service.getElementById(id) as FrameBlockModel;
|
const note = service.getElementById(id) as FrameBlockModel;
|
||||||
expect(note.background).toBe('--affine-palette-transparent');
|
expect(note.background).toBe('--affine-palette-transparent');
|
||||||
service.updateElement(id, {
|
service.crud.updateElement(id, {
|
||||||
background: FrameBackgroundColor.Purple,
|
background: FrameBackgroundColor.Purple,
|
||||||
});
|
});
|
||||||
|
|
||||||
const id2 = service.addBlock('affine:frame', {}, surface!.id);
|
const id2 = service.crud.addBlock('affine:frame', {}, surface!.id);
|
||||||
|
assertExists(id2);
|
||||||
const frame2 = service.getElementById(id2) as FrameBlockModel;
|
const frame2 = service.getElementById(id2) as FrameBlockModel;
|
||||||
expect(frame2.background).toBe(FrameBackgroundColor.Purple);
|
expect(frame2.background).toBe(FrameBackgroundColor.Purple);
|
||||||
service.updateElement(id, {
|
service.crud.updateElement(id2, {
|
||||||
background: { normal: '#def4e740' },
|
background: { normal: '#def4e740' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const id3 = service.addBlock('affine:frame', {}, surface!.id);
|
const id3 = service.crud.addBlock('affine:frame', {}, surface!.id);
|
||||||
|
assertExists(id3);
|
||||||
const frame3 = service.getElementById(id3) as FrameBlockModel;
|
const frame3 = service.getElementById(id3) as FrameBlockModel;
|
||||||
expect(frame3.background).toEqual({ normal: '#def4e740' });
|
expect(frame3.background).toEqual({ normal: '#def4e740' });
|
||||||
service.updateElement(id, {
|
service.crud.updateElement(id3, {
|
||||||
background: { light: '#a381aa23', dark: '#6e907452' },
|
background: { light: '#a381aa23', dark: '#6e907452' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const id4 = service.addBlock('affine:frame', {}, surface!.id);
|
const id4 = service.crud.addBlock('affine:frame', {}, surface!.id);
|
||||||
|
assertExists(id4);
|
||||||
const frame4 = service.getElementById(id4) as FrameBlockModel;
|
const frame4 = service.getElementById(id4) as FrameBlockModel;
|
||||||
expect(frame4.background).toEqual({
|
expect(frame4.background).toEqual({
|
||||||
light: '#a381aa23',
|
light: '#a381aa23',
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ describe('add new edgeless blocks or canvas elements should update layer automat
|
|||||||
test('add note, note, shape sequentially', async () => {
|
test('add note, note, shape sequentially', async () => {
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ describe('add new edgeless blocks or canvas elements should update layer automat
|
|||||||
|
|
||||||
test('add note, shape, note sequentially', async () => {
|
test('add note, shape, note sequentially', async () => {
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
@@ -68,7 +68,7 @@ describe('add new edgeless blocks or canvas elements should update layer automat
|
|||||||
|
|
||||||
test('delete element should update layer automatically', () => {
|
test('delete element should update layer automatically', () => {
|
||||||
const id = addNote(doc);
|
const id = addNote(doc);
|
||||||
const canvasElId = service.addElement('shape', {
|
const canvasElId = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -76,20 +76,20 @@ test('delete element should update layer automatically', () => {
|
|||||||
|
|
||||||
expect(service.layer.layers.length).toBe(1);
|
expect(service.layer.layers.length).toBe(1);
|
||||||
|
|
||||||
service.removeElement(canvasElId);
|
service.removeElement(canvasElId!);
|
||||||
|
|
||||||
expect(service.layer.layers.length).toBe(0);
|
expect(service.layer.layers.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('change element should update layer automatically', async () => {
|
test('change element should update layer automatically', async () => {
|
||||||
const id = addNote(doc);
|
const id = addNote(doc);
|
||||||
const canvasElId = service.addElement('shape', {
|
const canvasElId = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
|
|
||||||
await wait();
|
await wait();
|
||||||
|
|
||||||
service.updateElement(id, {
|
service.crud.updateElement(id, {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(id)!,
|
service.getElementById(id)!,
|
||||||
'forward'
|
'forward'
|
||||||
@@ -99,9 +99,9 @@ test('change element should update layer automatically', async () => {
|
|||||||
'block'
|
'block'
|
||||||
);
|
);
|
||||||
|
|
||||||
service.updateElement(canvasElId, {
|
service.crud.updateElement(canvasElId!, {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(canvasElId)!,
|
service.getElementById(canvasElId!)!,
|
||||||
'forward'
|
'forward'
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@@ -112,7 +112,7 @@ test('change element should update layer automatically', async () => {
|
|||||||
|
|
||||||
test('new added canvas elements should be placed in the topmost canvas layer', async () => {
|
test('new added canvas elements should be placed in the topmost canvas layer', async () => {
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -130,11 +130,11 @@ test("there should be at lease one layer in canvasLayers property even there's n
|
|||||||
|
|
||||||
test('if the topmost layer is canvas layer, the length of canvasLayers array should equal to the counts of canvas layers', () => {
|
test('if the topmost layer is canvas layer, the length of canvasLayers array should equal to the counts of canvas layers', () => {
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -145,11 +145,11 @@ test('if the topmost layer is canvas layer, the length of canvasLayers array sho
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('a new layer should be created in canvasLayers prop when the topmost layer is not canvas layer', () => {
|
test('a new layer should be created in canvasLayers prop when the topmost layer is not canvas layer', () => {
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
@@ -162,13 +162,13 @@ test('layer zindex should update correctly when elements changed', async () => {
|
|||||||
const noteId = addNote(doc);
|
const noteId = addNote(doc);
|
||||||
const note = service.getElementById(noteId);
|
const note = service.getElementById(noteId);
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
const topShapeId = service.addElement('shape', {
|
const topShapeId = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
});
|
||||||
const topShape = service.getElementById(topShapeId);
|
const topShape = service.getElementById(topShapeId!)!;
|
||||||
|
|
||||||
await wait();
|
await wait();
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ test('layer zindex should update correctly when elements changed', async () => {
|
|||||||
|
|
||||||
service.doc.captureSync();
|
service.doc.captureSync();
|
||||||
|
|
||||||
service.updateElement(noteId, {
|
service.crud.updateElement(noteId, {
|
||||||
index: service.layer.getReorderedIndex(note!, 'front'),
|
index: service.layer.getReorderedIndex(note!, 'front'),
|
||||||
});
|
});
|
||||||
await wait();
|
await wait();
|
||||||
@@ -198,7 +198,7 @@ test('layer zindex should update correctly when elements changed', async () => {
|
|||||||
};
|
};
|
||||||
assert2StepState();
|
assert2StepState();
|
||||||
|
|
||||||
service.updateElement(topShapeId, {
|
service.crud.updateElement(topShapeId!, {
|
||||||
index: service.layer.getReorderedIndex(topShape!, 'front'),
|
index: service.layer.getReorderedIndex(topShape!, 'front'),
|
||||||
});
|
});
|
||||||
await wait();
|
await wait();
|
||||||
@@ -235,7 +235,7 @@ test('blocks should rerender when their z-index changed', async () => {
|
|||||||
await wait();
|
await wait();
|
||||||
assertBlocksContent();
|
assertBlocksContent();
|
||||||
|
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
index: CommonUtils.generateKeyBetween(
|
index: CommonUtils.generateKeyBetween(
|
||||||
service.getElementById(blocks[1])!.index,
|
service.getElementById(blocks[1])!.index,
|
||||||
@@ -252,19 +252,19 @@ describe('layer reorder functionality', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ids = [
|
ids = [
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
addNote(doc),
|
addNote(doc),
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
addNote(doc),
|
addNote(doc),
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
test('forward', async () => {
|
test('forward', async () => {
|
||||||
service.updateElement(ids[0], {
|
service.crud.updateElement(ids[0], {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(ids[0])!,
|
service.getElementById(ids[0])!,
|
||||||
'forward'
|
'forward'
|
||||||
@@ -284,7 +284,7 @@ describe('layer reorder functionality', () => {
|
|||||||
|
|
||||||
await wait();
|
await wait();
|
||||||
|
|
||||||
service.updateElement(ids[1], {
|
service.crud.updateElement(ids[1], {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(ids[1])!,
|
service.getElementById(ids[1])!,
|
||||||
'forward'
|
'forward'
|
||||||
@@ -304,7 +304,7 @@ describe('layer reorder functionality', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('front', async () => {
|
test('front', async () => {
|
||||||
service.updateElement(ids[0], {
|
service.crud.updateElement(ids[0], {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(ids[0])!,
|
service.getElementById(ids[0])!,
|
||||||
'front'
|
'front'
|
||||||
@@ -319,7 +319,7 @@ describe('layer reorder functionality', () => {
|
|||||||
)
|
)
|
||||||
).toBe(3);
|
).toBe(3);
|
||||||
|
|
||||||
service.updateElement(ids[1], {
|
service.crud.updateElement(ids[1], {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(ids[1])!,
|
service.getElementById(ids[1])!,
|
||||||
'front'
|
'front'
|
||||||
@@ -334,7 +334,7 @@ describe('layer reorder functionality', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('backward', async () => {
|
test('backward', async () => {
|
||||||
service.updateElement(ids[3], {
|
service.crud.updateElement(ids[3], {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(ids[3])!,
|
service.getElementById(ids[3])!,
|
||||||
'backward'
|
'backward'
|
||||||
@@ -354,7 +354,7 @@ describe('layer reorder functionality', () => {
|
|||||||
|
|
||||||
await wait();
|
await wait();
|
||||||
|
|
||||||
service.updateElement(ids[2], {
|
service.crud.updateElement(ids[2], {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(ids[2])!,
|
service.getElementById(ids[2])!,
|
||||||
'backward'
|
'backward'
|
||||||
@@ -374,7 +374,7 @@ describe('layer reorder functionality', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('back', async () => {
|
test('back', async () => {
|
||||||
service.updateElement(ids[3], {
|
service.crud.updateElement(ids[3], {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(ids[3])!,
|
service.getElementById(ids[3])!,
|
||||||
'back'
|
'back'
|
||||||
@@ -389,7 +389,7 @@ describe('layer reorder functionality', () => {
|
|||||||
|
|
||||||
await wait();
|
await wait();
|
||||||
|
|
||||||
service.updateElement(ids[2], {
|
service.crud.updateElement(ids[2], {
|
||||||
index: service.layer.getReorderedIndex(
|
index: service.layer.getReorderedIndex(
|
||||||
service.getElementById(ids[2])!,
|
service.getElementById(ids[2])!,
|
||||||
'back'
|
'back'
|
||||||
@@ -412,7 +412,7 @@ describe('group related functionality', () => {
|
|||||||
const children = new DocCollection.Y.Map<boolean>();
|
const children = new DocCollection.Y.Map<boolean>();
|
||||||
childIds.forEach(id => children.set(id, true));
|
childIds.forEach(id => children.set(id, true));
|
||||||
|
|
||||||
return service.addElement('group', {
|
return service.crud.addElement('group', {
|
||||||
children,
|
children,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -420,17 +420,17 @@ describe('group related functionality', () => {
|
|||||||
test("new added group should effect it children's layer", async () => {
|
test("new added group should effect it children's layer", async () => {
|
||||||
const edgeless = getDocRootBlock(doc, editor, 'edgeless');
|
const edgeless = getDocRootBlock(doc, editor, 'edgeless');
|
||||||
const elements = [
|
const elements = [
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
addNote(doc),
|
addNote(doc),
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
addNote(doc),
|
addNote(doc),
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
];
|
];
|
||||||
|
|
||||||
await wait(0);
|
await wait(0);
|
||||||
@@ -490,23 +490,23 @@ describe('group related functionality', () => {
|
|||||||
|
|
||||||
test("change group index should update its children's layer", () => {
|
test("change group index should update its children's layer", () => {
|
||||||
const elements = [
|
const elements = [
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
addNote(doc),
|
addNote(doc),
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
addNote(doc),
|
addNote(doc),
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
];
|
];
|
||||||
|
|
||||||
const groupId = createGroup(
|
const groupId = createGroup(
|
||||||
service,
|
service,
|
||||||
elements.filter((_, idx) => idx !== 1 && idx !== 3)
|
elements.filter((_, idx) => idx !== 1 && idx !== 3)
|
||||||
);
|
)!;
|
||||||
const group = service.getElementById(groupId)!;
|
const group = service.getElementById(groupId)!;
|
||||||
|
|
||||||
expect(service.layer.layers.length).toBe(2);
|
expect(service.layer.layers.length).toBe(2);
|
||||||
@@ -525,17 +525,17 @@ describe('group related functionality', () => {
|
|||||||
test('should keep relative index order of elements after group, ungroup, undo, redo', () => {
|
test('should keep relative index order of elements after group, ungroup, undo, redo', () => {
|
||||||
const edgeless = getDocRootBlock(doc, editor, 'edgeless');
|
const edgeless = getDocRootBlock(doc, editor, 'edgeless');
|
||||||
const elementIds = [
|
const elementIds = [
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
addNote(doc),
|
addNote(doc),
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
addNote(doc),
|
addNote(doc),
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
}),
|
})!,
|
||||||
];
|
];
|
||||||
service.doc.captureSync();
|
service.doc.captureSync();
|
||||||
const elements = elementIds.map(id => service.getElementById(id)!);
|
const elements = elementIds.map(id => service.getElementById(id)!);
|
||||||
@@ -549,7 +549,7 @@ describe('group related functionality', () => {
|
|||||||
|
|
||||||
expect(isKeptRelativeOrder()).toBeTruthy();
|
expect(isKeptRelativeOrder()).toBeTruthy();
|
||||||
|
|
||||||
const groupId = createGroup(edgeless.service, elementIds);
|
const groupId = createGroup(edgeless.service, elementIds)!;
|
||||||
expect(isKeptRelativeOrder()).toBeTruthy();
|
expect(isKeptRelativeOrder()).toBeTruthy();
|
||||||
|
|
||||||
service.ungroup(service.getElementById(groupId) as GroupElementModel);
|
service.ungroup(service.getElementById(groupId) as GroupElementModel);
|
||||||
@@ -577,19 +577,19 @@ describe('compare function', () => {
|
|||||||
const children = new DocCollection.Y.Map<boolean>();
|
const children = new DocCollection.Y.Map<boolean>();
|
||||||
childIds.forEach(id => children.set(id, true));
|
childIds.forEach(id => children.set(id, true));
|
||||||
|
|
||||||
return service.addElement('group', {
|
return service.crud.addElement('group', {
|
||||||
children,
|
children,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
test('compare same element', () => {
|
test('compare same element', () => {
|
||||||
const shapeId = service.addElement('shape', {
|
const shapeId = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
const shapeEl = service.getElementById(shapeId)!;
|
const shapeEl = service.getElementById(shapeId)!;
|
||||||
expect(service.layer.compare(shapeEl, shapeEl)).toBe(SORT_ORDER.SAME);
|
expect(service.layer.compare(shapeEl, shapeEl)).toBe(SORT_ORDER.SAME);
|
||||||
|
|
||||||
const groupId = createGroup(service, [shapeId]);
|
const groupId = createGroup(service, [shapeId])!;
|
||||||
const groupEl = service.getElementById(groupId)!;
|
const groupEl = service.getElementById(groupId)!;
|
||||||
expect(service.layer.compare(groupEl, groupEl)).toBe(SORT_ORDER.SAME);
|
expect(service.layer.compare(groupEl, groupEl)).toBe(SORT_ORDER.SAME);
|
||||||
|
|
||||||
@@ -599,13 +599,13 @@ describe('compare function', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('compare a group and its child', () => {
|
test('compare a group and its child', () => {
|
||||||
const shapeId = service.addElement('shape', {
|
const shapeId = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
const shapeEl = service.getElementById(shapeId)!;
|
const shapeEl = service.getElementById(shapeId)!;
|
||||||
const noteId = addNote(doc);
|
const noteId = addNote(doc);
|
||||||
const note = service.getElementById(noteId)! as NoteBlockModel;
|
const note = service.getElementById(noteId)! as NoteBlockModel;
|
||||||
const groupId = createGroup(service, [shapeId, noteId]);
|
const groupId = createGroup(service, [shapeId, noteId])!;
|
||||||
const groupEl = service.getElementById(groupId)!;
|
const groupEl = service.getElementById(groupId)!;
|
||||||
|
|
||||||
expect(service.layer.compare(groupEl, shapeEl)).toBe(SORT_ORDER.BEFORE);
|
expect(service.layer.compare(groupEl, shapeEl)).toBe(SORT_ORDER.BEFORE);
|
||||||
@@ -615,13 +615,13 @@ describe('compare function', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('compare two different elements', () => {
|
test('compare two different elements', () => {
|
||||||
const shape1Id = service.addElement('shape', {
|
const shape1Id = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
const shape1 = service.getElementById(shape1Id)!;
|
const shape1 = service.getElementById(shape1Id)!;
|
||||||
const shape2Id = service.addElement('shape', {
|
const shape2Id = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
const shape2 = service.getElementById(shape2Id)!;
|
const shape2 = service.getElementById(shape2Id)!;
|
||||||
const note1Id = addNote(doc);
|
const note1Id = addNote(doc);
|
||||||
|
|
||||||
@@ -643,12 +643,12 @@ describe('compare function', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('compare nested elements', () => {
|
test('compare nested elements', () => {
|
||||||
const shape1Id = service.addElement('shape', {
|
const shape1Id = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
const shape2Id = service.addElement('shape', {
|
const shape2Id = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
const note1Id = addNote(doc);
|
const note1Id = addNote(doc);
|
||||||
const note2Id = addNote(doc);
|
const note2Id = addNote(doc);
|
||||||
const group1Id = createGroup(service, [
|
const group1Id = createGroup(service, [
|
||||||
@@ -656,8 +656,8 @@ describe('compare function', () => {
|
|||||||
shape2Id,
|
shape2Id,
|
||||||
note1Id,
|
note1Id,
|
||||||
note2Id,
|
note2Id,
|
||||||
]);
|
])!;
|
||||||
const group2Id = createGroup(service, [group1Id]);
|
const group2Id = createGroup(service, [group1Id])!;
|
||||||
|
|
||||||
const shape1 = service.getElementById(shape1Id)!;
|
const shape1 = service.getElementById(shape1Id)!;
|
||||||
const shape2 = service.getElementById(shape2Id)!;
|
const shape2 = service.getElementById(shape2Id)!;
|
||||||
@@ -688,24 +688,24 @@ describe('compare function', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('compare two nested elements', () => {
|
test('compare two nested elements', () => {
|
||||||
const groupAShapeId = service.addElement('shape', {
|
const groupAShapeId = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
const groupANoteId = addNote(doc);
|
const groupANoteId = addNote(doc);
|
||||||
const groupAId = createGroup(service, [
|
const groupAId = createGroup(service, [
|
||||||
createGroup(service, [groupAShapeId, groupANoteId]),
|
createGroup(service, [groupAShapeId, groupANoteId])!,
|
||||||
]);
|
])!;
|
||||||
const groupAShape = service.getElementById(groupAShapeId)!;
|
const groupAShape = service.getElementById(groupAShapeId)!;
|
||||||
const groupANote = service.getElementById(groupANoteId)!;
|
const groupANote = service.getElementById(groupANoteId)!;
|
||||||
const groupA = service.getElementById(groupAId)!;
|
const groupA = service.getElementById(groupAId)!;
|
||||||
|
|
||||||
const groupBShapeId = service.addElement('shape', {
|
const groupBShapeId = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
const groupBNoteId = addNote(doc);
|
const groupBNoteId = addNote(doc);
|
||||||
const groupBId = createGroup(service, [
|
const groupBId = createGroup(service, [
|
||||||
createGroup(service, [groupBShapeId, groupBNoteId]),
|
createGroup(service, [groupBShapeId, groupBNoteId])!,
|
||||||
]);
|
])!;
|
||||||
const groupBShape = service.getElementById(groupBShapeId)!;
|
const groupBShape = service.getElementById(groupBShapeId)!;
|
||||||
const groupBNote = service.getElementById(groupBNoteId)!;
|
const groupBNote = service.getElementById(groupBNoteId)!;
|
||||||
const groupB = service.getElementById(groupBId)!;
|
const groupB = service.getElementById(groupBId)!;
|
||||||
@@ -759,17 +759,17 @@ describe('compare function', () => {
|
|||||||
test('indexed canvas should be inserted into edgeless portal when switch to edgeless mode', async () => {
|
test('indexed canvas should be inserted into edgeless portal when switch to edgeless mode', async () => {
|
||||||
let surface = getSurface(doc, editor);
|
let surface = getSurface(doc, editor);
|
||||||
|
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
|
|
||||||
addNote(doc);
|
addNote(doc);
|
||||||
|
|
||||||
await wait();
|
await wait();
|
||||||
|
|
||||||
service.addElement('shape', {
|
service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
|
|
||||||
editor.mode = 'page';
|
editor.mode = 'page';
|
||||||
await wait();
|
await wait();
|
||||||
@@ -855,9 +855,9 @@ describe('index generator', () => {
|
|||||||
let preinsertedNote: NoteBlockModel;
|
let preinsertedNote: NoteBlockModel;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const shapeId = service.addElement('shape', {
|
const shapeId = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
});
|
})!;
|
||||||
const noteId = addNote(doc);
|
const noteId = addNote(doc);
|
||||||
|
|
||||||
preinsertedShape = service.getElementById(
|
preinsertedShape = service.getElementById(
|
||||||
|
|||||||
@@ -29,20 +29,20 @@ describe('basic', () => {
|
|||||||
noteAId = addNote(doc, {
|
noteAId = addNote(doc, {
|
||||||
index: service.generateIndex(),
|
index: service.generateIndex(),
|
||||||
});
|
});
|
||||||
shapeAId = service.addElement('shape', {
|
shapeAId = service.crud.addElement('shape', {
|
||||||
type: 'rect',
|
type: 'rect',
|
||||||
xywh: '[0, 0, 100, 100]',
|
xywh: '[0, 0, 100, 100]',
|
||||||
index: service.generateIndex(),
|
index: service.generateIndex(),
|
||||||
});
|
})!;
|
||||||
noteBId = addNote(doc, {
|
noteBId = addNote(doc, {
|
||||||
index: service.generateIndex(),
|
index: service.generateIndex(),
|
||||||
});
|
});
|
||||||
shapeBId = service.addElement('shape', {
|
shapeBId = service.crud.addElement('shape', {
|
||||||
type: 'rect',
|
type: 'rect',
|
||||||
xywh: '[100, 0, 100, 100]',
|
xywh: '[100, 0, 100, 100]',
|
||||||
index: service.generateIndex(),
|
index: service.generateIndex(),
|
||||||
});
|
})!;
|
||||||
frameId = service.addBlock(
|
frameId = service.crud.addBlock(
|
||||||
'affine:frame',
|
'affine:frame',
|
||||||
{
|
{
|
||||||
xywh: '[0, 0, 800, 200]',
|
xywh: '[0, 0, 800, 200]',
|
||||||
@@ -122,7 +122,7 @@ describe('basic', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('content in group should be rendered in the correct order', async () => {
|
test('content in group should be rendered in the correct order', async () => {
|
||||||
const groupId = service.addElement('group', {
|
const groupId = service.crud.addElement('group', {
|
||||||
children: {
|
children: {
|
||||||
[shapeAId]: true,
|
[shapeAId]: true,
|
||||||
[shapeBId]: true,
|
[shapeBId]: true,
|
||||||
@@ -186,14 +186,14 @@ describe('basic', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('group should be rendered in surface-ref viewport', async () => {
|
test('group should be rendered in surface-ref viewport', async () => {
|
||||||
const groupId = service.addElement('group', {
|
const groupId = service.crud.addElement('group', {
|
||||||
children: {
|
children: {
|
||||||
[shapeAId]: true,
|
[shapeAId]: true,
|
||||||
[shapeBId]: true,
|
[shapeBId]: true,
|
||||||
[noteAId]: true,
|
[noteAId]: true,
|
||||||
[noteBId]: true,
|
[noteBId]: true,
|
||||||
},
|
},
|
||||||
});
|
})!;
|
||||||
const surfaceRefId = doc.addBlock(
|
const surfaceRefId = doc.addBlock(
|
||||||
'affine:surface-ref',
|
'affine:surface-ref',
|
||||||
{
|
{
|
||||||
@@ -247,7 +247,7 @@ describe('basic', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('view in edgeless mode button', async () => {
|
test('view in edgeless mode button', async () => {
|
||||||
const groupId = service.addElement('group', {
|
const groupId = service.crud.addElement('group', {
|
||||||
children: {
|
children: {
|
||||||
[shapeAId]: true,
|
[shapeAId]: true,
|
||||||
[shapeBId]: true,
|
[shapeBId]: true,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe('default tool', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('element click selection', async () => {
|
test('element click selection', async () => {
|
||||||
const id = service.addElement('shape', {
|
const id = service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
xywh: '[0,0,100,100]',
|
xywh: '[0,0,100,100]',
|
||||||
fillColor: 'red',
|
fillColor: 'red',
|
||||||
@@ -47,7 +47,7 @@ describe('default tool', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('element drag moving', async () => {
|
test('element drag moving', async () => {
|
||||||
const id = edgeless.service.addElement('shape', {
|
const id = edgeless.service.crud.addElement('shape', {
|
||||||
shapeType: 'rect',
|
shapeType: 'rect',
|
||||||
xywh: '[0,0,100,100]',
|
xywh: '[0,0,100,100]',
|
||||||
fillColor: 'red',
|
fillColor: 'red',
|
||||||
@@ -64,7 +64,7 @@ describe('default tool', () => {
|
|||||||
drag(edgeless.host, { x: 0, y: 50 }, { x: 0, y: 150 });
|
drag(edgeless.host, { x: 0, y: 50 }, { x: 0, y: 150 });
|
||||||
await wait();
|
await wait();
|
||||||
|
|
||||||
const element = service.getElementById(id)!;
|
const element = service.getElementById(id!)!;
|
||||||
expect(element.xywh).toEqual(`[0,100,100,100]`);
|
expect(element.xywh).toEqual(`[0,100,100,100]`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -508,7 +508,7 @@ const CREATE_AS_LINKED_DOC = {
|
|||||||
y = viewportCenter.y - height / 2;
|
y = viewportCenter.y - height / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
service.addBlock(
|
service.crud.addBlock(
|
||||||
'affine:embed-linked-doc',
|
'affine:embed-linked-doc',
|
||||||
{
|
{
|
||||||
xywh: `[${x}, ${y}, ${width}, ${height}]`,
|
xywh: `[${x}, ${y}, ${width}, ${height}]`,
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ export class AIChatBlockPeekView extends LitElement {
|
|||||||
|
|
||||||
const edgelessService = this._rootService as EdgelessRootService;
|
const edgelessService = this._rootService as EdgelessRootService;
|
||||||
const bound = calcChildBound(this.parentModel, edgelessService);
|
const bound = calcChildBound(this.parentModel, edgelessService);
|
||||||
const aiChatBlockId = edgelessService.addBlock(
|
const aiChatBlockId = edgelessService.crud.addBlock(
|
||||||
'affine:embed-ai-chat' as keyof BlockSuite.BlockModels,
|
'affine:embed-ai-chat' as keyof BlockSuite.BlockModels,
|
||||||
{
|
{
|
||||||
xywh: bound.serialize(),
|
xywh: bound.serialize(),
|
||||||
@@ -193,7 +193,7 @@ export class AIChatBlockPeekView extends LitElement {
|
|||||||
this.updateContext({ currentChatBlockId: aiChatBlockId });
|
this.updateContext({ currentChatBlockId: aiChatBlockId });
|
||||||
|
|
||||||
// Connect the parent chat block to the AI chat block
|
// Connect the parent chat block to the AI chat block
|
||||||
edgelessService.addElement(CanvasElementType.CONNECTOR, {
|
edgelessService.crud.addElement(CanvasElementType.CONNECTOR, {
|
||||||
mode: ConnectorMode.Curve,
|
mode: ConnectorMode.Curve,
|
||||||
controllers: [],
|
controllers: [],
|
||||||
source: { id: this.parentChatBlockId },
|
source: { id: this.parentChatBlockId },
|
||||||
|
|||||||
@@ -530,7 +530,7 @@ export function patchEdgelessClipboard() {
|
|||||||
rootDocId,
|
rootDocId,
|
||||||
rootWorkspaceId,
|
rootWorkspaceId,
|
||||||
} = block.props;
|
} = block.props;
|
||||||
const blockId = component.service.addBlock(
|
const blockId = component.service.crud.addBlock(
|
||||||
AIChatBlockFlavour,
|
AIChatBlockFlavour,
|
||||||
{
|
{
|
||||||
xywh,
|
xywh,
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ export const ShapeSettings = () => {
|
|||||||
const { shapeType, radius } = shape;
|
const { shapeType, radius } = shape;
|
||||||
const shapeName = getShapeName(shapeType, radius);
|
const shapeName = getShapeName(shapeType, radius);
|
||||||
const props = editorSetting.get(`shape:${shapeName}`);
|
const props = editorSetting.get(`shape:${shapeName}`);
|
||||||
edgelessService.updateElement(shape.id, props);
|
edgelessService.crud.updateElement(shape.id, props);
|
||||||
});
|
});
|
||||||
doc.awarenessStore.setReadonly(doc.blockCollection, true);
|
doc.awarenessStore.setReadonly(doc.blockCollection, true);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
const props = editorSetting.get(keyName) as any;
|
const props = editorSetting.get(keyName) as any;
|
||||||
doc.awarenessStore.setReadonly(doc.blockCollection, false);
|
doc.awarenessStore.setReadonly(doc.blockCollection, false);
|
||||||
elements.forEach(element => {
|
elements.forEach(element => {
|
||||||
edgelessService.updateElement(element.id, props);
|
edgelessService.crud.updateElement(element.id, props);
|
||||||
});
|
});
|
||||||
doc.awarenessStore.setReadonly(doc.blockCollection, true);
|
doc.awarenessStore.setReadonly(doc.blockCollection, true);
|
||||||
}, [editorSetting, getElements, keyName]);
|
}, [editorSetting, getElements, keyName]);
|
||||||
|
|||||||
Reference in New Issue
Block a user