1
1
// @flow
2
2
3
3
import 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" ;
6
6
7
7
import type { KeypointsDefinition } from "../ImageCanvas/region-tools" ;
8
8
import MainLayout from "../MainLayout" ;
@@ -30,8 +30,8 @@ export type AnnotatorProps = {
30
30
images ?: Array < Image > ;
31
31
showPointDistances ?: boolean ;
32
32
pointDistancePrecision ?: number ;
33
- RegionEditLabel ?: Node ;
34
- onExit : ( state : MainLayoutState ) => any ;
33
+ RegionEditLabel ?: ComponentType < any > | FunctionComponent < any > | null ;
34
+ onExit : ( state : MainLayoutState ) => void ;
35
35
videoTime ?: number ;
36
36
videoSrc ?: string ;
37
37
keyframes ?: Object ;
@@ -102,58 +102,71 @@ export const Annotator = ({
102
102
if ( selectedImage === - 1 ) selectedImage = undefined ;
103
103
}
104
104
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
147
157
) ;
148
158
149
159
const dispatch = useEventCallback ( ( action : Action ) => {
150
160
if ( action . type === "HEADER_BUTTON_CLICKED" ) {
161
+ const value = ( Immutable ( state ) as ImmutableObject < MainLayoutState > )
162
+ . without ( "history" )
163
+ . asMutable ( { deep : true } ) ;
151
164
if ( [ "Exit" , "Done" , "Save" , "Complete" ] . includes ( action . buttonName ) ) {
152
- return onExit ( Immutable ( state ) . without ( "history" ) ) ;
165
+ return onExit ( value ) ;
153
166
} else if ( action . buttonName === "Next" && onNextImage ) {
154
- return onNextImage ( Immutable ( state ) . without ( "history" ) ) ;
167
+ return onNextImage ( value ) ;
155
168
} else if ( action . buttonName === "Prev" && onPrevImage ) {
156
- return onPrevImage ( Immutable ( state ) . without ( "history" ) ) ;
169
+ return onPrevImage ( value ) ;
157
170
}
158
171
}
159
172
dispatchToReducer ( action ) ;
@@ -167,13 +180,15 @@ export const Annotator = ({
167
180
} ) ;
168
181
169
182
useEffect ( ( ) => {
170
- if ( selectedImage === undefined ) return ;
183
+ if ( selectedImage === undefined || state . annotationType !== "image" ) return ;
184
+ const image = state . images [ selectedImage ] ;
171
185
dispatchToReducer ( {
172
186
type : "SELECT_IMAGE" ,
173
187
imageIndex : + selectedImage ,
174
- image : state . images [ selectedImage ] ,
188
+ image,
175
189
} ) ;
176
- } , [ selectedImage , state . images ] ) ;
190
+ // @ts -ignore
191
+ } , [ selectedImage , state . annotationType , state . images ] ) ;
177
192
178
193
if ( ! images && ! videoSrc )
179
194
return 'Missing required prop "images" or "videoSrc"' ;
0 commit comments