Files
AFFiNE-Mirror/blocksuite/affine/shared/src/utils/edgeless.ts
T
L-Sun 091bac1047 fix(editor): add comment entire to inner toolbar (#13304)
Close
[BS-3624](https://linear.app/affine-design/issue/BS-3624/page模式单选图片的时候希望有comment-按钮)




#### PR Dependency Tree


* **PR #13304** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a comment button to the image and surface reference block
toolbars for easier commenting.

* **Refactor**
* Simplified array flattening operations across multiple components and
utilities by replacing `.map(...).flat()` with `.flatMap(...)`,
improving code readability and maintainability.

* **Bug Fixes**
* Improved comment creation logic to allow adding comments even when
selections exist.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-07-29 13:21:56 +08:00

78 lines
2.1 KiB
TypeScript

import { FrameBlockModel, GroupElementModel } from '@blocksuite/affine-model';
import {
deserializeXYWH,
getQuadBoundWithRotation,
} from '@blocksuite/global/gfx';
import type { GfxBlockElementModel, GfxModel } from '@blocksuite/std/gfx';
import type { BlockModel } from '@blocksuite/store';
export function getSelectedRect(selected: GfxModel[]): DOMRect {
if (selected.length === 0) {
return new DOMRect();
}
const lockedElementsByFrame = selected.flatMap(selectable => {
if (selectable instanceof FrameBlockModel && selectable.isLocked()) {
return selectable.descendantElements;
}
return [];
});
selected = [...new Set([...selected, ...lockedElementsByFrame])];
if (selected.length === 1) {
const [x, y, w, h] = deserializeXYWH(selected[0].xywh);
return new DOMRect(x, y, w, h);
}
return getElementsWithoutGroup(selected).reduce(
(bounds, selectable, index) => {
const rotate = isTopLevelBlock(selectable) ? 0 : selectable.rotate;
const [x, y, w, h] = deserializeXYWH(selectable.xywh);
let { left, top, right, bottom } = getQuadBoundWithRotation({
x,
y,
w,
h,
rotate,
});
if (index !== 0) {
left = Math.min(left, bounds.left);
top = Math.min(top, bounds.top);
right = Math.max(right, bounds.right);
bottom = Math.max(bottom, bounds.bottom);
}
bounds.x = left;
bounds.y = top;
bounds.width = right - left;
bounds.height = bottom - top;
return bounds;
},
new DOMRect()
);
}
export function getElementsWithoutGroup(elements: GfxModel[]) {
const set = new Set<GfxModel>();
elements.forEach(element => {
if (element instanceof GroupElementModel) {
element.descendantElements
.filter(descendant => !(descendant instanceof GroupElementModel))
.forEach(descendant => set.add(descendant));
} else {
set.add(element);
}
});
return Array.from(set);
}
export function isTopLevelBlock(
selectable: BlockModel | GfxModel | null
): selectable is GfxBlockElementModel {
return !!selectable && 'flavour' in selectable;
}