mirror of
https://github.com/upscayl/upscayl.git
synced 2024-11-28 01:10:52 +01:00
315 lines
10 KiB
TypeScript
315 lines
10 KiB
TypeScript
"use client";
|
|
import { useState, useEffect } from "react";
|
|
import { ELECTRON_COMMANDS } from "@common/electron-commands";
|
|
import { useAtomValue, useSetAtom } from "jotai";
|
|
import { customModelIdsAtom } from "../atoms/models-list-atom";
|
|
import {
|
|
batchModeAtom,
|
|
savedOutputPathAtom,
|
|
progressAtom,
|
|
rememberOutputFolderAtom,
|
|
} from "../atoms/user-settings-atom";
|
|
import useLogger from "../components/hooks/use-logger";
|
|
import { useToast } from "@/components/ui/use-toast";
|
|
import { ToastAction } from "@/components/ui/toast";
|
|
import UpscaylSVGLogo from "@/components/icons/upscayl-logo-svg";
|
|
import { translationAtom } from "@/atoms/translations-atom";
|
|
import Sidebar from "@/components/sidebar";
|
|
import MainContent from "@/components/main-content";
|
|
import getDirectoryFromPath from "@common/get-directory-from-path";
|
|
import { FEATURE_FLAGS } from "@common/feature-flags";
|
|
import { ImageFormat, VALID_IMAGE_FORMATS } from "@/lib/valid-formats";
|
|
import { initCustomModels } from "@/components/hooks/use-custom-models";
|
|
|
|
const Home = () => {
|
|
const t = useAtomValue(translationAtom);
|
|
const logit = useLogger();
|
|
const { toast } = useToast();
|
|
|
|
initCustomModels();
|
|
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [imagePath, setImagePath] = useState("");
|
|
const [upscaledImagePath, setUpscaledImagePath] = useState("");
|
|
const [dimensions, setDimensions] = useState({
|
|
width: null,
|
|
height: null,
|
|
});
|
|
const setOutputPath = useSetAtom(savedOutputPathAtom);
|
|
const rememberOutputFolder = useAtomValue(rememberOutputFolderAtom);
|
|
const batchMode = useAtomValue(batchModeAtom);
|
|
const [batchFolderPath, setBatchFolderPath] = useState("");
|
|
const [upscaledBatchFolderPath, setUpscaledBatchFolderPath] = useState("");
|
|
const setProgress = useSetAtom(progressAtom);
|
|
const [doubleUpscaylCounter, setDoubleUpscaylCounter] = useState(0);
|
|
const setModelIds = useSetAtom(customModelIdsAtom);
|
|
|
|
const selectImageHandler = async () => {
|
|
resetImagePaths();
|
|
const path = await window.electron.invoke(ELECTRON_COMMANDS.SELECT_FILE);
|
|
if (path === null) return;
|
|
logit("🖼 Selected Image Path: ", path);
|
|
setImagePath(path);
|
|
const dirname = getDirectoryFromPath(path);
|
|
logit("📁 Selected Image Directory: ", dirname);
|
|
if (!FEATURE_FLAGS.APP_STORE_BUILD) {
|
|
if (!rememberOutputFolder) {
|
|
setOutputPath(dirname);
|
|
}
|
|
}
|
|
validateImagePath(path);
|
|
};
|
|
|
|
const selectFolderHandler = async () => {
|
|
resetImagePaths();
|
|
const path = await window.electron.invoke(ELECTRON_COMMANDS.SELECT_FOLDER);
|
|
if (path !== null) {
|
|
logit("🖼 Selected Folder Path: ", path);
|
|
setBatchFolderPath(path);
|
|
if (!rememberOutputFolder) {
|
|
setOutputPath(path);
|
|
}
|
|
} else {
|
|
logit("🚫 Folder selection cancelled");
|
|
setBatchFolderPath("");
|
|
if (!rememberOutputFolder) {
|
|
setOutputPath("");
|
|
}
|
|
}
|
|
};
|
|
|
|
const validateImagePath = (path: string) => {
|
|
if (path.length > 0) {
|
|
logit("🖼 imagePath: ", path);
|
|
const extension = path.split(".").pop().toLowerCase() as ImageFormat;
|
|
logit("🔤 Extension: ", extension);
|
|
if (!VALID_IMAGE_FORMATS.includes(extension)) {
|
|
toast({
|
|
title: t("ERRORS.INVALID_IMAGE_ERROR.TITLE"),
|
|
description: t("ERRORS.INVALID_IMAGE_ERROR.DESCRIPTION"),
|
|
});
|
|
resetImagePaths();
|
|
}
|
|
} else {
|
|
resetImagePaths();
|
|
}
|
|
};
|
|
|
|
// ELECTRON EVENT LISTENERS
|
|
useEffect(() => {
|
|
const handleErrors = (data: string) => {
|
|
if (data.includes("Invalid GPU")) {
|
|
toast({
|
|
title: t("ERRORS.GPU_ERROR.TITLE"),
|
|
description: t("ERRORS.GPU_ERROR.DESCRIPTION", { data }),
|
|
action: (
|
|
<div className="flex flex-col gap-2">
|
|
<ToastAction
|
|
altText={t("ERRORS.COPY_ERROR.TITLE")}
|
|
onClick={() => {
|
|
navigator.clipboard.writeText(data);
|
|
}}
|
|
>
|
|
{t("ERRORS.COPY_ERROR.TITLE")}
|
|
</ToastAction>
|
|
<a href="https://docs.upscayl.org/" target="_blank">
|
|
<ToastAction altText={t("ERRORS.OPEN_DOCS_TITLE")}>
|
|
{t("ERRORS.OPEN_DOCS_BUTTON_TITLE")}
|
|
</ToastAction>
|
|
</a>
|
|
</div>
|
|
),
|
|
});
|
|
resetImagePaths();
|
|
} else if (data.includes("write") || data.includes("read")) {
|
|
if (batchMode) return;
|
|
toast({
|
|
title: t("ERRORS.READ_WRITE_ERROR.TITLE"),
|
|
description: t("ERRORS.READ_WRITE_ERROR.DESCRIPTION", { data }),
|
|
action: (
|
|
<div className="flex flex-col gap-2">
|
|
<ToastAction
|
|
altText="Copy Error"
|
|
onClick={() => {
|
|
navigator.clipboard.writeText(data);
|
|
}}
|
|
>
|
|
{t("ERRORS.COPY_ERROR.TITLE")}
|
|
</ToastAction>
|
|
<a href="https://docs.upscayl.org/" target="_blank">
|
|
<ToastAction altText={t("ERRORS.OPEN_DOCS_TITLE")}>
|
|
{t("ERRORS.OPEN_DOCS_BUTTON_TITLE")}
|
|
</ToastAction>
|
|
</a>
|
|
</div>
|
|
),
|
|
});
|
|
resetImagePaths();
|
|
} else if (data.includes("tile size")) {
|
|
toast({
|
|
title: t("ERRORS.TILE_SIZE_ERROR.TITLE"),
|
|
description: t("ERRORS.TILE_SIZE_ERROR.DESCRIPTION", { data }),
|
|
});
|
|
resetImagePaths();
|
|
} else if (data.includes("uncaughtException")) {
|
|
toast({
|
|
title: t("ERRORS.EXCEPTION_ERROR.TITLE"),
|
|
description: t("ERRORS.EXCEPTION_ERROR.DESCRIPTION"),
|
|
});
|
|
resetImagePaths();
|
|
}
|
|
};
|
|
// LOG
|
|
window.electron.on(ELECTRON_COMMANDS.LOG, (_, data: string) => {
|
|
logit(`🎒 BACKEND REPORTED: `, data);
|
|
});
|
|
// SCALING AND CONVERTING
|
|
window.electron.on(
|
|
ELECTRON_COMMANDS.SCALING_AND_CONVERTING,
|
|
(_, data: string) => {
|
|
setProgress(t("APP.PROGRESS.PROCESSING_TITLE"));
|
|
},
|
|
);
|
|
// UPSCAYL ERROR
|
|
window.electron.on(ELECTRON_COMMANDS.UPSCAYL_ERROR, (_, data: string) => {
|
|
toast({
|
|
title: t("ERRORS.GENERIC_ERROR.TITLE"),
|
|
description: data,
|
|
});
|
|
resetImagePaths();
|
|
});
|
|
// UPSCAYL PROGRESS
|
|
window.electron.on(
|
|
ELECTRON_COMMANDS.UPSCAYL_PROGRESS,
|
|
(_, data: string) => {
|
|
if (data.length > 0 && data.length < 10) {
|
|
setProgress(data);
|
|
} else if (data.includes("converting")) {
|
|
setProgress(t("APP.PROGRESS.SCALING_CONVERTING_TITLE"));
|
|
} else if (data.includes("Successful")) {
|
|
setProgress(t("APP.PROGRESS.SUCCESS_TITLE"));
|
|
}
|
|
handleErrors(data);
|
|
logit(`🚧 UPSCAYL_PROGRESS: `, data);
|
|
},
|
|
);
|
|
// FOLDER UPSCAYL PROGRESS
|
|
window.electron.on(
|
|
ELECTRON_COMMANDS.FOLDER_UPSCAYL_PROGRESS,
|
|
(_, data: string) => {
|
|
if (data.includes("Successful")) {
|
|
setProgress(t("APP.PROGRESS.SUCCESS_TITLE"));
|
|
}
|
|
if (data.length > 0 && data.length < 10) {
|
|
setProgress(data);
|
|
}
|
|
handleErrors(data);
|
|
logit(`🚧 FOLDER_UPSCAYL_PROGRESS: `, data);
|
|
},
|
|
);
|
|
// DOUBLE UPSCAYL PROGRESS
|
|
window.electron.on(
|
|
ELECTRON_COMMANDS.DOUBLE_UPSCAYL_PROGRESS,
|
|
(_, data: string) => {
|
|
if (data.length > 0 && data.length < 10) {
|
|
if (data === "0.00%") {
|
|
setDoubleUpscaylCounter(doubleUpscaylCounter + 1);
|
|
}
|
|
setProgress(data);
|
|
}
|
|
handleErrors(data);
|
|
logit(`🚧 DOUBLE_UPSCAYL_PROGRESS: `, data);
|
|
},
|
|
);
|
|
// UPSCAYL DONE
|
|
window.electron.on(ELECTRON_COMMANDS.UPSCAYL_DONE, (_, data: string) => {
|
|
setProgress("");
|
|
setUpscaledImagePath(data);
|
|
logit("upscaledImagePath: ", data);
|
|
logit(`💯 UPSCAYL_DONE: `, data);
|
|
});
|
|
// FOLDER UPSCAYL DONE
|
|
window.electron.on(
|
|
ELECTRON_COMMANDS.FOLDER_UPSCAYL_DONE,
|
|
(_, data: string) => {
|
|
setProgress("");
|
|
setUpscaledBatchFolderPath(data);
|
|
logit(`💯 FOLDER_UPSCAYL_DONE: `, data);
|
|
},
|
|
);
|
|
// DOUBLE UPSCAYL DONE
|
|
window.electron.on(
|
|
ELECTRON_COMMANDS.DOUBLE_UPSCAYL_DONE,
|
|
(_, data: string) => {
|
|
setProgress("");
|
|
setTimeout(() => setUpscaledImagePath(data), 500);
|
|
setDoubleUpscaylCounter(0);
|
|
logit(`💯 DOUBLE_UPSCAYL_DONE: `, data);
|
|
},
|
|
);
|
|
// CUSTOM FOLDER LISTENER
|
|
window.electron.on(
|
|
ELECTRON_COMMANDS.CUSTOM_MODEL_FILES_LIST,
|
|
(_, data: string[]) => {
|
|
logit(`📜 CUSTOM_MODEL_FILES_LIST: `, data);
|
|
console.log("🚀 => data:", data);
|
|
setModelIds(data);
|
|
},
|
|
);
|
|
}, []);
|
|
|
|
// LOADING STATE
|
|
useEffect(() => {
|
|
setIsLoading(false);
|
|
}, []);
|
|
|
|
// HANDLERS
|
|
const resetImagePaths = () => {
|
|
logit("🔄 Resetting image paths");
|
|
setDimensions({
|
|
width: null,
|
|
height: null,
|
|
});
|
|
setProgress("");
|
|
setImagePath("");
|
|
setUpscaledImagePath("");
|
|
setBatchFolderPath("");
|
|
setUpscaledBatchFolderPath("");
|
|
};
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<UpscaylSVGLogo className="absolute left-1/2 top-1/2 w-36 -translate-x-1/2 -translate-y-1/2 animate-pulse" />
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="flex h-screen w-screen flex-row overflow-hidden bg-base-300">
|
|
<Sidebar
|
|
imagePath={imagePath}
|
|
dimensions={dimensions}
|
|
setUpscaledImagePath={setUpscaledImagePath}
|
|
batchFolderPath={batchFolderPath}
|
|
setUpscaledBatchFolderPath={setUpscaledBatchFolderPath}
|
|
selectImageHandler={selectImageHandler}
|
|
selectFolderHandler={selectFolderHandler}
|
|
/>
|
|
<MainContent
|
|
imagePath={imagePath}
|
|
resetImagePaths={resetImagePaths}
|
|
upscaledBatchFolderPath={upscaledBatchFolderPath}
|
|
setImagePath={setImagePath}
|
|
validateImagePath={validateImagePath}
|
|
selectFolderHandler={selectFolderHandler}
|
|
selectImageHandler={selectImageHandler}
|
|
batchFolderPath={batchFolderPath}
|
|
upscaledImagePath={upscaledImagePath}
|
|
doubleUpscaylCounter={doubleUpscaylCounter}
|
|
setDimensions={setDimensions}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Home;
|