feat: allow avif
, jfif
, webp
, bmp
, ico
image types (#6500
* feat: allow `avif`, `jfif`, `webp`, `bmp`, `ico` image types * dedupe for SSOT * more SSOT
This commit is contained in:
parent
2a4799d8c8
commit
fee760d38c
@ -60,6 +60,7 @@ import {
|
|||||||
ENV,
|
ENV,
|
||||||
EVENT,
|
EVENT,
|
||||||
GRID_SIZE,
|
GRID_SIZE,
|
||||||
|
IMAGE_MIME_TYPES,
|
||||||
IMAGE_RENDER_TIMEOUT,
|
IMAGE_RENDER_TIMEOUT,
|
||||||
isAndroid,
|
isAndroid,
|
||||||
isBrave,
|
isBrave,
|
||||||
@ -5743,7 +5744,9 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
|
|
||||||
const imageFile = await fileOpen({
|
const imageFile = await fileOpen({
|
||||||
description: "Image",
|
description: "Image",
|
||||||
extensions: ["jpg", "png", "svg", "gif"],
|
extensions: Object.keys(
|
||||||
|
IMAGE_MIME_TYPES,
|
||||||
|
) as (keyof typeof IMAGE_MIME_TYPES)[],
|
||||||
});
|
});
|
||||||
|
|
||||||
const imageElement = this.createImageElement({
|
const imageElement = this.createImageElement({
|
||||||
|
@ -105,20 +105,30 @@ export const CANVAS_ONLY_ACTIONS = ["selectAll"];
|
|||||||
|
|
||||||
export const GRID_SIZE = 20; // TODO make it configurable?
|
export const GRID_SIZE = 20; // TODO make it configurable?
|
||||||
|
|
||||||
export const MIME_TYPES = {
|
export const IMAGE_MIME_TYPES = {
|
||||||
excalidraw: "application/vnd.excalidraw+json",
|
|
||||||
excalidrawlib: "application/vnd.excalidrawlib+json",
|
|
||||||
json: "application/json",
|
|
||||||
svg: "image/svg+xml",
|
svg: "image/svg+xml",
|
||||||
"excalidraw.svg": "image/svg+xml",
|
|
||||||
png: "image/png",
|
png: "image/png",
|
||||||
"excalidraw.png": "image/png",
|
|
||||||
jpg: "image/jpeg",
|
jpg: "image/jpeg",
|
||||||
gif: "image/gif",
|
gif: "image/gif",
|
||||||
webp: "image/webp",
|
webp: "image/webp",
|
||||||
bmp: "image/bmp",
|
bmp: "image/bmp",
|
||||||
ico: "image/x-icon",
|
ico: "image/x-icon",
|
||||||
|
avif: "image/avif",
|
||||||
|
jfif: "image/jfif",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const MIME_TYPES = {
|
||||||
|
json: "application/json",
|
||||||
|
// excalidraw data
|
||||||
|
excalidraw: "application/vnd.excalidraw+json",
|
||||||
|
excalidrawlib: "application/vnd.excalidrawlib+json",
|
||||||
|
// image-encoded excalidraw data
|
||||||
|
"excalidraw.svg": "image/svg+xml",
|
||||||
|
"excalidraw.png": "image/png",
|
||||||
|
// binary
|
||||||
binary: "application/octet-stream",
|
binary: "application/octet-stream",
|
||||||
|
// image
|
||||||
|
...IMAGE_MIME_TYPES,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const EXPORT_DATA_TYPES = {
|
export const EXPORT_DATA_TYPES = {
|
||||||
@ -189,16 +199,6 @@ export const DEFAULT_EXPORT_PADDING = 10; // px
|
|||||||
|
|
||||||
export const DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT = 1440;
|
export const DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT = 1440;
|
||||||
|
|
||||||
export const ALLOWED_IMAGE_MIME_TYPES = [
|
|
||||||
MIME_TYPES.png,
|
|
||||||
MIME_TYPES.jpg,
|
|
||||||
MIME_TYPES.svg,
|
|
||||||
MIME_TYPES.gif,
|
|
||||||
MIME_TYPES.webp,
|
|
||||||
MIME_TYPES.bmp,
|
|
||||||
MIME_TYPES.ico,
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export const MAX_ALLOWED_FILE_BYTES = 2 * 1024 * 1024;
|
export const MAX_ALLOWED_FILE_BYTES = 2 * 1024 * 1024;
|
||||||
|
|
||||||
export const SVG_NS = "http://www.w3.org/2000/svg";
|
export const SVG_NS = "http://www.w3.org/2000/svg";
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { cleanAppStateForExport } from "../appState";
|
import { cleanAppStateForExport } from "../appState";
|
||||||
import { ALLOWED_IMAGE_MIME_TYPES, MIME_TYPES } from "../constants";
|
import { IMAGE_MIME_TYPES, MIME_TYPES } from "../constants";
|
||||||
import { clearElementsForExport } from "../element";
|
import { clearElementsForExport } from "../element";
|
||||||
import { ExcalidrawElement, FileId } from "../element/types";
|
import { ExcalidrawElement, FileId } from "../element/types";
|
||||||
import { CanvasError } from "../errors";
|
import { CanvasError } from "../errors";
|
||||||
@ -117,11 +117,9 @@ export const isImageFileHandle = (handle: FileSystemHandle | null) => {
|
|||||||
|
|
||||||
export const isSupportedImageFile = (
|
export const isSupportedImageFile = (
|
||||||
blob: Blob | null | undefined,
|
blob: Blob | null | undefined,
|
||||||
): blob is Blob & { type: typeof ALLOWED_IMAGE_MIME_TYPES[number] } => {
|
): blob is Blob & { type: ValueOf<typeof IMAGE_MIME_TYPES> } => {
|
||||||
const { type } = blob || {};
|
const { type } = blob || {};
|
||||||
return (
|
return !!type && (Object.values(IMAGE_MIME_TYPES) as string[]).includes(type);
|
||||||
!!type && (ALLOWED_IMAGE_MIME_TYPES as readonly string[]).includes(type)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const loadSceneOrLibraryFromBlob = async (
|
export const loadSceneOrLibraryFromBlob = async (
|
||||||
|
@ -8,16 +8,7 @@ import { EVENT, MIME_TYPES } from "../constants";
|
|||||||
import { AbortError } from "../errors";
|
import { AbortError } from "../errors";
|
||||||
import { debounce } from "../utils";
|
import { debounce } from "../utils";
|
||||||
|
|
||||||
type FILE_EXTENSION =
|
type FILE_EXTENSION = Exclude<keyof typeof MIME_TYPES, "binary">;
|
||||||
| "gif"
|
|
||||||
| "jpg"
|
|
||||||
| "png"
|
|
||||||
| "excalidraw.png"
|
|
||||||
| "svg"
|
|
||||||
| "excalidraw.svg"
|
|
||||||
| "json"
|
|
||||||
| "excalidraw"
|
|
||||||
| "excalidrawlib";
|
|
||||||
|
|
||||||
const INPUT_CHANGE_INTERVAL_MS = 500;
|
const INPUT_CHANGE_INTERVAL_MS = 500;
|
||||||
|
|
||||||
|
@ -29,9 +29,9 @@ import { isOverScrollBars } from "./scene";
|
|||||||
import { MaybeTransformHandleType } from "./element/transformHandles";
|
import { MaybeTransformHandleType } from "./element/transformHandles";
|
||||||
import Library from "./data/library";
|
import Library from "./data/library";
|
||||||
import type { FileSystemHandle } from "./data/filesystem";
|
import type { FileSystemHandle } from "./data/filesystem";
|
||||||
import type { ALLOWED_IMAGE_MIME_TYPES, MIME_TYPES } from "./constants";
|
import type { IMAGE_MIME_TYPES, MIME_TYPES } from "./constants";
|
||||||
import { ContextMenuItems } from "./components/ContextMenu";
|
import { ContextMenuItems } from "./components/ContextMenu";
|
||||||
import { Merge, ForwardRef } from "./utility-types";
|
import { Merge, ForwardRef, ValueOf } from "./utility-types";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export type Point = Readonly<RoughPoint>;
|
export type Point = Readonly<RoughPoint>;
|
||||||
@ -60,7 +60,7 @@ export type DataURL = string & { _brand: "DataURL" };
|
|||||||
|
|
||||||
export type BinaryFileData = {
|
export type BinaryFileData = {
|
||||||
mimeType:
|
mimeType:
|
||||||
| typeof ALLOWED_IMAGE_MIME_TYPES[number]
|
| ValueOf<typeof IMAGE_MIME_TYPES>
|
||||||
// future user or unknown file type
|
// future user or unknown file type
|
||||||
| typeof MIME_TYPES.binary;
|
| typeof MIME_TYPES.binary;
|
||||||
id: FileId;
|
id: FileId;
|
||||||
@ -419,7 +419,7 @@ export type AppClassProperties = {
|
|||||||
FileId,
|
FileId,
|
||||||
{
|
{
|
||||||
image: HTMLImageElement | Promise<HTMLImageElement>;
|
image: HTMLImageElement | Promise<HTMLImageElement>;
|
||||||
mimeType: typeof ALLOWED_IMAGE_MIME_TYPES[number];
|
mimeType: ValueOf<typeof IMAGE_MIME_TYPES>;
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
files: BinaryFiles;
|
files: BinaryFiles;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user