feat(core): extract edgeless selected images (#13420)

> CLOSE AF-2782

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

* **New Features**
* Added support for extracting image files from selected elements in
edgeless editor mode, allowing users to retrieve image files alongside
canvas snapshots.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
德布劳外 · 贾贵
2025-08-05 18:43:18 +08:00
committed by GitHub
parent 46acf9aa4f
commit 6ffa60c501
2 changed files with 20 additions and 1 deletions

View File

@@ -34,6 +34,7 @@ import { Doc as YDoc } from 'yjs';
import { getStoreManager } from '../../manager/store'; import { getStoreManager } from '../../manager/store';
import type { ChatContextValue } from '../components/ai-chat-content'; import type { ChatContextValue } from '../components/ai-chat-content';
import { isAttachment } from './attachment'; import { isAttachment } from './attachment';
import { isImage } from './image';
import { import {
getSelectedAttachments, getSelectedAttachments,
getSelectedImagesAsBlobs, getSelectedImagesAsBlobs,
@@ -63,6 +64,7 @@ async function extractEdgelessSelected(
let snapshot: DocSnapshot | null = null; let snapshot: DocSnapshot | null = null;
let markdown = ''; let markdown = '';
const attachments: ChatContextValue['attachments'] = []; const attachments: ChatContextValue['attachments'] = [];
const images: File[] = [];
if (selectedElements.length) { if (selectedElements.length) {
const transformer = host.store.getTransformer(); const transformer = host.store.getTransformer();
@@ -103,6 +105,14 @@ async function extractEdgelessSelected(
if (name && sourceId) { if (name && sourceId) {
attachments.push({ name, sourceId }); attachments.push({ name, sourceId });
} }
} else if (isImage(element)) {
const { sourceId } = element.props;
if (sourceId) {
const blob = await host.store.blobSync.get(sourceId);
if (blob) {
images.push(new File([blob], sourceId));
}
}
} else if (element instanceof GfxPrimitiveElementModel) { } else if (element instanceof GfxPrimitiveElementModel) {
needSnapshot = true; needSnapshot = true;
const props = getElementProps(element, new Map()); const props = getElementProps(element, new Map());
@@ -130,7 +140,7 @@ async function extractEdgelessSelected(
if (!blob) return null; if (!blob) return null;
return { return {
images: [new File([blob], 'selected.png')], images: [new File([blob], 'selected.png'), ...images],
snapshot: snapshot ? JSON.stringify(snapshot) : null, snapshot: snapshot ? JSON.stringify(snapshot) : null,
combinedElementsMarkdown: markdown.length ? markdown : null, combinedElementsMarkdown: markdown.length ? markdown : null,
attachments, attachments,

View File

@@ -1,4 +1,7 @@
import { ImageBlockModel } from '@blocksuite/affine/model';
import { FetchUtils } from '@blocksuite/affine/shared/adapters'; import { FetchUtils } from '@blocksuite/affine/shared/adapters';
import type { BlockModel } from '@blocksuite/affine/store';
import type { GfxModel } from '@blocksuite/std/gfx';
export async function fetchImageToFile( export async function fetchImageToFile(
url: string, url: string,
@@ -107,3 +110,9 @@ export function canvasToBlob(
export function randomSeed(min = 0, max = Date.now()) { export function randomSeed(min = 0, max = Date.now()) {
return Math.round(Math.random() * (max - min)) + min; return Math.round(Math.random() * (max - min)) + min;
} }
export function isImage(
model: GfxModel | BlockModel
): model is ImageBlockModel {
return model instanceof ImageBlockModel;
}