2023-09-03 11:16:48 +02:00
"use client" ;
2024-04-17 18:18:45 +02:00
import { useState , useEffect , useCallback } from "react" ;
2024-01-16 08:33:43 +01:00
import COMMAND from "../../common/commands" ;
2022-12-21 17:24:13 +01:00
import { ReactCompareSlider } from "react-compare-slider" ;
2022-11-11 21:39:28 +01:00
import Header from "../components/Header" ;
import Footer from "../components/Footer" ;
2023-07-22 13:07:53 +02:00
import ProgressBar from "../components/upscayl-tab/view/ProgressBar" ;
import RightPaneInfo from "../components/upscayl-tab/view/RightPaneInfo" ;
import ImageOptions from "../components/upscayl-tab/view/ImageOptions" ;
import LeftPaneImageSteps from "../components/upscayl-tab/config/LeftPaneImageSteps" ;
2023-03-18 18:08:50 +01:00
import Tabs from "../components/Tabs" ;
2023-07-22 13:07:53 +02:00
import SettingsTab from "../components/settings-tab" ;
2023-11-22 16:54:02 +01:00
import { useAtom , useAtomValue } from "jotai" ;
2023-04-08 08:53:32 +02:00
import { logAtom } from "../atoms/logAtom" ;
2023-04-09 07:48:53 +02:00
import { modelsListAtom } from "../atoms/modelsListAtom" ;
2023-09-03 11:16:48 +02:00
import {
batchModeAtom ,
2024-01-23 09:44:32 +01:00
lensSizeAtom ,
2023-11-22 16:57:44 +01:00
compressionAtom ,
2023-09-03 11:16:48 +02:00
dontShowCloudModalAtom ,
2023-11-22 16:54:02 +01:00
noImageProcessingAtom ,
2024-04-09 20:11:24 +02:00
savedOutputPathAtom ,
2024-01-15 10:07:22 +01:00
overwriteAtom ,
2023-11-10 12:41:35 +01:00
progressAtom ,
2023-09-03 11:16:48 +02:00
scaleAtom ,
2024-01-23 09:44:32 +01:00
viewTypeAtom ,
2024-02-14 07:32:52 +01:00
rememberOutputFolderAtom ,
2024-04-17 18:18:45 +02:00
showSidebarAtom ,
2024-04-20 17:44:42 +02:00
customWidthAtom ,
useCustomWidthAtom ,
2023-09-03 11:16:48 +02:00
} from "../atoms/userSettingsAtom" ;
2023-04-30 03:44:47 +02:00
import useLog from "../components/hooks/useLog" ;
2023-08-23 17:05:41 +02:00
import { UpscaylCloudModal } from "../components/UpscaylCloudModal" ;
2023-10-25 13:44:22 +02:00
import { featureFlags } from "@common/feature-flags" ;
2023-11-22 16:54:02 +01:00
import {
BatchUpscaylPayload ,
DoubleUpscaylPayload ,
ImageUpscaylPayload ,
} from "@common/types/types" ;
2023-11-23 10:25:55 +01:00
import { NewsModal } from "@/components/NewsModal" ;
2023-11-26 09:04:03 +01:00
import { newsAtom , showNewsModalAtom } from "@/atoms/newsAtom" ;
import matter from "gray-matter" ;
2024-04-17 18:18:45 +02:00
import { PanelLeftCloseIcon , PanelRightCloseIcon } from "lucide-react" ;
import { cn } from "@/lib/utils" ;
2024-04-21 16:04:59 +02:00
import { useToast } from "@/components/ui/use-toast" ;
import { ToastAction } from "@/components/ui/toast" ;
2023-03-31 12:33:48 +02:00
2022-11-11 21:39:28 +01:00
const Home = ( ) = > {
2023-11-23 09:53:09 +01:00
const allowedFileTypes = [ "png" , "jpg" , "jpeg" , "webp" ] ;
2023-11-22 16:54:02 +01:00
// LOCAL STATES
2023-08-14 12:56:11 +02:00
const [ os , setOs ] = useState < "linux" | "mac" | "win" | undefined > ( undefined ) ;
2023-11-23 09:53:09 +01:00
const [ imagePath , setImagePath ] = useState ( "" ) ;
2023-09-05 17:25:44 +02:00
const [ upscaledImagePath , setUpscaledImagePath ] = useState ( "" ) ;
2022-12-24 08:17:54 +01:00
const [ model , setModel ] = useState ( "realesrgan-x4plus" ) ;
2022-11-11 21:39:28 +01:00
const [ version , setVersion ] = useState ( "" ) ;
const [ batchFolderPath , setBatchFolderPath ] = useState ( "" ) ;
const [ doubleUpscayl , setDoubleUpscayl ] = useState ( false ) ;
2024-01-15 10:07:22 +01:00
const overwrite = useAtomValue ( overwriteAtom ) ;
2023-11-22 16:54:02 +01:00
const [ upscaledBatchFolderPath , setUpscaledBatchFolderPath ] = useState ( "" ) ;
2022-12-02 15:21:42 +01:00
const [ doubleUpscaylCounter , setDoubleUpscaylCounter ] = useState ( 0 ) ;
2022-12-16 17:20:46 +01:00
const [ gpuId , setGpuId ] = useState ( "" ) ;
const [ saveImageAs , setSaveImageAs ] = useState ( "png" ) ;
2024-01-23 09:44:32 +01:00
const [ zoomAmount , setZoomAmount ] = useState ( "100" ) ;
2022-12-21 11:32:45 +01:00
const [ backgroundPosition , setBackgroundPosition ] = useState ( "0% 0%" ) ;
2022-12-24 08:17:54 +01:00
const [ dimensions , setDimensions ] = useState ( {
width : null ,
height : null ,
} ) ;
2023-03-18 18:08:50 +01:00
const [ selectedTab , setSelectedTab ] = useState ( 0 ) ;
2023-11-22 16:54:02 +01:00
const [ isLoading , setIsLoading ] = useState ( true ) ;
const [ showCloudModal , setShowCloudModal ] = useState ( false ) ;
2024-04-17 18:18:45 +02:00
const [ minSize , setMinSize ] = useState ( 22 ) ;
2024-01-23 09:44:32 +01:00
const [ cursorPosition , setCursorPosition ] = useState ( { x : 0 , y : 0 } ) ;
2023-11-22 16:54:02 +01:00
// ATOMIC STATES
2024-04-09 20:11:24 +02:00
const [ outputPath , setOutputPath ] = useAtom ( savedOutputPathAtom ) ;
2023-11-22 16:57:44 +01:00
const [ compression , setCompression ] = useAtom ( compressionAtom ) ;
2023-11-22 16:54:02 +01:00
const [ progress , setProgress ] = useAtom ( progressAtom ) ;
const [ batchMode , setBatchMode ] = useAtom ( batchModeAtom ) ;
2023-04-08 08:53:32 +02:00
const [ logData , setLogData ] = useAtom ( logAtom ) ;
2023-04-09 07:48:53 +02:00
const [ modelOptions , setModelOptions ] = useAtom ( modelsListAtom ) ;
2023-04-14 12:31:37 +02:00
const [ scale ] = useAtom ( scaleAtom ) ;
2023-09-03 11:16:48 +02:00
const [ dontShowCloudModal , setDontShowCloudModal ] = useAtom (
2024-02-07 02:23:19 +01:00
dontShowCloudModalAtom ,
2023-09-03 11:16:48 +02:00
) ;
2023-11-22 16:54:02 +01:00
const noImageProcessing = useAtomValue ( noImageProcessingAtom ) ;
2023-11-23 06:58:29 +01:00
const [ news , setNews ] = useAtom ( newsAtom ) ;
2023-11-26 09:04:03 +01:00
const [ showNewsModal , setShowNewsModal ] = useAtom ( showNewsModalAtom ) ;
2024-01-23 09:44:32 +01:00
const viewType = useAtomValue ( viewTypeAtom ) ;
const lensSize = useAtomValue ( lensSizeAtom ) ;
2024-02-14 07:32:52 +01:00
const rememberOutputFolder = useAtomValue ( rememberOutputFolderAtom ) ;
2024-04-17 18:18:45 +02:00
const [ showSidebar , setShowSidebar ] = useAtom ( showSidebarAtom ) ;
2024-04-20 17:44:42 +02:00
const customWidth = useAtomValue ( customWidthAtom ) ;
const useCustomWidth = useAtomValue ( useCustomWidthAtom ) ;
2023-08-23 17:05:41 +02:00
2023-04-30 03:44:47 +02:00
const { logit } = useLog ( ) ;
2024-04-21 16:04:59 +02:00
const { toast } = useToast ( ) ;
2023-04-30 03:44:47 +02:00
2024-01-23 09:44:32 +01:00
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 } % ` ) ;
} ;
2023-11-23 09:53:09 +01:00
// SET CONFIG VARIABLES ON FIRST RUN
2022-11-11 21:39:28 +01:00
useEffect ( ( ) = > {
2023-11-23 09:53:09 +01:00
// UPSCAYL VERSION
const upscaylVersion = navigator ? . userAgent ? . match (
2024-02-07 02:23:19 +01:00
/Upscayl\/([\d\.]+\d+)/ ,
2023-11-23 09:53:09 +01:00
) [ 1 ] ;
setVersion ( upscaylVersion ) ;
} , [ ] ) ;
2023-11-23 10:25:55 +01:00
// ELECTRON EVENT LISTENERS
2023-11-23 09:53:09 +01:00
useEffect ( ( ) = > {
2023-04-08 08:53:32 +02:00
const handleErrors = ( data : string ) = > {
2024-04-21 16:04:59 +02:00
if ( data . includes ( "Invalid GPU" ) ) {
toast ( {
title : "GPU Error" ,
description : ` GPU error occurred. Please read the wiki for troubleshooting! ${ data } ) ` ,
action : (
< a href = "https://github.com/upscayl/upscayl/wiki/" target = "_blank" >
< ToastAction altText = "Open Wiki" > Troubleshoot < / ToastAction >
< / a >
) ,
} ) ;
2022-11-11 21:39:28 +01:00
resetImagePaths ( ) ;
2024-04-21 16:04:59 +02:00
} else if ( data . includes ( "write" ) || data . includes ( "read" ) ) {
2022-11-11 21:39:28 +01:00
if ( batchMode ) return ;
2024-04-21 16:04:59 +02:00
toast ( {
title : "Read/Write Error" ,
description : ` Make sure that the path is correct and you have proper read/write permissions ( ${ data } ) ` ,
action : (
< a href = "https://github.com/upscayl/upscayl/wiki/" target = "_blank" >
< ToastAction altText = "Open Wiki" > Troubleshoot < / ToastAction >
< / a >
) ,
} ) ;
resetImagePaths ( ) ;
} else if ( data . includes ( "tile size" ) ) {
toast ( {
title : "Error" ,
description : ` The tile size is wrong. Please change the tile size in the settings or set to 0 ( ${ data } ) ` ,
} ) ;
2022-11-11 21:39:28 +01:00
resetImagePaths ( ) ;
} else if ( data . includes ( "uncaughtException" ) ) {
2024-04-21 16:04:59 +02:00
toast ( {
title : "Exception Error" ,
description : ` Upscayl encountered an error. Possibly, the upscayl binary failed to execute the commands properly. Try checking the logs to see if you get any information. You can post an issue on Upscayl's GitHub repository for more help. ` ,
} ) ;
2022-11-11 21:39:28 +01:00
resetImagePaths ( ) ;
}
} ;
2023-11-23 09:53:09 +01:00
// OS
2023-08-14 12:55:30 +02:00
window . electron . on (
2023-09-10 19:42:18 +02:00
COMMAND . OS ,
2023-08-14 12:55:30 +02:00
( _ , data : "linux" | "mac" | "win" | undefined ) = > {
if ( data ) {
setOs ( data ) ;
}
2024-02-07 02:23:19 +01:00
} ,
2023-08-14 12:55:30 +02:00
) ;
2023-04-14 12:31:37 +02:00
// LOG
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . LOG , ( _ , data : string ) = > {
2024-04-21 16:04:59 +02:00
logit ( ` 𝌖 BACKEND REPORTED: ` , data ) ;
2023-04-14 12:31:37 +02:00
} ) ;
2023-11-23 09:53:09 +01:00
// SCALING AND CONVERTING
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . SCALING_AND_CONVERTING , ( _ , data : string ) = > {
2023-09-09 14:18:00 +02:00
setProgress ( "Processing the image..." ) ;
} ) ;
2023-11-23 09:53:09 +01:00
// UPSCAYL ERROR
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . UPSCAYL_ERROR , ( _ , data : string ) = > {
2024-04-21 16:04:59 +02:00
toast ( {
title : "Error" ,
description : data ,
} ) ;
2023-09-09 13:03:16 +02:00
resetImagePaths ( ) ;
} ) ;
2022-12-16 17:20:46 +01:00
// UPSCAYL PROGRESS
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . UPSCAYL_PROGRESS , ( _ , data : string ) = > {
2022-11-11 21:39:28 +01:00
if ( data . length > 0 && data . length < 10 ) {
setProgress ( data ) ;
2023-09-04 17:59:17 +02:00
} else if ( data . includes ( "converting" ) ) {
setProgress ( "Scaling and converting image..." ) ;
2023-10-21 16:14:42 +02:00
} else if ( data . includes ( "Successful" ) ) {
2023-10-21 17:50:59 +02:00
setProgress ( "Upscayl Successful!" ) ;
2022-11-11 21:39:28 +01:00
}
handleErrors ( data ) ;
2023-05-06 07:17:35 +02:00
logit ( ` 🚧 UPSCAYL_PROGRESS: ` , data ) ;
2022-11-11 21:39:28 +01:00
} ) ;
2022-12-16 17:20:46 +01:00
// FOLDER UPSCAYL PROGRESS
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . FOLDER_UPSCAYL_PROGRESS , ( _ , data : string ) = > {
2023-10-21 17:50:59 +02:00
if ( data . includes ( "Successful" ) ) {
setProgress ( "Upscayl Successful!" ) ;
}
2022-11-11 21:39:28 +01:00
if ( data . length > 0 && data . length < 10 ) {
setProgress ( data ) ;
}
handleErrors ( data ) ;
2023-05-06 07:17:35 +02:00
logit ( ` 🚧 FOLDER_UPSCAYL_PROGRESS: ` , data ) ;
2022-11-11 21:39:28 +01:00
} ) ;
2022-12-16 17:20:46 +01:00
// DOUBLE UPSCAYL PROGRESS
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . DOUBLE_UPSCAYL_PROGRESS , ( _ , data : string ) = > {
2022-11-11 21:39:28 +01:00
if ( data . length > 0 && data . length < 10 ) {
2022-12-02 15:21:42 +01:00
if ( data === "0.00%" ) {
setDoubleUpscaylCounter ( doubleUpscaylCounter + 1 ) ;
}
2022-11-11 21:39:28 +01:00
setProgress ( data ) ;
}
handleErrors ( data ) ;
2023-05-06 07:17:35 +02:00
logit ( ` 🚧 DOUBLE_UPSCAYL_PROGRESS: ` , data ) ;
2022-11-11 21:39:28 +01:00
} ) ;
2022-12-16 17:20:46 +01:00
// UPSCAYL DONE
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . UPSCAYL_DONE , ( _ , data : string ) = > {
2022-11-11 21:39:28 +01:00
setProgress ( "" ) ;
2023-09-13 18:15:42 +02:00
setUpscaledImagePath ( data ) ;
2023-07-22 15:00:46 +02:00
logit ( "upscaledImagePath: " , data ) ;
2023-05-06 07:17:35 +02:00
logit ( ` 💯 UPSCAYL_DONE: ` , data ) ;
2022-11-11 21:39:28 +01:00
} ) ;
2022-12-16 17:20:46 +01:00
// FOLDER UPSCAYL DONE
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . FOLDER_UPSCAYL_DONE , ( _ , data : string ) = > {
2022-11-11 21:39:28 +01:00
setProgress ( "" ) ;
setUpscaledBatchFolderPath ( data ) ;
2023-05-06 07:17:35 +02:00
logit ( ` 💯 FOLDER_UPSCAYL_DONE: ` , data ) ;
2022-11-11 21:39:28 +01:00
} ) ;
2022-12-16 17:20:46 +01:00
// DOUBLE UPSCAYL DONE
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . DOUBLE_UPSCAYL_DONE , ( _ , data : string ) = > {
2022-12-02 15:21:42 +01:00
setProgress ( "" ) ;
2023-09-11 05:57:16 +02:00
setTimeout ( ( ) = > setUpscaledImagePath ( data ) , 500 ) ;
2022-12-02 15:21:42 +01:00
setDoubleUpscaylCounter ( 0 ) ;
2023-05-06 07:17:35 +02:00
logit ( ` 💯 DOUBLE_UPSCAYL_DONE: ` , data ) ;
2022-11-11 21:39:28 +01:00
} ) ;
2023-04-09 07:48:53 +02:00
// CUSTOM FOLDER LISTENER
2023-09-10 19:42:18 +02:00
window . electron . on ( COMMAND . 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
const combinedModelOptions = [ . . . modelOptions , . . . newModelOptions ] ;
const uniqueModelOptions = combinedModelOptions . filter (
// Check if any model in the array appears more than once
( model , index , array ) = >
2024-02-07 02:23:19 +01:00
array . findIndex ( ( t ) = > t . value === model . value ) === index ,
2023-09-10 19:42:18 +02:00
) ;
setModelOptions ( uniqueModelOptions ) ;
} ) ;
2023-04-09 07:48:53 +02:00
} , [ ] ) ;
2023-11-23 09:53:09 +01:00
// FETCH CUSTOM MODELS FROM CUSTOM MODELS PATH
2023-04-09 07:48:53 +02:00
useEffect ( ( ) = > {
const customModelsPath = JSON . parse (
2024-02-07 02:23:19 +01:00
localStorage . getItem ( "customModelsPath" ) ,
2023-04-09 07:48:53 +02:00
) ;
if ( customModelsPath !== null ) {
2023-09-10 19:42:18 +02:00
window . electron . send ( COMMAND . GET_MODELS_LIST , customModelsPath ) ;
2023-05-06 07:17:35 +02:00
logit ( "🎯 GET_MODELS_LIST: " , customModelsPath ) ;
2023-04-09 07:48:53 +02:00
}
2022-11-11 21:39:28 +01:00
} , [ ] ) ;
2023-11-23 09:53:09 +01:00
// FETCH NEWS
2023-11-23 06:58:29 +01:00
useEffect ( ( ) = > {
2024-01-15 14:44:44 +01:00
// TODO: ADD AN ABOUT TAB
if ( window && window . navigator . onLine === false ) return ;
2023-12-03 07:36:00 +01:00
try {
fetch ( "https://raw.githubusercontent.com/upscayl/upscayl/main/news.md" , {
cache : "no-cache" ,
2023-11-23 09:53:09 +01:00
} )
2023-12-03 07:36:00 +01:00
. then ( ( res ) = > {
return res . text ( ) ;
} )
. then ( ( result ) = > {
const newsData = result ;
if ( ! newsData ) {
console . log ( "📰 Could not fetch news data" ) ;
return ;
2023-11-26 09:04:03 +01:00
}
2023-12-03 07:36:00 +01:00
const markdownData = matter ( newsData ) ;
if ( ! markdownData ) return ;
2024-01-15 14:49:25 +01:00
if ( markdownData && markdownData . data . dontShow ) {
2023-12-03 07:36:00 +01:00
return ;
}
if (
markdownData &&
news &&
markdownData ? . data ? . version === news ? . data ? . version
) {
console . log ( "📰 News is up to date" ) ;
if ( showNewsModal === false ) {
setShowNewsModal ( false ) ;
}
} else if ( markdownData ) {
setNews ( matter ( newsData ) ) ;
setShowNewsModal ( true ) ;
}
} ) ;
} catch ( error ) {
console . log ( "Could not fetch Upscayl News" ) ;
}
2023-11-26 09:04:03 +01:00
} , [ news ] ) ;
2023-11-23 06:58:29 +01:00
2023-11-23 09:53:09 +01:00
// LOADING STATE
2023-10-15 05:57:11 +02:00
useEffect ( ( ) = > {
setIsLoading ( false ) ;
} , [ ] ) ;
2023-11-23 09:53:09 +01:00
// * HANDLERS
2022-12-16 17:20:46 +01:00
const resetImagePaths = ( ) = > {
2023-05-06 07:17:35 +02:00
logit ( "🔄 Resetting image paths" ) ;
2022-12-24 08:17:54 +01:00
setDimensions ( {
width : null ,
height : null ,
} ) ;
2022-12-16 17:20:46 +01:00
setProgress ( "" ) ;
2023-11-23 09:53:09 +01:00
setImagePath ( "" ) ;
2022-12-16 17:20:46 +01:00
setUpscaledImagePath ( "" ) ;
setBatchFolderPath ( "" ) ;
setUpscaledBatchFolderPath ( "" ) ;
} ;
2023-11-23 09:53:09 +01:00
// UTILS
// CHECK IF IMAGE IS VALID
const validateImagePath = ( path : string ) = > {
if ( path . length > 0 ) {
logit ( "🖼 imagePath: " , path ) ;
const extension = path . toLocaleLowerCase ( ) . split ( "." ) . pop ( ) ;
logit ( "🔤 Extension: " , extension ) ;
if ( ! allowedFileTypes . includes ( extension . toLowerCase ( ) ) ) {
2024-04-21 16:04:59 +02:00
toast ( {
title : "Invalid Image" ,
description :
"Please select an image with a valid extension like PNG, JPG, JPEG, or WEBP." ,
} ) ;
2023-11-23 09:53:09 +01:00
resetImagePaths ( ) ;
}
} else {
resetImagePaths ( ) ;
}
} ;
2022-12-16 17:20:46 +01:00
// HANDLERS
2023-04-08 08:53:32 +02:00
const handleMouseMove = useCallback ( ( e : any ) = > {
2022-12-21 11:32:45 +01:00
const { left , top , width , height } = e . target . getBoundingClientRect ( ) ;
const x = ( ( e . pageX - left ) / width ) * 100 ;
const y = ( ( e . pageY - top ) / height ) * 100 ;
setBackgroundPosition ( ` ${ x } % ${ y } % ` ) ;
2023-04-08 08:53:32 +02:00
} , [ ] ) ;
2022-12-21 11:32:45 +01:00
2022-11-11 21:39:28 +01:00
const selectImageHandler = async ( ) = > {
resetImagePaths ( ) ;
2023-09-10 19:42:18 +02:00
var path = await window . electron . invoke ( COMMAND . SELECT_FILE ) ;
2023-11-23 09:53:09 +01:00
if ( path === null ) return ;
logit ( "🖼 Selected Image Path: " , path ) ;
setImagePath ( path ) ;
var dirname = path . match ( /(.*)[\/\\]/ ) [ 1 ] || "" ;
logit ( "📁 Selected Image Directory: " , dirname ) ;
if ( ! featureFlags . APP_STORE_BUILD ) {
2024-02-14 07:32:52 +01:00
if ( ! rememberOutputFolder ) {
setOutputPath ( dirname ) ;
}
2022-11-11 21:39:28 +01:00
}
2023-11-23 09:53:09 +01:00
validateImagePath ( path ) ;
2022-11-11 21:39:28 +01:00
} ;
const selectFolderHandler = async ( ) = > {
resetImagePaths ( ) ;
2023-09-10 19:42:18 +02:00
var path = await window . electron . invoke ( COMMAND . SELECT_FOLDER ) ;
2023-04-09 07:16:15 +02:00
if ( path !== null ) {
2023-05-06 07:17:35 +02:00
logit ( "🖼 Selected Folder Path: " , path ) ;
2022-11-11 21:39:28 +01:00
setBatchFolderPath ( path ) ;
2024-02-14 07:32:52 +01:00
if ( ! rememberOutputFolder ) {
setOutputPath ( path ) ;
}
2023-05-01 08:34:45 +02:00
} else {
2023-05-06 07:17:35 +02:00
logit ( "🚫 Folder selection cancelled" ) ;
2023-05-01 08:34:45 +02:00
setBatchFolderPath ( "" ) ;
2024-02-14 07:32:52 +01:00
if ( ! rememberOutputFolder ) {
setOutputPath ( "" ) ;
}
2022-11-11 21:39:28 +01:00
}
} ;
2023-04-08 08:53:32 +02:00
const handleModelChange = ( e : any ) = > {
2022-11-11 21:39:28 +01:00
setModel ( e . value ) ;
2023-05-06 07:17:35 +02:00
logit ( "🔀 Model changed: " , e . value ) ;
2022-12-24 09:45:15 +01:00
localStorage . setItem (
"model" ,
2024-02-07 02:23:19 +01:00
JSON . stringify ( { label : e.label , value : e.value } ) ,
2022-12-24 09:45:15 +01:00
) ;
2022-11-11 21:39:28 +01:00
} ;
2022-12-16 17:20:46 +01:00
// DRAG AND DROP HANDLERS
2022-11-11 21:39:28 +01:00
const handleDragEnter = ( e ) = > {
e . preventDefault ( ) ;
console . log ( "drag enter" ) ;
} ;
const handleDragLeave = ( e ) = > {
e . preventDefault ( ) ;
console . log ( "drag leave" ) ;
} ;
const handleDragOver = ( e ) = > {
e . preventDefault ( ) ;
console . log ( "drag over" ) ;
} ;
const openFolderHandler = ( e ) = > {
2023-05-06 07:17:35 +02:00
logit ( "📂 OPEN_FOLDER: " , upscaledBatchFolderPath ) ;
2023-09-10 19:42:18 +02:00
window . electron . send ( COMMAND . OPEN_FOLDER , upscaledBatchFolderPath ) ;
2022-11-11 21:39:28 +01:00
} ;
const handleDrop = ( e ) = > {
e . preventDefault ( ) ;
resetImagePaths ( ) ;
2023-04-20 20:34:49 +02:00
if (
e . dataTransfer . items . length === 0 ||
e . dataTransfer . files . length === 0
) {
2023-05-06 07:17:35 +02:00
logit ( "👎 No valid files dropped" ) ;
2024-04-21 16:04:59 +02:00
toast ( {
title : "Invalid Image" ,
description : "Please drag and drop an image" ,
} ) ;
2023-04-20 20:34:49 +02:00
return ;
}
2022-11-11 21:39:28 +01:00
const type = e . dataTransfer . items [ 0 ] . type ;
const filePath = e . dataTransfer . files [ 0 ] . path ;
const extension = e . dataTransfer . files [ 0 ] . name . split ( "." ) . at ( - 1 ) ;
2023-05-06 07:17:35 +02:00
logit ( "⤵️ Dropped file: " , JSON . stringify ( { type , filePath , extension } ) ) ;
2022-11-11 21:39:28 +01:00
if (
2023-08-14 12:55:30 +02:00
! type . includes ( "image" ) ||
! allowedFileTypes . includes ( extension . toLowerCase ( ) )
2022-11-11 21:39:28 +01:00
) {
2023-05-06 07:17:35 +02:00
logit ( "🚫 Invalid file dropped" ) ;
2024-04-21 16:04:59 +02:00
toast ( {
title : "Invalid Image" ,
description : "Please drag and drop an image" ,
} ) ;
2022-11-11 21:39:28 +01:00
} else {
2023-08-14 12:55:30 +02:00
logit ( "🖼 Setting image path: " , filePath ) ;
2023-11-23 09:53:09 +01:00
setImagePath ( filePath ) ;
2022-11-11 21:39:28 +01:00
var dirname = filePath . match ( /(.*)[\/\\]/ ) [ 1 ] || "" ;
2023-05-06 07:17:35 +02:00
logit ( "🗂 Setting output path: " , dirname ) ;
2024-02-14 07:32:52 +01:00
if ( ! featureFlags . APP_STORE_BUILD ) {
if ( ! rememberOutputFolder ) {
setOutputPath ( dirname ) ;
}
}
2023-11-23 09:53:09 +01:00
validateImagePath ( filePath ) ;
2022-11-11 21:39:28 +01:00
}
} ;
const handlePaste = ( e ) = > {
resetImagePaths ( ) ;
e . preventDefault ( ) ;
const type = e . clipboardData . items [ 0 ] . type ;
const filePath = e . clipboardData . files [ 0 ] . path ;
const extension = e . clipboardData . files [ 0 ] . name . split ( "." ) . at ( - 1 ) ;
2023-05-06 07:17:35 +02:00
logit ( "📋 Pasted file: " , JSON . stringify ( { type , filePath , extension } ) ) ;
2022-11-11 21:39:28 +01:00
if (
! type . includes ( "image" ) &&
! allowedFileTypes . includes ( extension . toLowerCase ( ) )
) {
2024-04-21 16:04:59 +02:00
toast ( {
title : "Invalid Image" ,
description : "Please drag and drop an image" ,
} ) ;
2022-11-11 21:39:28 +01:00
} else {
2023-11-23 09:53:09 +01:00
setImagePath ( filePath ) ;
2022-11-11 21:39:28 +01:00
var dirname = filePath . match ( /(.*)[\/\\]/ ) [ 1 ] || "" ;
2023-05-06 07:17:35 +02:00
logit ( "🗂 Setting output path: " , dirname ) ;
2024-02-14 07:32:52 +01:00
if ( ! rememberOutputFolder ) {
setOutputPath ( dirname ) ;
2023-04-28 14:47:51 +02:00
}
2022-11-11 21:39:28 +01:00
}
} ;
const upscaylHandler = async ( ) = > {
2023-08-14 12:55:30 +02:00
logit ( "🔄 Resetting Upscaled Image Path" ) ;
setUpscaledImagePath ( "" ) ;
2023-09-09 15:01:31 +02:00
setUpscaledBatchFolderPath ( "" ) ;
2023-08-14 12:55:30 +02:00
if ( imagePath !== "" || batchFolderPath !== "" ) {
2022-11-11 21:39:28 +01:00
setProgress ( "Hold on..." ) ;
2023-11-22 16:54:02 +01:00
// Double Upscayl
2022-11-11 21:39:28 +01:00
if ( doubleUpscayl ) {
2023-11-22 16:54:02 +01:00
window . electron . send < DoubleUpscaylPayload > ( COMMAND . DOUBLE_UPSCAYL , {
2022-11-11 21:39:28 +01:00
imagePath ,
outputPath ,
model ,
2022-12-16 17:20:46 +01:00
gpuId : gpuId.length === 0 ? null : gpuId ,
saveImageAs ,
2023-04-14 12:31:37 +02:00
scale ,
2023-11-22 16:54:02 +01:00
noImageProcessing ,
2023-11-23 06:39:46 +01:00
compression : compression.toString ( ) ,
2024-04-21 19:14:39 +02:00
customWidth : customWidth > 0 ? customWidth . toString ( ) : null ,
2024-04-20 17:44:42 +02:00
useCustomWidth ,
2022-11-11 21:39:28 +01:00
} ) ;
2023-05-06 07:17:35 +02:00
logit ( "🏁 DOUBLE_UPSCAYL" ) ;
2022-11-11 21:39:28 +01:00
} else if ( batchMode ) {
2023-11-22 16:54:02 +01:00
// Batch Upscayl
2022-11-11 21:39:28 +01:00
setDoubleUpscayl ( false ) ;
2023-11-22 16:54:02 +01:00
window . electron . send < BatchUpscaylPayload > ( COMMAND . FOLDER_UPSCAYL , {
2022-11-11 21:39:28 +01:00
batchFolderPath ,
outputPath ,
model ,
2022-12-16 17:20:46 +01:00
gpuId : gpuId.length === 0 ? null : gpuId ,
saveImageAs ,
2023-04-14 12:31:37 +02:00
scale ,
2023-11-22 16:54:02 +01:00
noImageProcessing ,
2023-11-23 06:39:46 +01:00
compression : compression.toString ( ) ,
2024-04-21 19:14:39 +02:00
customWidth : customWidth > 0 ? customWidth . toString ( ) : null ,
2024-04-20 17:44:42 +02:00
useCustomWidth ,
2022-11-11 21:39:28 +01:00
} ) ;
2023-05-06 07:17:35 +02:00
logit ( "🏁 FOLDER_UPSCAYL" ) ;
2022-11-11 21:39:28 +01:00
} else {
2023-11-22 16:54:02 +01:00
// Single Image Upscayl
window . electron . send < ImageUpscaylPayload > ( COMMAND . UPSCAYL , {
2022-11-11 21:39:28 +01:00
imagePath ,
outputPath ,
model ,
2022-12-16 17:20:46 +01:00
gpuId : gpuId.length === 0 ? null : gpuId ,
saveImageAs ,
2023-04-14 12:31:37 +02:00
scale ,
2023-08-27 18:11:01 +02:00
overwrite ,
2023-11-22 16:54:02 +01:00
noImageProcessing ,
2023-11-23 06:39:46 +01:00
compression : compression.toString ( ) ,
2024-04-21 19:14:39 +02:00
customWidth : customWidth > 0 ? customWidth . toString ( ) : null ,
2024-04-20 17:44:42 +02:00
useCustomWidth ,
2022-11-11 21:39:28 +01:00
} ) ;
2023-05-06 07:17:35 +02:00
logit ( "🏁 UPSCAYL" ) ;
2022-11-11 21:39:28 +01:00
}
2023-11-22 16:54:02 +01:00
} else {
2024-04-21 16:04:59 +02:00
toast ( {
title : "No image selected" ,
description : "Please select an image to upscale" ,
} ) ;
2023-05-06 07:17:35 +02:00
logit ( "🚫 No valid image selected" ) ;
2022-11-11 21:39:28 +01:00
}
} ;
2023-04-28 20:21:42 +02:00
const stopHandler = ( ) = > {
2023-09-10 19:42:18 +02:00
window . electron . send ( COMMAND . STOP ) ;
2023-05-06 07:17:35 +02:00
logit ( "🛑 Stopping Upscayl" ) ;
2023-04-28 20:21:42 +02:00
resetImagePaths ( ) ;
2023-04-30 02:54:45 +02:00
} ;
2023-10-15 05:57:11 +02:00
if ( isLoading ) {
2023-08-30 06:54:16 +02:00
return (
< img
2023-09-01 06:32:46 +02:00
src = "icon.png"
2023-08-30 06:54:16 +02:00
alt = "Upscayl icon"
2024-02-07 02:23:19 +01:00
className = "absolute left-1/2 top-1/2 w-36 -translate-x-1/2 -translate-y-1/2 animate-pulse"
2023-08-30 06:54:16 +02:00
/ >
) ;
}
2022-11-11 21:39:28 +01:00
return (
2022-11-11 22:32:24 +01:00
< div className = "flex h-screen w-screen flex-row overflow-hidden bg-base-300" >
2024-04-17 18:18:45 +02:00
{ /* TOP LOGO WHEN SIDEBAR IS HIDDEN */ }
{ ! showSidebar && (
< div className = "fixed right-2 top-2 z-50 flex items-center justify-center gap-2 rounded-[7px] bg-base-300 px-2 py-1 font-medium text-base-content " >
< img src = "/icon.png" alt = "Logo" className = "w-5" / >
Upscayl
< / div >
) }
{ /* SIDEBAR BUTTON */ }
< button
className = { cn (
"fixed left-0 top-1/2 z-50 -translate-y-1/2 rounded-r-full bg-base-100 p-4 " ,
showSidebar ? "hidden" : "" ,
) }
onClick = { ( ) = > setShowSidebar ( ( prev ) = > ! prev ) }
>
< PanelRightCloseIcon / >
< / button >
2024-04-18 20:45:12 +02:00
2024-04-17 18:18:45 +02:00
{ /* LEFT PANE */ }
< div
className = { ` relative flex h-screen min-w-[350px] max-w-[350px] flex-col bg-base-100 ${ showSidebar ? "" : "hidden" } ` }
>
< button
className = "absolute -right-0 top-1/2 z-50 -translate-y-1/2 translate-x-1/2 rounded-full bg-base-100 p-4"
onClick = { ( ) = > setShowSidebar ( ( prev ) = > ! prev ) }
>
< PanelLeftCloseIcon / >
< / button >
2024-04-18 20:45:12 +02:00
2024-04-17 18:18:45 +02:00
{ /* UPSCAYL CLOUD MODAL */ }
2023-11-02 16:03:21 +01:00
{ featureFlags . SHOW_UPSCAYL_CLOUD_INFO && (
< UpscaylCloudModal
show = { showCloudModal }
setShow = { setShowCloudModal }
setDontShowCloudModal = { setDontShowCloudModal }
/ >
) }
2024-04-17 18:18:45 +02:00
{ /* MACOS TITLEBAR */ }
2023-08-30 06:54:16 +02:00
{ window . electron . platform === "mac" && (
2024-02-07 02:23:19 +01:00
< div className = "mac-titlebar pt-8" > < / div >
2023-08-30 06:54:16 +02:00
) }
2022-11-11 21:39:28 +01:00
{ /* HEADER */ }
2023-08-30 09:58:15 +02:00
< Header version = { version } / >
2023-11-02 16:03:21 +01:00
{ ! dontShowCloudModal && featureFlags . SHOW_UPSCAYL_CLOUD_INFO && (
2023-09-03 11:16:48 +02:00
< button
2024-04-18 23:58:47 +02:00
className = "mx-5 mb-5 animate-pulse rounded-btn bg-success p-1 text-sm text-slate-50 shadow-lg shadow-success/40"
2023-09-03 11:16:48 +02:00
onClick = { ( ) = > {
setShowCloudModal ( true ) ;
2024-02-07 02:23:19 +01:00
} }
>
2023-09-03 11:16:48 +02:00
Introducing Upscayl Cloud
< / button >
) }
2023-08-30 07:35:40 +02:00
2024-04-17 18:18:45 +02:00
{ /* NEWS DIALOG */ }
2023-11-23 10:25:55 +01:00
< NewsModal
show = { showNewsModal }
setShow = { ( val : boolean ) = > {
setShowNewsModal ( val ) ;
setNews ( ( prev ) = > ( { . . . prev , seen : true } ) ) ;
} }
news = { news }
/ >
2023-03-18 18:08:50 +01:00
< Tabs selectedTab = { selectedTab } setSelectedTab = { setSelectedTab } / >
2023-08-14 12:55:30 +02:00
2023-03-18 18:08:50 +01:00
{ selectedTab === 0 && (
2022-11-23 19:24:30 +01:00
< LeftPaneImageSteps
selectImageHandler = { selectImageHandler }
selectFolderHandler = { selectFolderHandler }
handleModelChange = { handleModelChange }
upscaylHandler = { upscaylHandler }
batchMode = { batchMode }
setBatchMode = { setBatchMode }
imagePath = { imagePath }
doubleUpscayl = { doubleUpscayl }
setDoubleUpscayl = { setDoubleUpscayl }
2022-12-24 08:17:54 +01:00
dimensions = { dimensions }
2023-05-01 11:23:11 +02:00
setGpuId = { setGpuId }
2023-09-19 17:14:15 +02:00
model = { model }
2023-05-01 11:23:11 +02:00
setModel = { setModel }
setSaveImageAs = { setSaveImageAs }
2022-11-23 19:24:30 +01:00
/ >
) }
2023-03-18 18:08:50 +01:00
{ selectedTab === 1 && (
< SettingsTab
batchMode = { batchMode }
setModel = { setModel }
2023-09-13 16:07:45 +02:00
compression = { compression }
setCompression = { setCompression }
2023-03-18 18:08:50 +01:00
gpuId = { gpuId }
setGpuId = { setGpuId }
saveImageAs = { saveImageAs }
setSaveImageAs = { setSaveImageAs }
2023-04-08 08:53:32 +02:00
logData = { logData }
2023-08-14 12:55:30 +02:00
os = { os }
2023-09-03 11:16:48 +02:00
show = { showCloudModal }
setShow = { setShowCloudModal }
setDontShowCloudModal = { setDontShowCloudModal }
2023-03-18 18:08:50 +01:00
/ >
) }
{ /* )} */ }
2022-11-11 21:39:28 +01:00
< Footer / >
< / div >
{ /* RIGHT PANE */ }
< div
className = "relative flex h-screen w-full flex-col items-center justify-center"
onDrop = { ( e ) = > handleDrop ( e ) }
onDragOver = { ( e ) = > handleDragOver ( e ) }
onDragEnter = { ( e ) = > handleDragEnter ( e ) }
onDragLeave = { ( e ) = > handleDragLeave ( e ) }
2023-11-10 14:23:55 +01:00
onDoubleClick = { ( ) = > {
if ( batchMode ) {
selectFolderHandler ( ) ;
} else {
selectImageHandler ( ) ;
}
} }
2024-02-07 02:23:19 +01:00
onPaste = { ( e ) = > handlePaste ( e ) }
>
2023-08-30 06:54:16 +02:00
{ window . electron . platform === "mac" && (
2024-02-07 02:23:19 +01:00
< div className = "mac-titlebar absolute top-0 h-8 w-full" > < / div >
2023-08-30 06:54:16 +02:00
) }
2022-11-11 21:39:28 +01:00
{ progress . length > 0 &&
upscaledImagePath . length === 0 &&
2023-08-14 12:55:30 +02:00
upscaledBatchFolderPath . length === 0 ? (
2022-12-02 15:21:42 +01:00
< ProgressBar
2023-07-23 11:07:18 +02:00
batchMode = { batchMode }
2022-12-02 15:21:42 +01:00
progress = { progress }
doubleUpscaylCounter = { doubleUpscaylCounter }
2023-04-28 20:21:42 +02:00
stopHandler = { stopHandler }
2022-12-02 15:21:42 +01:00
/ >
2022-11-11 21:39:28 +01:00
) : null }
2022-11-25 08:30:03 +01:00
{ /* DEFAULT PANE INFO */ }
2023-08-14 12:55:30 +02:00
{ ( ( ! batchMode &&
2023-04-29 17:01:42 +02:00
imagePath . length === 0 &&
2022-11-11 21:39:28 +01:00
upscaledImagePath . length === 0 ) ||
2023-08-14 12:55:30 +02:00
( batchMode &&
2023-04-29 17:01:42 +02:00
batchFolderPath . length === 0 &&
2023-08-14 12:55:30 +02:00
upscaledBatchFolderPath . length === 0 ) ) && (
< RightPaneInfo version = { version } batchMode = { batchMode } / >
2022-11-11 21:39:28 +01:00
) }
2022-11-25 08:30:03 +01:00
{ /* SHOW SELECTED IMAGE */ }
2022-11-11 21:39:28 +01:00
{ ! batchMode &&
upscaledImagePath . length === 0 &&
imagePath . length > 0 && (
2022-12-24 08:40:45 +01:00
< >
< ImageOptions
zoomAmount = { zoomAmount }
setZoomAmount = { setZoomAmount }
resetImagePaths = { resetImagePaths }
hideZoomOptions = { true }
/ >
< img
2023-09-11 05:57:16 +02:00
src = { "file:///" + imagePath }
2022-12-24 08:40:45 +01:00
onLoad = { ( e : any ) = > {
setDimensions ( {
width : e.target.naturalWidth ,
height : e.target.naturalHeight ,
} ) ;
} }
draggable = "false"
alt = ""
2023-10-14 03:00:49 +02:00
className = "h-full w-full bg-gradient-to-br from-base-300 to-base-100 object-contain"
2022-12-24 08:40:45 +01:00
/ >
< / >
2022-11-11 21:39:28 +01:00
) }
2022-11-25 08:30:03 +01:00
{ /* BATCH UPSCALE SHOW SELECTED FOLDER */ }
2022-11-11 21:39:28 +01:00
{ batchMode &&
upscaledBatchFolderPath . length === 0 &&
batchFolderPath . length > 0 && (
2024-01-15 11:25:28 +01:00
< p className = "select-none text-base-content" >
2023-09-09 15:01:31 +02:00
< span className = "font-bold" > Selected folder : < / span > { " " }
{ batchFolderPath }
2022-11-11 21:39:28 +01:00
< / p >
) }
2022-11-25 08:30:03 +01:00
{ /* BATCH UPSCALE DONE INFO */ }
2022-11-11 21:39:28 +01:00
{ batchMode && upscaledBatchFolderPath . length > 0 && (
2024-02-14 07:32:52 +01:00
< div className = "z-50 flex flex-col items-center" >
2024-01-15 11:25:28 +01:00
< p className = "select-none py-4 font-bold text-base-content" >
2022-11-11 21:39:28 +01:00
All done !
< / p >
< button
2024-02-07 02:23:19 +01:00
className = "bg-gradient-blue btn btn-primary rounded-btn p-3 font-medium text-white/90 transition-colors"
onClick = { openFolderHandler }
>
2022-11-11 21:39:28 +01:00
Open Upscayled Folder
< / button >
2024-02-14 07:32:52 +01:00
< / div >
2022-11-11 21:39:28 +01:00
) }
2024-01-23 09:44:32 +01:00
< ImageOptions
zoomAmount = { zoomAmount }
setZoomAmount = { setZoomAmount }
resetImagePaths = { resetImagePaths }
/ >
{ ! batchMode &&
viewType === "lens" &&
upscaledImagePath &&
imagePath && (
< div
2024-02-07 02:34:06 +01:00
className = "group relative h-full w-full overflow-hidden"
2024-02-07 02:23:19 +01:00
onMouseMove = { handleMouseMoveCompare }
>
2024-01-23 09:44:32 +01:00
< img
2024-02-07 02:23:19 +01:00
className = { ` absolute left-0 top-0 h-full w-full object-contain transition-transform group-hover:scale-[ ${
2024-01-23 09:44:32 +01:00
zoomAmount + "%"
} ] ` }
src = { "file:///" + imagePath }
style = { {
backgroundPosition : "0% 0%" ,
transformOrigin : backgroundPosition ,
} }
/ >
< div
2024-02-07 02:27:54 +01:00
className = { ` invisible absolute left-0 top-0 h-full w-full bg-white mix-blend-difference group-hover:visible group-hover:scale-[ ${
2024-01-23 09:44:32 +01:00
zoomAmount + "%"
} ] ` }
style = { {
clipPath : ` circle( ${
2024-02-07 02:34:06 +01:00
( lensSize + 2 * ( parseInt ( zoomAmount ) / 100 ) ) /
( parseInt ( zoomAmount ) / 100 )
2024-01-23 09:44:32 +01:00
} px at $ { cursorPosition . x } px $ { cursorPosition . y } px ) ` ,
backgroundPosition : "0% 0%" ,
transformOrigin : backgroundPosition ,
} }
/ >
< img
2024-02-07 02:23:19 +01:00
className = { ` absolute h-full w-full object-contain transition-transform group-hover:scale-[ ${
2024-01-23 09:44:32 +01:00
zoomAmount + "%"
} ] ` }
src = { "file:///" + upscaledImagePath }
style = { {
clipPath : ` circle( ${
2024-02-07 02:34:06 +01:00
( lensSize + parseInt ( zoomAmount ) / 100 ) /
2024-02-07 02:23:19 +01:00
( parseInt ( zoomAmount ) / 100 )
2024-01-23 09:44:32 +01:00
} px at $ { cursorPosition . x } px $ { cursorPosition . y } px ) ` ,
2024-02-07 02:23:19 +01:00
backgroundPosition : backgroundPosition ,
2024-01-23 09:44:32 +01:00
transformOrigin : backgroundPosition ,
} }
/ >
< / div >
) }
2022-11-25 08:30:03 +01:00
{ /* COMPARISON SLIDER */ }
2024-01-23 09:44:32 +01:00
{ ! 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 ,
} }
2024-01-23 09:54:08 +01:00
className = { ` h-full w-full bg-gradient-to-br from-base-300 to-base-100 transition-transform group-hover:scale-[ ${ zoomAmount } %] ` }
2024-01-23 09:44:32 +01:00
/ >
< / >
}
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"
/ >
< / >
) }
2022-11-11 21:39:28 +01:00
< / div >
< / div >
) ;
} ;
export default Home ;