返回 DeepSeek-Reasonix
composerClipboard.ts
根目录 / desktop / frontend / src / lib / composerClipboard.ts
1 import type { KeyboardEvent } from "react";
2 import { sha256 } from "./attachDedup";
3
4 function fileKey(file: File): string {
5 return `${file.name}:${file.type}:${file.size}:${file.lastModified}`;
6 }
7
8 export function clipboardFiles(data: DataTransfer): File[] {
9 const files = Array.from(data.files);
10 const seen = new Set(files.map(fileKey));
11 for (const item of Array.from(data.items)) {
12 if (item.kind !== "file") continue;
13 const file = item.getAsFile();
14 if (!file) continue;
15 const key = fileKey(file);
16 if (seen.has(key)) continue;
17 seen.add(key);
18 files.push(file);
19 }
20 return files;
21 }
22
23 export function clipboardHasImageHint(data: DataTransfer): boolean {
24 const imageType = (value: string) => {
25 const type = value.toLowerCase();
26 return type.startsWith("image/") || type.includes("png") || type.includes("jpeg") || type.includes("jpg") || type.includes("tiff");
27 };
28 return Array.from(data.items).some((item) => imageType(item.type)) || Array.from(data.types).some(imageType);
29 }
30
31 export function isPasteShortcut(e: KeyboardEvent<HTMLElement>): boolean {
32 return e.key.toLowerCase() === "v" && (e.metaKey || e.ctrlKey) && !e.altKey;
33 }
34
35 export async function dataURLHash(dataUrl: string): Promise<string> {
36 try {
37 const res = await fetch(dataUrl);
38 return sha256(await res.blob());
39 } catch {
40 return "";
41 }
42 }
43
43 lines TYPESCRIPT