mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-15 21:41:52 +08:00
feat(editor): limit embed edgeless iframe block width and height (#11192)
[BS-2841](https://linear.app/affine-design/issue/BS-2841/iframe-embed-block-edgeless-block-component-限制-resize-时的最大最小宽高)
This commit is contained in:
@@ -69,6 +69,10 @@ import {
|
||||
AI_CHAT_BLOCK_MAX_WIDTH,
|
||||
AI_CHAT_BLOCK_MIN_HEIGHT,
|
||||
AI_CHAT_BLOCK_MIN_WIDTH,
|
||||
EMBED_IFRAME_BLOCK_MAX_HEIGHT,
|
||||
EMBED_IFRAME_BLOCK_MAX_WIDTH,
|
||||
EMBED_IFRAME_BLOCK_MIN_HEIGHT,
|
||||
EMBED_IFRAME_BLOCK_MIN_WIDTH,
|
||||
} from '../../utils/consts.js';
|
||||
import {
|
||||
getSelectableBounds,
|
||||
@@ -81,6 +85,7 @@ import {
|
||||
isEmbedFigmaBlock,
|
||||
isEmbedGithubBlock,
|
||||
isEmbedHtmlBlock,
|
||||
isEmbedIframeBlock,
|
||||
isEmbedLinkedDocBlock,
|
||||
isEmbedLoomBlock,
|
||||
isEmbedSyncedDocBlock,
|
||||
@@ -114,6 +119,13 @@ export type SelectedRect = {
|
||||
|
||||
export const EDGELESS_SELECTED_RECT_WIDGET = 'edgeless-selected-rect';
|
||||
|
||||
interface ResizeConstraints {
|
||||
minWidth: number;
|
||||
maxWidth: number;
|
||||
minHeight: number;
|
||||
maxHeight: number;
|
||||
}
|
||||
|
||||
export class EdgelessSelectedRectWidget extends WidgetComponent<
|
||||
RootBlockModel,
|
||||
EdgelessRootBlockComponent
|
||||
@@ -526,6 +538,11 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEmbedIframeBlock(element)) {
|
||||
this.#adjustEmbedIframe(element, bound, direction);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._isProportionalElement(element)) {
|
||||
this.#adjustProportional(element, bound, direction);
|
||||
return;
|
||||
@@ -949,37 +966,43 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
|
||||
* TODO: Remove this function after the edgeless refactor completed
|
||||
* This function is used to adjust the element bound and scale
|
||||
* Should not be used in the future
|
||||
* Related issue: https://linear.app/affine-design/issue/BS-1009/
|
||||
* @deprecated
|
||||
*/
|
||||
#adjustAIChat(element: GfxModel, bound: Bound, direction: HandleDirection) {
|
||||
#adjustBlockWithConstraints(
|
||||
element: GfxModel,
|
||||
bound: Bound,
|
||||
direction: HandleDirection,
|
||||
constraints: ResizeConstraints
|
||||
) {
|
||||
const curBound = Bound.deserialize(element.xywh);
|
||||
const { minWidth, maxWidth, minHeight, maxHeight } = constraints;
|
||||
|
||||
let scale = 1;
|
||||
if ('scale' in element) {
|
||||
scale = element.scale as number;
|
||||
if ('props' in element && 'scale' in element.props) {
|
||||
scale = element.props.scale as number;
|
||||
}
|
||||
let width = curBound.w / scale;
|
||||
let height = curBound.h / scale;
|
||||
|
||||
// Handle shift key scaling (maintain aspect ratio)
|
||||
if (this._shiftKey) {
|
||||
scale = bound.w / width;
|
||||
this._scalePercent = `${Math.round(scale * 100)}%`;
|
||||
this._scaleDirection = direction;
|
||||
}
|
||||
|
||||
// Apply constraints
|
||||
width = bound.w / scale;
|
||||
width = clamp(width, AI_CHAT_BLOCK_MIN_WIDTH, AI_CHAT_BLOCK_MAX_WIDTH);
|
||||
width = clamp(width, minWidth, maxWidth);
|
||||
bound.w = width * scale;
|
||||
|
||||
height = bound.h / scale;
|
||||
height = clamp(height, AI_CHAT_BLOCK_MIN_HEIGHT, AI_CHAT_BLOCK_MAX_HEIGHT);
|
||||
height = clamp(height, minHeight, maxHeight);
|
||||
bound.h = height * scale;
|
||||
|
||||
this._isWidthLimit =
|
||||
width === AI_CHAT_BLOCK_MIN_WIDTH || width === AI_CHAT_BLOCK_MAX_WIDTH;
|
||||
this._isHeightLimit =
|
||||
height === AI_CHAT_BLOCK_MIN_HEIGHT ||
|
||||
height === AI_CHAT_BLOCK_MAX_HEIGHT;
|
||||
// Update limit flags
|
||||
this._isWidthLimit = width === minWidth || width === maxWidth;
|
||||
this._isHeightLimit = height === minHeight || height === maxHeight;
|
||||
|
||||
this.gfx.updateElement(element.id, {
|
||||
scale,
|
||||
@@ -987,6 +1010,42 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Remove this function after the edgeless refactor completed
|
||||
* This function is used to adjust the element bound and scale
|
||||
* Should not be used in the future
|
||||
* Related issue: https://linear.app/affine-design/issue/BS-1009/
|
||||
* @deprecated
|
||||
*/
|
||||
#adjustAIChat(element: GfxModel, bound: Bound, direction: HandleDirection) {
|
||||
this.#adjustBlockWithConstraints(element, bound, direction, {
|
||||
minWidth: AI_CHAT_BLOCK_MIN_WIDTH,
|
||||
maxWidth: AI_CHAT_BLOCK_MAX_WIDTH,
|
||||
minHeight: AI_CHAT_BLOCK_MIN_HEIGHT,
|
||||
maxHeight: AI_CHAT_BLOCK_MAX_HEIGHT,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Remove this function after the edgeless refactor completed
|
||||
* This function is used to adjust the element bound and scale
|
||||
* Should not be used in the future
|
||||
* Related issue: https://linear.app/affine-design/issue/BS-2841/
|
||||
* @deprecated
|
||||
*/
|
||||
#adjustEmbedIframe(
|
||||
element: GfxModel,
|
||||
bound: Bound,
|
||||
direction: HandleDirection
|
||||
) {
|
||||
this.#adjustBlockWithConstraints(element, bound, direction, {
|
||||
minWidth: EMBED_IFRAME_BLOCK_MIN_WIDTH,
|
||||
maxWidth: EMBED_IFRAME_BLOCK_MAX_WIDTH,
|
||||
minHeight: EMBED_IFRAME_BLOCK_MIN_HEIGHT,
|
||||
maxHeight: EMBED_IFRAME_BLOCK_MAX_HEIGHT,
|
||||
});
|
||||
}
|
||||
|
||||
#adjustConnector(
|
||||
element: ConnectorElementModel,
|
||||
bounds: Bound,
|
||||
|
||||
@@ -14,3 +14,8 @@ export const AI_CHAT_BLOCK_MIN_WIDTH = 260;
|
||||
export const AI_CHAT_BLOCK_MIN_HEIGHT = 160;
|
||||
export const AI_CHAT_BLOCK_MAX_WIDTH = 320;
|
||||
export const AI_CHAT_BLOCK_MAX_HEIGHT = 300;
|
||||
|
||||
export const EMBED_IFRAME_BLOCK_MIN_WIDTH = 218;
|
||||
export const EMBED_IFRAME_BLOCK_MIN_HEIGHT = 44;
|
||||
export const EMBED_IFRAME_BLOCK_MAX_WIDTH = 3400;
|
||||
export const EMBED_IFRAME_BLOCK_MAX_HEIGHT = 2200;
|
||||
|
||||
@@ -88,6 +88,21 @@ export function isAIChatBlock(element: BlockModel | GfxModel | null) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Remove this function after the edgeless refactor completed
|
||||
* This function is used to check if the block is an EmbedIframeBlock for edgeless selected rect
|
||||
* Should not be used in the future
|
||||
* Related issue: https://linear.app/affine-design/issue/BS-2841/
|
||||
* @deprecated
|
||||
*/
|
||||
export function isEmbedIframeBlock(element: BlockModel | GfxModel | null) {
|
||||
return (
|
||||
!!element &&
|
||||
'flavour' in element &&
|
||||
element.flavour === 'affine:embed-iframe'
|
||||
);
|
||||
}
|
||||
|
||||
export function isEmbeddedLinkBlock(element: BlockModel | GfxModel | null) {
|
||||
return (
|
||||
isEmbeddedBlock(element) &&
|
||||
|
||||
Reference in New Issue
Block a user