diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts index d98d89d2c..db428d477 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts @@ -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, diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/utils/consts.ts b/blocksuite/affine/blocks/block-root/src/edgeless/utils/consts.ts index 15dd17fd4..eb3497b4d 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/utils/consts.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/utils/consts.ts @@ -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; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/utils/query.ts b/blocksuite/affine/blocks/block-root/src/edgeless/utils/query.ts index cd09176eb..304c96217 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/utils/query.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/utils/query.ts @@ -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) &&