diff --git a/web/apps/photos/src/services/imageProcessor.ts b/web/apps/photos/src/services/imageProcessor.ts deleted file mode 100644 index ac67c54ec..000000000 --- a/web/apps/photos/src/services/imageProcessor.ts +++ /dev/null @@ -1,72 +0,0 @@ -import ElectronAPIs from "@ente/shared/electron"; -import { WorkerSafeElectronService } from "@ente/shared/electron/service"; -import { CustomError } from "@ente/shared/error"; -import { addLogLine } from "@ente/shared/logging"; -import { logError } from "@ente/shared/sentry"; -import { convertBytesToHumanReadable } from "@ente/shared/utils/size"; -import { ElectronFile } from "types/upload"; - -class ElectronImageProcessorService { - async convertToJPEG(fileBlob: Blob, filename: string): Promise { - try { - const startTime = Date.now(); - const inputFileData = new Uint8Array(await fileBlob.arrayBuffer()); - const convertedFileData = - await WorkerSafeElectronService.convertToJPEG( - inputFileData, - filename, - ); - addLogLine( - `originalFileSize:${convertBytesToHumanReadable( - fileBlob?.size, - )},convertedFileSize:${convertBytesToHumanReadable( - convertedFileData?.length, - )}, native conversion time: ${Date.now() - startTime}ms `, - ); - return new Blob([convertedFileData]); - } catch (e) { - if ( - e.message !== - CustomError.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED - ) { - logError(e, "failed to convert to jpeg natively"); - } - throw e; - } - } - - async generateImageThumbnail( - inputFile: File | ElectronFile, - maxDimension: number, - maxSize: number, - ): Promise { - try { - const startTime = Date.now(); - const thumb = await ElectronAPIs.generateImageThumbnail( - inputFile, - maxDimension, - maxSize, - ); - addLogLine( - `originalFileSize:${convertBytesToHumanReadable( - inputFile?.size, - )},thumbFileSize:${convertBytesToHumanReadable( - thumb?.length, - )}, native thumbnail generation time: ${ - Date.now() - startTime - }ms `, - ); - return thumb; - } catch (e) { - if ( - e.message !== - CustomError.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED - ) { - logError(e, "failed to generate image thumbnail natively"); - } - throw e; - } - } -} - -export default new ElectronImageProcessorService(); diff --git a/web/apps/photos/src/services/upload/thumbnailService.ts b/web/apps/photos/src/services/upload/thumbnailService.ts index 64df2f016..61e42f9e9 100644 --- a/web/apps/photos/src/services/upload/thumbnailService.ts +++ b/web/apps/photos/src/services/upload/thumbnailService.ts @@ -1,3 +1,4 @@ +import ElectronAPIs from "@ente/shared/electron"; import { CustomError } from "@ente/shared/error"; import { addLogLine } from "@ente/shared/logging"; import { getFileNameSize } from "@ente/shared/logging/web"; @@ -8,7 +9,6 @@ import { BLACK_THUMBNAIL_BASE64 } from "constants/upload"; import isElectron from "is-electron"; import * as FFmpegService from "services/ffmpeg/ffmpegService"; import HeicConversionService from "services/heicConversionService"; -import imageProcessor from "services/imageProcessor"; import { ElectronFile, FileTypeInfo } from "types/upload"; import { isFileHEIC } from "utils/file"; import { getUint8ArrayView } from "../readerService"; @@ -86,7 +86,7 @@ async function generateImageThumbnail( ) { if (isElectron()) { try { - return await imageProcessor.generateImageThumbnail( + return await generateImageThumbnailInElectron( file, MAX_THUMBNAIL_DIMENSION, MAX_THUMBNAIL_SIZE, @@ -99,6 +99,39 @@ async function generateImageThumbnail( } } +const generateImageThumbnailInElectron = async ( + inputFile: File | ElectronFile, + maxDimension: number, + maxSize: number, +): Promise => { + try { + const startTime = Date.now(); + const thumb = await ElectronAPIs.generateImageThumbnail( + inputFile, + maxDimension, + maxSize, + ); + addLogLine( + `originalFileSize:${convertBytesToHumanReadable( + inputFile?.size, + )},thumbFileSize:${convertBytesToHumanReadable( + thumb?.length, + )}, native thumbnail generation time: ${ + Date.now() - startTime + }ms `, + ); + return thumb; + } catch (e) { + if ( + e.message !== + CustomError.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED + ) { + logError(e, "failed to generate image thumbnail natively"); + } + throw e; + } +}; + export async function generateImageThumbnailUsingCanvas( file: File | ElectronFile, fileTypeInfo: FileTypeInfo, diff --git a/web/apps/photos/src/utils/file/index.ts b/web/apps/photos/src/utils/file/index.ts index 96f4749bf..2e02794c4 100644 --- a/web/apps/photos/src/utils/file/index.ts +++ b/web/apps/photos/src/utils/file/index.ts @@ -53,8 +53,8 @@ import { import { FileTypeInfo } from "types/upload"; import { default as ElectronAPIs } from "@ente/shared/electron"; +import { workerBridge } from "@ente/shared/worker/worker-bridge"; import { t } from "i18next"; -import imageProcessor from "services/imageProcessor"; import { getFileExportPath, getUniqueFileExportName } from "utils/export"; const WAIT_TIME_IMAGE_CONVERSION = 30 * 1000; @@ -452,8 +452,7 @@ export async function getRenderableImage(fileName: string, imageBlob: Blob) { imageBlob.size, )}`, ); - throw new Error("bypass"); - convertedImageBlob = await imageProcessor.convertToJPEG( + convertedImageBlob = await convertToJPEGInElectron( imageBlob, fileName, ); @@ -485,6 +484,36 @@ export async function getRenderableImage(fileName: string, imageBlob: Blob) { } } +const convertToJPEGInElectron = async ( + fileBlob: Blob, + filename: string, +): Promise => { + try { + const startTime = Date.now(); + const inputFileData = new Uint8Array(await fileBlob.arrayBuffer()); + const convertedFileData = await workerBridge.convertToJPEG( + inputFileData, + filename, + ); + addLogLine( + `originalFileSize:${convertBytesToHumanReadable( + fileBlob?.size, + )},convertedFileSize:${convertBytesToHumanReadable( + convertedFileData?.length, + )}, native conversion time: ${Date.now() - startTime}ms `, + ); + return new Blob([convertedFileData]); + } catch (e) { + if ( + e.message !== + CustomError.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED + ) { + logError(e, "failed to convert to jpeg natively"); + } + throw e; + } +}; + export function isFileHEIC(exactType: string) { return ( exactType.toLowerCase().endsWith(TYPE_HEIC) || diff --git a/web/packages/shared/electron/service.ts b/web/packages/shared/electron/service.ts deleted file mode 100644 index f926d20b2..000000000 --- a/web/packages/shared/electron/service.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { inWorker } from "@/next/env"; -import * as Comlink from "comlink"; -import { wrap } from "comlink"; -import { ElectronAPIsType } from "./types"; -import { WorkerSafeElectronClient } from "./worker/client"; - -export interface LimitedElectronAPIs - extends Pick {} - -class WorkerSafeElectronServiceImpl implements LimitedElectronAPIs { - proxiedElectron: - | Comlink.Remote - | WorkerSafeElectronClient; - ready: Promise; - - constructor() { - this.ready = this.init(); - } - private async init() { - if (inWorker()) { - const workerSafeElectronClient = - wrap(self); - - this.proxiedElectron = await new workerSafeElectronClient(); - } else { - this.proxiedElectron = new WorkerSafeElectronClient(); - } - } - - async convertToJPEG( - inputFileData: Uint8Array, - filename: string, - ): Promise { - await this.ready; - return this.proxiedElectron.convertToJPEG(inputFileData, filename); - } - - async logToDisk(message: string) { - await this.ready; - return this.proxiedElectron.logToDisk(message); - } -} - -export const WorkerSafeElectronService = new WorkerSafeElectronServiceImpl(); diff --git a/web/packages/shared/electron/worker/client.ts b/web/packages/shared/electron/worker/client.ts deleted file mode 100644 index f6b99ee88..000000000 --- a/web/packages/shared/electron/worker/client.ts +++ /dev/null @@ -1,21 +0,0 @@ -import ElectronAPIs from "@ente/shared/electron"; - -export interface ProxiedLimitedElectronAPIs { - convertToJPEG: ( - inputFileData: Uint8Array, - filename: string, - ) => Promise; - logToDisk: (message: string) => void; -} - -export class WorkerSafeElectronClient implements ProxiedLimitedElectronAPIs { - async convertToJPEG( - inputFileData: Uint8Array, - filename: string, - ): Promise { - return await ElectronAPIs.convertToJPEG(inputFileData, filename); - } - logToDisk(message: string) { - return ElectronAPIs.logToDisk(message); - } -} diff --git a/web/packages/shared/logging/web.ts b/web/packages/shared/logging/web.ts index 9584cd385..45127121b 100644 --- a/web/packages/shared/logging/web.ts +++ b/web/packages/shared/logging/web.ts @@ -1,8 +1,8 @@ -import { inWorker, isDevBuild } from "@/next/env"; +import { isDevBuild } from "@/next/env"; import { logError } from "@ente/shared/sentry"; import { - getData, LS_KEYS, + getData, removeData, setData, } from "@ente/shared/storage/localStorage"; @@ -20,22 +20,13 @@ export interface Log { logLine: string; } -export function logWeb(logLine2: string) { - const logLine = `${logLine2}`; - console.log("logWeb", logLine); +export function logWeb(logLine: string) { try { const log: Log = { logLine, timestamp: Date.now() }; const logs = getLogs(); if (logs.length > MAX_LOG_LINES) { logs.slice(logs.length - MAX_LOG_LINES); } - console.log("inWorker", inWorker()); - console.log("pushing", logLine); - console.log("length", logLine.length); - logs.push({ - logLine: `length ${logLine.length}`, - timestamp: Date.now(), - }); logs.push(log); setLogs(logs); } catch (e) { diff --git a/web/packages/shared/worker/comlinkWorker.ts b/web/packages/shared/worker/comlinkWorker.ts index bcf3b4f3d..0cbae504c 100644 --- a/web/packages/shared/worker/comlinkWorker.ts +++ b/web/packages/shared/worker/comlinkWorker.ts @@ -1,5 +1,6 @@ import { addLocalLog, logToDisk } from "@ente/shared/logging"; import { Remote, expose, wrap } from "comlink"; +import ElectronAPIs from "../electron"; import { logError } from "../sentry"; export class ComlinkWorker InstanceType> { @@ -20,7 +21,6 @@ export class ComlinkWorker InstanceType> { addLocalLog(() => `Initiated ${this.name}`); const comlink = wrap(this.worker); this.remote = new comlink() as Promise>>; - // expose(WorkerSafeElectronClient, this.worker); expose(workerBridge, this.worker); } @@ -43,6 +43,8 @@ export class ComlinkWorker InstanceType> { */ const workerBridge = { logToDisk, + convertToJPEG: (inputFileData: Uint8Array, filename: string) => + ElectronAPIs.convertToJPEG(inputFileData, filename), }; export type WorkerBridge = typeof workerBridge; diff --git a/web/packages/shared/worker/worker-bridge.ts b/web/packages/shared/worker/worker-bridge.ts index 7001dfe4c..e783e4b67 100644 --- a/web/packages/shared/worker/worker-bridge.ts +++ b/web/packages/shared/worker/worker-bridge.ts @@ -9,4 +9,4 @@ import type { WorkerBridge } from "./comlinkWorker"; * this object will be transparently (but asynchrorously) relayed to the * implementation of the {@link WorkerBridge} in `comlinkWorker.ts`. */ -export const workerBridge = wrap(self); +export const workerBridge = wrap(globalThis);