diff --git a/desktop/package.json b/desktop/package.json index 1f368c4b98..69d54f75be 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -39,7 +39,7 @@ "@typescript-eslint/eslint-plugin": "^7", "@typescript-eslint/parser": "^7", "concurrently": "^8", - "electron": "30.0.0-beta.8", + "electron": "^29", "electron-builder": "^24", "electron-builder-notarize": "^1.5", "eslint": "^8", diff --git a/desktop/src/main.ts b/desktop/src/main.ts index 72e2b8233e..8526e23632 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -132,43 +132,12 @@ const registerPrivilegedSchemes = () => { // TODO(MR): Remove the commented bits if we don't end up // needing them by the time the IPC refactoring is done. - // standard: true, - // // Prevent the insecure origin issues when fetching this + // Prevent the insecure origin issues when fetching this // secure: true, - // // Allow the web fetch API in the renderer to use this scheme. - // supportFetchAPI: true, - // // Allow it to be used with video tags. - // stream: true, - standard: true, - /** - * Default false. - */ - secure: true, - /** - * Default false. - */ - bypassCSP: true, - /** - * Default false. - */ - allowServiceWorkers: true, - /** - * Default false. - */ + // Allow the web fetch API in the renderer to use this scheme. supportFetchAPI: true, - /** - * Default false. - */ - corsEnabled: true, - /** - * Default false. - */ - stream: true, - /** - * Enable V8 code cache for the scheme, only works when `standard` is also set to - * true. Default false. - */ - codeCache: true, + // Allow it to be used with video tags. + // stream: true, }, }, ]); diff --git a/desktop/src/main/services/ffmpeg.ts b/desktop/src/main/services/ffmpeg.ts index 3072d5ee7b..2597bae60f 100644 --- a/desktop/src/main/services/ffmpeg.ts +++ b/desktop/src/main/services/ffmpeg.ts @@ -2,8 +2,8 @@ import pathToFfmpeg from "ffmpeg-static"; import { existsSync } from "node:fs"; import fs from "node:fs/promises"; import { ElectronFile } from "../../types/ipc"; -import { writeStream } from "../stream"; import log from "../log"; +import { writeStream } from "../stream"; import { generateTempFilePath, getTempDirPath } from "../temp"; import { execAsync } from "../util"; diff --git a/desktop/src/main/services/imageProcessor.ts b/desktop/src/main/services/imageProcessor.ts index d87fb0c5f2..696119d80f 100644 --- a/desktop/src/main/services/imageProcessor.ts +++ b/desktop/src/main/services/imageProcessor.ts @@ -2,9 +2,9 @@ import { existsSync } from "fs"; import fs from "node:fs/promises"; import path from "path"; import { CustomErrors, ElectronFile } from "../../types/ipc"; -import { writeStream } from "../stream"; import log from "../log"; import { isPlatform } from "../platform"; +import { writeStream } from "../stream"; import { generateTempFilePath } from "../temp"; import { execAsync, isDev } from "../util"; import { deleteTempFile } from "./ffmpeg"; diff --git a/desktop/src/main/services/ml-clip.ts b/desktop/src/main/services/ml-clip.ts index af8198a3cf..46af2552bc 100644 --- a/desktop/src/main/services/ml-clip.ts +++ b/desktop/src/main/services/ml-clip.ts @@ -11,8 +11,8 @@ import fs from "node:fs/promises"; import * as ort from "onnxruntime-node"; import Tokenizer from "../../thirdparty/clip-bpe-ts/mod"; import { CustomErrors } from "../../types/ipc"; -import { writeStream } from "../stream"; import log from "../log"; +import { writeStream } from "../stream"; import { generateTempFilePath } from "../temp"; import { deleteTempFile } from "./ffmpeg"; import { diff --git a/desktop/src/main/services/ml.ts b/desktop/src/main/services/ml.ts index e1d68e2ddd..60e8241e16 100644 --- a/desktop/src/main/services/ml.ts +++ b/desktop/src/main/services/ml.ts @@ -15,8 +15,8 @@ import { existsSync } from "fs"; import fs from "node:fs/promises"; import path from "node:path"; import * as ort from "onnxruntime-node"; -import { writeStream } from "../stream"; import log from "../log"; +import { writeStream } from "../stream"; /** * Download the model named {@link modelName} if we don't already have it. diff --git a/desktop/src/main/stream.ts b/desktop/src/main/stream.ts index 73b04b2cd0..8ddb80dc6a 100644 --- a/desktop/src/main/stream.ts +++ b/desktop/src/main/stream.ts @@ -37,24 +37,7 @@ export const registerStreamProtocol = () => { /* host-pathname----- */ case "write": try { - // await writeStream(path, request.body); - console.log("starting stream"); - // let c = 0; - // for await (const p of request.body as any) { - // if (c == 327680) console.log(p); - // fs.appendFile(path, p); - // c += p.length; - // } - const reader = request.body.getReader(); - // eslint-disable-next-line no-constant-condition - while (true) { - const { value, done } = await reader.read(); - if (done) break; - console.log(`Received ${value.length} bytes`); - fs.appendFile(path, value); - } - console.log("ending stream"); - + await writeStream(path, request.body); return new Response("", { status: 200 }); } catch (e) { log.error(`Failed to write stream for ${url}`, e); diff --git a/desktop/yarn.lock b/desktop/yarn.lock index 0c314db0f7..a5b86f1eb3 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -1214,10 +1214,10 @@ electron-updater@^6.1: semver "^7.3.8" tiny-typed-emitter "^2.1.0" -electron@30.0.0-beta.8: - version "30.0.0-beta.8" - resolved "https://registry.yarnpkg.com/electron/-/electron-30.0.0-beta.8.tgz#c4430b9cb662ec147709deaededefe6d7dcc0522" - integrity sha512-G2IMMxUVJopiskD5G5iCQh71u1Emp+Q7nS1bWRU/9sK8bKwW1qtyBb3qoq0X9bd7y0LuKUb79AOr3Ix+J6EKaQ== +electron@^29: + version "29.3.0" + resolved "https://registry.yarnpkg.com/electron/-/electron-29.3.0.tgz#8e65cb08e9c0952c66d3196e1b5c811c43b8c5b0" + integrity sha512-ZxFKm0/v48GSoBuO3DdnMlCYXefEUKUHLMsKxyXY4nZGgzbBKpF/X8haZa2paNj23CLfsCKBOtfc2vsEQiOOsA== dependencies: "@electron/get" "^2.0.0" "@types/node" "^20.9.0" diff --git a/web/apps/photos/src/utils/native-stream.ts b/web/apps/photos/src/utils/native-stream.ts index 0176a2b7cc..7dba1acf9c 100644 --- a/web/apps/photos/src/utils/native-stream.ts +++ b/web/apps/photos/src/utils/native-stream.ts @@ -15,12 +15,19 @@ * @param stream The stream which should be written into the file. * */ export const writeStream = async (path: string, stream: ReadableStream) => { - writeStream_1("/tmp/1.txt", testStream()); -}; - -export const writeStream_1 = async (path: string, stream: ReadableStream) => { - // return writeStreamOneShot(path, stream) + // TODO(MR): This doesn't currently work. + // + // Not sure what I'm doing wrong here; I've opened an issue upstream + // https://github.com/electron/electron/issues/41872 + // + // A gist with a minimal reproduction + // https://gist.github.com/mnvr/e08d9f4876fb8400b7615347b4d268eb + // + // Meanwhile, write the complete body in one go (this'll eventually run into + // memory failures with large files - just a temporary stopgap to get the + // code to work). + /* // The duplex parameter needs to be set to 'half' when streaming requests. // // Currently browsers, and specifically in our case, since this code runs @@ -30,78 +37,19 @@ export const writeStream_1 = async (path: string, stream: ReadableStream) => { const req = new Request(`stream://write${path}`, { // GET can't have a body method: "POST", - headers: { - "Content-Type": "application/octet-stream", - "Content-Length": "1128608", - }, body: stream, // @ts-expect-error TypeScript's libdom.d.ts does not include the // "duplex" parameter, e.g. see // https://github.com/node-fetch/node-fetch/issues/1769. duplex: "half", }); - const res = await fetch(req); - if (!res.ok) - throw new Error( - `Failed to write stream to ${path}: HTTP ${res.status}`, - ); -}; + */ -const testStream = () => { - return new ReadableStream({ - async start(controller) { - const send = (count: number, char: string) => - controller.enqueue( - new TextEncoder().encode(Array(count).fill(char).join("")), - ); - - send(65536, "1"); - send(65536, "2"); - send(65536, "3"); - send(65536, "4"); - send(65536, "5"); - send(65536, "6"); - send(65536, "7"); - send(65536, "8"); - send(65536, "9"); - send(65536, "1"); - send(65536, "2"); - send(65536, "3"); - send(65536, "4"); - send(65536, "5"); - send(65536, "6"); - send(65536, "7"); - send(65536, "8"); - send(14496, "9"); - - controller.close(); - }, - }); -}; - -export const writeStreamOneShot = async ( - path: string, - stream: ReadableStream, -) => { - const response = new Response(stream); - const blob = await response.blob(); - // const ReadableStream() - - // The duplex parameter needs to be set to 'half' when streaming requests. - // - // Currently browsers, and specifically in our case, since this code runs - // only within our desktop (Electron) app, Chromium, don't support 'full' - // duplex mode (i.e. streaming both the request and the response). - // https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests const req = new Request(`stream://write${path}`, { - // GET can't have a body method: "POST", - body: blob, - // @ts-expect-erroXXX TypeScript's libdom.d.ts does not include the - // "duplex" parameter, e.g. see - // https://github.com/node-fetch/node-fetch/issues/1769. - // duplex: "half", + body: await new Response(stream).blob(), }); + const res = await fetch(req); if (!res.ok) throw new Error(