@@ -10,42 +10,35 @@ import {
1010 Text ,
1111} from '@invoke-ai/ui-library' ;
1212import { useAppSelector } from 'app/store/storeHooks' ;
13- import type { CropBox } from 'features/editImageModal/lib/editor' ;
14- import { closeEditImageModal , type EditImageModalState } from 'features/editImageModal/store' ;
13+ import type { AspectRatioID } from 'features/controlLayers/store/types' ;
14+ import { ASPECT_RATIO_MAP , isAspectRatioID } from 'features/controlLayers/store/types' ;
15+ import type { CropBox } from 'features/cropper/lib/editor' ;
16+ import { cropImageModalApi , type CropImageModalState } from 'features/cropper/store' ;
1517import { selectAutoAddBoardId } from 'features/gallery/store/gallerySelectors' ;
16- import React , { useCallback , useEffect , useRef , useState } from 'react' ;
18+ import React , { memo , useCallback , useEffect , useRef , useState } from 'react' ;
1719import { useUploadImageMutation } from 'services/api/endpoints/images' ;
20+ import { objectEntries } from 'tsafe' ;
1821
1922type Props = {
20- editor : EditImageModalState [ 'editor' ] ;
21- onApplyCrop : EditImageModalState [ 'onApplyCrop' ] ;
22- onReady : EditImageModalState [ 'onReady' ] ;
23+ editor : CropImageModalState [ 'editor' ] ;
24+ onApplyCrop : CropImageModalState [ 'onApplyCrop' ] ;
25+ onReady : CropImageModalState [ 'onReady' ] ;
2326} ;
2427
25- const CROP_ASPECT_RATIO_MAP : Record < string , number > = {
26- '16:9' : 16 / 9 ,
27- '3:2' : 3 / 2 ,
28- '4:3' : 4 / 3 ,
29- '1:1' : 1 ,
30- '3:4' : 3 / 4 ,
31- '2:3' : 2 / 3 ,
32- '9:16' : 9 / 16 ,
33- } ;
34-
35- const getAspectRatioString = ( ratio : number | null ) => {
28+ const getAspectRatioString = ( ratio : number | null ) : AspectRatioID => {
3629 if ( ! ratio ) {
37- return 'free ' ;
30+ return 'Free ' ;
3831 }
39- const entries = Object . entries ( CROP_ASPECT_RATIO_MAP ) ;
32+ const entries = objectEntries ( ASPECT_RATIO_MAP ) ;
4033 for ( const [ key , value ] of entries ) {
41- if ( value === ratio ) {
34+ if ( value . ratio === ratio ) {
4235 return key ;
4336 }
4437 }
45- return 'free ' ;
38+ return 'Free ' ;
4639} ;
4740
48- export const EditorContainer = ( { editor, onApplyCrop, onReady } : Props ) => {
41+ export const CropImageEditor = memo ( ( { editor, onApplyCrop, onReady } : Props ) => {
4942 const containerRef = useRef < HTMLDivElement > ( null ) ;
5043 const [ zoom , setZoom ] = useState ( 100 ) ;
5144 const [ cropBox , setCropBox ] = useState < CropBox | null > ( null ) ;
@@ -90,12 +83,15 @@ export const EditorContainer = ({ editor, onApplyCrop, onReady }: Props) => {
9083 const handleAspectRatioChange = useCallback (
9184 ( e : React . ChangeEvent < HTMLSelectElement > ) => {
9285 const newRatio = e . target . value ;
86+ if ( ! isAspectRatioID ( newRatio ) ) {
87+ return ;
88+ }
9389 setAspectRatio ( newRatio ) ;
9490
95- if ( newRatio === 'free ' ) {
91+ if ( newRatio === 'Free ' ) {
9692 editor . setCropAspectRatio ( null ) ;
9793 } else {
98- editor . setCropAspectRatio ( CROP_ASPECT_RATIO_MAP [ newRatio ] ?? null ) ;
94+ editor . setCropAspectRatio ( ASPECT_RATIO_MAP [ newRatio ] ?. ratio ?? null ) ;
9995 }
10096 } ,
10197 [ editor ]
@@ -107,11 +103,11 @@ export const EditorContainer = ({ editor, onApplyCrop, onReady }: Props) => {
107103
108104 const handleApplyCrop = useCallback ( async ( ) => {
109105 await onApplyCrop ( ) ;
110- closeEditImageModal ( ) ;
106+ cropImageModalApi . close ( ) ;
111107 } , [ onApplyCrop ] ) ;
112108
113109 const handleCancelCrop = useCallback ( ( ) => {
114- closeEditImageModal ( ) ;
110+ cropImageModalApi . close ( ) ;
115111 } , [ ] ) ;
116112
117113 const handleExport = useCallback ( async ( ) => {
@@ -157,15 +153,15 @@ export const EditorContainer = ({ editor, onApplyCrop, onReady }: Props) => {
157153 < Flex gap = { 2 } alignItems = "center" >
158154 < FormControl flex = { 1 } >
159155 < FormLabel > Aspect Ratio:</ FormLabel >
160- < Select size = "sm" value = { aspectRatio } onChange = { handleAspectRatioChange } w = { 64 } >
161- < option value = "free " > Free</ option >
156+ < Select size = "sm" value = { aspectRatio } onChange = { handleAspectRatioChange } w = { 32 } >
157+ < option value = "Free " > Free</ option >
162158 < option value = "16:9" > 16:9</ option >
163159 < option value = "3:2" > 3:2</ option >
164160 < option value = "4:3" > 4:3</ option >
165- < option value = "1:1" > 1:1 (Square) </ option >
161+ < option value = "1:1" > 1:1</ option >
166162 < option value = "3:4" > 3:4</ option >
167- < option value = "2:3" > 2:3 (Portrait) </ option >
168- < option value = "9:16" > 9:16 (Portrait) </ option >
163+ < option value = "2:3" > 2:3</ option >
164+ < option value = "9:16" > 9:16</ option >
169165 </ Select >
170166 </ FormControl >
171167
@@ -184,7 +180,7 @@ export const EditorContainer = ({ editor, onApplyCrop, onReady }: Props) => {
184180 < Button onClick = { handleApplyCrop } > Apply</ Button >
185181 < Button onClick = { handleResetCrop } > Reset</ Button >
186182 < Button onClick = { handleCancelCrop } > Cancel</ Button >
187- < Button onClick = { handleExport } > Export </ Button >
183+ < Button onClick = { handleExport } > Save to Assets </ Button >
188184 </ ButtonGroup >
189185 </ Flex >
190186
@@ -212,4 +208,6 @@ export const EditorContainer = ({ editor, onApplyCrop, onReady }: Props) => {
212208 </ Flex >
213209 </ Flex >
214210 ) ;
215- } ;
211+ } ) ;
212+
213+ CropImageEditor . displayName = 'CropImageEditor' ;
0 commit comments