/** * 「问 AI」输入框里贴图、拖图的规则(不碰 React):认哪些格式、每张多大、最多几张, * 贴进来还没发的图片在页面上的样子,发给扩展端的样子。 */ import type { AskImage } from './types' /** 认的格式:Claude 认的这几种 */ export const IMAGE_TYPES: readonly string[] = ['image/png', 'image/jpeg', 'image/gif', 'image/webp'] export const MAX_IMAGE_BYTES = 5 * 1024 * 1024 /** 一个问题最多带几张 */ export const MAX_IMAGES = 6 /** 贴进输入框、还没发的一张图片:url 是 data: 地址,缩略图、大图、发送都用它 */ export interface PendingImage { id: number mediaType: string url: string } /** 剪贴板 / 拖进来的东西里的文件;文字、网页片段这些不算(照常粘成文字) */ export function transferFiles(items: ArrayLike<{ kind: string, getAsFile: () => F | null }>): F[] { return Array.from(items).flatMap(item => item.kind === 'file' ? item.getAsFile() ?? [] : []) } /** * 挑出能带上的:只认 PNG、JPEG、GIF、WebP,每张不超过 MAX_IMAGE_BYTES,连同已经有的 have 张最多 MAX_IMAGES 张,按先后取; * 有没加上的给一句原因。 */ export function pickImages(files: readonly F[], have: number): { accepted: F[], notice?: string } { const images = files.filter(file => IMAGE_TYPES.includes(file.type)) const small = images.filter(file => file.size <= MAX_IMAGE_BYTES) const accepted = small.slice(0, Math.max(0, MAX_IMAGES - have)) const reasons = [ ...(images.length < files.length ? ['只能贴 PNG、JPEG、GIF、WebP 图片'] : []), ...(small.length < images.length ? [`每张图片不能超过 ${MAX_IMAGE_BYTES / 1024 / 1024} MB`] : []), ...(accepted.length < small.length ? [`一个问题最多带 ${MAX_IMAGES} 张图片`] : []), ] return reasons.length === 0 ? { accepted } : { accepted, notice: `${reasons.join(';')},有 ${files.length - accepted.length} 个没加上。` } } let imageCounter = 0 /** 读成 data: 地址(缩略图直接用,页面的安全策略允许 data: 图片) */ export function readImage(file: File): Promise { return new Promise((resolve, reject) => { const reader = new FileReader() reader.onload = () => resolve({ id: ++imageCounter, mediaType: file.type, url: String(reader.result) }) reader.onerror = () => reject(reader.error ?? new Error('读不出图片')) reader.readAsDataURL(file) }) } /** 发给扩展端的样子:data: 地址去掉前缀剩下的 base64 */ export function toAskImage(image: PendingImage): AskImage { return { mediaType: image.mediaType, base64: image.url.slice(image.url.indexOf(',') + 1) } }