mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
perf(editor): optimize the search for the closest element (#9587)
Closes: [BS-2275](https://linear.app/affine-design/issue/BS-2275/拖拽-indicator-查找优化)
This commit is contained in:
@@ -9,7 +9,7 @@ import {
|
||||
} from '../dom/index.js';
|
||||
import { matchFlavours } from '../model/index.js';
|
||||
import { getDropRectByPoint } from './get-drop-rect-by-point.js';
|
||||
import { DropFlags, type DroppingType, type DropResult } from './types.js';
|
||||
import { DropFlags, type DropPlacement, type DropTarget } from './types.js';
|
||||
|
||||
function getVisiblePreviousElementSibling(element: Element | null) {
|
||||
if (!element) return null;
|
||||
@@ -43,7 +43,7 @@ export function calcDropTarget(
|
||||
* Allow the dragging block to be dropped as sublist
|
||||
*/
|
||||
allowSublist: boolean = true
|
||||
): DropResult | null {
|
||||
): DropTarget | null {
|
||||
const schema = model.doc.getSchemaByFlavour('affine:database');
|
||||
const children = schema?.model.children ?? [];
|
||||
|
||||
@@ -64,7 +64,7 @@ export function calcDropTarget(
|
||||
}
|
||||
}
|
||||
|
||||
let type: DroppingType = 'none';
|
||||
let placement: DropPlacement = 'none';
|
||||
const height = 3 * scale;
|
||||
const dropResult = getDropRectByPoint(point, model, element);
|
||||
if (!dropResult) return null;
|
||||
@@ -75,10 +75,10 @@ export function calcDropTarget(
|
||||
const rect = Rect.fromDOMRect(domRect);
|
||||
rect.top -= height / 2;
|
||||
rect.height = height;
|
||||
type = 'database';
|
||||
placement = 'database';
|
||||
|
||||
return {
|
||||
type,
|
||||
placement,
|
||||
rect,
|
||||
modelState: {
|
||||
model,
|
||||
@@ -91,10 +91,10 @@ export function calcDropTarget(
|
||||
const distanceToTop = Math.abs(domRect.top - point.y);
|
||||
const distanceToBottom = Math.abs(domRect.bottom - point.y);
|
||||
const before = distanceToTop < distanceToBottom;
|
||||
type = before ? 'before' : 'after';
|
||||
placement = before ? 'before' : 'after';
|
||||
|
||||
return {
|
||||
type,
|
||||
placement,
|
||||
rect: Rect.fromLWTH(
|
||||
domRect.left,
|
||||
domRect.width,
|
||||
@@ -113,10 +113,10 @@ export function calcDropTarget(
|
||||
const distanceToBottom = Math.abs(domRect.bottom - point.y);
|
||||
const before = distanceToTop < distanceToBottom;
|
||||
|
||||
type = before ? 'before' : 'after';
|
||||
placement = before ? 'before' : 'after';
|
||||
let offsetY = 4;
|
||||
|
||||
if (type === 'before') {
|
||||
if (placement === 'before') {
|
||||
// before
|
||||
let prev;
|
||||
let prevRect;
|
||||
@@ -127,7 +127,7 @@ export function calcDropTarget(
|
||||
draggingElements.length &&
|
||||
prev === draggingElements[draggingElements.length - 1]
|
||||
) {
|
||||
type = 'none';
|
||||
placement = 'none';
|
||||
} else {
|
||||
prevRect = getRectByBlockComponent(prev);
|
||||
}
|
||||
@@ -153,7 +153,7 @@ export function calcDropTarget(
|
||||
!hasChild &&
|
||||
point.x > domRect.x + BLOCK_CHILDREN_CONTAINER_PADDING_LEFT
|
||||
) {
|
||||
type = 'in';
|
||||
placement = 'in';
|
||||
}
|
||||
// after
|
||||
let next;
|
||||
@@ -162,11 +162,11 @@ export function calcDropTarget(
|
||||
next = getVisibleNextElementSibling(element);
|
||||
if (next) {
|
||||
if (
|
||||
type === 'after' &&
|
||||
placement === 'after' &&
|
||||
draggingElements.length &&
|
||||
next === draggingElements[0]
|
||||
) {
|
||||
type = 'none';
|
||||
placement = 'none';
|
||||
next = null;
|
||||
}
|
||||
} else {
|
||||
@@ -181,22 +181,22 @@ export function calcDropTarget(
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'none') return null;
|
||||
if (placement === 'none') return null;
|
||||
|
||||
let top = domRect.top;
|
||||
if (type === 'before') {
|
||||
if (placement === 'before') {
|
||||
top -= offsetY;
|
||||
} else {
|
||||
top += domRect.height + offsetY;
|
||||
}
|
||||
|
||||
if (type === 'in') {
|
||||
if (placement === 'in') {
|
||||
domRect.x += BLOCK_CHILDREN_CONTAINER_PADDING_LEFT;
|
||||
domRect.width -= BLOCK_CHILDREN_CONTAINER_PADDING_LEFT;
|
||||
}
|
||||
|
||||
return {
|
||||
type,
|
||||
placement,
|
||||
rect: Rect.fromLWTH(domRect.left, domRect.width, top - height / 2, height),
|
||||
modelState: {
|
||||
model,
|
||||
|
||||
@@ -18,12 +18,12 @@ export enum DropFlags {
|
||||
}
|
||||
|
||||
/**
|
||||
* A dropping type.
|
||||
* A drop placement.
|
||||
*/
|
||||
export type DroppingType = 'none' | 'before' | 'after' | 'database' | 'in';
|
||||
export type DropPlacement = 'none' | 'before' | 'after' | 'database' | 'in';
|
||||
|
||||
export type DropResult = {
|
||||
type: DroppingType;
|
||||
export type DropTarget = {
|
||||
placement: DropPlacement;
|
||||
rect: Rect;
|
||||
modelState: EditingState;
|
||||
};
|
||||
|
||||
@@ -146,8 +146,8 @@ export function getClosestBlockComponentByPoint(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Indented paragraphs or list
|
||||
bounds = getRectByBlockComponent(element);
|
||||
// Indented paragraphs or list
|
||||
childBounds = element
|
||||
.querySelector('.affine-block-children-container')
|
||||
?.firstElementChild?.getBoundingClientRect();
|
||||
@@ -263,8 +263,8 @@ export function getClosestBlockComponentByElement(
|
||||
* https://github.com/toeverything/blocksuite/pull/1121
|
||||
*/
|
||||
export function getRectByBlockComponent(element: Element | BlockComponent) {
|
||||
if (isDatabase(element)) return element.getBoundingClientRect();
|
||||
return (element.firstElementChild ?? element).getBoundingClientRect();
|
||||
if (!isDatabase(element)) element = element.firstElementChild ?? element;
|
||||
return element.getBoundingClientRect();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,9 +303,8 @@ function findBlockComponent(elements: Element[], parent?: Element) {
|
||||
if (hasBlockId(element) && isBlock(element)) return element;
|
||||
if (isImage(element)) {
|
||||
const element = elements[i];
|
||||
if (i < len && hasBlockId(element) && isBlock(element)) {
|
||||
return elements[i];
|
||||
}
|
||||
if (!element) return null;
|
||||
if (hasBlockId(element) && isBlock(element)) return element;
|
||||
return getClosestBlockComponentByElement(element);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user