1
0
mirror of https://github.com/upscayl/upscayl.git synced 2025-02-17 11:18:36 +01:00

Refactor code and remove config vars to fix ASCII path decoding

This commit is contained in:
Nayam Amarshe 2024-04-25 00:59:51 +05:30
parent 618b46f553
commit 5feabea516
15 changed files with 142 additions and 159 deletions

5
common/decode-path.ts Normal file
View File

@ -0,0 +1,5 @@
import path from "path";
export default function decodePath(filePath: string): string {
return path.normalize(decodeURIComponent(filePath));
}

View File

@ -0,0 +1,15 @@
export default function getDirectoryFromPath(filePath: string): string {
// Define the path separator based on the operating system
const separator = filePath.includes("/") ? "/" : "\\";
// Split the file path by the path separator
const pathParts = filePath.split(separator);
// Remove the last element to get the directory
pathParts.pop();
// Join the remaining parts back together to form the directory path
const directoryPath = pathParts.join(separator);
return directoryPath || "";
}

8
common/get-file-name.ts Normal file
View File

@ -0,0 +1,8 @@
export default function getFilenameFromPath(
path: string,
withExtension: boolean = true,
) {
if (!path) return "";
if (withExtension) return path.split("/").slice(-1)[0];
return path.split("/").slice(-1)[0].split(".").slice(0, -1).join(".");
}

24
common/sanitize-path.ts Normal file
View File

@ -0,0 +1,24 @@
export function sanitizePath(filePath: string) {
// const protocolPrefix = "file://";
// Normalize the file path to use forward slashes (for Windows)
const normalizedFilePath = filePath.replace(/\\/g, "/");
// Split the file path into segments based on forward slashes
const pathSegments = normalizedFilePath.split("/");
// Encode each segment separately using encodeURIComponent
const encodedPathSegments = pathSegments.map((segment) =>
encodeURIComponent(segment),
);
// Join the encoded segments back together with forward slashes
const encodedFilePath = encodedPathSegments.join("/");
// Combine the protocol prefix with the encoded file path to create the final file URL
const fileUrl = encodedFilePath;
console.log("🚀 => fileUrl:", fileUrl);
// Return the final Electron file URL
return fileUrl;
}

View File

@ -1,10 +1,12 @@
import { ImageFormat } from "@electron/types/types";
export type ImageUpscaylPayload = { export type ImageUpscaylPayload = {
imagePath: string; imagePath: string;
outputPath?: string; outputPath: string;
scale: string; scale: string;
model: string; model: string;
gpuId: string; gpuId: string;
saveImageAs: string; saveImageAs: ImageFormat;
overwrite: boolean; overwrite: boolean;
compression: string; compression: string;
noImageProcessing: boolean; noImageProcessing: boolean;
@ -14,11 +16,14 @@ export type ImageUpscaylPayload = {
export type DoubleUpscaylPayload = { export type DoubleUpscaylPayload = {
model: string; model: string;
/**
* The path to the image to upscale.
*/
imagePath: string; imagePath: string;
outputPath: string; outputPath: string;
scale: string; scale: string;
gpuId: string; gpuId: string;
saveImageAs: string; saveImageAs: ImageFormat;
compression: string; compression: string;
noImageProcessing: boolean; noImageProcessing: boolean;
customWidth: string; customWidth: string;
@ -30,7 +35,7 @@ export type BatchUpscaylPayload = {
outputPath: string; outputPath: string;
model: string; model: string;
gpuId: string; gpuId: string;
saveImageAs: string; saveImageAs: ImageFormat;
scale: string; scale: string;
compression: string; compression: string;
noImageProcessing: boolean; noImageProcessing: boolean;

View File

@ -3,9 +3,6 @@ import { getMainWindow } from "../main-window";
import { import {
childProcesses, childProcesses,
savedCustomModelsPath, savedCustomModelsPath,
rememberOutputFolder,
setCompression,
setNoImageProcessing,
setStopped, setStopped,
stopped, stopped,
} from "../utils/config-variables"; } from "../utils/config-variables";
@ -16,55 +13,33 @@ import slash from "../utils/slash";
import { modelsPath } from "../utils/get-resource-paths"; import { modelsPath } from "../utils/get-resource-paths";
import COMMAND from "../../common/commands"; import COMMAND from "../../common/commands";
import { BatchUpscaylPayload } from "../../common/types/types"; import { BatchUpscaylPayload } from "../../common/types/types";
import { ImageFormat } from "../types/types";
import showNotification from "../utils/show-notification"; import showNotification from "../utils/show-notification";
import { DEFAULT_MODELS } from "../../common/models-list"; import { DEFAULT_MODELS } from "../../common/models-list";
const batchUpscayl = async (event, payload: BatchUpscaylPayload) => { const batchUpscayl = async (event, payload: BatchUpscaylPayload) => {
const mainWindow = getMainWindow(); const mainWindow = getMainWindow();
if (!mainWindow) return; if (!mainWindow) return;
// GET THE MODEL
const model = payload.model;
const gpuId = payload.gpuId;
const saveImageAs = payload.saveImageAs as ImageFormat;
console.log("PAYLOAD: ", payload);
// GET THE IMAGE DIRECTORY
let inputDir = payload.batchFolderPath;
// GET THE OUTPUT DIRECTORY
let outputFolderPath = payload.outputPath;
if (rememberOutputFolder === true && outputFolderPath) {
outputFolderPath = outputFolderPath;
}
// ! Don't do fetchLocalStorage() again, it causes the values to be reset
setNoImageProcessing(payload.noImageProcessing);
setCompression(parseInt(payload.compression));
const isDefaultModel = DEFAULT_MODELS.includes(model);
const scale = payload.scale; const scale = payload.scale;
const useCustomWidth = payload.useCustomWidth; const useCustomWidth = payload.useCustomWidth;
const customWidth = useCustomWidth ? payload.customWidth : ""; const customWidth = useCustomWidth ? payload.customWidth : "";
const model = payload.model;
const gpuId = payload.gpuId;
const saveImageAs = payload.saveImageAs;
// GET THE IMAGE DIRECTORY
let inputDir = decodeURIComponent(payload.batchFolderPath);
// GET THE OUTPUT DIRECTORY
let outputFolderPath = decodeURIComponent(payload.outputPath);
const outputFolderName = `upscayl_${saveImageAs}_${model}_${ const outputFolderName = `upscayl_${saveImageAs}_${model}_${
useCustomWidth ? `${customWidth}px` : `${scale}x` useCustomWidth ? `${customWidth}px` : `${scale}x`
}`; }`;
outputFolderPath += slash + outputFolderName; outputFolderPath += slash + outputFolderName;
// CREATE THE OUTPUT DIRECTORY
if (!fs.existsSync(outputFolderPath)) { if (!fs.existsSync(outputFolderPath)) {
fs.mkdirSync(outputFolderPath, { recursive: true }); fs.mkdirSync(outputFolderPath, { recursive: true });
} }
// Delete .DS_Store files const isDefaultModel = DEFAULT_MODELS.includes(model);
fs.readdirSync(inputDir).forEach((file) => {
if (
file === ".DS_Store" ||
file.toLowerCase() === "desktop.ini" ||
file.startsWith(".")
) {
logit("🗑️ Deleting .DS_Store file");
fs.unlinkSync(inputDir + slash + file);
}
});
// UPSCALE // UPSCALE
const upscayl = spawnUpscayl( const upscayl = spawnUpscayl(

View File

@ -1,12 +1,8 @@
import path, { parse } from "path"; import { parse } from "path";
import { getMainWindow } from "../main-window"; import { getMainWindow } from "../main-window";
import { import {
childProcesses, childProcesses,
savedCustomModelsPath, savedCustomModelsPath,
savedOutputPath,
rememberOutputFolder,
setCompression,
setNoImageProcessing,
setStopped, setStopped,
stopped, stopped,
} from "../utils/config-variables"; } from "../utils/config-variables";
@ -23,38 +19,31 @@ import { DoubleUpscaylPayload } from "../../common/types/types";
import { ImageFormat } from "../types/types"; import { ImageFormat } from "../types/types";
import showNotification from "../utils/show-notification"; import showNotification from "../utils/show-notification";
import { DEFAULT_MODELS } from "../../common/models-list"; import { DEFAULT_MODELS } from "../../common/models-list";
import getModelScale from "../../common/check-model-scale"; import getFilenameFromPath from "../../common/get-file-name";
import decodePath from "../../common/decode-path";
import getDirectoryFromPath from "../../common/get-directory-from-path";
const doubleUpscayl = async (event, payload: DoubleUpscaylPayload) => { const doubleUpscayl = async (event, payload: DoubleUpscaylPayload) => {
const mainWindow = getMainWindow(); const mainWindow = getMainWindow();
if (!mainWindow) return; if (!mainWindow) return;
const model = payload.model as string; const compression = payload.compression;
const imagePath = payload.imagePath; const scale = parseInt(payload.scale) ** 2;
let inputDir = (imagePath.match(/(.*)[\/\\]/) || [""])[1]; const useCustomWidth = payload.useCustomWidth;
let outputDir = path.normalize(payload.outputPath); const customWidth = useCustomWidth ? payload.customWidth : "";
const model = payload.model;
if (rememberOutputFolder === true && savedOutputPath) {
outputDir = savedOutputPath;
}
const gpuId = payload.gpuId as string; const gpuId = payload.gpuId as string;
const saveImageAs = payload.saveImageAs as ImageFormat; const saveImageAs = payload.saveImageAs as ImageFormat;
const imagePath = decodePath(payload.imagePath);
setNoImageProcessing(payload.noImageProcessing); let inputDir = getDirectoryFromPath(imagePath);
setCompression(parseInt(payload.compression)); let outputDir = decodePath(payload.outputPath);
const fullfileName = getFilenameFromPath(imagePath);
const fileName = parse(fullfileName).name;
const isDefaultModel = DEFAULT_MODELS.includes(model); const isDefaultModel = DEFAULT_MODELS.includes(model);
// COPY IMAGE TO TMP FOLDER // COPY IMAGE TO TMP FOLDER
const fullfileName = imagePath.split(slash).slice(-1)[0] as string;
const fileName = parse(fullfileName).name;
const modelScale = getModelScale(model);
const scale = parseInt(payload.scale) ** 2;
const useCustomWidth = payload.useCustomWidth;
const customWidth = useCustomWidth ? payload.customWidth : "";
const outFile = const outFile =
outputDir + outputDir +
slash + slash +
@ -69,7 +58,7 @@ const doubleUpscayl = async (event, payload: DoubleUpscaylPayload) => {
let upscayl = spawnUpscayl( let upscayl = spawnUpscayl(
getDoubleUpscaleArguments({ getDoubleUpscaleArguments({
inputDir, inputDir,
fullfileName, fullfileName: decodeURIComponent(fullfileName),
outFile, outFile,
modelsPath: isDefaultModel modelsPath: isDefaultModel
? modelsPath ? modelsPath
@ -128,13 +117,7 @@ const doubleUpscayl = async (event, payload: DoubleUpscaylPayload) => {
logit("💯 Done upscaling"); logit("💯 Done upscaling");
mainWindow.setProgressBar(-1); mainWindow.setProgressBar(-1);
mainWindow.webContents.send( mainWindow.webContents.send(COMMAND.DOUBLE_UPSCAYL_DONE, outFile);
COMMAND.DOUBLE_UPSCAYL_DONE,
outFile.replace(
/([^/\\]+)$/i,
encodeURIComponent(outFile.match(/[^/\\]+$/i)![0]),
),
);
showNotification("Upscayled", "Image upscayled successfully!"); showNotification("Upscayled", "Image upscayled successfully!");
} }
}; };
@ -188,6 +171,7 @@ const doubleUpscayl = async (event, payload: DoubleUpscaylPayload) => {
saveImageAs, saveImageAs,
scale: scale.toString(), scale: scale.toString(),
customWidth, customWidth,
compression,
}), }),
logit, logit,
); );

View File

@ -2,14 +2,8 @@ import fs from "fs";
import { modelsPath } from "../utils/get-resource-paths"; import { modelsPath } from "../utils/get-resource-paths";
import COMMAND from "../../common/commands"; import COMMAND from "../../common/commands";
import { import {
savedCompression,
savedCustomModelsPath, savedCustomModelsPath,
savedBatchUpscaylFolderPath,
savedOutputPath,
rememberOutputFolder,
setChildProcesses, setChildProcesses,
setCompression,
setNoImageProcessing,
setStopped, setStopped,
stopped, stopped,
} from "../utils/config-variables"; } from "../utils/config-variables";
@ -23,6 +17,9 @@ import { ImageUpscaylPayload } from "../../common/types/types";
import { ImageFormat } from "../types/types"; import { ImageFormat } from "../types/types";
import showNotification from "../utils/show-notification"; import showNotification from "../utils/show-notification";
import { DEFAULT_MODELS } from "../../common/models-list"; import { DEFAULT_MODELS } from "../../common/models-list";
import getFilenameFromPath from "../../common/get-file-name";
import decodePath from "../../common/decode-path";
import getDirectoryFromPath from "../../common/get-directory-from-path";
const imageUpscayl = async (event, payload: ImageUpscaylPayload) => { const imageUpscayl = async (event, payload: ImageUpscaylPayload) => {
const mainWindow = getMainWindow(); const mainWindow = getMainWindow();
@ -32,34 +29,20 @@ const imageUpscayl = async (event, payload: ImageUpscaylPayload) => {
return; return;
} }
setNoImageProcessing(payload.noImageProcessing);
setCompression(parseInt(payload.compression));
// GET VARIABLES // GET VARIABLES
const compression = payload.compression;
const scale = payload.scale;
const useCustomWidth = payload.useCustomWidth;
const customWidth = useCustomWidth ? payload.customWidth : "";
const model = payload.model as string; const model = payload.model as string;
const gpuId = payload.gpuId as string; const gpuId = payload.gpuId as string;
const saveImageAs = payload.saveImageAs as ImageFormat; const saveImageAs = payload.saveImageAs as ImageFormat;
const overwrite = payload.overwrite as boolean; const overwrite = payload.overwrite as boolean;
let inputDir = (payload.imagePath.match(/(.*)[\/\\]/)?.[1] || "") as string; const imagePath = decodePath(payload.imagePath);
let outputDir: string | undefined = let inputDir = getDirectoryFromPath(imagePath);
savedBatchUpscaylFolderPath || (payload.outputPath as string); let outputDir = decodePath(payload.outputPath);
if ( const fileNameWithExt = getFilenameFromPath(imagePath);
rememberOutputFolder === true && const fileName = parse(fileNameWithExt).name;
savedOutputPath &&
savedOutputPath?.length > 0
) {
logit("🧠 Using saved output path");
outputDir = savedOutputPath;
}
const isDefaultModel = DEFAULT_MODELS.includes(model);
logit("Is Default Model? : ", isDefaultModel);
const fullfileName = payload.imagePath.replace(/^.*[\\\/]/, "") as string;
const fileName = parse(fullfileName).name;
const fileExt = parse(fullfileName).ext;
const useCustomWidth = payload.useCustomWidth;
const customWidth = useCustomWidth ? payload.customWidth : "";
const scale = payload.scale;
const outFile = const outFile =
outputDir + outputDir +
@ -71,17 +54,13 @@ const imageUpscayl = async (event, payload: ImageUpscaylPayload) => {
"." + "." +
saveImageAs; saveImageAs;
const isDefaultModel = DEFAULT_MODELS.includes(model);
// UPSCALE // UPSCALE
if (fs.existsSync(outFile) && !overwrite) { if (fs.existsSync(outFile) && !overwrite) {
// If already upscayled, just output that file // If already upscayled, just output that file
logit("✅ Already upscayled at: ", outFile); logit("✅ Already upscayled at: ", outFile);
mainWindow.webContents.send( mainWindow.webContents.send(COMMAND.UPSCAYL_DONE, outFile);
COMMAND.UPSCAYL_DONE,
outFile.replace(
/([^/\\]+)$/i,
encodeURIComponent(outFile.match(/[^/\\]+$/i)![0]),
),
);
} else { } else {
logit( logit(
"✅ Upscayl Variables: ", "✅ Upscayl Variables: ",
@ -90,18 +69,18 @@ const imageUpscayl = async (event, payload: ImageUpscaylPayload) => {
gpuId, gpuId,
saveImageAs, saveImageAs,
inputDir, inputDir,
fileNameWithExt,
outputDir, outputDir,
fullfileName, outFile,
fileName, fileName,
scale, scale,
outFile, compression,
compression: savedCompression,
}), }),
); );
const upscayl = spawnUpscayl( const upscayl = spawnUpscayl(
getSingleImageArguments({ getSingleImageArguments({
inputDir, inputDir: decodeURIComponent(inputDir),
fullfileName, fileNameWithExt: decodeURIComponent(fileNameWithExt),
outFile, outFile,
modelsPath: isDefaultModel modelsPath: isDefaultModel
? modelsPath ? modelsPath
@ -146,13 +125,7 @@ const imageUpscayl = async (event, payload: ImageUpscaylPayload) => {
// Free up memory // Free up memory
upscayl.kill(); upscayl.kill();
mainWindow.setProgressBar(-1); mainWindow.setProgressBar(-1);
mainWindow.webContents.send( mainWindow.webContents.send(COMMAND.UPSCAYL_DONE, outFile);
COMMAND.UPSCAYL_DONE,
outFile.replace(
/([^/\\]+)$/i,
encodeURIComponent(outFile.match(/[^/\\]+$/i)![0]),
),
);
showNotification("Upscayl", "Image upscayled successfully!"); showNotification("Upscayl", "Image upscayled successfully!");
} }
}; };

View File

@ -40,12 +40,6 @@ export function setRememberOutputFolder(value: boolean): void {
logit("💾 Updating Remember Output Folder: ", rememberOutputFolder); logit("💾 Updating Remember Output Folder: ", rememberOutputFolder);
} }
export let savedCompression = 0;
export function setCompression(value: number): void {
savedCompression = value;
logit("📐 Updating Compression: ", savedCompression);
}
export let stopped = false; export let stopped = false;
export let childProcesses: { export let childProcesses: {
process: ChildProcessWithoutNullStreams; process: ChildProcessWithoutNullStreams;
@ -148,14 +142,7 @@ export function fetchLocalStorage(): void {
setRememberOutputFolder(lastSaveOutputFolder); setRememberOutputFolder(lastSaveOutputFolder);
} }
}); });
// GET IMAGE COMPRESSION (NUMBER) FROM LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("compression");', true)
.then((lastSavedCompression: string | null) => {
if (lastSavedCompression !== null) {
setCompression(parseInt(lastSavedCompression));
}
});
// GET PROCESS IMAGE (BOOLEAN) FROM LOCAL STORAGE // GET PROCESS IMAGE (BOOLEAN) FROM LOCAL STORAGE
mainWindow.webContents mainWindow.webContents
.executeJavaScript('localStorage.getItem("noImageProcessing");', true) .executeJavaScript('localStorage.getItem("noImageProcessing");', true)

View File

@ -5,7 +5,7 @@ const slash: string = getPlatform() === "win" ? "\\" : "/";
export const getSingleImageArguments = ({ export const getSingleImageArguments = ({
inputDir, inputDir,
fullfileName, fileNameWithExt,
outFile, outFile,
modelsPath, modelsPath,
model, model,
@ -15,7 +15,7 @@ export const getSingleImageArguments = ({
customWidth, customWidth,
}: { }: {
inputDir: string; inputDir: string;
fullfileName: string; fileNameWithExt: string;
outFile: string; outFile: string;
modelsPath: string; modelsPath: string;
model: string; model: string;
@ -29,7 +29,7 @@ export const getSingleImageArguments = ({
return [ return [
// INPUT IMAGE // INPUT IMAGE
"-i", "-i",
inputDir + slash + fullfileName, inputDir + slash + fileNameWithExt,
// OUTPUT IMAGE // OUTPUT IMAGE
"-o", "-o",
outFile, outFile,
@ -109,6 +109,7 @@ export const getDoubleUpscaleSecondPassArguments = ({
saveImageAs: ImageFormat; saveImageAs: ImageFormat;
scale: string; scale: string;
customWidth: string; customWidth: string;
compression: string;
}) => { }) => {
const modelScale = (parseInt(getModelScale(model)) ** 2).toString(); const modelScale = (parseInt(getModelScale(model)) ** 2).toString();
let includeScale = modelScale !== scale && !customWidth; let includeScale = modelScale !== scale && !customWidth;

View File

@ -1,7 +1,7 @@
{ {
"name": "upscayl", "name": "upscayl",
"private": true, "private": true,
"version": "2.10.9", "version": "2.11.0",
"productName": "Upscayl", "productName": "Upscayl",
"author": { "author": {
"name": "Nayam Amarshe", "name": "Nayam Amarshe",

View File

@ -10,6 +10,10 @@ export const scaleAtom = atomWithStorage<string>("scale", "4");
export const batchModeAtom = atom<boolean>(false); export const batchModeAtom = atom<boolean>(false);
/**
* The path to the last folder the user saved an image to.
* Reset to "" if rememberOutputFolder is false.
*/
export const savedOutputPathAtom = atomWithStorage<string | null>( export const savedOutputPathAtom = atomWithStorage<string | null>(
"savedOutputPath", "savedOutputPath",
null, null,

View File

@ -9,12 +9,7 @@ import { DonateButton } from "./DonateButton";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { themeChange } from "theme-change"; import { themeChange } from "theme-change";
import { useAtom, useAtomValue } from "jotai"; import { useAtom, useAtomValue } from "jotai";
import { import { customModelsPathAtom, scaleAtom } from "../../atoms/userSettingsAtom";
customModelsPathAtom,
noImageProcessingAtom,
overwriteAtom,
scaleAtom,
} from "../../atoms/userSettingsAtom";
import { modelsListAtom } from "../../atoms/modelsListAtom"; import { modelsListAtom } from "../../atoms/modelsListAtom";
import useLog from "../hooks/useLog"; import useLog from "../hooks/useLog";
import { CompressionInput } from "./CompressionInput"; import { CompressionInput } from "./CompressionInput";

View File

@ -334,7 +334,7 @@ function LeftPaneImageSteps({
</p> </p>
)} )}
<button <button
className="btn btn-accent" className="btn btn-secondary"
onClick={ onClick={
progress.length > 0 || !outputPath progress.length > 0 || !outputPath
? () => ? () =>

View File

@ -1,5 +1,5 @@
"use client"; "use client";
import { useState, useEffect, useCallback } from "react"; import { useState, useEffect, useCallback, useMemo } from "react";
import COMMAND from "../../common/commands"; import COMMAND from "../../common/commands";
import { ReactCompareSlider } from "react-compare-slider"; import { ReactCompareSlider } from "react-compare-slider";
import Header from "../components/Header"; import Header from "../components/Header";
@ -40,16 +40,13 @@ import {
import { NewsModal } from "@/components/NewsModal"; import { NewsModal } from "@/components/NewsModal";
import { newsAtom, showNewsModalAtom } from "@/atoms/newsAtom"; import { newsAtom, showNewsModalAtom } from "@/atoms/newsAtom";
import matter from "gray-matter"; import matter from "gray-matter";
import { import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
ChevronLeftIcon,
ChevronRightIcon,
PanelLeftCloseIcon,
PanelRightCloseIcon,
} from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useToast } from "@/components/ui/use-toast"; import { useToast } from "@/components/ui/use-toast";
import { ToastAction } from "@/components/ui/toast"; import { ToastAction } from "@/components/ui/toast";
import Logo from "@/components/icons/Logo"; import Logo from "@/components/icons/Logo";
import { sanitizePath } from "@common/sanitize-path";
import getDirectoryFromPath from "@common/get-directory-from-path";
const Home = () => { const Home = () => {
const allowedFileTypes = ["png", "jpg", "jpeg", "webp"]; const allowedFileTypes = ["png", "jpg", "jpeg", "webp"];
@ -103,6 +100,16 @@ const Home = () => {
const { logit } = useLog(); const { logit } = useLog();
const { toast } = useToast(); const { toast } = useToast();
const sanitizedImagePath = useMemo(
() => sanitizePath(imagePath),
[imagePath],
);
const sanitizedUpscaledImagePath = useMemo(
() => sanitizePath(upscaledImagePath),
[upscaledImagePath],
);
const handleMouseMoveCompare = (e: React.MouseEvent) => { const handleMouseMoveCompare = (e: React.MouseEvent) => {
const { left, top, height, width } = const { left, top, height, width } =
e.currentTarget.getBoundingClientRect(); e.currentTarget.getBoundingClientRect();
@ -129,7 +136,7 @@ const Home = () => {
if (data.includes("Invalid GPU")) { if (data.includes("Invalid GPU")) {
toast({ toast({
title: "GPU Error", title: "GPU Error",
description: `GPU error occurred. Please read the wiki for troubleshooting! ${data})`, description: `Ran into an issue with the GPU. Please read the wiki for troubleshooting! (${data})`,
action: ( action: (
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<ToastAction <ToastAction
@ -345,7 +352,7 @@ const Home = () => {
setIsLoading(false); setIsLoading(false);
}, []); }, []);
// * HANDLERS // HANDLERS
const resetImagePaths = () => { const resetImagePaths = () => {
logit("🔄 Resetting image paths"); logit("🔄 Resetting image paths");
setDimensions({ setDimensions({
@ -393,7 +400,7 @@ const Home = () => {
if (path === null) return; if (path === null) return;
logit("🖼 Selected Image Path: ", path); logit("🖼 Selected Image Path: ", path);
setImagePath(path); setImagePath(path);
var dirname = path.match(/(.*)[\/\\]/)[1] || ""; var dirname = getDirectoryFromPath(path);
logit("📁 Selected Image Directory: ", dirname); logit("📁 Selected Image Directory: ", dirname);
if (!featureFlags.APP_STORE_BUILD) { if (!featureFlags.APP_STORE_BUILD) {
if (!rememberOutputFolder) { if (!rememberOutputFolder) {
@ -478,7 +485,7 @@ const Home = () => {
} else { } else {
logit("🖼 Setting image path: ", filePath); logit("🖼 Setting image path: ", filePath);
setImagePath(filePath); setImagePath(filePath);
var dirname = filePath.match(/(.*)[\/\\]/)[1] || ""; var dirname = getDirectoryFromPath(filePath);
logit("🗂 Setting output path: ", dirname); logit("🗂 Setting output path: ", dirname);
if (!featureFlags.APP_STORE_BUILD) { if (!featureFlags.APP_STORE_BUILD) {
if (!rememberOutputFolder) { if (!rememberOutputFolder) {
@ -506,7 +513,7 @@ const Home = () => {
}); });
} else { } else {
setImagePath(filePath); setImagePath(filePath);
var dirname = filePath.match(/(.*)[\/\\]/)[1] || ""; var dirname = getDirectoryFromPath(filePath);
logit("🗂 Setting output path: ", dirname); logit("🗂 Setting output path: ", dirname);
if (!rememberOutputFolder) { if (!rememberOutputFolder) {
setOutputPath(dirname); setOutputPath(dirname);
@ -748,7 +755,7 @@ const Home = () => {
hideZoomOptions={true} hideZoomOptions={true}
/> />
<img <img
src={"file:///" + imagePath} src={"file:///" + sanitizePath(imagePath)}
onLoad={(e: any) => { onLoad={(e: any) => {
setDimensions({ setDimensions({
width: e.target.naturalWidth, width: e.target.naturalWidth,
@ -851,7 +858,7 @@ const Home = () => {
<img <img
/* USE REGEX TO GET THE FILENAME AND ENCODE IT INTO PROPER FORM IN ORDER TO AVOID ERRORS DUE TO SPECIAL CHARACTERS */ /* USE REGEX TO GET THE FILENAME AND ENCODE IT INTO PROPER FORM IN ORDER TO AVOID ERRORS DUE TO SPECIAL CHARACTERS */
src={"file:///" + imagePath} src={"file:///" + sanitizedImagePath}
alt="Original" alt="Original"
onMouseMove={handleMouseMove} onMouseMove={handleMouseMove}
style={{ style={{
@ -870,7 +877,7 @@ const Home = () => {
</p> </p>
<img <img
/* USE REGEX TO GET THE FILENAME AND ENCODE IT INTO PROPER FORM IN ORDER TO AVOID ERRORS DUE TO SPECIAL CHARACTERS */ /* USE REGEX TO GET THE FILENAME AND ENCODE IT INTO PROPER FORM IN ORDER TO AVOID ERRORS DUE TO SPECIAL CHARACTERS */
src={"file:///" + upscaledImagePath} src={"file:///" + sanitizedUpscaledImagePath}
alt="Upscayl" alt="Upscayl"
style={{ style={{
objectFit: "contain", objectFit: "contain",