1
0
mirror of https://github.com/upscayl/upscayl.git synced 2024-12-13 16:21:08 +01:00
upscayl/renderer/components/SettingsTab.tsx

317 lines
9.8 KiB
TypeScript
Raw Normal View History

2023-03-18 18:08:50 +01:00
import React, { useEffect, useState } from "react";
import { themeChange } from "theme-change";
2023-04-09 05:53:01 +02:00
import commands from "../../electron/commands";
2023-04-09 07:16:15 +02:00
import { useAtom } from "jotai";
2023-04-28 14:47:51 +02:00
import { customModelsPathAtom, scaleAtom } from "../atoms/userSettingsAtom";
import { modelsListAtom } from "../atoms/modelsListAtom";
2023-03-18 18:08:50 +01:00
interface IProps {
batchMode: boolean;
setModel: React.Dispatch<React.SetStateAction<string>>;
saveImageAs: string;
setSaveImageAs: React.Dispatch<React.SetStateAction<string>>;
gpuId: string;
setGpuId: React.Dispatch<React.SetStateAction<string>>;
2023-04-08 08:53:32 +02:00
logData: string[];
2023-03-18 18:08:50 +01:00
}
function SettingsTab({
batchMode,
setModel,
gpuId,
setGpuId,
saveImageAs,
setSaveImageAs,
2023-04-08 08:53:32 +02:00
logData,
2023-03-18 18:08:50 +01:00
}: IProps) {
2023-04-09 07:16:15 +02:00
// STATES
2023-03-18 18:08:50 +01:00
const [currentModel, setCurrentModel] = useState<{
label: string;
value: string;
}>({
label: null,
value: null,
});
2023-04-08 08:53:32 +02:00
const [isCopied, setIsCopied] = useState(false);
2023-04-09 07:16:15 +02:00
const [customModelsPath, setCustomModelsPath] = useAtom(customModelsPathAtom);
const [modelOptions, setModelOptions] = useAtom(modelsListAtom);
2023-04-12 15:31:07 +02:00
const [scale, setScale] = useAtom(scaleAtom);
2023-04-28 14:47:51 +02:00
const [rememberOutputFolder, setRememberOutputFolder] = useState(false);
2023-04-28 04:00:59 +02:00
2023-03-18 18:08:50 +01:00
useEffect(() => {
themeChange(false);
if (!localStorage.getItem("saveImageAs")) {
localStorage.setItem("saveImageAs", "png");
} else {
const currentlySavedImageFormat = localStorage.getItem("saveImageAs");
setSaveImageAs(currentlySavedImageFormat);
}
if (!localStorage.getItem("model")) {
setCurrentModel(modelOptions[0]);
setModel(modelOptions[0].value);
localStorage.setItem("model", JSON.stringify(modelOptions[0]));
} else {
const currentlySavedModel = JSON.parse(
localStorage.getItem("model")
2023-04-28 14:47:51 +02:00
) as typeof modelOptions[0];
2023-03-18 18:08:50 +01:00
setCurrentModel(currentlySavedModel);
setModel(currentlySavedModel.value);
}
if (!localStorage.getItem("gpuId")) {
localStorage.setItem("gpuId", "");
} else {
const currentlySavedGpuId = localStorage.getItem("gpuId");
setGpuId(currentlySavedGpuId);
}
2023-04-28 14:47:51 +02:00
if (!localStorage.getItem("rememberOutputFolder")) {
localStorage.setItem("rememberOutputFolder", "false");
} else {
const currentlySavedRememberOutputFolder = localStorage.getItem(
"rememberOutputFolder"
);
console.log(
"🚀 => file: SettingsTab.tsx:80 => currentlySavedRememberOutputFolder:",
currentlySavedRememberOutputFolder
);
setRememberOutputFolder(
currentlySavedRememberOutputFolder === "true" ? true : false
);
}
2023-03-18 18:08:50 +01:00
}, []);
useEffect(() => {
console.log("Current Model: ", currentModel);
}, [currentModel]);
2023-04-09 07:16:15 +02:00
// HANDLERS
2023-03-18 18:08:50 +01:00
const setExportType = (format: string) => {
setSaveImageAs(format);
localStorage.setItem("saveImageAs", format);
};
const handleGpuIdChange = (e) => {
setGpuId(e.target.value);
localStorage.setItem("gpuId", e.target.value);
};
2023-04-08 08:53:32 +02:00
const copyOnClickHandler = () => {
navigator.clipboard.writeText(logData.join("\n"));
setIsCopied(true);
setTimeout(() => {
setIsCopied(false);
}, 2000);
};
2023-03-18 18:08:50 +01:00
const availableThemes = [
{ label: "light", value: "light" },
{ label: "dark", value: "dark" },
{ label: "cupcake", value: "cupcake" },
{ label: "bumblebee", value: "bumblebee" },
{ label: "emerald", value: "emerald" },
{ label: "corporate", value: "corporate" },
{ label: "synthwave", value: "synthwave" },
{ label: "retro", value: "retro" },
{ label: "cyberpunk", value: "cyberpunk" },
{ label: "valentine", value: "valentine" },
{ label: "halloween", value: "halloween" },
{ label: "garden", value: "garden" },
{ label: "forest", value: "forest" },
{ label: "aqua", value: "aqua" },
{ label: "lofi", value: "lofi" },
{ label: "pastel", value: "pastel" },
{ label: "fantasy", value: "fantasy" },
{ label: "wireframe", value: "wireframe" },
{ label: "black", value: "black" },
{ label: "luxury", value: "luxury" },
{ label: "dracula", value: "dracula" },
{ label: "cmyk", value: "cmyk" },
{ label: "autumn", value: "autumn" },
{ label: "business", value: "business" },
{ label: "acid", value: "acid" },
{ label: "lemonade", value: "lemonade" },
{ label: "night", value: "night" },
{ label: "coffee", value: "coffee" },
{ label: "winter", value: "winter" },
];
return (
<div className="animate-step-in animate flex h-screen flex-col gap-7 overflow-y-auto p-5 overflow-x-hidden">
{/* THEME SELECTOR */}
<div className="flex flex-col gap-2">
2023-04-15 05:50:46 +02:00
<p className="text-sm font-medium">UPSCAYL THEME</p>
2023-03-18 18:08:50 +01:00
<select data-choose-theme className="select-primary select">
<option value="dark">Default</option>
{availableThemes.map((theme) => {
return (
<option value={theme.value} key={theme.value}>
{theme.label.toLocaleUpperCase()}
</option>
);
})}
</select>
</div>
<div className="flex flex-col gap-2">
<p className="text-sm font-medium">SAVE OUTPUT FOLDER (PERMANENTLY)</p>
<input
type="checkbox"
className="toggle-primary toggle"
2023-04-28 14:47:51 +02:00
checked={rememberOutputFolder}
2023-04-28 04:00:59 +02:00
onClick={() => {
2023-04-28 14:47:51 +02:00
setRememberOutputFolder((oldValue) => {
if (oldValue === true) {
localStorage.removeItem("lastOutputFolderPath");
}
return !oldValue;
});
localStorage.setItem(
"rememberOutputFolder",
JSON.stringify(!rememberOutputFolder)
);
2023-04-28 04:00:59 +02:00
}}
/>
</div>
2023-03-18 18:08:50 +01:00
{/* GPU ID INPUT */}
<div className="flex flex-col gap-2">
2023-04-15 05:50:46 +02:00
<p className="text-sm font-medium">GPU ID</p>
2023-03-18 18:08:50 +01:00
<input
type="text"
placeholder="Type here"
className="input-bordered input w-full max-w-xs"
value={gpuId}
onChange={handleGpuIdChange}
/>
</div>
2023-04-09 05:53:01 +02:00
{/* GPU ID INPUT */}
<div className="flex flex-col items-start gap-2">
2023-04-15 05:50:46 +02:00
<p className="text-sm font-medium">ADD CUSTOM MODELS</p>
2023-04-09 07:16:15 +02:00
<p className="text-sm text-base-content/60">{customModelsPath}</p>
2023-04-09 05:53:01 +02:00
<button
className="btn-primary btn"
onClick={async () => {
2023-04-09 07:16:15 +02:00
const customModelPath = await window.electron.invoke(
2023-04-09 05:53:01 +02:00
commands.SELECT_CUSTOM_MODEL_FOLDER
);
2023-04-09 07:16:15 +02:00
if (customModelPath !== null) {
setCustomModelsPath(customModelPath);
2023-04-09 07:48:53 +02:00
window.electron.send(commands.GET_MODELS_LIST, customModelPath);
2023-04-09 07:16:15 +02:00
}
2023-04-28 04:00:59 +02:00
}}>
2023-04-09 05:53:01 +02:00
Select Folder
</button>
</div>
{/* IMAGE FORMAT BUTTONS */}
<div className="flex flex-col gap-2">
<div className="flex flex-row gap-1">
<p className="text-sm font-medium">SAVE IMAGE AS</p>
<p className="badge-primary badge text-[10px] font-medium">
EXPERIMENTAL
</p>
</div>
<div className="flex flex-col gap-2">
{batchMode && (
<p className="text-xs text-base-content/70">
Only PNG is supported in Batch Upscale
</p>
)}
<div className="flex flex-wrap gap-2">
{/* PNG */}
<button
className={`btn-primary btn ${
saveImageAs === "png" && "btn-accent"
}`}
2023-04-28 04:00:59 +02:00
onClick={() => setExportType("png")}>
PNG
</button>
{/* JPG */}
<button
className={`btn-primary btn ${
saveImageAs === "jpg" && "btn-accent"
}`}
2023-04-28 04:00:59 +02:00
onClick={() => setExportType("jpg")}>
JPG
</button>
{/* WEBP */}
<button
className={`btn-primary btn ${
saveImageAs === "webp" && "btn-accent"
}`}
2023-04-28 04:00:59 +02:00
onClick={() => setExportType("webp")}>
WEBP
</button>
</div>
</div>
</div>
{/* IMAGE SCALE */}
2023-04-12 15:31:07 +02:00
<div>
2023-04-15 05:50:46 +02:00
<div className="flex flex-row gap-1">
<p className="text-sm font-medium">IMAGE SCALE</p>
<p className="badge-primary badge text-[10px] font-medium">
2023-04-14 12:31:37 +02:00
EXPERIMENTAL
</p>
</div>
2023-04-12 15:31:07 +02:00
<input
type="range"
min="2"
max="4"
value={scale}
onChange={(e: any) => {
2023-04-14 12:31:37 +02:00
setScale(e.target.value.toString());
2023-04-12 15:31:07 +02:00
}}
step="1"
className="range range-primary mt-2"
/>
<div className="flex w-full justify-between px-2 text-xs font-semibold text-base-content">
<span>2x</span>
<span>3x</span>
<span>4x</span>
</div>
</div>
2023-03-18 18:08:50 +01:00
<div className="relative flex flex-col gap-2">
<button
2023-04-27 20:18:44 +02:00
className="btn-primary btn-xs btn absolute right-2 top-10 z-10"
2023-04-28 04:00:59 +02:00
onClick={copyOnClickHandler}>
2023-04-08 08:53:32 +02:00
{isCopied ? <span>Copied 📋</span> : <span>Copy 📋</span>}
2023-03-18 18:08:50 +01:00
</button>
2023-04-15 05:50:46 +02:00
<p className="text-sm font-medium">LOGS</p>
2023-04-09 05:53:01 +02:00
<code className="rounded-btn relative flex h-52 max-h-52 flex-col gap-3 overflow-y-auto break-all bg-base-200 p-4 text-xs">
2023-04-08 09:11:47 +02:00
{logData.length === 0 && (
<p className="text-base-content/70">No logs to show</p>
)}
2023-04-08 08:53:32 +02:00
{logData.map((logLine) => {
console.log(logData);
return <p className="">{logLine}</p>;
})}
2023-03-18 18:08:50 +01:00
</code>
</div>
{/* DONATE BUTTON */}
<div className="mt-auto flex flex-col items-center justify-center gap-2 text-sm font-medium">
<p>If you like what we do :)</p>
<a href="https://buymeacoffee.com/fossisthefuture" target="_blank">
<button className="btn-primary btn">Donate</button>
</a>
</div>
</div>
);
}
export default SettingsTab;