diff --git a/blocksuite/affine/model/src/consts/image.ts b/blocksuite/affine/model/src/consts/image.ts new file mode 100644 index 0000000000..2f281f8a6a --- /dev/null +++ b/blocksuite/affine/model/src/consts/image.ts @@ -0,0 +1 @@ +export const MAX_IMAGE_WIDTH = 460; diff --git a/blocksuite/affine/model/src/consts/index.ts b/blocksuite/affine/model/src/consts/index.ts index f871216c5c..bde0ac46d0 100644 --- a/blocksuite/affine/model/src/consts/index.ts +++ b/blocksuite/affine/model/src/consts/index.ts @@ -2,6 +2,7 @@ export * from './brush.js'; export * from './connector.js'; export * from './doc.js'; export * from './frame.js'; +export * from './image.js'; export * from './line.js'; export * from './mindmap.js'; export * from './note.js'; diff --git a/blocksuite/blocks/src/image-block/image-service.ts b/blocksuite/blocks/src/image-block/image-service.ts index 01a26515fc..e48f751653 100644 --- a/blocksuite/blocks/src/image-block/image-service.ts +++ b/blocksuite/blocks/src/image-block/image-service.ts @@ -1,5 +1,5 @@ import { FileDropConfigExtension } from '@blocksuite/affine-components/drag-indicator'; -import { ImageBlockSchema } from '@blocksuite/affine-model'; +import { ImageBlockSchema, MAX_IMAGE_WIDTH } from '@blocksuite/affine-model'; import { DragHandleConfigExtension, TelemetryProvider, @@ -52,7 +52,9 @@ export const ImageDropOption = FileDropConfigExtension({ if (isInsideEdgelessEditor(std.host)) { const gfx = std.get(GfxControllerIdentifier); point = gfx.viewport.toViewCoordFromClientCoord(point); - addImages(std, files, point).catch(console.error); + addImages(std, files, { point, maxWidth: MAX_IMAGE_WIDTH }).catch( + console.error + ); std.getOptional(TelemetryProvider)?.track('CanvasElementAdded', { control: 'canvas:drop', diff --git a/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts b/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts index 7e491364a1..f28b558681 100644 --- a/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts +++ b/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { CanvasElementType, SurfaceGroupLikeModel, @@ -9,6 +8,7 @@ import { BookmarkStyles, DEFAULT_NOTE_HEIGHT, DEFAULT_NOTE_WIDTH, + MAX_IMAGE_WIDTH, ReferenceInfoSchema, } from '@blocksuite/affine-model'; import { @@ -256,7 +256,10 @@ export class EdgelessClipboardController extends PageClipboard { // when only images in clipboard, add image-blocks else add all files as attachments if (attachmentFiles.length === 0) { - await addImages(this.std, imageFiles, point); + await addImages(this.std, imageFiles, { + point, + maxWidth: MAX_IMAGE_WIDTH, + }); } else { await addAttachments(this.std, [...files], point); } @@ -359,7 +362,7 @@ export class EdgelessClipboardController extends PageClipboard { const svg = tryGetSvgFromClipboard(data); if (svg) { - await addImages(this.std, [svg], point); + await addImages(this.std, [svg], { point, maxWidth: MAX_IMAGE_WIDTH }); return; } try { diff --git a/blocksuite/blocks/src/root-block/edgeless/components/toolbar/note/note-menu.ts b/blocksuite/blocks/src/root-block/edgeless/components/toolbar/note/note-menu.ts index b5ea8a0f6d..dd1e5f5b1a 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/toolbar/note/note-menu.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/toolbar/note/note-menu.ts @@ -1,4 +1,5 @@ import { AttachmentIcon, LinkIcon } from '@blocksuite/affine-components/icons'; +import { MAX_IMAGE_WIDTH } from '@blocksuite/affine-model'; import { TelemetryProvider } from '@blocksuite/affine-shared/services'; import type { GfxToolsFullOptionValue } from '@blocksuite/block-std/gfx'; import { effect } from '@preact/signals-core'; @@ -55,7 +56,9 @@ export class EdgelessNoteMenu extends EdgelessToolbarToolMixin(LitElement) { private async _addImages() { this._imageLoading = true; const imageFiles = await getImageFilesFromLocal(); - const ids = await addImages(this.edgeless.std, imageFiles); + const ids = await addImages(this.edgeless.std, imageFiles, { + maxWidth: MAX_IMAGE_WIDTH, + }); this._imageLoading = false; this.edgeless.gfx.tool.setTool('default'); this.edgeless.gfx.selection.set({ elements: ids }); diff --git a/blocksuite/blocks/src/root-block/edgeless/utils/common.ts b/blocksuite/blocks/src/root-block/edgeless/utils/common.ts index 084ef886a0..235d226690 100644 --- a/blocksuite/blocks/src/root-block/edgeless/utils/common.ts +++ b/blocksuite/blocks/src/root-block/edgeless/utils/common.ts @@ -118,7 +118,10 @@ export async function addAttachments( export async function addImages( std: BlockStdScope, files: File[], - point?: IVec + options: { + point?: IVec; + maxWidth?: number; + } ): Promise { const imageFiles = [...files].filter(file => file.type.startsWith('image/')); if (!imageFiles.length) return []; @@ -145,6 +148,7 @@ export async function addImages( return []; } + const { point, maxWidth } = options; let { x, y } = gfx.viewport.center; if (point) [x, y] = gfx.viewport.toModelCoord(...point); @@ -166,6 +170,7 @@ export async function addImages( { size: file.size, xywh: bound.serialize(), + index: gfx.layer.generateIndex(), }, gfx.surface ); @@ -180,17 +185,22 @@ export async function addImages( const imageSize = await readImageSize(file); const center = Vec.toVec(point); - const bound = calcBoundByOrigin( - center, - inTopLeft, - imageSize.width, - imageSize.height - ); + // If maxWidth is provided, limit the width of the image to maxWidth + // Otherwise, use the original width + const width = maxWidth + ? Math.min(imageSize.width, maxWidth) + : imageSize.width; + const height = maxWidth + ? (imageSize.height / imageSize.width) * width + : imageSize.height; + const bound = calcBoundByOrigin(center, inTopLeft, width, height); std.doc.withoutTransact(() => { gfx.updateElement(blockId, { sourceId, ...imageSize, + width, + height, xywh: bound.serialize(), } satisfies Partial); }); diff --git a/packages/frontend/core/src/blocksuite/presets/ai/actions/edgeless-response.ts b/packages/frontend/core/src/blocksuite/presets/ai/actions/edgeless-response.ts index fb7ff25c01..e50b20b8db 100644 --- a/packages/frontend/core/src/blocksuite/presets/ai/actions/edgeless-response.ts +++ b/packages/frontend/core/src/blocksuite/presets/ai/actions/edgeless-response.ts @@ -339,7 +339,7 @@ function responseToCreateImage(host: EditorHost) { const [x, y] = edgelessRoot.service.viewport.toViewCoord(minX, minY); host.doc.transact(() => { - addImages(edgelessRoot.std, [img], [x, y]) + addImages(edgelessRoot.std, [img], { point: [x, y] }) .then(blockIds => { const imageBlockId = blockIds[0]; const imageBlock = host.doc.getBlock(imageBlockId);