From 3bd0070b1207eafff10538be7618adb4379d6d3f Mon Sep 17 00:00:00 2001 From: Nayam Amarshe <25067102+NayamAmarshe@users.noreply.github.com> Date: Mon, 11 Sep 2023 07:55:14 +0530 Subject: [PATCH] Add remaining commands and close fix for macOS --- electron/commands/batch-upscayl.ts | 156 +++++++++ electron/commands/double-upscayl.ts | 234 ++++++++++++++ electron/index.ts | 477 +--------------------------- electron/main-window.ts | 98 +++++- 4 files changed, 502 insertions(+), 463 deletions(-) create mode 100644 electron/commands/batch-upscayl.ts create mode 100644 electron/commands/double-upscayl.ts diff --git a/electron/commands/batch-upscayl.ts b/electron/commands/batch-upscayl.ts new file mode 100644 index 0000000..436ba62 --- /dev/null +++ b/electron/commands/batch-upscayl.ts @@ -0,0 +1,156 @@ +import fs from "fs"; +import { getMainWindow } from "../main-window"; +import { + childProcesses, + customModelsFolderPath, + outputFolderPath, + saveOutputFolder, + setStopped, + stopped, +} from "../utils/config-variables"; +import logit from "../utils/logit"; +import { spawnUpscayl } from "../utils/spawn-upscayl"; +import { getBatchArguments } from "../utils/get-arguments"; +import slash from "../utils/slash"; +import { modelsPath } from "../utils/get-resource-paths"; +import COMMAND from "../constants/commands"; +import convertAndScale from "../utils/convert-and-scale"; +import DEFAULT_MODELS from "../constants/models"; + +const batchUpscayl = async (event, payload) => { + const mainWindow = getMainWindow(); + if (!mainWindow) return; + // GET THE MODEL + const model = payload.model; + const gpuId = payload.gpuId; + const saveImageAs = payload.saveImageAs; + // const scale = payload.scale as string; + + // GET THE IMAGE DIRECTORY + let inputDir = payload.batchFolderPath; + // GET THE OUTPUT DIRECTORY + let outputDir = payload.outputPath; + + if (saveOutputFolder === true && outputFolderPath) { + outputDir = outputFolderPath; + } + + const isDefaultModel = DEFAULT_MODELS.includes(model); + + let scale = "4"; + if (model.includes("x2")) { + scale = "2"; + } else if (model.includes("x3")) { + scale = "3"; + } else { + scale = "4"; + } + + outputDir += `_${model}_x${payload.scale}`; + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + + // Delete .DS_Store files + fs.readdirSync(inputDir).forEach((file) => { + if (file === ".DS_Store") { + logit("🗑️ Deleting .DS_Store file"); + fs.unlinkSync(inputDir + slash + file); + } + }); + + // UPSCALE + const upscayl = spawnUpscayl( + "realesrgan", + getBatchArguments( + inputDir, + outputDir, + isDefaultModel ? modelsPath : customModelsFolderPath ?? modelsPath, + model, + gpuId, + "png", + scale + ), + logit + ); + + childProcesses.push(upscayl); + + setStopped(false); + let failed = false; + + const onData = (data: any) => { + if (!mainWindow) return; + data = data.toString(); + mainWindow.webContents.send( + COMMAND.FOLDER_UPSCAYL_PROGRESS, + data.toString() + ); + if (data.includes("invalid") || data.includes("failed")) { + logit("❌ INVALID GPU OR INVALID FILES IN FOLDER - FAILED"); + failed = true; + upscayl.kill(); + } + }; + const onError = (data: any) => { + if (!mainWindow) return; + mainWindow.setProgressBar(-1); + mainWindow.webContents.send( + COMMAND.FOLDER_UPSCAYL_PROGRESS, + data.toString() + ); + failed = true; + upscayl.kill(); + mainWindow && + mainWindow.webContents.send( + COMMAND.UPSCAYL_ERROR, + "Error upscaling image. Error: " + data + ); + return; + }; + const onClose = () => { + if (!mainWindow) return; + if (!failed && !stopped) { + logit("💯 Done upscaling"); + logit("♻ Scaling and converting now..."); + upscayl.kill(); + mainWindow && mainWindow.webContents.send(COMMAND.SCALING_AND_CONVERTING); + // Get number of files in output folder + const files = fs.readdirSync(inputDir); + try { + files.forEach(async (file) => { + console.log("Filename: ", file.slice(0, -3)); + await convertAndScale( + inputDir + slash + file, + outputDir + slash + file.slice(0, -3) + "png", + outputDir + slash + file.slice(0, -3) + saveImageAs, + payload.scale, + saveImageAs, + onError + ); + // Remove the png file (default) if the saveImageAs is not png + if (saveImageAs !== "png") { + fs.unlinkSync(outputDir + slash + file.slice(0, -3) + "png"); + } + }); + mainWindow.webContents.send(COMMAND.FOLDER_UPSCAYL_DONE, outputDir); + } catch (error) { + logit("❌ Error processing (scaling and converting) the image.", error); + upscayl.kill(); + mainWindow && + mainWindow.webContents.send( + COMMAND.UPSCAYL_ERROR, + "Error processing (scaling and converting) the image. Please report this error on Upscayl GitHub Issues page." + ); + } + } else { + upscayl.kill(); + } + }; + + upscayl.process.stderr.on("data", onData); + upscayl.process.on("error", onError); + upscayl.process.on("close", onClose); +}; + +export default batchUpscayl; diff --git a/electron/commands/double-upscayl.ts b/electron/commands/double-upscayl.ts new file mode 100644 index 0000000..20e27bf --- /dev/null +++ b/electron/commands/double-upscayl.ts @@ -0,0 +1,234 @@ +import path, { parse } from "path"; +import { getMainWindow } from "../main-window"; +import { + childProcesses, + customModelsFolderPath, + outputFolderPath, + quality, + saveOutputFolder, + setStopped, + stopped, +} from "../utils/config-variables"; +import DEFAULT_MODELS from "../constants/models"; +import slash from "../utils/slash"; +import { spawnUpscayl } from "../utils/spawn-upscayl"; +import { + getDoubleUpscaleArguments, + getDoubleUpscaleSecondPassArguments, +} from "../utils/get-arguments"; +import { modelsPath } from "../utils/get-resource-paths"; +import logit from "../utils/logit"; +import COMMAND from "../constants/commands"; +import sharp from "sharp"; + +const doubleUpscayl = async (event, payload) => { + const mainWindow = getMainWindow(); + if (!mainWindow) return; + + const model = payload.model as string; + const imagePath = payload.imagePath; + let inputDir = (imagePath.match(/(.*)[\/\\]/) || [""])[1]; + let outputDir = path.normalize(payload.outputPath); + + if (saveOutputFolder === true && outputFolderPath) { + outputDir = outputFolderPath; + } + const gpuId = payload.gpuId as string; + const saveImageAs = payload.saveImageAs as string; + + const isDefaultModel = DEFAULT_MODELS.includes(model); + + // COPY IMAGE TO TMP FOLDER + + const fullfileName = imagePath.split(slash).slice(-1)[0] as string; + const fileName = parse(fullfileName).name; + const outFile = + outputDir + slash + fileName + "_upscayl_16x_" + model + "." + saveImageAs; + + let scale = "4"; + if (model.includes("x2")) { + scale = "2"; + } else if (model.includes("x3")) { + scale = "3"; + } else { + scale = "4"; + } + + // UPSCALE + let upscayl = spawnUpscayl( + "realesrgan", + getDoubleUpscaleArguments( + inputDir, + fullfileName, + outFile, + isDefaultModel ? modelsPath : customModelsFolderPath ?? modelsPath, + model, + gpuId, + saveImageAs, + scale + ), + logit + ); + + childProcesses.push(upscayl); + + setStopped(false); + let failed = false; + let isAlpha = false; + let failed2 = false; + + const onData = (data) => { + if (!mainWindow) return; + // CONVERT DATA TO STRING + data = data.toString(); + // SEND UPSCAYL PROGRESS TO RENDERER + mainWindow.webContents.send(COMMAND.DOUBLE_UPSCAYL_PROGRESS, data); + // IF PROGRESS HAS ERROR, UPSCAYL FAILED + if (data.includes("invalid gpu") || data.includes("failed")) { + upscayl.kill(); + failed = true; + } + if (data.includes("has alpha channel")) { + isAlpha = true; + } + }; + + const onError = (data) => { + if (!mainWindow) return; + mainWindow.setProgressBar(-1); + data.toString(); + // SEND UPSCAYL PROGRESS TO RENDERER + mainWindow.webContents.send(COMMAND.DOUBLE_UPSCAYL_PROGRESS, data); + // SET FAILED TO TRUE + failed = true; + mainWindow && + mainWindow.webContents.send( + COMMAND.UPSCAYL_ERROR, + "Error upscaling image. Error: " + data + ); + upscayl.kill(); + return; + }; + + const onClose2 = async (code) => { + if (!mainWindow) return; + if (!failed2 && !stopped) { + logit("💯 Done upscaling"); + logit("♻ Scaling and converting now..."); + mainWindow.webContents.send(COMMAND.SCALING_AND_CONVERTING); + try { + const originalImage = await sharp( + inputDir + slash + fullfileName + ).metadata(); + if (!mainWindow || !originalImage) { + throw new Error("Could not grab the original image!"); + } + // Resize the image to the scale + const newImage = sharp(isAlpha ? outFile + ".png" : outFile) + .resize( + originalImage.width && + originalImage.width * parseInt(payload.scale), + originalImage.height && + originalImage.height * parseInt(payload.scale) + ) + .withMetadata(); // Keep metadata + // Change the output according to the saveImageAs + if (saveImageAs === "png") { + newImage.png({ quality: 100 - quality }); + } else if (saveImageAs === "jpg") { + newImage.jpeg({ quality: 100 - quality }); + } + // Save the image + await newImage + .toFile(isAlpha ? outFile + ".png" : outFile) + .then(() => { + logit( + "✅ Done converting to: ", + isAlpha ? outFile + ".png" : outFile + ); + }) + .catch((error) => { + logit("❌ Error converting to: ", saveImageAs, error); + upscayl.kill(); + onError(error); + }); + mainWindow.setProgressBar(-1); + mainWindow.webContents.send( + COMMAND.DOUBLE_UPSCAYL_DONE, + isAlpha + ? (outFile + ".png").replace( + /([^/\\]+)$/i, + encodeURIComponent((outFile + ".png").match(/[^/\\]+$/i)![0]) + ) + : outFile.replace( + /([^/\\]+)$/i, + encodeURIComponent(outFile.match(/[^/\\]+$/i)![0]) + ) + ); + } catch (error) { + logit("❌ Error reading original image metadata", error); + mainWindow && + mainWindow.webContents.send( + COMMAND.UPSCAYL_ERROR, + "Error processing (scaling and converting) the image. Please report this error on Upscayl GitHub Issues page." + ); + upscayl.kill(); + } + } + }; + + upscayl.process.stderr.on("data", onData); + upscayl.process.on("error", onError); + upscayl.process.on("close", (code) => { + // IF NOT FAILED + if (!failed && !stopped) { + // UPSCALE + let upscayl2 = spawnUpscayl( + "realesrgan", + getDoubleUpscaleSecondPassArguments( + isAlpha, + outFile, + isDefaultModel ? modelsPath : customModelsFolderPath ?? modelsPath, + model, + gpuId, + saveImageAs, + scale + ), + logit + ); + + childProcesses.push(upscayl2); + + upscayl2.process.stderr.on("data", (data) => { + if (!mainWindow) return; + // CONVERT DATA TO STRING + data = data.toString(); + // SEND UPSCAYL PROGRESS TO RENDERER + mainWindow.webContents.send(COMMAND.DOUBLE_UPSCAYL_PROGRESS, data); + // IF PROGRESS HAS ERROR, UPSCAYL FAILED + if (data.includes("invalid gpu") || data.includes("failed")) { + upscayl2.kill(); + failed2 = true; + } + }); + upscayl2.process.on("error", (data) => { + if (!mainWindow) return; + data.toString(); + // SEND UPSCAYL PROGRESS TO RENDERER + mainWindow.webContents.send(COMMAND.DOUBLE_UPSCAYL_PROGRESS, data); + // SET FAILED TO TRUE + failed2 = true; + mainWindow && + mainWindow.webContents.send( + COMMAND.UPSCAYL_ERROR, + "Error upscaling image. Error: " + data + ); + upscayl2.kill(); + return; + }); + upscayl2.process.on("close", onClose2); + } + }); +}; + +export default doubleUpscayl; diff --git a/electron/index.ts b/electron/index.ts index ef43747..a428345 100644 --- a/electron/index.ts +++ b/electron/index.ts @@ -6,7 +6,6 @@ import { ipcMain, dialog, MessageBoxOptions, - shell, protocol, net, } from "electron"; @@ -19,22 +18,11 @@ import selectFile from "./commands/select-file"; import getModelsList from "./commands/get-models-list"; import customModelsSelect from "./commands/custom-models-select"; import imageUpscayl from "./commands/image-upscayl"; -import { - overwrite, - setCustomModelsFolderPath, - setFolderPath, - setImagePath, - setOutputFolderPath, - setOverwrite, - setQuality, - setSaveOutputFolder, - setStopped, -} from "./utils/config-variables"; -import { createMainWindow, getMainWindow } from "./main-window"; +import { createMainWindow } from "./main-window"; import electronIsDev from "electron-is-dev"; -import { getPlatform } from "./utils/get-device-specs"; -import { join } from "path"; import { execPath, modelsPath } from "./utils/get-resource-paths"; +import batchUpscayl from "./commands/batch-upscayl"; +import doubleUpscayl from "./commands/double-upscayl"; // INITIALIZATION log.initialize({ preload: true }); @@ -43,479 +31,44 @@ logit("🚃 App Path: ", app.getAppPath()); app.whenReady().then(async () => { await prepareNext("./renderer"); createMainWindow(); + log.info("🚀 UPSCAYL EXEC PATH: ", execPath("realesrgan")); log.info("🚀 MODELS PATH: ", modelsPath); + protocol.handle("file:", (request) => { const pathname = decodeURI(request.url); return net.fetch(pathname); }); + if (!electronIsDev) { autoUpdater.checkForUpdates(); } - - const mainWindow = getMainWindow(); - - if (!mainWindow) { - console.log("No main window"); - return; - } - - const url = electronIsDev - ? "http://localhost:8000" - : (new URL("file:///").pathname = join( - __dirname, - "../renderer/out/index.html" - )).toString(); - mainWindow.loadURL(url); - - mainWindow.webContents.setWindowOpenHandler(({ url }) => { - shell.openExternal(url); - return { action: "deny" }; - }); - - mainWindow.once("ready-to-show", () => { - if (!mainWindow) return; - mainWindow.show(); - }); - - // GET LAST IMAGE PATH TO LOCAL STORAGE - mainWindow.webContents - .executeJavaScript('localStorage.getItem("lastImagePath");', true) - .then((lastImagePath: string | null) => { - if (lastImagePath && lastImagePath.length > 0) { - setImagePath(lastImagePath); - } - }); - // GET LAST FOLDER PATH TO LOCAL STORAGE - mainWindow.webContents - .executeJavaScript('localStorage.getItem("lastFolderPath");', true) - .then((lastFolderPath: string | null) => { - if (lastFolderPath && lastFolderPath.length > 0) { - setFolderPath(lastFolderPath); - } - }); - // GET LAST CUSTOM MODELS FOLDER PATH TO LOCAL STORAGE - mainWindow.webContents - .executeJavaScript( - 'localStorage.getItem("lastCustomModelsFolderPath");', - true - ) - .then((lastCustomModelsFolderPath: string | null) => { - if (lastCustomModelsFolderPath && lastCustomModelsFolderPath.length > 0) { - setCustomModelsFolderPath(lastCustomModelsFolderPath); - } - }); - // GET LAST CUSTOM MODELS FOLDER PATH TO LOCAL STORAGE - mainWindow.webContents - .executeJavaScript('localStorage.getItem("lastOutputFolderPath");', true) - .then((lastOutputFolderPath: string | null) => { - if (lastOutputFolderPath && lastOutputFolderPath.length > 0) { - setOutputFolderPath(lastOutputFolderPath); - } - }); - // GET LAST SAVE OUTPUT FOLDER (BOOLEAN) TO LOCAL STORAGE - mainWindow.webContents - .executeJavaScript('localStorage.getItem("rememberOutputFolder");', true) - .then((lastSaveOutputFolder: boolean | null) => { - if (lastSaveOutputFolder !== null) { - setSaveOutputFolder(lastSaveOutputFolder); - } - }); - // GET IMAGE QUALITY (NUMBER) TO LOCAL STORAGE - mainWindow.webContents - .executeJavaScript('localStorage.getItem("quality");', true) - .then((lastSavedQuality: string | null) => { - if (lastSavedQuality !== null) { - if (parseInt(lastSavedQuality) === 100) { - setQuality(99); - } else { - setQuality(parseInt(lastSavedQuality)); - } - } - }); - // GET IMAGE QUALITY (NUMBER) TO LOCAL STORAGE - mainWindow.webContents - .executeJavaScript('localStorage.getItem("overwrite");', true) - .then((lastSavedOverwrite: string | null) => { - if (lastSavedOverwrite !== null) { - console.log("Setting Overwrite: ", lastSavedOverwrite); - setOverwrite(lastSavedOverwrite === "true"); - console.log("Set Overwrite: ", overwrite); - } - }); - - mainWindow.webContents.send(COMMAND.OS, getPlatform()); }); // Quit the app once all windows are closed -app.on("window-all-closed", app.quit); +app.on("window-all-closed", () => { + if (process.platform !== "darwin") { + app.quit(); + } +}); -//------------------------Open Folder-----------------------------// -ipcMain.on(COMMAND.OPEN_FOLDER, openFolder); - -//------------------------Stop Command-----------------------------// ipcMain.on(COMMAND.STOP, stop); -//------------------------Select Folder-----------------------------// +ipcMain.on(COMMAND.OPEN_FOLDER, openFolder); + ipcMain.handle(COMMAND.SELECT_FOLDER, selectFolder); -//------------------------Select File-----------------------------// ipcMain.handle(COMMAND.SELECT_FILE, selectFile); -//------------------------Get Models List-----------------------------// ipcMain.on(COMMAND.GET_MODELS_LIST, getModelsList); -//------------------------Custom Models Select-----------------------------// ipcMain.handle(COMMAND.SELECT_CUSTOM_MODEL_FOLDER, customModelsSelect); -//------------------------Image Upscayl-----------------------------// ipcMain.on(COMMAND.UPSCAYL, imageUpscayl); -//------------------------Batch Upscayl-----------------------------// -// ipcMain.on(COMMAND.FOLDER_UPSCAYL, async (event, payload) => { -// if (!mainWindow) return; -// // GET THE MODEL -// const model = payload.model; -// const gpuId = payload.gpuId; -// const saveImageAs = payload.saveImageAs; -// // const scale = payload.scale as string; +ipcMain.on(COMMAND.FOLDER_UPSCAYL, batchUpscayl); -// // GET THE IMAGE DIRECTORY -// let inputDir = payload.batchFolderPath; -// // GET THE OUTPUT DIRECTORY -// let outputDir = payload.outputPath; - -// if (saveOutputFolder === true && outputFolderPath) { -// outputDir = outputFolderPath; -// } - -// const isDefaultModel = defaultModels.includes(model); - -// let scale = "4"; -// if (model.includes("x2")) { -// scale = "2"; -// } else if (model.includes("x3")) { -// scale = "3"; -// } else { -// scale = "4"; -// } - -// outputDir += `_${model}_x${payload.scale}`; -// if (!fs.existsSync(outputDir)) { -// fs.mkdirSync(outputDir, { recursive: true }); -// } - -// // Delete .DS_Store files -// fs.readdirSync(inputDir).forEach((file) => { -// if (file === ".DS_Store") { -// logit("🗑️ Deleting .DS_Store file"); -// fs.unlinkSync(inputDir + slash + file); -// } -// }); - -// // UPSCALE -// const upscayl = spawnUpscayl( -// "realesrgan", -// getBatchArguments( -// inputDir, -// outputDir, -// isDefaultModel ? modelsPath : customModelsFolderPath ?? modelsPath, -// model, -// gpuId, -// "png", -// scale -// ), -// logit -// ); - -// childProcesses.push(upscayl); - -// stopped = false; -// let failed = false; - -// const onData = (data: any) => { -// if (!mainWindow) return; -// data = data.toString(); -// mainWindow.webContents.send( -// COMMAND.FOLDER_UPSCAYL_PROGRESS, -// data.toString() -// ); -// if (data.includes("invalid") || data.includes("failed")) { -// logit("❌ INVALID GPU OR INVALID FILES IN FOLDER - FAILED"); -// failed = true; -// upscayl.kill(); -// } -// }; -// const onError = (data: any) => { -// if (!mainWindow) return; -// mainWindow.setProgressBar(-1); -// mainWindow.webContents.send( -// COMMAND.FOLDER_UPSCAYL_PROGRESS, -// data.toString() -// ); -// failed = true; -// upscayl.kill(); -// mainWindow && -// mainWindow.webContents.send( -// COMMAND.UPSCAYL_ERROR, -// "Error upscaling image. Error: " + data -// ); -// return; -// }; -// const onClose = () => { -// if (!mainWindow) return; -// if (!failed && !stopped) { -// logit("💯 Done upscaling"); -// logit("♻ Scaling and converting now..."); -// upscayl.kill(); -// mainWindow && mainWindow.webContents.send(COMMAND.SCALING_AND_CONVERTING); -// // Get number of files in output folder -// const files = fs.readdirSync(inputDir); -// try { -// files.forEach(async (file) => { -// console.log("Filename: ", file.slice(0, -3)); -// await convertAndScale( -// inputDir + slash + file, -// outputDir + slash + file.slice(0, -3) + "png", -// outputDir + slash + file.slice(0, -3) + saveImageAs, -// payload.scale, -// saveImageAs, -// onError -// ); -// // Remove the png file (default) if the saveImageAs is not png -// if (saveImageAs !== "png") { -// fs.unlinkSync(outputDir + slash + file.slice(0, -3) + "png"); -// } -// }); -// mainWindow.webContents.send(COMMAND.FOLDER_UPSCAYL_DONE, outputDir); -// } catch (error) { -// logit("❌ Error processing (scaling and converting) the image.", error); -// upscayl.kill(); -// mainWindow && -// mainWindow.webContents.send( -// COMMAND.UPSCAYL_ERROR, -// "Error processing (scaling and converting) the image. Please report this error on Upscayl GitHub Issues page." -// ); -// } -// } else { -// upscayl.kill(); -// } -// }; - -// upscayl.process.stderr.on("data", onData); -// upscayl.process.on("error", onError); -// upscayl.process.on("close", onClose); -// }); - -// //------------------------Double Upscayl-----------------------------// -// ipcMain.on(COMMAND.DOUBLE_UPSCAYL, async (event, payload) => { -// if (!mainWindow) return; - -// const model = payload.model as string; -// const imagePath = payload.imagePath; -// let inputDir = (imagePath.match(/(.*)[\/\\]/) || [""])[1]; -// let outputDir = path.normalize(payload.outputPath); - -// if (saveOutputFolder === true && outputFolderPath) { -// outputDir = outputFolderPath; -// } -// const gpuId = payload.gpuId as string; -// const saveImageAs = payload.saveImageAs as string; - -// const isDefaultModel = defaultModels.includes(model); - -// // COPY IMAGE TO TMP FOLDER - -// const fullfileName = imagePath.split(slash).slice(-1)[0] as string; -// const fileName = parse(fullfileName).name; -// const outFile = -// outputDir + slash + fileName + "_upscayl_16x_" + model + "." + saveImageAs; - -// let scale = "4"; -// if (model.includes("x2")) { -// scale = "2"; -// } else if (model.includes("x3")) { -// scale = "3"; -// } else { -// scale = "4"; -// } - -// // UPSCALE -// let upscayl = spawnUpscayl( -// "realesrgan", -// getDoubleUpscaleArguments( -// inputDir, -// fullfileName, -// outFile, -// isDefaultModel ? modelsPath : customModelsFolderPath ?? modelsPath, -// model, -// gpuId, -// saveImageAs, -// scale -// ), -// logit -// ); - -// childProcesses.push(upscayl); - -// stopped = false; -// let failed = false; -// let isAlpha = false; -// let failed2 = false; - -// const onData = (data) => { -// if (!mainWindow) return; -// // CONVERT DATA TO STRING -// data = data.toString(); -// // SEND UPSCAYL PROGRESS TO RENDERER -// mainWindow.webContents.send(COMMAND.DOUBLE_UPSCAYL_PROGRESS, data); -// // IF PROGRESS HAS ERROR, UPSCAYL FAILED -// if (data.includes("invalid gpu") || data.includes("failed")) { -// upscayl.kill(); -// failed = true; -// } -// if (data.includes("has alpha channel")) { -// isAlpha = true; -// } -// }; - -// const onError = (data) => { -// if (!mainWindow) return; -// mainWindow.setProgressBar(-1); -// data.toString(); -// // SEND UPSCAYL PROGRESS TO RENDERER -// mainWindow.webContents.send(COMMAND.DOUBLE_UPSCAYL_PROGRESS, data); -// // SET FAILED TO TRUE -// failed = true; -// mainWindow && -// mainWindow.webContents.send( -// COMMAND.UPSCAYL_ERROR, -// "Error upscaling image. Error: " + data -// ); -// upscayl.kill(); -// return; -// }; - -// const onClose2 = async (code) => { -// if (!mainWindow) return; -// if (!failed2 && !stopped) { -// logit("💯 Done upscaling"); -// logit("♻ Scaling and converting now..."); -// mainWindow.webContents.send(COMMAND.SCALING_AND_CONVERTING); -// try { -// const originalImage = await sharp( -// inputDir + slash + fullfileName -// ).metadata(); -// if (!mainWindow || !originalImage) { -// throw new Error("Could not grab the original image!"); -// } -// // Resize the image to the scale -// const newImage = sharp(isAlpha ? outFile + ".png" : outFile) -// .resize( -// originalImage.width && -// originalImage.width * parseInt(payload.scale), -// originalImage.height && -// originalImage.height * parseInt(payload.scale) -// ) -// .withMetadata(); // Keep metadata -// // Change the output according to the saveImageAs -// if (saveImageAs === "png") { -// newImage.png({ quality: 100 - quality }); -// } else if (saveImageAs === "jpg") { -// newImage.jpeg({ quality: 100 - quality }); -// } -// // Save the image -// await newImage -// .toFile(isAlpha ? outFile + ".png" : outFile) -// .then(() => { -// logit( -// "✅ Done converting to: ", -// isAlpha ? outFile + ".png" : outFile -// ); -// }) -// .catch((error) => { -// logit("❌ Error converting to: ", saveImageAs, error); -// upscayl.kill(); -// onError(error); -// }); -// mainWindow.setProgressBar(-1); -// mainWindow.webContents.send( -// COMMAND.DOUBLE_UPSCAYL_DONE, -// isAlpha -// ? (outFile + ".png").replace( -// /([^/\\]+)$/i, -// encodeURIComponent((outFile + ".png").match(/[^/\\]+$/i)![0]) -// ) -// : outFile.replace( -// /([^/\\]+)$/i, -// encodeURIComponent(outFile.match(/[^/\\]+$/i)![0]) -// ) -// ); -// } catch (error) { -// logit("❌ Error reading original image metadata", error); -// mainWindow && -// mainWindow.webContents.send( -// COMMAND.UPSCAYL_ERROR, -// "Error processing (scaling and converting) the image. Please report this error on Upscayl GitHub Issues page." -// ); -// upscayl.kill(); -// } -// } -// }; - -// upscayl.process.stderr.on("data", onData); -// upscayl.process.on("error", onError); -// upscayl.process.on("close", (code) => { -// // IF NOT FAILED -// if (!failed && !stopped) { -// // UPSCALE -// let upscayl2 = spawnUpscayl( -// "realesrgan", -// getDoubleUpscaleSecondPassArguments( -// isAlpha, -// outFile, -// isDefaultModel ? modelsPath : customModelsFolderPath ?? modelsPath, -// model, -// gpuId, -// saveImageAs, -// scale -// ), -// logit -// ); - -// childProcesses.push(upscayl2); - -// upscayl2.process.stderr.on("data", (data) => { -// if (!mainWindow) return; -// // CONVERT DATA TO STRING -// data = data.toString(); -// // SEND UPSCAYL PROGRESS TO RENDERER -// mainWindow.webContents.send(COMMAND.DOUBLE_UPSCAYL_PROGRESS, data); -// // IF PROGRESS HAS ERROR, UPSCAYL FAILED -// if (data.includes("invalid gpu") || data.includes("failed")) { -// upscayl2.kill(); -// failed2 = true; -// } -// }); -// upscayl2.process.on("error", (data) => { -// if (!mainWindow) return; -// data.toString(); -// // SEND UPSCAYL PROGRESS TO RENDERER -// mainWindow.webContents.send(COMMAND.DOUBLE_UPSCAYL_PROGRESS, data); -// // SET FAILED TO TRUE -// failed2 = true; -// mainWindow && -// mainWindow.webContents.send( -// COMMAND.UPSCAYL_ERROR, -// "Error upscaling image. Error: " + data -// ); -// upscayl2.kill(); -// return; -// }); -// upscayl2.process.on("close", onClose2); -// } -// }); -// }); +ipcMain.on(COMMAND.DOUBLE_UPSCAYL, doubleUpscayl); //------------------------Auto-Update Code-----------------------------// autoUpdater.autoInstallOnAppQuit = false; diff --git a/electron/main-window.ts b/electron/main-window.ts index e1a235f..16e7b62 100644 --- a/electron/main-window.ts +++ b/electron/main-window.ts @@ -1,6 +1,18 @@ -import { BrowserWindow } from "electron"; +import { BrowserWindow, shell } from "electron"; import { getPlatform } from "./utils/get-device-specs"; import { join } from "path"; +import COMMAND from "./constants/commands"; +import { + overwrite, + setCustomModelsFolderPath, + setFolderPath, + setImagePath, + setOutputFolderPath, + setOverwrite, + setQuality, + setSaveOutputFolder, +} from "./utils/config-variables"; +import electronIsDev from "electron-is-dev"; let mainWindow: BrowserWindow | null; @@ -22,6 +34,90 @@ const createMainWindow = () => { titleBarStyle: getPlatform() === "mac" ? "hiddenInset" : "default", }); + const url = electronIsDev + ? "http://localhost:8000" + : (new URL("file:///").pathname = join( + __dirname, + "../renderer/out/index.html" + )).toString(); + mainWindow.loadURL(url); + + mainWindow.webContents.setWindowOpenHandler(({ url }) => { + shell.openExternal(url); + return { action: "deny" }; + }); + + mainWindow.once("ready-to-show", () => { + if (!mainWindow) return; + mainWindow.show(); + }); + + // GET LAST IMAGE PATH TO LOCAL STORAGE + mainWindow.webContents + .executeJavaScript('localStorage.getItem("lastImagePath");', true) + .then((lastImagePath: string | null) => { + if (lastImagePath && lastImagePath.length > 0) { + setImagePath(lastImagePath); + } + }); + // GET LAST FOLDER PATH TO LOCAL STORAGE + mainWindow.webContents + .executeJavaScript('localStorage.getItem("lastFolderPath");', true) + .then((lastFolderPath: string | null) => { + if (lastFolderPath && lastFolderPath.length > 0) { + setFolderPath(lastFolderPath); + } + }); + // GET LAST CUSTOM MODELS FOLDER PATH TO LOCAL STORAGE + mainWindow.webContents + .executeJavaScript( + 'localStorage.getItem("lastCustomModelsFolderPath");', + true + ) + .then((lastCustomModelsFolderPath: string | null) => { + if (lastCustomModelsFolderPath && lastCustomModelsFolderPath.length > 0) { + setCustomModelsFolderPath(lastCustomModelsFolderPath); + } + }); + // GET LAST CUSTOM MODELS FOLDER PATH TO LOCAL STORAGE + mainWindow.webContents + .executeJavaScript('localStorage.getItem("lastOutputFolderPath");', true) + .then((lastOutputFolderPath: string | null) => { + if (lastOutputFolderPath && lastOutputFolderPath.length > 0) { + setOutputFolderPath(lastOutputFolderPath); + } + }); + // GET LAST SAVE OUTPUT FOLDER (BOOLEAN) TO LOCAL STORAGE + mainWindow.webContents + .executeJavaScript('localStorage.getItem("rememberOutputFolder");', true) + .then((lastSaveOutputFolder: boolean | null) => { + if (lastSaveOutputFolder !== null) { + setSaveOutputFolder(lastSaveOutputFolder); + } + }); + // GET IMAGE QUALITY (NUMBER) TO LOCAL STORAGE + mainWindow.webContents + .executeJavaScript('localStorage.getItem("quality");', true) + .then((lastSavedQuality: string | null) => { + if (lastSavedQuality !== null) { + if (parseInt(lastSavedQuality) === 100) { + setQuality(99); + } else { + setQuality(parseInt(lastSavedQuality)); + } + } + }); + // GET IMAGE QUALITY (NUMBER) TO LOCAL STORAGE + mainWindow.webContents + .executeJavaScript('localStorage.getItem("overwrite");', true) + .then((lastSavedOverwrite: string | null) => { + if (lastSavedOverwrite !== null) { + setOverwrite(lastSavedOverwrite === "true"); + } + }); + + mainWindow.webContents.send(COMMAND.OS, getPlatform()); + mainWindow.setMenuBarVisibility(false); };