diff --git a/web/packages/media/formats.ts b/web/packages/media/formats.ts index bc1bde9729..c2a98ca635 100644 --- a/web/packages/media/formats.ts +++ b/web/packages/media/formats.ts @@ -26,15 +26,6 @@ const needsJPEGConversionExtensions = [ export const needsJPEGConversion = (extension: string) => needsJPEGConversionExtensions.includes(extension.toLowerCase()); -/** - * Return true if {@link extension} _might_ be supported by the user's browser. - * - * For example, JPEG 2000 (jp2) is supported by Safari, but not by Chrome or - * Firefox, and this function will return true for `jp2`. - */ -export const hasPartialBrowserSupport = (extension: string) => - ["jp2"].includes(extension.toLowerCase()); - /** * Return `true` if {@link extension} in for an HEIC-like file. */ diff --git a/web/packages/new/photos/utils/file.ts b/web/packages/new/photos/utils/file.ts index a19218ec6b..f63d775319 100644 --- a/web/packages/new/photos/utils/file.ts +++ b/web/packages/new/photos/utils/file.ts @@ -2,26 +2,19 @@ import { isDesktop } from "@/base/app"; import log from "@/base/log"; import { CustomErrorMessage } from "@/base/types/ipc"; import { workerBridge } from "@/base/worker/worker-bridge"; -import { hasPartialBrowserSupport, needsJPEGConversion } from "@/media/formats"; +import { needsJPEGConversion } from "@/media/formats"; import { heicToJPEG } from "@/media/heic-convert"; import type { EnteFile } from "../types/file"; import { detectFileTypeInfo } from "./detect-type"; -class ModuleState { - /** - * This will be set to true if we get an error from the Node.js side of our - * desktop app telling us that native JPEG conversion is not available for - * the current OS/arch combination. - * - * That way, we can stop pestering it again and again (saving an IPC - * round-trip). - * - * Note the double negative when it is used. - */ - isNativeJPEGConversionNotAvailable = false; -} - -const moduleState = new ModuleState(); +/** + * This will be set to false if we get an error from the Node.js side of our + * desktop app telling us that native JPEG conversion is not available for the + * current OS/arch combination. + * + * That way, we can stop pestering it again and again, saving an IPC round-trip. + */ +let _isNativeJPEGConversionAvailable = true; /** * @returns a string to use as an identifier when logging information about the @@ -78,8 +71,8 @@ export function mergeMetadata(files: EnteFile[]): EnteFile[] { * 1. Try to detect the MIME type of the file from its contents and/or name. * * 2. If this detected type is one of the types that we know that the browser - * doesn't know how to render, continue. Otherwise return the imageBlob that - * was passed in (after setting its MIME type). + * likely cannot render, continue. Otherwise return the imageBlob that was + * passed in (after setting its MIME type). * * 3. If we're running in our desktop app and this MIME type is something our * desktop app can natively convert to a JPEG (using ffmpeg), do that and @@ -88,27 +81,27 @@ export function mergeMetadata(files: EnteFile[]): EnteFile[] { * 4. If this is an HEIC file, use our (WASM) HEIC converter and return the * resultant JPEG blob. * - * 5. Otherwise (or if any error occurs in the aforementioned steps), return - * `undefined`. + * 5. Otherwise return the original (with the MIME type if we were able to + * deduce one). + * + * In will catch all errors and return the original in those cases. */ export const renderableImageBlob = async ( fileName: string, imageBlob: Blob, ) => { try { - const tempFile = new File([imageBlob], fileName); - const fileTypeInfo = await detectFileTypeInfo(tempFile); - log.debug( - () => - `Need renderable image for ${JSON.stringify({ fileName, ...fileTypeInfo })}`, - ); - const { extension } = fileTypeInfo; + const file = new File([imageBlob], fileName); + const fileTypeInfo = await detectFileTypeInfo(file); + const { extension, mimeType } = fileTypeInfo; + + log.debug(() => ["Get renderable blob", { fileName, ...fileTypeInfo }]); if (needsJPEGConversion(extension)) { - const available = !moduleState.isNativeJPEGConversionNotAvailable; - if (isDesktop && available) { - // If we're running in our desktop app, see if our Node.js layer - // can convert this into a JPEG using native tools. + // If we're running in our desktop app, see if our Node.js layer can + // convert this into a JPEG using native tools. + + if (isDesktop && _isNativeJPEGConversionAvailable) { try { return await nativeConvertToJPEG(imageBlob); } catch (e) { @@ -116,23 +109,20 @@ export const renderableImageBlob = async ( e instanceof Error && e.message.endsWith(CustomErrorMessage.NotAvailable) ) { - moduleState.isNativeJPEGConversionNotAvailable = true; + _isNativeJPEGConversionAvailable = false; } else { log.error("Native conversion to JPEG failed", e); } } } + // If the previous step failed, or if native JPEG conversion is not + // available on this platform, for HEIC/HEIF files we can fallback + // to our web HEIC converter. + if (extension == "heic" || extension == "heif") { - // If the previous step failed, or if native JPEG conversion is - // not available on this platform, for HEIC/HEIF files we can - // fallback to our web HEIC converter. return await heicToJPEG(imageBlob); } - - // Continue if it might be possibly supported in some browsers, - // otherwise bail out. - if (!hasPartialBrowserSupport(extension)) return undefined; } // Either it is something that the browser already knows how to render @@ -143,16 +133,21 @@ export const renderableImageBlob = async ( // // Give it to the browser, attaching the mime type if possible. - const mimeType = fileTypeInfo.mimeType; if (!mimeType) { - log.info("Trying to render a file without a MIME type", fileName); + log.info( + "Attempting to get renderable blob for a file without a MIME type", + fileName, + ); return imageBlob; } else { return new Blob([imageBlob], { type: mimeType }); } } catch (e) { - log.error(`Failed to get renderable image for ${fileName}`, e); - return undefined; + log.error( + `Failed to get renderable blob for ${fileName}, will fallback to the original`, + e, + ); + return imageBlob; } };