11// @flow
22
33import type { Action , Image , MainLayoutState } from "../MainLayout/types" ;
4- import { useEffect , useReducer } from "react" ;
5- import Immutable from "seamless-immutable" ;
4+ import { ComponentType , FunctionComponent , useEffect , useReducer } from "react" ;
5+ import Immutable , { ImmutableObject } from "seamless-immutable" ;
66
77import type { KeypointsDefinition } from "../ImageCanvas/region-tools" ;
88import MainLayout from "../MainLayout" ;
@@ -30,8 +30,8 @@ export type AnnotatorProps = {
3030 images ?: Array < Image > ;
3131 showPointDistances ?: boolean ;
3232 pointDistancePrecision ?: number ;
33- RegionEditLabel ?: Node ;
34- onExit : ( state : MainLayoutState ) => any ;
33+ RegionEditLabel ?: ComponentType < any > | FunctionComponent < any > | null ;
34+ onExit : ( state : MainLayoutState ) => void ;
3535 videoTime ?: number ;
3636 videoSrc ?: string ;
3737 keyframes ?: Object ;
@@ -102,58 +102,71 @@ export const Annotator = ({
102102 if ( selectedImage === - 1 ) selectedImage = undefined ;
103103 }
104104 const annotationType = images ? "image" : "video" ;
105- const [ state , dispatchToReducer ] = useReducer (
106- historyHandler (
107- combineReducers (
108- annotationType === "image" ? imageReducer : videoReducer ,
109- generalReducer
110- )
111- ) ,
112- Immutable ( {
113- annotationType,
114- showTags,
115- allowedArea,
116- showPointDistances,
117- pointDistancePrecision,
118- selectedTool,
119- fullImageSegmentationMode : fullImageSegmentationMode ,
120- autoSegmentationOptions,
121- mode : null ,
122- taskDescription,
123- showMask : true ,
124- labelImages : imageClsList . length > 0 || imageTagList . length > 0 ,
125- regionClsList,
126- regionTagList,
127- imageClsList,
128- imageTagList,
129- currentVideoTime : videoTime ,
130- enabledTools,
131- history : [ ] ,
132- videoName,
133- keypointDefinitions,
134- allowComments,
135- ...( annotationType === "image"
136- ? {
137- selectedImage,
138- images,
139- selectedImageFrameTime :
140- images && images . length > 0 ? images [ 0 ] . frameTime : undefined ,
141- }
142- : {
143- videoSrc,
144- keyframes,
145- } ) ,
146- } )
105+ const combinedReducers = (
106+ annotationType === "image"
107+ ? combineReducers ( imageReducer , generalReducer )
108+ : combineReducers ( videoReducer , generalReducer )
109+ ) as (
110+ state : ImmutableObject < MainLayoutState > ,
111+ action : Action
112+ ) => ImmutableObject < MainLayoutState > ;
113+
114+ const immutableState = Immutable ( {
115+ annotationType,
116+ showTags,
117+ allowedArea,
118+ showPointDistances,
119+ pointDistancePrecision,
120+ selectedTool,
121+ fullImageSegmentationMode : fullImageSegmentationMode ,
122+ autoSegmentationOptions,
123+ mode : null ,
124+ taskDescription,
125+ showMask : true ,
126+ labelImages : imageClsList . length > 0 || imageTagList . length > 0 ,
127+ regionClsList,
128+ regionTagList,
129+ imageClsList,
130+ imageTagList,
131+ currentVideoTime : videoTime ,
132+ enabledTools,
133+ history : [ ] ,
134+ videoName,
135+ keypointDefinitions,
136+ allowComments,
137+ ...( annotationType === "image"
138+ ? {
139+ selectedImage,
140+ images,
141+ selectedImageFrameTime :
142+ images && images . length > 0 ? images [ 0 ] . frameTime : undefined ,
143+ }
144+ : {
145+ videoSrc,
146+ keyframes,
147+ } ) ,
148+ } ) ;
149+ const [ state , dispatchToReducer ] = useReducer <
150+ ( state : MainLayoutState , action : Action ) => MainLayoutState
151+ > (
152+ historyHandler ( combinedReducers ) as unknown as (
153+ state : MainLayoutState ,
154+ action : Action
155+ ) => MainLayoutState ,
156+ immutableState as unknown as MainLayoutState
147157 ) ;
148158
149159 const dispatch = useEventCallback ( ( action : Action ) => {
150160 if ( action . type === "HEADER_BUTTON_CLICKED" ) {
161+ const value = ( Immutable ( state ) as ImmutableObject < MainLayoutState > )
162+ . without ( "history" )
163+ . asMutable ( { deep : true } ) ;
151164 if ( [ "Exit" , "Done" , "Save" , "Complete" ] . includes ( action . buttonName ) ) {
152- return onExit ( Immutable ( state ) . without ( "history" ) ) ;
165+ return onExit ( value ) ;
153166 } else if ( action . buttonName === "Next" && onNextImage ) {
154- return onNextImage ( Immutable ( state ) . without ( "history" ) ) ;
167+ return onNextImage ( value ) ;
155168 } else if ( action . buttonName === "Prev" && onPrevImage ) {
156- return onPrevImage ( Immutable ( state ) . without ( "history" ) ) ;
169+ return onPrevImage ( value ) ;
157170 }
158171 }
159172 dispatchToReducer ( action ) ;
@@ -167,13 +180,15 @@ export const Annotator = ({
167180 } ) ;
168181
169182 useEffect ( ( ) => {
170- if ( selectedImage === undefined ) return ;
183+ if ( selectedImage === undefined || state . annotationType !== "image" ) return ;
184+ const image = state . images [ selectedImage ] ;
171185 dispatchToReducer ( {
172186 type : "SELECT_IMAGE" ,
173187 imageIndex : + selectedImage ,
174- image : state . images [ selectedImage ] ,
188+ image,
175189 } ) ;
176- } , [ selectedImage , state . images ] ) ;
190+ // @ts -ignore
191+ } , [ selectedImage , state . annotationType , state . images ] ) ;
177192
178193 if ( ! images && ! videoSrc )
179194 return 'Missing required prop "images" or "videoSrc"' ;
0 commit comments