Treat SVG attachments as files
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { DesktopDialogBridge } from "@/desktop/host";
|
||||
import { RASTER_IMAGE_FILE_EXTENSIONS } from "@/attachments/file-types";
|
||||
import { i18n } from "@/i18n/i18next";
|
||||
import { isAbsolutePath } from "@/utils/path";
|
||||
|
||||
@@ -17,20 +18,6 @@ export interface ExpoImagePickerAssetLike {
|
||||
file?: File | null;
|
||||
}
|
||||
|
||||
const IMAGE_FILE_EXTENSIONS = [
|
||||
"png",
|
||||
"jpg",
|
||||
"jpeg",
|
||||
"gif",
|
||||
"webp",
|
||||
"avif",
|
||||
"heic",
|
||||
"heif",
|
||||
"tiff",
|
||||
"bmp",
|
||||
"svg",
|
||||
];
|
||||
|
||||
function shouldTreatAsFileUri(uri: string): boolean {
|
||||
return uri.startsWith("file://") || isAbsolutePath(uri);
|
||||
}
|
||||
@@ -89,7 +76,7 @@ export async function openImagePathsWithDesktopDialog(
|
||||
filters: [
|
||||
{
|
||||
name: i18n.t("imageAttachmentPicker.dialogFilterName"),
|
||||
extensions: IMAGE_FILE_EXTENSIONS,
|
||||
extensions: RASTER_IMAGE_FILE_EXTENSIONS,
|
||||
},
|
||||
],
|
||||
title: i18n.t("imageAttachmentPicker.dialogTitle"),
|
||||
|
||||
@@ -2,6 +2,11 @@ import { useState, useRef, useEffect } from "react";
|
||||
import type { ImageAttachment } from "@/composer/types";
|
||||
import { getDesktopHost } from "@/desktop/host";
|
||||
import { persistAttachmentFromBlob, persistAttachmentFromFileUri } from "@/attachments/service";
|
||||
import {
|
||||
getRasterImageMimeTypeFromPath,
|
||||
isRasterImageFile,
|
||||
isRasterImagePath,
|
||||
} from "@/attachments/file-types";
|
||||
import { isWeb } from "@/constants/platform";
|
||||
|
||||
export interface DroppedFileItem {
|
||||
@@ -26,20 +31,6 @@ interface UseFileDropZoneReturn {
|
||||
}
|
||||
|
||||
const IS_WEB = isWeb;
|
||||
const IMAGE_MIME_BY_EXTENSION: Record<string, string> = {
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".gif": "image/gif",
|
||||
".webp": "image/webp",
|
||||
".bmp": "image/bmp",
|
||||
".svg": "image/svg+xml",
|
||||
".heic": "image/heic",
|
||||
".heif": "image/heif",
|
||||
".avif": "image/avif",
|
||||
".tif": "image/tiff",
|
||||
".tiff": "image/tiff",
|
||||
};
|
||||
|
||||
type DesktopDragDropPayload =
|
||||
| {
|
||||
@@ -61,26 +52,8 @@ interface DesktopDragDropEvent {
|
||||
payload: DesktopDragDropPayload;
|
||||
}
|
||||
|
||||
function isImageFile(file: File): boolean {
|
||||
return file.type.startsWith("image/");
|
||||
}
|
||||
|
||||
function getFileExtension(path: string): string {
|
||||
const normalizedPath = path.split("#", 1)[0]?.split("?", 1)[0] ?? path;
|
||||
const extensionIndex = normalizedPath.lastIndexOf(".");
|
||||
if (extensionIndex < 0) {
|
||||
return "";
|
||||
}
|
||||
return normalizedPath.slice(extensionIndex).toLowerCase();
|
||||
}
|
||||
|
||||
function isImagePath(path: string): boolean {
|
||||
return getFileExtension(path) in IMAGE_MIME_BY_EXTENSION;
|
||||
}
|
||||
|
||||
async function filePathToImageAttachment(path: string): Promise<ImageAttachment> {
|
||||
const extension = getFileExtension(path);
|
||||
const mimeType = IMAGE_MIME_BY_EXTENSION[extension] ?? "image/jpeg";
|
||||
const mimeType = getRasterImageMimeTypeFromPath(path) ?? "image/jpeg";
|
||||
return await persistAttachmentFromFileUri({ uri: path, mimeType });
|
||||
}
|
||||
|
||||
@@ -182,7 +155,7 @@ export function useFileDropZone({
|
||||
onGenericFilesDroppedRef.current(items);
|
||||
}
|
||||
|
||||
const imagePaths = payload.paths.filter(isImagePath);
|
||||
const imagePaths = payload.paths.filter(isRasterImagePath);
|
||||
if (imagePaths.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -273,7 +246,7 @@ export function useFileDropZone({
|
||||
onGenericFilesDroppedRef.current(genericItems);
|
||||
}
|
||||
|
||||
const imageFiles = files.filter(isImageFile);
|
||||
const imageFiles = files.filter(isRasterImageFile);
|
||||
|
||||
if (imageFiles.length === 0) return;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { getDesktopHost, isElectronRuntime } from "@/desktop/host";
|
||||
import { copyDesktopAttachmentFile } from "@/desktop/attachments/desktop-file-commands";
|
||||
import { readDesktopFileBase64 } from "@/desktop/attachments/desktop-preview-url";
|
||||
import { isWeb } from "@/constants/platform";
|
||||
import { getFileExtension, getMimeTypeFromPath } from "@/attachments/file-types";
|
||||
|
||||
export interface PickedFile {
|
||||
fileName: string;
|
||||
@@ -10,62 +11,6 @@ export interface PickedFile {
|
||||
bytes: Uint8Array;
|
||||
}
|
||||
|
||||
const MIME_BY_EXTENSION: Record<string, string> = {
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".gif": "image/gif",
|
||||
".webp": "image/webp",
|
||||
".bmp": "image/bmp",
|
||||
".svg": "image/svg+xml",
|
||||
".heic": "image/heic",
|
||||
".heif": "image/heif",
|
||||
".avif": "image/avif",
|
||||
".tif": "image/tiff",
|
||||
".tiff": "image/tiff",
|
||||
".pdf": "application/pdf",
|
||||
".txt": "text/plain",
|
||||
".md": "text/markdown",
|
||||
".json": "application/json",
|
||||
".js": "text/javascript",
|
||||
".ts": "text/typescript",
|
||||
".tsx": "text/typescript-jsx",
|
||||
".jsx": "text/javascript",
|
||||
".html": "text/html",
|
||||
".css": "text/css",
|
||||
".xml": "text/xml",
|
||||
".csv": "text/csv",
|
||||
".zip": "application/zip",
|
||||
".gz": "application/gzip",
|
||||
".tar": "application/x-tar",
|
||||
".mp3": "audio/mpeg",
|
||||
".mp4": "video/mp4",
|
||||
".mov": "video/quicktime",
|
||||
".webm": "video/webm",
|
||||
".wav": "audio/wav",
|
||||
".ogg": "audio/ogg",
|
||||
".doc": "application/msword",
|
||||
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
".xls": "application/vnd.ms-excel",
|
||||
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
".ppt": "application/vnd.ms-powerpoint",
|
||||
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
};
|
||||
|
||||
function getFileExtension(path: string): string {
|
||||
const normalizedPath = path.split("#", 1)[0]?.split("?", 1)[0] ?? path;
|
||||
const extensionIndex = normalizedPath.lastIndexOf(".");
|
||||
if (extensionIndex < 0) {
|
||||
return "";
|
||||
}
|
||||
return normalizedPath.slice(extensionIndex).toLowerCase();
|
||||
}
|
||||
|
||||
export function getMimeTypeFromPath(path: string): string {
|
||||
const ext = getFileExtension(path);
|
||||
return MIME_BY_EXTENSION[ext] ?? "application/octet-stream";
|
||||
}
|
||||
|
||||
function base64ToUint8Array(base64: string): Uint8Array {
|
||||
const binaryString = atob(base64);
|
||||
const bytes = new Uint8Array(binaryString.length);
|
||||
|
||||
Reference in New Issue
Block a user