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_MAX_WIDTH,
|
||||||
AI_CHAT_BLOCK_MIN_HEIGHT,
|
AI_CHAT_BLOCK_MIN_HEIGHT,
|
||||||
AI_CHAT_BLOCK_MIN_WIDTH,
|
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';
|
} from '../../utils/consts.js';
|
||||||
import {
|
import {
|
||||||
getSelectableBounds,
|
getSelectableBounds,
|
||||||
@@ -81,6 +85,7 @@ import {
|
|||||||
isEmbedFigmaBlock,
|
isEmbedFigmaBlock,
|
||||||
isEmbedGithubBlock,
|
isEmbedGithubBlock,
|
||||||
isEmbedHtmlBlock,
|
isEmbedHtmlBlock,
|
||||||
|
isEmbedIframeBlock,
|
||||||
isEmbedLinkedDocBlock,
|
isEmbedLinkedDocBlock,
|
||||||
isEmbedLoomBlock,
|
isEmbedLoomBlock,
|
||||||
isEmbedSyncedDocBlock,
|
isEmbedSyncedDocBlock,
|
||||||
@@ -114,6 +119,13 @@ export type SelectedRect = {
|
|||||||
|
|
||||||
export const EDGELESS_SELECTED_RECT_WIDGET = 'edgeless-selected-rect';
|
export const EDGELESS_SELECTED_RECT_WIDGET = 'edgeless-selected-rect';
|
||||||
|
|
||||||
|
interface ResizeConstraints {
|
||||||
|
minWidth: number;
|
||||||
|
maxWidth: number;
|
||||||
|
minHeight: number;
|
||||||
|
maxHeight: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class EdgelessSelectedRectWidget extends WidgetComponent<
|
export class EdgelessSelectedRectWidget extends WidgetComponent<
|
||||||
RootBlockModel,
|
RootBlockModel,
|
||||||
EdgelessRootBlockComponent
|
EdgelessRootBlockComponent
|
||||||
@@ -526,6 +538,11 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isEmbedIframeBlock(element)) {
|
||||||
|
this.#adjustEmbedIframe(element, bound, direction);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this._isProportionalElement(element)) {
|
if (this._isProportionalElement(element)) {
|
||||||
this.#adjustProportional(element, bound, direction);
|
this.#adjustProportional(element, bound, direction);
|
||||||
return;
|
return;
|
||||||
@@ -949,37 +966,43 @@ export class EdgelessSelectedRectWidget extends WidgetComponent<
|
|||||||
* TODO: Remove this function after the edgeless refactor completed
|
* TODO: Remove this function after the edgeless refactor completed
|
||||||
* This function is used to adjust the element bound and scale
|
* This function is used to adjust the element bound and scale
|
||||||
* Should not be used in the future
|
* Should not be used in the future
|
||||||
* Related issue: https://linear.app/affine-design/issue/BS-1009/
|
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
#adjustAIChat(element: GfxModel, bound: Bound, direction: HandleDirection) {
|
#adjustBlockWithConstraints(
|
||||||
|
element: GfxModel,
|
||||||
|
bound: Bound,
|
||||||
|
direction: HandleDirection,
|
||||||
|
constraints: ResizeConstraints
|
||||||
|
) {
|
||||||
const curBound = Bound.deserialize(element.xywh);
|
const curBound = Bound.deserialize(element.xywh);
|
||||||
|
const { minWidth, maxWidth, minHeight, maxHeight } = constraints;
|
||||||
|
|
||||||
let scale = 1;
|
let scale = 1;
|
||||||
if ('scale' in element) {
|
if ('props' in element && 'scale' in element.props) {
|
||||||
scale = element.scale as number;
|
scale = element.props.scale as number;
|
||||||
}
|
}
|
||||||
let width = curBound.w / scale;
|
let width = curBound.w / scale;
|
||||||
let height = curBound.h / scale;
|
let height = curBound.h / scale;
|
||||||
|
|
||||||
|
// Handle shift key scaling (maintain aspect ratio)
|
||||||
if (this._shiftKey) {
|
if (this._shiftKey) {
|
||||||
scale = bound.w / width;
|
scale = bound.w / width;
|
||||||
this._scalePercent = `${Math.round(scale * 100)}%`;
|
this._scalePercent = `${Math.round(scale * 100)}%`;
|
||||||
this._scaleDirection = direction;
|
this._scaleDirection = direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply constraints
|
||||||
width = bound.w / scale;
|
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;
|
bound.w = width * scale;
|
||||||
|
|
||||||
height = bound.h / 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;
|
bound.h = height * scale;
|
||||||
|
|
||||||
this._isWidthLimit =
|
// Update limit flags
|
||||||
width === AI_CHAT_BLOCK_MIN_WIDTH || width === AI_CHAT_BLOCK_MAX_WIDTH;
|
this._isWidthLimit = width === minWidth || width === maxWidth;
|
||||||
this._isHeightLimit =
|
this._isHeightLimit = height === minHeight || height === maxHeight;
|
||||||
height === AI_CHAT_BLOCK_MIN_HEIGHT ||
|
|
||||||
height === AI_CHAT_BLOCK_MAX_HEIGHT;
|
|
||||||
|
|
||||||
this.gfx.updateElement(element.id, {
|
this.gfx.updateElement(element.id, {
|
||||||
scale,
|
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(
|
#adjustConnector(
|
||||||
element: ConnectorElementModel,
|
element: ConnectorElementModel,
|
||||||
bounds: Bound,
|
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_MIN_HEIGHT = 160;
|
||||||
export const AI_CHAT_BLOCK_MAX_WIDTH = 320;
|
export const AI_CHAT_BLOCK_MAX_WIDTH = 320;
|
||||||
export const AI_CHAT_BLOCK_MAX_HEIGHT = 300;
|
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) {
|
export function isEmbeddedLinkBlock(element: BlockModel | GfxModel | null) {
|
||||||
return (
|
return (
|
||||||
isEmbeddedBlock(element) &&
|
isEmbeddedBlock(element) &&
|
||||||
|
|||||||
Reference in New Issue
Block a user