mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-24 03:08:13 +08:00
Unify file opening, importing, and pasting into a file ingest handler (#4548)
* Unify file and data ingest * Code review --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import { extractPixelData } from "/src/utility-functions/rasterization";
|
||||
import { stripIndents } from "/src/utility-functions/strip-indents";
|
||||
import type { EditorWrapper } from "/wrapper/pkg/graphite_wasm_wrapper";
|
||||
|
||||
@@ -114,28 +113,9 @@ export async function triggerClipboardRead(editor: EditorWrapper) {
|
||||
// Read an image from the clipboard and pass it to the editor to be loaded
|
||||
const imageType = item.types.find((type) => type.startsWith("image/"));
|
||||
|
||||
// Import the actual SVG content if it's an SVG
|
||||
if (imageType?.includes("svg")) {
|
||||
const blob = await item.getType("text/plain");
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
if (typeof reader.result === "string") editor.pasteSvg(undefined, reader.result);
|
||||
};
|
||||
reader.readAsText(blob);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Import the bitmap image if it's an image
|
||||
if (imageType) {
|
||||
const blob = await item.getType(imageType);
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
if (reader.result instanceof ArrayBuffer) {
|
||||
const imageData = await extractPixelData(new Blob([reader.result], { type: imageType }));
|
||||
editor.pasteImage(undefined, new Uint8Array(imageData.data), imageData.width, imageData.height);
|
||||
}
|
||||
};
|
||||
reader.readAsArrayBuffer(blob);
|
||||
editor.ingestFile(undefined, imageType, new Uint8Array(await blob.arrayBuffer()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { extractPixelData } from "/src/utility-functions/rasterization";
|
||||
import type { EditorWrapper, FileFilter } from "/wrapper/pkg/graphite_wasm_wrapper";
|
||||
|
||||
export function downloadFileURL(filename: string, url: string) {
|
||||
@@ -85,24 +84,9 @@ export async function pasteFile(item: DataTransferItem, editor: EditorWrapper, m
|
||||
const file = item.getAsFile();
|
||||
if (!file) return;
|
||||
|
||||
const extension = file.name.split(".").pop()?.toLowerCase() ?? "";
|
||||
if (file.type.startsWith("image/svg")) {
|
||||
const svg = await file.text();
|
||||
editor.pasteSvg(file.name, svg, mouse?.[0], mouse?.[1], insertParentId, insertIndex);
|
||||
} else if (editor.rasterImageExtensions().includes(extension)) {
|
||||
// Formats the editor decodes itself keep their original bytes instead of being rasterized by the browser
|
||||
editor.pasteImageFile(file.name, await file.bytes(), mouse?.[0], mouse?.[1], insertParentId, insertIndex);
|
||||
} else if (file.type.startsWith("image/")) {
|
||||
const imageData = await extractPixelData(file);
|
||||
editor.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height, mouse?.[0], mouse?.[1], insertParentId, insertIndex);
|
||||
} else {
|
||||
// TODO: When we eventually have sub-documents, this should be changed to import the document as a node instead of opening it in a separate tab
|
||||
editor.openFile(file.name, await file.bytes());
|
||||
}
|
||||
editor.ingestFile(file.name, file.type, await file.bytes(), mouse?.[0], mouse?.[1], insertParentId, insertIndex);
|
||||
}
|
||||
|
||||
export function acceptStringFromFilters(filters: FileFilter[]): string {
|
||||
const extensions = filters.flatMap((filter) => filter.extensions);
|
||||
const imageMime = extensions.some((extension) => ["svg", "png", "jpg", "jpeg", "bmp", "gif", "webp", "avif", "tif", "tiff"].includes(extension)) ? ["image/*"] : [];
|
||||
return [...imageMime, ...extensions.map((extension) => `.${extension}`)].join(",");
|
||||
return filters.flatMap((filter) => [...filter.mimeTypes, ...filter.extensions.map((extension) => `.${extension}`)]).join(",");
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function loadDemoArtwork(editor: EditorWrapper) {
|
||||
|
||||
const filename = url.pathname.split("/").pop() || "Untitled.graphite";
|
||||
const content = await response.bytes();
|
||||
editor.openFile(filename, content);
|
||||
editor.ingestPicked(filename, "", content, "Open");
|
||||
|
||||
history.replaceState("", "", `${window.location.pathname}${window.location.search}`);
|
||||
} catch {
|
||||
|
||||
@@ -51,15 +51,6 @@ export async function rasterizeSVG(svg: string, width: number, height: number, m
|
||||
return blob;
|
||||
}
|
||||
|
||||
/// Convert an image source (e.g. PNG document) into pixel data, a width, and a height
|
||||
export async function extractPixelData(imageData: ImageBitmapSource): Promise<ImageData> {
|
||||
const canvasContext = await imageToCanvasContext(imageData);
|
||||
const width = canvasContext.canvas.width;
|
||||
const height = canvasContext.canvas.height;
|
||||
|
||||
return canvasContext.getImageData(0, 0, width, height);
|
||||
}
|
||||
|
||||
export async function imageToCanvasContext(imageData: ImageBitmapSource): Promise<CanvasRenderingContext2D> {
|
||||
// Special handling to rasterize an SVG file
|
||||
let svgImageData;
|
||||
|
||||
Reference in New Issue
Block a user