2023-11-10 12:41:35 +01:00
import { useAtom , useAtomValue } from "jotai" ;
2024-04-17 18:18:45 +02:00
import React , { useCallback , useEffect , useState } from "react" ;
2023-07-23 11:07:18 +02:00
import { Tooltip } from "react-tooltip" ;
2022-12-08 04:25:26 +01:00
import { themeChange } from "theme-change" ;
2024-04-20 13:11:03 +02:00
import { TModelsList , modelsListAtom } from "../../../atoms/modelsListAtom" ;
2023-07-22 13:07:53 +02:00
import useLog from "../../hooks/useLog" ;
2023-09-19 16:51:38 +02:00
import {
noImageProcessingAtom ,
2024-04-09 20:11:24 +02:00
savedOutputPathAtom ,
2023-11-10 12:41:35 +01:00
progressAtom ,
2024-02-14 07:32:52 +01:00
rememberOutputFolderAtom ,
2023-09-19 16:51:38 +02:00
scaleAtom ,
2024-04-21 19:14:39 +02:00
customWidthAtom ,
useCustomWidthAtom ,
2023-09-19 16:51:38 +02:00
} from "../../../atoms/userSettingsAtom" ;
2023-11-02 16:03:21 +01:00
import { featureFlags } from "@common/feature-flags" ;
2024-01-15 10:25:29 +01:00
import getModelScale from "@common/check-model-scale" ;
2024-02-14 07:32:52 +01:00
import COMMAND from "@common/commands" ;
2024-04-20 13:11:03 +02:00
import Select from "react-select" ;
import { cn } from "@/lib/utils" ;
2024-04-21 16:04:59 +02:00
import { useToast } from "@/components/ui/use-toast" ;
2024-04-21 19:27:16 +02:00
import { ImageScaleSelect } from "@/components/settings-tab/ImageScaleSelect" ;
2022-11-11 21:39:28 +01:00
2022-11-15 15:54:06 +01:00
interface IProps {
selectImageHandler : ( ) = > Promise < void > ;
selectFolderHandler : ( ) = > Promise < void > ;
handleModelChange : ( e : any ) = > void ;
upscaylHandler : ( ) = > Promise < void > ;
batchMode : boolean ;
2023-03-12 08:41:43 +01:00
setBatchMode : React.Dispatch < React.SetStateAction < boolean > > ;
2022-11-15 15:54:06 +01:00
imagePath : string ;
doubleUpscayl : boolean ;
2023-03-12 08:41:43 +01:00
setDoubleUpscayl : React.Dispatch < React.SetStateAction < boolean > > ;
2022-12-24 08:17:54 +01:00
dimensions : {
width : number | null ;
height : number | null ;
} ;
2023-05-01 11:23:11 +02:00
setSaveImageAs : React.Dispatch < React.SetStateAction < string > > ;
2023-09-19 17:14:15 +02:00
model : string ;
2023-05-01 11:23:11 +02:00
setModel : React.Dispatch < React.SetStateAction < string > > ;
setGpuId : React.Dispatch < React.SetStateAction < string > > ;
2022-11-15 15:54:06 +01:00
}
2022-11-23 19:24:30 +01:00
function LeftPaneImageSteps ( {
2022-11-15 15:54:06 +01:00
selectImageHandler ,
selectFolderHandler ,
handleModelChange ,
upscaylHandler ,
batchMode ,
setBatchMode ,
imagePath ,
doubleUpscayl ,
setDoubleUpscayl ,
2022-12-24 08:17:54 +01:00
dimensions ,
2023-05-01 11:23:11 +02:00
setSaveImageAs ,
2023-09-19 17:14:15 +02:00
model ,
2023-05-01 11:23:11 +02:00
setModel ,
setGpuId ,
2022-11-15 15:54:06 +01:00
} : IProps ) {
2024-04-20 13:11:03 +02:00
const [ currentModel , setCurrentModel ] = useState < TModelsList [ 0 ] > ( {
2022-12-24 09:45:15 +01:00
label : null ,
value : null ,
} ) ;
2023-05-01 09:44:12 +02:00
const modelOptions = useAtomValue ( modelsListAtom ) ;
2024-04-21 19:27:16 +02:00
const [ scale , setScale ] = useAtom ( scaleAtom ) ;
2023-09-19 16:51:38 +02:00
const noImageProcessing = useAtomValue ( noImageProcessingAtom ) ;
2024-04-09 20:11:24 +02:00
const [ outputPath , setOutputPath ] = useAtom ( savedOutputPathAtom ) ;
2023-11-10 12:41:35 +01:00
const [ progress , setProgress ] = useAtom ( progressAtom ) ;
2024-02-14 07:32:52 +01:00
const rememberOutputFolder = useAtomValue ( rememberOutputFolderAtom ) ;
2024-04-17 18:18:45 +02:00
const [ open , setOpen ] = React . useState ( false ) ;
2024-04-21 19:14:39 +02:00
const [ customWidth , setCustomWidth ] = useAtom ( customWidthAtom ) ;
const [ useCustomWidth , setUseCustomWidth ] = useAtom ( useCustomWidthAtom ) ;
2023-03-12 08:41:43 +01:00
2024-02-07 02:46:01 +01:00
const [ targetWidth , setTargetWidth ] = useState < number > ( null ) ;
const [ targetHeight , setTargetHeight ] = useState < number > ( null ) ;
2023-05-01 11:23:11 +02:00
const { logit } = useLog ( ) ;
2024-04-21 16:04:59 +02:00
const { toast } = useToast ( ) ;
2023-05-01 11:23:11 +02:00
2024-02-14 07:32:52 +01:00
const outputHandler = async ( ) = > {
var path = await window . electron . invoke ( COMMAND . SELECT_FOLDER ) ;
if ( path !== null ) {
logit ( "🗂 Setting Output Path: " , path ) ;
setOutputPath ( path ) ;
} else {
setOutputPath ( null ) ;
}
} ;
2023-05-01 11:23:11 +02:00
useEffect ( ( ) = > {
themeChange ( false ) ;
if ( ! localStorage . getItem ( "saveImageAs" ) ) {
2023-05-06 07:17:35 +02:00
logit ( "⚙️ Setting saveImageAs to png" ) ;
2023-05-01 11:23:11 +02:00
localStorage . setItem ( "saveImageAs" , "png" ) ;
} else {
const currentlySavedImageFormat = localStorage . getItem ( "saveImageAs" ) ;
logit (
2023-09-13 16:07:45 +02:00
"⚙️ Getting saveImageAs from localStorage: " ,
2024-02-07 02:46:01 +01:00
currentlySavedImageFormat ,
2023-05-01 11:23:11 +02:00
) ;
setSaveImageAs ( currentlySavedImageFormat ) ;
}
if ( ! localStorage . getItem ( "model" ) ) {
setCurrentModel ( modelOptions [ 0 ] ) ;
setModel ( modelOptions [ 0 ] . value ) ;
localStorage . setItem ( "model" , JSON . stringify ( modelOptions [ 0 ] ) ) ;
2023-05-06 07:17:35 +02:00
logit ( "🔀 Setting model to" , modelOptions [ 0 ] . value ) ;
2023-05-01 11:23:11 +02:00
} else {
const currentlySavedModel = JSON . parse (
2024-02-07 02:46:01 +01:00
localStorage . getItem ( "model" ) ,
2023-05-01 11:23:11 +02:00
) as ( typeof modelOptions ) [ 0 ] ;
setCurrentModel ( currentlySavedModel ) ;
setModel ( currentlySavedModel . value ) ;
logit (
2023-09-13 16:07:45 +02:00
"⚙️ Getting model from localStorage: " ,
2024-02-07 02:46:01 +01:00
JSON . stringify ( currentlySavedModel ) ,
2023-05-01 11:23:11 +02:00
) ;
}
if ( ! localStorage . getItem ( "gpuId" ) ) {
localStorage . setItem ( "gpuId" , "" ) ;
2023-05-06 07:17:35 +02:00
logit ( "⚙️ Setting gpuId to empty string" ) ;
2023-05-01 11:23:11 +02:00
} else {
const currentlySavedGpuId = localStorage . getItem ( "gpuId" ) ;
setGpuId ( currentlySavedGpuId ) ;
2023-09-13 16:07:45 +02:00
logit ( "⚙️ Getting gpuId from localStorage: " , currentlySavedGpuId ) ;
2023-05-01 11:23:11 +02:00
}
} , [ ] ) ;
useEffect ( ( ) = > {
2023-05-06 07:17:35 +02:00
logit ( "🔀 Setting model to" , currentModel . value ) ;
2023-05-01 11:23:11 +02:00
} , [ currentModel ] ) ;
2024-02-07 02:46:01 +01:00
useEffect ( ( ) = > {
setTargetWidth ( getUpscaleResolution ( ) . width ) ;
setTargetHeight ( getUpscaleResolution ( ) . height ) ;
} , [ dimensions . width , dimensions . height , doubleUpscayl , scale ] ) ;
2023-08-30 07:35:40 +02:00
const getUpscaleResolution = useCallback ( ( ) = > {
2023-06-03 02:49:13 +02:00
const newDimensions = {
width : dimensions.width ,
height : dimensions.height ,
} ;
2023-08-30 07:35:40 +02:00
2023-09-19 16:51:38 +02:00
let doubleScale = parseInt ( scale ) * parseInt ( scale ) ;
let singleScale = parseInt ( scale ) ;
2024-04-21 19:14:39 +02:00
if ( useCustomWidth ) {
2023-09-19 16:51:38 +02:00
}
2023-08-30 07:35:40 +02:00
2023-06-03 02:49:13 +02:00
if ( doubleUpscayl ) {
2023-08-30 07:35:40 +02:00
const newWidth = dimensions . width * doubleScale ;
const newHeight = dimensions . height * doubleScale ;
2024-04-21 19:14:39 +02:00
newDimensions . width = newWidth ;
newDimensions . height = newHeight ;
2023-06-03 02:49:13 +02:00
} else {
2023-08-30 07:35:40 +02:00
newDimensions . width = dimensions . width * singleScale ;
newDimensions . height = dimensions . height * singleScale ;
2023-06-03 02:49:13 +02:00
}
return newDimensions ;
2023-08-30 07:35:40 +02:00
} , [ dimensions . width , dimensions . height , doubleUpscayl , scale ] ) ;
2023-06-03 02:49:13 +02:00
2022-11-11 21:39:28 +01:00
return (
2023-08-30 06:54:16 +02:00
< div
2024-02-07 02:46:01 +01:00
className = { ` animate-step-in animate flex h-screen flex-col gap-7 overflow-y-auto overflow-x-hidden p-5 ` }
>
2022-11-11 21:39:28 +01:00
{ /* BATCH OPTION */ }
2022-11-11 22:32:24 +01:00
< div className = "flex flex-row items-center gap-2" >
< input
type = "checkbox"
2022-11-15 15:42:20 +01:00
className = "toggle"
2023-04-15 07:00:19 +02:00
defaultChecked = { batchMode }
2023-11-10 12:41:35 +01:00
onClick = { ( ) = > {
2024-02-14 07:32:52 +01:00
if ( ! rememberOutputFolder ) {
setOutputPath ( "" ) ;
}
2023-11-10 12:41:35 +01:00
setProgress ( "" ) ;
setBatchMode ( ( oldValue ) = > ! oldValue ) ;
2024-02-07 02:46:01 +01:00
} }
> < / input >
2022-11-23 19:24:30 +01:00
< p
2023-08-30 06:54:16 +02:00
className = "mr-1 inline-block cursor-help text-sm"
2023-07-23 11:07:18 +02:00
data - tooltip - id = "tooltip"
2024-02-07 02:46:01 +01:00
data - tooltip - content = "This will let you Upscayl all files in a folder at once"
>
2023-06-18 17:47:45 +02:00
Batch Upscayl
2022-11-23 19:24:30 +01:00
< / p >
2022-11-11 21:39:28 +01:00
< / div >
{ /* STEP 1 */ }
2024-04-21 19:14:39 +02:00
< div className = "animate-step-in" >
2022-11-11 21:39:28 +01:00
< p className = "step-heading" > Step 1 < / p >
< button
2024-02-07 02:46:01 +01:00
className = "btn btn-primary"
onClick = { ! batchMode ? selectImageHandler : selectFolderHandler }
2024-04-21 19:14:39 +02:00
data - tooltip - id = "tooltip"
data - tooltip - content = { imagePath }
2024-02-07 02:46:01 +01:00
>
2022-11-15 15:54:06 +01:00
Select { batchMode ? "Folder" : "Image" }
2022-11-11 21:39:28 +01:00
< / button >
< / div >
{ /* STEP 2 */ }
2024-04-21 19:27:16 +02:00
< div className = "animate-step-in group flex flex-col gap-4" >
< div >
< p className = "step-heading" > Step 2 < / p >
< p className = "mb-2 text-sm" > Select Model < / p >
2022-11-11 21:39:28 +01:00
2024-04-21 19:27:16 +02:00
< Select
onMenuOpen = { ( ) = > setOpen ( true ) }
onMenuClose = { ( ) = > setOpen ( false ) }
options = { modelOptions }
components = { {
IndicatorSeparator : ( ) = > null ,
DropdownIndicator : ( ) = > null ,
} }
onChange = { ( e ) = > {
handleModelChange ( e ) ;
setCurrentModel ( { label : e.label , value : e.value } ) ;
} }
className = { cn (
"react-select-container transition-all group-hover:w-full group-active:w-full focus:w-full" ,
open && "!w-full" ,
) }
classNamePrefix = "react-select"
value = { currentModel }
/ >
< / div >
2022-11-11 21:39:28 +01:00
2023-03-18 13:33:17 +01:00
{ ! batchMode && (
2024-04-21 19:27:16 +02:00
< div className = "flex items-center gap-1" >
2022-11-11 21:39:28 +01:00
< input
type = "checkbox"
2022-11-11 22:32:24 +01:00
className = "checkbox"
2022-11-15 15:54:06 +01:00
checked = { doubleUpscayl }
2022-11-11 21:39:28 +01:00
onChange = { ( e ) = > {
if ( e . target . checked ) {
2022-11-15 15:54:06 +01:00
setDoubleUpscayl ( true ) ;
2022-11-11 21:39:28 +01:00
} else {
2022-11-15 15:54:06 +01:00
setDoubleUpscayl ( false ) ;
2022-11-11 21:39:28 +01:00
}
} }
/ >
< p
2022-11-11 22:32:24 +01:00
className = "cursor-pointer text-sm"
2022-11-11 21:39:28 +01:00
onClick = { ( e ) = > {
2022-11-15 15:54:06 +01:00
setDoubleUpscayl ( ! doubleUpscayl ) ;
2024-02-07 02:46:01 +01:00
} }
>
2022-11-11 21:39:28 +01:00
Double Upscayl
< / p >
2022-11-23 19:24:30 +01:00
< button
2024-02-07 02:46:01 +01:00
className = "badge badge-neutral badge-sm cursor-help"
2023-07-23 11:07:18 +02:00
data - tooltip - id = "tooltip"
2024-04-21 19:14:39 +02:00
data - tooltip - content = "Enable this option to run upscayl twice on an image. Note that this may cause a significant increase in processing time and possibly performance issues for scales greater than 4X."
2024-02-07 02:46:01 +01:00
>
2024-01-15 11:04:11 +01:00
?
2022-11-23 19:24:30 +01:00
< / button >
2022-11-11 21:39:28 +01:00
< / div >
) }
2024-04-21 19:27:16 +02:00
< ImageScaleSelect scale = { scale } setScale = { setScale } hideInfo / >
2022-11-11 21:39:28 +01:00
< / div >
{ /* STEP 3 */ }
2024-04-21 19:14:39 +02:00
< div className = "animate-step-in" >
2024-01-15 14:13:16 +01:00
< div className = "flex flex-col pb-2" >
< div className = "step-heading flex items-center gap-2" >
< span className = "leading-none" > Step 3 < / span >
{ featureFlags . APP_STORE_BUILD && (
< button
2024-02-07 02:46:01 +01:00
className = "badge badge-outline badge-sm cursor-pointer"
2024-01-15 14:13:16 +01:00
onClick = { ( ) = >
alert (
2024-02-07 02:46:01 +01:00
"Due to MacOS App Store security restrictions, Upscayl requires you to select an output folder everytime you start it.\n\nTo avoid this, you can permanently save a default output folder in the Upscayl 'Settings' tab." ,
2024-01-15 14:13:16 +01:00
)
2024-02-07 02:46:01 +01:00
}
>
2024-01-15 14:13:16 +01:00
?
< / button >
) }
< / div >
2023-11-10 12:41:35 +01:00
{ ! outputPath && featureFlags . APP_STORE_BUILD && (
2023-11-02 16:03:21 +01:00
< div className = "text-xs" >
2024-02-07 02:46:01 +01:00
< span className = "rounded-btn bg-base-200 px-2 font-medium uppercase text-base-content/50" >
2023-11-02 16:03:21 +01:00
Not selected
< / span >
< / div >
) }
< / div >
{ ! batchMode && ! featureFlags . APP_STORE_BUILD && (
< p className = "mb-2 text-sm" >
Defaults to { ! batchMode ? "Image's" : "Folder's" } path
< / p >
) }
2024-04-21 19:14:39 +02:00
< button
className = "btn btn-primary"
data - tooltip - content = { outputPath }
data - tooltip - id = "tooltip"
onClick = { outputHandler }
>
2022-11-11 21:39:28 +01:00
Set Output Folder
< / button >
< / div >
{ /* STEP 4 */ }
< div className = "animate-step-in" >
< p className = "step-heading" > Step 4 < / p >
2022-12-24 08:17:54 +01:00
{ dimensions . width && dimensions . height && (
< p className = "mb-2 text-sm" >
2024-02-08 15:57:35 +01:00
Upscayl from { " " }
2022-12-24 08:17:54 +01:00
< span className = "font-bold" >
{ dimensions . width } x { dimensions . height }
< / span > { " " }
2024-02-08 15:57:35 +01:00
to { " " }
< span className = "font-bold" >
2023-06-03 02:49:50 +02:00
{ getUpscaleResolution ( ) . width } x { getUpscaleResolution ( ) . height }
2024-02-08 15:57:35 +01:00
< / span >
2022-12-24 08:17:54 +01:00
< / p >
) }
2022-11-11 21:39:28 +01:00
< button
2024-02-07 02:46:01 +01:00
className = "btn btn-accent"
2023-11-10 12:41:35 +01:00
onClick = {
progress . length > 0 || ! outputPath
2024-04-21 16:04:59 +02:00
? ( ) = >
toast ( {
description : "Please select an output folder first" ,
} )
2023-11-10 12:41:35 +01:00
: upscaylHandler
2024-02-07 02:46:01 +01:00
}
>
2022-11-15 15:54:06 +01:00
{ progress . length > 0 ? "Upscayling⏳" : "Upscayl" }
2022-11-11 21:39:28 +01:00
< / button >
< / div >
2022-11-23 19:24:30 +01:00
2024-04-21 19:14:39 +02:00
< Tooltip
className = "z-[999] max-w-sm break-words !bg-secondary"
id = "tooltip"
/ >
2022-11-11 21:39:28 +01:00
< / div >
) ;
}
2022-11-23 19:24:30 +01:00
export default LeftPaneImageSteps ;