1
0
mirror of https://github.com/upscayl/upscayl.git synced 2025-02-19 12:15:47 +01:00
upscayl/renderer/pages/index.tsx

334 lines
11 KiB
TypeScript
Raw Normal View History

2023-09-03 14:46:48 +05:30
"use client";
2024-09-24 20:06:23 +05:30
import { useState, useEffect } from "react";
2024-10-04 14:07:54 +05:30
import { ELECTRON_COMMANDS } from "@common/electron-commands";
2024-09-24 20:21:20 +05:30
import { useAtom, useAtomValue, useSetAtom } from "jotai";
2024-09-25 07:48:58 +05:30
import { modelsListAtom } from "../atoms/models-list-atom";
2023-09-03 14:46:48 +05:30
import {
batchModeAtom,
2024-04-09 23:41:24 +05:30
savedOutputPathAtom,
2023-11-10 17:11:35 +05:30
progressAtom,
2024-02-14 12:02:52 +05:30
rememberOutputFolderAtom,
2024-09-25 07:48:58 +05:30
} from "../atoms/user-settings-atom";
import useLogger from "../components/hooks/use-logger";
2024-09-25 07:48:58 +05:30
import { newsAtom, showNewsModalAtom } from "@/atoms/news-atom";
2024-04-21 19:34:59 +05:30
import { useToast } from "@/components/ui/use-toast";
import { ToastAction } from "@/components/ui/toast";
2024-09-25 07:48:58 +05:30
import UpscaylSVGLogo from "@/components/icons/upscayl-logo-svg";
import { translationAtom } from "@/atoms/translations-atom";
2024-09-24 20:05:33 +05:30
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 { VALID_IMAGE_FORMATS } from "@/lib/valid-formats";
2024-09-24 20:21:20 +05:30
import { initCustomModels } from "@/components/hooks/use-custom-models";
2023-03-31 16:03:48 +05:30
2022-11-12 02:09:28 +05:30
const Home = () => {
const t = useAtomValue(translationAtom);
const logit = useLogger();
2024-09-24 20:05:33 +05:30
const { toast } = useToast();
2024-09-24 20:21:20 +05:30
initCustomModels();
const [isLoading, setIsLoading] = useState(true);
2023-11-23 14:23:09 +05:30
const [imagePath, setImagePath] = useState("");
2024-09-24 20:21:20 +05:30
const [upscaledImagePath, setUpscaledImagePath] = useState("");
2022-12-24 12:47:54 +05:30
const [dimensions, setDimensions] = useState({
width: null,
height: null,
});
2024-09-24 20:21:20 +05:30
const setOutputPath = useSetAtom(savedOutputPathAtom);
const rememberOutputFolder = useAtomValue(rememberOutputFolderAtom);
const batchMode = useAtomValue(batchModeAtom);
2024-09-24 20:05:33 +05:30
const [batchFolderPath, setBatchFolderPath] = useState("");
const [upscaledBatchFolderPath, setUpscaledBatchFolderPath] = useState("");
2024-09-24 20:21:20 +05:30
const setProgress = useSetAtom(progressAtom);
2024-09-24 20:05:33 +05:30
const [doubleUpscaylCounter, setDoubleUpscaylCounter] = useState(0);
2024-09-24 20:21:20 +05:30
2023-04-09 11:18:53 +05:30
const [modelOptions, setModelOptions] = useAtom(modelsListAtom);
2024-09-24 20:21:20 +05:30
2023-11-23 11:28:29 +05:30
const [news, setNews] = useAtom(newsAtom);
2023-11-26 13:34:03 +05:30
const [showNewsModal, setShowNewsModal] = useAtom(showNewsModalAtom);
2024-09-24 20:05:33 +05:30
const selectImageHandler = async () => {
resetImagePaths();
2024-10-04 14:07:54 +05:30
const path = await window.electron.invoke(ELECTRON_COMMANDS.SELECT_FILE);
2024-09-24 20:05:33 +05:30
if (path === null) return;
logit("🖼 Selected Image Path: ", path);
setImagePath(path);
2024-10-04 14:07:54 +05:30
const dirname = getDirectoryFromPath(path);
2024-09-24 20:05:33 +05:30
logit("📁 Selected Image Directory: ", dirname);
if (!FEATURE_FLAGS.APP_STORE_BUILD) {
if (!rememberOutputFolder) {
setOutputPath(dirname);
}
}
validateImagePath(path);
};
2024-09-24 20:21:20 +05:30
2024-09-24 20:05:33 +05:30
const selectFolderHandler = async () => {
resetImagePaths();
2024-10-04 14:07:54 +05:30
const path = await window.electron.invoke(ELECTRON_COMMANDS.SELECT_FOLDER);
2024-09-24 20:05:33 +05:30
if (path !== null) {
logit("🖼 Selected Folder Path: ", path);
setBatchFolderPath(path);
if (!rememberOutputFolder) {
setOutputPath(path);
}
} else {
logit("🚫 Folder selection cancelled");
setBatchFolderPath("");
if (!rememberOutputFolder) {
setOutputPath("");
}
2024-09-22 07:06:13 +05:30
}
2024-01-23 14:14:32 +05:30
};
2023-11-23 14:23:09 +05:30
2024-09-24 20:21:20 +05:30
const validateImagePath = (path: string) => {
if (path.length > 0) {
logit("🖼 imagePath: ", path);
2024-10-04 14:34:11 +05:30
const extension = path.split(".").pop().toLowerCase();
2024-09-24 20:21:20 +05:30
logit("🔤 Extension: ", extension);
2024-10-04 14:34:11 +05:30
if (!VALID_IMAGE_FORMATS.includes(extension)) {
2024-09-24 20:21:20 +05:30
toast({
title: t("ERRORS.INVALID_IMAGE_ERROR.TITLE"),
description: t("ERRORS.INVALID_IMAGE_ERROR.DESCRIPTION"),
});
resetImagePaths();
}
} else {
resetImagePaths();
}
};
2023-11-23 14:55:55 +05:30
// ELECTRON EVENT LISTENERS
2023-11-23 14:23:09 +05:30
useEffect(() => {
2023-04-08 12:23:32 +05:30
const handleErrors = (data: string) => {
2024-04-21 19:34:59 +05:30
if (data.includes("Invalid GPU")) {
toast({
title: t("ERRORS.GPU_ERROR.TITLE"),
description: t("ERRORS.GPU_ERROR.DESCRIPTION", { data }),
2024-04-21 19:34:59 +05:30
action: (
2024-04-22 13:25:44 +05:30
<div className="flex flex-col gap-2">
<ToastAction
altText={t("ERRORS.COPY_ERROR.TITLE")}
2024-04-22 13:25:44 +05:30
onClick={() => {
navigator.clipboard.writeText(data);
}}
>
{t("ERRORS.COPY_ERROR.TITLE")}
2024-04-22 13:25:44 +05:30
</ToastAction>
2024-04-25 01:58:03 +05:30
<a href="https://docs.upscayl.org/" target="_blank">
<ToastAction altText={t("ERRORS.OPEN_DOCS_TITLE")}>
{t("ERRORS.OPEN_DOCS_BUTTON_TITLE")}
</ToastAction>
2024-04-22 13:25:44 +05:30
</a>
</div>
2024-04-21 19:34:59 +05:30
),
});
2022-11-12 02:09:28 +05:30
resetImagePaths();
2024-04-21 19:34:59 +05:30
} else if (data.includes("write") || data.includes("read")) {
2022-11-12 02:09:28 +05:30
if (batchMode) return;
2024-04-21 19:34:59 +05:30
toast({
title: t("ERRORS.READ_WRITE_ERROR.TITLE"),
description: t("ERRORS.READ_WRITE_ERROR.DESCRIPTION", { data }),
2024-04-21 19:34:59 +05:30
action: (
2024-04-22 13:25:44 +05:30
<div className="flex flex-col gap-2">
<ToastAction
altText="Copy Error"
onClick={() => {
navigator.clipboard.writeText(data);
}}
>
{t("ERRORS.COPY_ERROR.TITLE")}
2024-04-22 13:25:44 +05:30
</ToastAction>
2024-04-25 01:58:03 +05:30
<a href="https://docs.upscayl.org/" target="_blank">
<ToastAction altText={t("ERRORS.OPEN_DOCS_TITLE")}>
{t("ERRORS.OPEN_DOCS_BUTTON_TITLE")}
</ToastAction>
2024-04-22 13:25:44 +05:30
</a>
</div>
2024-04-21 19:34:59 +05:30
),
});
resetImagePaths();
} else if (data.includes("tile size")) {
toast({
title: t("ERRORS.TILE_SIZE_ERROR.TITLE"),
description: t("ERRORS.TILE_SIZE_ERROR.DESCRIPTION", { data }),
2024-04-21 19:34:59 +05:30
});
2022-11-12 02:09:28 +05:30
resetImagePaths();
} else if (data.includes("uncaughtException")) {
2024-04-21 19:34:59 +05:30
toast({
title: t("ERRORS.EXCEPTION_ERROR.TITLE"),
description: t("ERRORS.EXCEPTION_ERROR.DESCRIPTION"),
2024-04-21 19:34:59 +05:30
});
2022-11-12 02:09:28 +05:30
resetImagePaths();
}
};
2023-04-14 16:01:37 +05:30
// LOG
2024-09-24 20:05:33 +05:30
window.electron.on(ELECTRON_COMMANDS.LOG, (_, data: string) => {
2024-04-25 16:13:16 +05:30
logit(`🎒 BACKEND REPORTED: `, data);
2023-04-14 16:01:37 +05:30
});
2023-11-23 14:23:09 +05:30
// SCALING AND CONVERTING
2024-09-24 20:05:33 +05:30
window.electron.on(
ELECTRON_COMMANDS.SCALING_AND_CONVERTING,
(_, data: string) => {
setProgress(t("APP.PROGRESS.PROCESSING_TITLE"));
},
);
2023-11-23 14:23:09 +05:30
// UPSCAYL ERROR
2024-09-24 20:05:33 +05:30
window.electron.on(ELECTRON_COMMANDS.UPSCAYL_ERROR, (_, data: string) => {
2024-04-21 19:34:59 +05:30
toast({
title: t("ERRORS.GENERIC_ERROR.TITLE"),
2024-04-21 19:34:59 +05:30
description: data,
});
2023-09-09 16:33:16 +05:30
resetImagePaths();
});
2022-12-16 21:50:46 +05:30
// UPSCAYL PROGRESS
2024-09-24 20:05:33 +05:30
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);
},
);
2022-12-16 21:50:46 +05:30
// FOLDER UPSCAYL PROGRESS
2024-09-24 20:05:33 +05:30
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);
},
);
2022-12-16 21:50:46 +05:30
// DOUBLE UPSCAYL PROGRESS
2024-09-24 20:05:33 +05:30
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);
2022-12-02 19:51:42 +05:30
}
2024-09-24 20:05:33 +05:30
handleErrors(data);
logit(`🚧 DOUBLE_UPSCAYL_PROGRESS: `, data);
},
);
2022-12-16 21:50:46 +05:30
// UPSCAYL DONE
2024-09-24 20:05:33 +05:30
window.electron.on(ELECTRON_COMMANDS.UPSCAYL_DONE, (_, data: string) => {
2022-11-12 02:09:28 +05:30
setProgress("");
2023-09-13 21:45:42 +05:30
setUpscaledImagePath(data);
2023-07-22 18:30:46 +05:30
logit("upscaledImagePath: ", data);
logit(`💯 UPSCAYL_DONE: `, data);
2022-11-12 02:09:28 +05:30
});
2022-12-16 21:50:46 +05:30
// FOLDER UPSCAYL DONE
2024-09-24 20:05:33 +05:30
window.electron.on(
ELECTRON_COMMANDS.FOLDER_UPSCAYL_DONE,
(_, data: string) => {
setProgress("");
setUpscaledBatchFolderPath(data);
logit(`💯 FOLDER_UPSCAYL_DONE: `, data);
},
);
2022-12-16 21:50:46 +05:30
// DOUBLE UPSCAYL DONE
2024-09-24 20:05:33 +05:30
window.electron.on(
ELECTRON_COMMANDS.DOUBLE_UPSCAYL_DONE,
(_, data: string) => {
setProgress("");
setTimeout(() => setUpscaledImagePath(data), 500);
setDoubleUpscaylCounter(0);
logit(`💯 DOUBLE_UPSCAYL_DONE: `, data);
},
);
2023-04-09 11:18:53 +05:30
// CUSTOM FOLDER LISTENER
2024-09-24 20:05:33 +05:30
window.electron.on(
ELECTRON_COMMANDS.CUSTOM_MODEL_FILES_LIST,
(_, data: string[]) => {
logit(`📜 CUSTOM_MODEL_FILES_LIST: `, data);
const newModelOptions = data.map((model) => {
return {
value: model,
label: model,
};
});
// Add newModelsList to modelOptions and remove duplicates
2024-10-04 14:09:29 +05:30
const modelMap = new Map();
[...modelOptions, ...newModelOptions].forEach((model) => {
modelMap.set(model.value, model);
});
const uniqueModelOptions = Array.from(modelMap.values());
2024-09-24 20:05:33 +05:30
setModelOptions(uniqueModelOptions);
},
);
2023-04-09 11:18:53 +05:30
}, []);
2023-11-23 14:23:09 +05:30
// LOADING STATE
2023-10-15 09:27:11 +05:30
useEffect(() => {
setIsLoading(false);
}, []);
// HANDLERS
2022-12-16 21:50:46 +05:30
const resetImagePaths = () => {
logit("🔄 Resetting image paths");
2022-12-24 12:47:54 +05:30
setDimensions({
width: null,
height: null,
});
2022-12-16 21:50:46 +05:30
setProgress("");
2023-11-23 14:23:09 +05:30
setImagePath("");
2022-12-16 21:50:46 +05:30
setUpscaledImagePath("");
setBatchFolderPath("");
setUpscaledBatchFolderPath("");
};
2023-10-15 09:27:11 +05:30
if (isLoading) {
2023-08-30 10:24:16 +05:30
return (
<UpscaylSVGLogo className="absolute left-1/2 top-1/2 w-36 -translate-x-1/2 -translate-y-1/2 animate-pulse" />
2023-08-30 10:24:16 +05:30
);
}
2022-11-12 02:09:28 +05:30
return (
2022-11-12 03:02:24 +05:30
<div className="flex h-screen w-screen flex-row overflow-hidden bg-base-300">
2024-09-24 20:05:33 +05:30
<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}
/>
2022-11-12 02:09:28 +05:30
</div>
);
};
export default Home;