1
- import { Box , Flex , Grid , Heading , Icon , Text } from '@invoke-ai/ui-library' ;
1
+ import { Box , Button , Flex , Grid , Heading , Icon , Text } from '@invoke-ai/ui-library' ;
2
2
import { useAppDispatch , useAppSelector } from 'app/store/storeHooks' ;
3
3
import { useImageUploadButton } from 'common/hooks/useImageUploadButton' ;
4
4
import { setUpscaleInitialImageDndTarget } from 'features/dnd/dnd' ;
5
5
import { DndDropTarget } from 'features/dnd/DndDropTarget' ;
6
6
import { DndImage } from 'features/dnd/DndImage' ;
7
7
import { DndImageIcon } from 'features/dnd/DndImageIcon' ;
8
- import ParamSpandrelModel from 'features/parameters/components/Upscale/ParamSpandrelModel' ;
9
- import { selectUpscaleInitialImage , upscaleInitialImageChanged } from 'features/parameters/store/upscaleSlice' ;
10
- import { MainModelPicker } from 'features/settingsAccordions/components/GenerationSettingsAccordion/MainModelPicker' ;
11
- import { UpscaleScaleSlider } from 'features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleScaleSlider' ;
8
+ import { selectUpscaleInitialImage , upscaleInitialImageChanged , creativityChanged , structureChanged , selectCreativity , selectStructure } from 'features/parameters/store/upscaleSlice' ;
12
9
import { memo , useCallback , useMemo } from 'react' ;
13
10
import { useTranslation } from 'react-i18next' ;
14
- import { PiArrowCounterClockwiseBold , PiImageBold , PiUploadBold } from 'react-icons/pi' ;
11
+ import { PiArrowCounterClockwiseBold , PiImageBold , PiUploadBold , PiShieldCheckBold , PiScalesBold , PiPaletteBold , PiSparkleBold } from 'react-icons/pi' ;
15
12
import type { ImageDTO } from 'services/api/types' ;
16
13
17
14
import { LaunchpadButton } from './LaunchpadButton' ;
@@ -20,6 +17,8 @@ export const UpscalingLaunchpadPanel = memo(() => {
20
17
const { t } = useTranslation ( ) ;
21
18
const dispatch = useAppDispatch ( ) ;
22
19
const upscaleInitialImage = useAppSelector ( selectUpscaleInitialImage ) ;
20
+ const creativity = useAppSelector ( selectCreativity ) ;
21
+ const structure = useAppSelector ( selectStructure ) ;
23
22
24
23
const dndTargetData = useMemo ( ( ) => setUpscaleInitialImageDndTarget . getData ( ) , [ ] ) ;
25
24
@@ -36,6 +35,27 @@ export const UpscalingLaunchpadPanel = memo(() => {
36
35
37
36
const uploadApi = useImageUploadButton ( { allowMultiple : false , onUpload } ) ;
38
37
38
+ // Preset button handlers
39
+ const onConservativeClick = useCallback ( ( ) => {
40
+ dispatch ( creativityChanged ( - 5 ) ) ;
41
+ dispatch ( structureChanged ( 5 ) ) ;
42
+ } , [ dispatch ] ) ;
43
+
44
+ const onBalancedClick = useCallback ( ( ) => {
45
+ dispatch ( creativityChanged ( 0 ) ) ;
46
+ dispatch ( structureChanged ( 0 ) ) ;
47
+ } , [ dispatch ] ) ;
48
+
49
+ const onCreativeClick = useCallback ( ( ) => {
50
+ dispatch ( creativityChanged ( 5 ) ) ;
51
+ dispatch ( structureChanged ( - 2 ) ) ;
52
+ } , [ dispatch ] ) ;
53
+
54
+ const onArtisticClick = useCallback ( ( ) => {
55
+ dispatch ( creativityChanged ( 8 ) ) ;
56
+ dispatch ( structureChanged ( - 5 ) ) ;
57
+ } , [ dispatch ] ) ;
58
+
39
59
return (
40
60
< Flex flexDir = "column" h = "full" w = "full" alignItems = "center" gap = { 2 } >
41
61
< Flex flexDir = "column" w = "full" gap = { 4 } px = { 14 } maxW = { 768 } pt = "20vh" >
@@ -57,34 +77,14 @@ export const UpscalingLaunchpadPanel = memo(() => {
57
77
</ >
58
78
) : (
59
79
< >
60
- < Flex position = "relative" w = { 16 } h = { 16 } alignItems = "center" justifyContent = "center" >
61
- < DndImage imageDTO = { upscaleInitialImage } />
62
- < Flex position = "absolute" flexDir = "column" top = { 1 } insetInlineEnd = { 1 } gap = { 1 } >
63
- < DndImageIcon
64
- onClick = { onReset }
65
- icon = { < PiArrowCounterClockwiseBold size = { 12 } /> }
66
- tooltip = { t ( 'common.reset' ) }
67
- />
68
- </ Flex >
69
- < Text
70
- position = "absolute"
71
- background = "base.900"
72
- color = "base.50"
73
- fontSize = "xs"
74
- fontWeight = "semibold"
75
- bottom = { 0 }
76
- left = { 0 }
77
- opacity = { 0.7 }
78
- px = { 1 }
79
- lineHeight = { 1.25 }
80
- borderTopEndRadius = "base"
81
- borderBottomStartRadius = "base"
82
- pointerEvents = "none"
83
- > { `${ upscaleInitialImage . width } x${ upscaleInitialImage . height } ` } </ Text >
84
- </ Flex >
80
+ < Icon as = { PiImageBold } boxSize = { 8 } color = "base.500" />
85
81
< Flex flexDir = "column" alignItems = "flex-start" gap = { 2 } >
86
- < Heading size = "sm" > { t ( 'ui.launchpad.upscaling.imageReady.title' ) } </ Heading >
87
- < Text color = "base.300" > { t ( 'ui.launchpad.upscaling.imageReady.description' ) } </ Text >
82
+ < Heading size = "sm" > { t ( 'ui.launchpad.upscaling.replaceImage.title' ) } </ Heading >
83
+ < Text color = "base.300" > { t ( 'ui.launchpad.upscaling.replaceImage.description' ) } </ Text >
84
+ </ Flex >
85
+ < Flex position = "absolute" right = { 3 } bottom = { 3 } >
86
+ < PiUploadBold />
87
+ < input { ...uploadApi . getUploadInputProps ( ) } />
88
88
</ Flex >
89
89
</ >
90
90
) }
@@ -108,33 +108,54 @@ export const UpscalingLaunchpadPanel = memo(() => {
108
108
{ /* Controls */ }
109
109
< style > { `.launchpad-hide-label .chakra-form__label { display: none !important; }` } </ style >
110
110
< Grid gridTemplateColumns = "1fr 1fr" gap = { 10 } alignItems = "start" mt = { upscaleInitialImage ? 8 : 12 } >
111
- { /* Left Column: All parameters stacked */ }
112
- < Flex flexDir = "column" gap = { 6 } alignItems = "flex-start" >
113
- < Box w = "full" >
114
- < Text fontWeight = "semibold" fontSize = "sm" mb = { 1 } >
115
- { t ( 'ui.launchpad.upscaling.upscaleModel' ) }
116
- </ Text >
117
- < Box className = "launchpad-hide-label" >
118
- < ParamSpandrelModel />
119
- </ Box >
120
- </ Box >
121
- < Box w = "full" >
122
- < Text fontWeight = "semibold" fontSize = "sm" mb = { 1 } >
123
- { t ( 'ui.launchpad.upscaling.model' ) }
124
- </ Text >
125
- < Box className = "launchpad-hide-label" >
126
- < MainModelPicker />
127
- </ Box >
128
- </ Box >
129
- < Box w = "full" >
130
- < Text fontWeight = "semibold" fontSize = "sm" mb = { 1 } >
131
- { t ( 'ui.launchpad.upscaling.scale' ) }
132
- </ Text >
133
- < Box className = "launchpad-hide-label" >
134
- < UpscaleScaleSlider />
135
- </ Box >
136
- </ Box >
137
- </ Flex >
111
+ { /* Left Column: Creativity and Structural Defaults */ }
112
+ < Box >
113
+ < Text fontWeight = "semibold" fontSize = "sm" mb = { 3 } >
114
+ Creativity & Structural Defaults
115
+ </ Text >
116
+ < Flex flexDir = "column" gap = { 2 } >
117
+ < Button
118
+ size = "sm"
119
+ variant = { creativity === - 5 && structure === 5 ? "solid" : "outline" }
120
+ colorScheme = "base"
121
+ justifyContent = "center"
122
+ onClick = { onConservativeClick }
123
+ leftIcon = { < PiShieldCheckBold /> }
124
+ >
125
+ Conservative
126
+ </ Button >
127
+ < Button
128
+ size = "sm"
129
+ variant = { creativity === 0 && structure === 0 ? "solid" : "outline" }
130
+ colorScheme = "base"
131
+ justifyContent = "center"
132
+ onClick = { onBalancedClick }
133
+ leftIcon = { < PiScalesBold /> }
134
+ >
135
+ Balanced
136
+ </ Button >
137
+ < Button
138
+ size = "sm"
139
+ variant = { creativity === 5 && structure === - 2 ? "solid" : "outline" }
140
+ colorScheme = "base"
141
+ justifyContent = "center"
142
+ onClick = { onCreativeClick }
143
+ leftIcon = { < PiPaletteBold /> }
144
+ >
145
+ Creative
146
+ </ Button >
147
+ < Button
148
+ size = "sm"
149
+ variant = { creativity === 8 && structure === - 5 ? "solid" : "outline" }
150
+ colorScheme = "base"
151
+ justifyContent = "center"
152
+ onClick = { onArtisticClick }
153
+ leftIcon = { < PiSparkleBold /> }
154
+ >
155
+ Artistic
156
+ </ Button >
157
+ </ Flex >
158
+ </ Box >
138
159
{ /* Right Column: Description/help text */ }
139
160
< Box >
140
161
< Text variant = "subtext" fontSize = "sm" lineHeight = "1.6" >
0 commit comments