mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-20 11:31:47 +08:00
1f45cc5dec
**Directory Structure Changes** - Renamed multiple block-related directories by removing the "block-" prefix: - `block-attachment` → `attachment` - `block-bookmark` → `bookmark` - `block-callout` → `callout` - `block-code` → `code` - `block-data-view` → `data-view` - `block-database` → `database` - `block-divider` → `divider` - `block-edgeless-text` → `edgeless-text` - `block-embed` → `embed`
138 lines
3.5 KiB
TypeScript
138 lines
3.5 KiB
TypeScript
import {
|
|
DEFAULT_NOTE_HEIGHT,
|
|
DEFAULT_NOTE_WIDTH,
|
|
NOTE_MIN_HEIGHT,
|
|
type NoteBlockModel,
|
|
NoteDisplayMode,
|
|
} from '@blocksuite/affine-model';
|
|
import { focusTextModel } from '@blocksuite/affine-rich-text';
|
|
import { TelemetryProvider } from '@blocksuite/affine-shared/services';
|
|
import type { NoteChildrenFlavour } from '@blocksuite/affine-shared/types';
|
|
import { handleNativeRangeAtPoint } from '@blocksuite/affine-shared/utils';
|
|
import { type IPoint, type Point, serializeXYWH } from '@blocksuite/global/gfx';
|
|
import type { BlockStdScope } from '@blocksuite/std';
|
|
import {
|
|
type GfxBlockElementModel,
|
|
GfxControllerIdentifier,
|
|
} from '@blocksuite/std/gfx';
|
|
|
|
import { DEFAULT_NOTE_OFFSET_X, DEFAULT_NOTE_OFFSET_Y } from '../consts';
|
|
import { EdgelessCRUDIdentifier } from '../extensions/crud-extension';
|
|
|
|
export function addNoteAtPoint(
|
|
std: BlockStdScope,
|
|
/**
|
|
* The point is in browser coordinate
|
|
*/
|
|
point: IPoint,
|
|
options: {
|
|
width?: number;
|
|
height?: number;
|
|
parentId?: string;
|
|
noteIndex?: number;
|
|
offsetX?: number;
|
|
offsetY?: number;
|
|
scale?: number;
|
|
} = {}
|
|
) {
|
|
const gfx = std.get(GfxControllerIdentifier);
|
|
const crud = std.get(EdgelessCRUDIdentifier);
|
|
const {
|
|
width = DEFAULT_NOTE_WIDTH,
|
|
height = DEFAULT_NOTE_HEIGHT,
|
|
offsetX = DEFAULT_NOTE_OFFSET_X,
|
|
offsetY = DEFAULT_NOTE_OFFSET_Y,
|
|
parentId = gfx.doc.root?.id,
|
|
noteIndex,
|
|
scale = 1,
|
|
} = options;
|
|
const [x, y] = gfx.viewport.toModelCoord(point.x, point.y);
|
|
const blockId = crud.addBlock(
|
|
'affine:note',
|
|
{
|
|
xywh: serializeXYWH(
|
|
x - offsetX * scale,
|
|
y - offsetY * scale,
|
|
width,
|
|
height
|
|
),
|
|
displayMode: NoteDisplayMode.EdgelessOnly,
|
|
},
|
|
parentId,
|
|
noteIndex
|
|
);
|
|
|
|
std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', {
|
|
control: 'canvas:draw',
|
|
page: 'whiteboard editor',
|
|
module: 'toolbar',
|
|
segment: 'toolbar',
|
|
type: 'note',
|
|
});
|
|
|
|
return blockId;
|
|
}
|
|
|
|
type NoteOptions = {
|
|
childFlavour: NoteChildrenFlavour;
|
|
childType: string | null;
|
|
collapse: boolean;
|
|
};
|
|
|
|
export function addNote(
|
|
std: BlockStdScope,
|
|
point: Point,
|
|
options: NoteOptions,
|
|
width = DEFAULT_NOTE_WIDTH,
|
|
height = DEFAULT_NOTE_HEIGHT
|
|
) {
|
|
const noteId = addNoteAtPoint(std, point, {
|
|
width,
|
|
height,
|
|
});
|
|
|
|
const gfx = std.get(GfxControllerIdentifier);
|
|
const doc = std.store;
|
|
|
|
const blockId = doc.addBlock(
|
|
options.childFlavour,
|
|
{ type: options.childType },
|
|
noteId
|
|
);
|
|
if (options.collapse && height > NOTE_MIN_HEIGHT) {
|
|
const note = doc.getModelById(noteId) as NoteBlockModel;
|
|
doc.updateBlock(note, () => {
|
|
note.props.edgeless.collapse = true;
|
|
note.props.edgeless.collapsedHeight = height;
|
|
});
|
|
}
|
|
gfx.tool.setTool(
|
|
// @ts-expect-error FIXME: resolve after gfx tool refactor
|
|
'default'
|
|
);
|
|
|
|
// Wait for edgelessTool updated
|
|
requestAnimationFrame(() => {
|
|
const blocks =
|
|
(doc.root?.children.filter(
|
|
child => child.flavour === 'affine:note'
|
|
) as GfxBlockElementModel[]) ?? [];
|
|
const element = blocks.find(b => b.id === noteId);
|
|
if (element) {
|
|
gfx.selection.set({
|
|
elements: [element.id],
|
|
editing: true,
|
|
});
|
|
|
|
// Waiting dom updated, `note mask` is removed
|
|
if (blockId) {
|
|
focusTextModel(gfx.std, blockId);
|
|
} else {
|
|
// Cannot reuse `handleNativeRangeClick` directly here,
|
|
// since `retargetClick` will re-target to pervious editor
|
|
handleNativeRangeAtPoint(point.x, point.y);
|
|
}
|
|
}
|
|
});
|
|
}
|