1
0
mirror of https://github.com/upscayl/upscayl.git synced 2024-09-24 03:18:28 +02:00
This commit is contained in:
Nayam Amarshe 2024-01-23 14:14:32 +05:30
parent 602cb72fdb
commit fad4560c12
6 changed files with 1531 additions and 7206 deletions

8439
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -210,9 +210,9 @@
"@types/react-dom": "^18.0.11",
"autoprefixer": "^10.4.16",
"cross-env": "^7.0.3",
"daisyui": "^3.9.3",
"electron": "^27.0.2",
"electron-builder": "^24.6.4",
"daisyui": "^3.9.4",
"electron": "^27.2.4",
"electron-builder": "^24.9.1",
"next": "^13.5.6",
"postcss": "^8.4.31",
"prettier": "^3.0.0",

View File

@ -33,3 +33,10 @@ export const turnOffNotificationsAtom = atomWithStorage(
"turnOffNotifications",
false
);
export const viewTypeAtom = atomWithStorage<"slider" | "lens">(
"viewType",
"lens"
);
export const lensSizeAtom = atomWithStorage<number>("lensSize", 100);

View File

@ -1,5 +1,7 @@
import { lensSizeAtom, viewTypeAtom } from "@/atoms/userSettingsAtom";
import SidebarClosed from "@/components/icons/SidebarClosed";
import SidebarOpened from "@/components/icons/SidebarOpened";
import { useAtom } from "jotai";
import React, { useEffect, useState } from "react";
const ImageOptions = ({
@ -14,6 +16,8 @@ const ImageOptions = ({
hideZoomOptions?: boolean;
}) => {
const [openSidebar, setOpenSidebar] = useState(false);
const [viewType, setViewType] = useAtom(viewTypeAtom);
const [lensSize, setLensSize] = useAtom(lensSizeAtom);
useEffect(() => {
if (!localStorage.getItem("zoomAmount")) {
@ -24,13 +28,11 @@ const ImageOptions = ({
}, []);
return (
<div className="">
{/* <div
className={`bg-base-100 p-4 rounded-btn rounded-r-none fixed top-1/2 right-0 z-50 shadow-xl shadow-black group flex items-center gap-2`}
onClick={() => setOpenSidebar(!openSidebar)}>
<Sidebar className="text-white text-xl" />
</div> */}
<div
onDoubleClick={(e) => {
e.stopPropagation();
}}
className="w-full h-full absolute">
<div
className={`transition-all duration-500 bg-base-100 text-base-content h-screen w-[28rem] fixed right-0 top-0 z-50 shadow-xl shadow-black ${
openSidebar ? "right-0" : "-right-full translate-x-full"
@ -46,65 +48,43 @@ const ImageOptions = ({
<SidebarClosed className="text-white text-xl" />
)}
</div>
<div className="flex flex-col justify-center gap-5 overflow-auto p-5">
<button className="btn-primary btn" onClick={resetImagePaths}>
Reset Image
</button>
{!hideZoomOptions && (
<div className="flex flex-row items-center gap-2">
<p className="w-20">Zoom:</p>
<button
className={`btn-primary btn ${
zoomAmount === "100%" ? "btn-secondary" : "btn-primary"
}`}
onClick={() => {
setZoomAmount("100%");
localStorage.setItem("zoomAmount", "100%");
}}>
100%
</button>
<button
className={`btn-primary btn ${
zoomAmount === "125%" ? "btn-secondary" : "btn-primary"
}`}
onClick={() => {
setZoomAmount("125%");
localStorage.setItem("zoomAmount", "125%");
}}>
125%
</button>
<button
className={`btn-primary btn ${
zoomAmount === "150%" ? "btn-secondary" : "btn-primary"
}`}
onClick={() => {
setZoomAmount("150%");
localStorage.setItem("zoomAmount", "150%");
}}>
150%
</button>
<button
className={`btn-primary btn ${
zoomAmount === "175%" ? "btn-secondary" : "btn-primary"
}`}
onClick={() => {
setZoomAmount("175%");
localStorage.setItem("zoomAmount", "175%");
}}>
175%
</button>
<button
className={`btn-primary btn ${
zoomAmount === "200%" ? "btn-secondary" : "btn-primary"
}`}
onClick={() => {
setZoomAmount("200%");
localStorage.setItem("zoomAmount", "200%");
}}>
200%
</button>
<div className="flex flex-col gap-2">
<p className="font-medium text-sm">Zoom Amount ({zoomAmount}%)</p>
<input
type="range"
min="100"
max="990"
step={10}
className="range range-md"
value={parseInt(zoomAmount)}
onChange={(e) => {
setZoomAmount(e.target.value);
localStorage.setItem("zoomAmount", e.target.value);
}}
/>
</div>
)}
<div className="flex flex-col gap-2">
<p className="font-medium text-sm">Lens Size ({lensSize / 10})</p>
<input
type="range"
min="20"
max="400"
step={10}
className="range range-md"
value={lensSize}
onChange={(e) => {
setLensSize(parseInt(e.target.value));
}}
/>
</div>
</div>
</div>
</div>

View File

@ -1,5 +1,5 @@
"use client";
import { useState, useEffect, useCallback } from "react";
import { useState, useEffect, useCallback, useRef } from "react";
import COMMAND from "../../common/commands";
import { ReactCompareSlider } from "react-compare-slider";
import Header from "../components/Header";
@ -15,6 +15,7 @@ import { logAtom } from "../atoms/logAtom";
import { modelsListAtom } from "../atoms/modelsListAtom";
import {
batchModeAtom,
lensSizeAtom,
compressionAtom,
dontShowCloudModalAtom,
noImageProcessingAtom,
@ -22,6 +23,7 @@ import {
overwriteAtom,
progressAtom,
scaleAtom,
viewTypeAtom,
} from "../atoms/userSettingsAtom";
import useLog from "../components/hooks/useLog";
import { UpscaylCloudModal } from "../components/UpscaylCloudModal";
@ -51,7 +53,7 @@ const Home = () => {
const [doubleUpscaylCounter, setDoubleUpscaylCounter] = useState(0);
const [gpuId, setGpuId] = useState("");
const [saveImageAs, setSaveImageAs] = useState("png");
const [zoomAmount, setZoomAmount] = useState("100%");
const [zoomAmount, setZoomAmount] = useState("100");
const [backgroundPosition, setBackgroundPosition] = useState("0% 0%");
const [dimensions, setDimensions] = useState({
width: null,
@ -61,6 +63,8 @@ const Home = () => {
const [isLoading, setIsLoading] = useState(true);
const [showCloudModal, setShowCloudModal] = useState(false);
const [cursorPosition, setCursorPosition] = useState({ x: 0, y: 0 });
// ATOMIC STATES
const [outputPath, setOutputPath] = useAtom(outputPathAtom);
const [compression, setCompression] = useAtom(compressionAtom);
@ -75,10 +79,22 @@ const Home = () => {
const noImageProcessing = useAtomValue(noImageProcessingAtom);
const [news, setNews] = useAtom(newsAtom);
const [showNewsModal, setShowNewsModal] = useAtom(showNewsModalAtom);
const viewType = useAtomValue(viewTypeAtom);
const lensSize = useAtomValue(lensSizeAtom);
const { logit } = useLog();
// * EFFECTS
const handleMouseMoveCompare = (e: React.MouseEvent) => {
const { left, top, height, width } =
e.currentTarget.getBoundingClientRect();
const x = e.clientX - left;
const y = e.clientY - top;
setCursorPosition({ x, y });
const xZoom = ((e.pageX - left) / width) * 100;
const yZoom = ((e.pageY - top) / height) * 100;
setBackgroundPosition(`${xZoom}% ${yZoom}%`);
};
// SET CONFIG VARIABLES ON FIRST RUN
useEffect(() => {
// UPSCAYL VERSION
@ -611,7 +627,6 @@ const Home = () => {
stopHandler={stopHandler}
/>
) : null}
{/* DEFAULT PANE INFO */}
{((!batchMode &&
imagePath.length === 0 &&
@ -621,7 +636,6 @@ const Home = () => {
upscaledBatchFolderPath.length === 0)) && (
<RightPaneInfo version={version} batchMode={batchMode} />
)}
{/* SHOW SELECTED IMAGE */}
{!batchMode &&
upscaledImagePath.length === 0 &&
@ -647,7 +661,6 @@ const Home = () => {
/>
</>
)}
{/* BATCH UPSCALE SHOW SELECTED FOLDER */}
{batchMode &&
upscaledBatchFolderPath.length === 0 &&
@ -657,7 +670,6 @@ const Home = () => {
{batchFolderPath}
</p>
)}
{/* BATCH UPSCALE DONE INFO */}
{batchMode && upscaledBatchFolderPath.length > 0 && (
<>
@ -671,59 +683,109 @@ const Home = () => {
</button>
</>
)}
<ImageOptions
zoomAmount={zoomAmount}
setZoomAmount={setZoomAmount}
resetImagePaths={resetImagePaths}
/>
{!batchMode &&
viewType === "lens" &&
upscaledImagePath &&
imagePath && (
<div
className="relative group overflow-hidden h-full w-full"
onMouseMove={handleMouseMoveCompare}>
<img
className={`absolute left-0 top-0 object-contain w-full h-full group-hover:scale-[${
zoomAmount + "%"
}]`}
src={"file:///" + imagePath}
style={{
backgroundPosition: "0% 0%",
transformOrigin: backgroundPosition,
}}
/>
<div
className={`absolute left-0 top-0 bg-white mix-blend-difference w-full h-full group-hover:visible invisible group-hover:scale-[${
zoomAmount + "%"
}]`}
style={{
clipPath: `circle(${
(lensSize + 2) / (parseInt(zoomAmount) / 100)
}px at ${cursorPosition.x}px ${cursorPosition.y}px)`,
backgroundPosition: "0% 0%",
transformOrigin: backgroundPosition,
}}
/>
<img
className={`absolute top-0 object-contain left-0 w-full h-full group-hover:scale-[${
zoomAmount + "%"
}]`}
src={"file:///" + upscaledImagePath}
style={{
clipPath: `circle(${
lensSize / (parseInt(zoomAmount) / 100)
}px at ${cursorPosition.x}px ${cursorPosition.y}px)`,
backgroundPosition: "0% 0%",
transformOrigin: backgroundPosition,
}}
/>
</div>
)}
{/* COMPARISON SLIDER */}
{!batchMode && imagePath.length > 0 && upscaledImagePath.length > 0 && (
<>
<ImageOptions
zoomAmount={zoomAmount}
setZoomAmount={setZoomAmount}
resetImagePaths={resetImagePaths}
/>
<ReactCompareSlider
itemOne={
<>
<p className="absolute bottom-1 left-1 rounded-md bg-black p-1 text-sm font-medium text-white opacity-30">
Original
</p>
{!batchMode &&
viewType === "slider" &&
imagePath.length > 0 &&
upscaledImagePath.length > 0 && (
<>
<ReactCompareSlider
itemOne={
<>
<p className="absolute bottom-1 left-1 rounded-md bg-black p-1 text-sm font-medium text-white opacity-30">
Original
</p>
<img
/* USE REGEX TO GET THE FILENAME AND ENCODE IT INTO PROPER FORM IN ORDER TO AVOID ERRORS DUE TO SPECIAL CHARACTERS */
src={"file:///" + imagePath}
alt="Original"
onMouseMove={handleMouseMove}
style={{
objectFit: "contain",
backgroundPosition: "0% 0%",
transformOrigin: backgroundPosition,
}}
className={`h-full w-full bg-gradient-to-br from-base-300 to-base-100 transition-transform group-hover:scale-[${zoomAmount}]`}
/>
</>
}
itemTwo={
<>
<p className="absolute bottom-1 right-1 rounded-md bg-black p-1 text-sm font-medium text-white opacity-30">
Upscayled
</p>
<img
/* USE REGEX TO GET THE FILENAME AND ENCODE IT INTO PROPER FORM IN ORDER TO AVOID ERRORS DUE TO SPECIAL CHARACTERS */
src={"file:///" + upscaledImagePath}
alt="Upscayl"
style={{
objectFit: "contain",
backgroundPosition: "0% 0%",
transformOrigin: backgroundPosition,
}}
onMouseMove={handleMouseMove}
className={`h-full w-full bg-gradient-to-br from-base-300 to-base-100 transition-transform group-hover:scale-[${zoomAmount}]`}
/>
</>
}
className="group h-screen"
/>
</>
)}
<img
/* USE REGEX TO GET THE FILENAME AND ENCODE IT INTO PROPER FORM IN ORDER TO AVOID ERRORS DUE TO SPECIAL CHARACTERS */
src={"file:///" + imagePath}
alt="Original"
onMouseMove={handleMouseMove}
style={{
objectFit: "contain",
backgroundPosition: "0% 0%",
transformOrigin: backgroundPosition,
}}
className={`h-full w-full bg-gradient-to-br from-base-300 to-base-100 transition-transform group-hover:scale-[${
parseInt(zoomAmount.slice(0, -1)) / 100
}]`}
/>
</>
}
itemTwo={
<>
<p className="absolute bottom-1 right-1 rounded-md bg-black p-1 text-sm font-medium text-white opacity-30">
Upscayled
</p>
<img
/* USE REGEX TO GET THE FILENAME AND ENCODE IT INTO PROPER FORM IN ORDER TO AVOID ERRORS DUE TO SPECIAL CHARACTERS */
src={"file:///" + upscaledImagePath}
alt="Upscayl"
style={{
objectFit: "contain",
backgroundPosition: "0% 0%",
transformOrigin: backgroundPosition,
}}
onMouseMove={handleMouseMove}
className={`h-full w-full bg-gradient-to-br from-base-300 to-base-100 transition-transform group-hover:scale-[${
zoomAmount || "100%"
}%]`}
/>
</>
}
className="group h-screen"
/>
</>
)}
</div>
</div>
);

View File

@ -4,11 +4,10 @@ module.exports = {
"./renderer/components/**/*.{js,ts,jsx,tsx}",
],
safelist: [
"group-hover:scale-[100%]",
"group-hover:scale-[125%]",
"group-hover:scale-[150%]",
"group-hover:scale-[175%]",
"group-hover:scale-[200%]",
...[...Array(99).keys()].flatMap((index) => [
`group-hover:scale-[${index * 10}%]`,
`group-hover:scale-[${index * 10}%]`,
]),
],
theme: {
extend: {