1
1
import { Flex } from '@invoke-ai/ui-library' ;
2
2
import { useStore } from '@nanostores/react' ;
3
3
import { skipToken } from '@reduxjs/toolkit/query' ;
4
+ import { useAppSelector , useAppStore } from 'app/store/storeHooks' ;
4
5
import { UploadImageIconButton } from 'common/hooks/useImageUploadButton' ;
6
+ import { bboxSizeOptimized , bboxSizeRecalled } from 'features/controlLayers/store/canvasSlice' ;
7
+ import { useCanvasIsStaging } from 'features/controlLayers/store/canvasStagingAreaSlice' ;
8
+ import { sizeOptimized , sizeRecalled } from 'features/controlLayers/store/paramsSlice' ;
5
9
import type { ImageWithDims } from 'features/controlLayers/store/types' ;
6
10
import type { setGlobalReferenceImageDndTarget , setRegionalGuidanceReferenceImageDndTarget } from 'features/dnd/dnd' ;
7
11
import { DndDropTarget } from 'features/dnd/DndDropTarget' ;
8
12
import { DndImage } from 'features/dnd/DndImage' ;
9
13
import { DndImageIcon } from 'features/dnd/DndImageIcon' ;
14
+ import { selectActiveTab } from 'features/ui/store/uiSelectors' ;
10
15
import { memo , useCallback , useEffect } from 'react' ;
11
16
import { useTranslation } from 'react-i18next' ;
12
- import { PiArrowCounterClockwiseBold } from 'react-icons/pi' ;
17
+ import { PiArrowCounterClockwiseBold , PiRulerBold } from 'react-icons/pi' ;
13
18
import { useGetImageDTOQuery } from 'services/api/endpoints/images' ;
14
19
import type { ImageDTO } from 'services/api/types' ;
15
20
import { $isConnected } from 'services/events/stores' ;
@@ -29,7 +34,10 @@ export const RefImageImage = memo(
29
34
dndTargetData,
30
35
} : Props < T > ) => {
31
36
const { t } = useTranslation ( ) ;
37
+ const store = useAppStore ( ) ;
32
38
const isConnected = useStore ( $isConnected ) ;
39
+ const tab = useAppSelector ( selectActiveTab ) ;
40
+ const isStaging = useCanvasIsStaging ( ) ;
33
41
const { currentData : imageDTO , isError } = useGetImageDTOQuery ( image ?. image_name ?? skipToken ) ;
34
42
const handleResetControlImage = useCallback ( ( ) => {
35
43
onChangeImage ( null ) ;
@@ -48,6 +56,20 @@ export const RefImageImage = memo(
48
56
[ onChangeImage ]
49
57
) ;
50
58
59
+ const recallSizeAndOptimize = useCallback ( ( ) => {
60
+ if ( ! imageDTO || ( tab === 'canvas' && isStaging ) ) {
61
+ return ;
62
+ }
63
+ const { width, height } = imageDTO ;
64
+ if ( tab === 'canvas' ) {
65
+ store . dispatch ( bboxSizeRecalled ( { width, height } ) ) ;
66
+ store . dispatch ( bboxSizeOptimized ( ) ) ;
67
+ } else if ( tab === 'generate' ) {
68
+ store . dispatch ( sizeRecalled ( { width, height } ) ) ;
69
+ store . dispatch ( sizeOptimized ( ) ) ;
70
+ }
71
+ } , [ imageDTO , isStaging , store , tab ] ) ;
72
+
51
73
return (
52
74
< Flex position = "relative" w = "full" h = "full" alignItems = "center" data-error = { ! imageDTO && ! image ?. image_name } >
53
75
{ ! imageDTO && (
@@ -69,6 +91,14 @@ export const RefImageImage = memo(
69
91
tooltip = { t ( 'common.reset' ) }
70
92
/>
71
93
</ Flex >
94
+ < Flex position = "absolute" flexDir = "column" bottom = { 2 } insetInlineEnd = { 2 } gap = { 1 } >
95
+ < DndImageIcon
96
+ onClick = { recallSizeAndOptimize }
97
+ icon = { < PiRulerBold size = { 16 } /> }
98
+ tooltip = { t ( 'parameters.useSize' ) }
99
+ isDisabled = { ! imageDTO || ( tab === 'canvas' && isStaging ) }
100
+ />
101
+ </ Flex >
72
102
</ >
73
103
) }
74
104
< DndDropTarget dndTarget = { dndTarget } dndTargetData = { dndTargetData } label = { t ( 'gallery.drop' ) } />
0 commit comments