8
8
* @flow
9
9
*/
10
10
11
- import type { ImageResult , ImageSource } from '../../modules/ImageLoader' ;
12
- import type {
13
- ImageLoadingProps ,
14
- ImageProps ,
15
- Source ,
16
- SourceState
17
- } from './types' ;
11
+ import type { ImageSource } from '../../modules/ImageLoader' ;
12
+ import type { ImageProps , Source } from './types' ;
18
13
19
14
import * as React from 'react' ;
20
15
import createElement from '../createElement' ;
@@ -100,11 +95,6 @@ function getFlatStyle(style, blurRadius, filterId) {
100
95
return [ flatStyle , resizeMode , _filter , tintColor ] ;
101
96
}
102
97
103
- function resolveAssetDimensions ( source : ImageSource ) {
104
- const { height, width } = source ;
105
- return { height, width } ;
106
- }
107
-
108
98
function resolveSource ( source : ?Source ) : ImageSource {
109
99
let resolvedSource = { uri : '' } ;
110
100
@@ -132,16 +122,8 @@ function resolveSource(source: ?Source): ImageSource {
132
122
resolvedSource = { uri, width : asset . width , height : asset . height } ;
133
123
} else if ( typeof source === 'string' ) {
134
124
resolvedSource . uri = source ;
135
- } else if ( Array . isArray ( source ) ) {
136
- if ( process . env . NODE_ENV !== 'production' ) {
137
- console . warn (
138
- 'The <Image> component does not support multiple sources passed as array, falling back to the first source in the list' ,
139
- { source }
140
- ) ;
141
- }
142
-
143
- return resolveSource ( source [ 0 ] ) ;
144
125
} else if ( source && typeof source . uri === 'string' ) {
126
+ // $FlowFixMe
145
127
const { uri, width, height, headers } = source ;
146
128
resolvedSource = { uri, width, height, headers } ;
147
129
}
@@ -159,19 +141,6 @@ function resolveSource(source: ?Source): ImageSource {
159
141
return resolvedSource ;
160
142
}
161
143
162
- function getSourceToDisplay ( main : SourceState , fallback : SourceState ) {
163
- if ( main . status === LOADED ) return main . source ;
164
-
165
- // If there's no fallback URI, it's safe to use the main source URI
166
- if ( main . status === LOADING && ! fallback . source . uri ) {
167
- // But it should not be used when the image would be loaded with custom headers
168
- // Because the actual URI is only set (as a local blob url) after loading
169
- if ( ! main . source . headers ) return main . source ;
170
- }
171
-
172
- return fallback . source ;
173
- }
174
-
175
144
interface ImageStatics {
176
145
getSize : (
177
146
uri : string ,
@@ -212,7 +181,9 @@ const Image: React.AbstractComponent<
212
181
}
213
182
}
214
183
215
- // Don't raise load events for the fallback source
184
+ // Only the main source is supposed to trigger onLoad/start/end events
185
+ // It would be ambiguous to trigger the same `onLoad` event when default source loads
186
+ // That's why we don't pass `onLoad` props for the fallback source hook
216
187
const fallbackSource = useSource ( { onError } , defaultSource ) ;
217
188
const mainSource = useSource (
218
189
{ onLoad, onLoadStart, onLoadEnd, onError } ,
@@ -222,15 +193,17 @@ const Image: React.AbstractComponent<
222
193
const hasTextAncestor = React . useContext ( TextAncestorContext ) ;
223
194
const hiddenImageRef = React . useRef ( null ) ;
224
195
const filterRef = React . useRef ( _filterId ++ ) ;
196
+ const shouldDisplaySource =
197
+ mainSource . status === LOADED ||
198
+ ( mainSource . status === LOADING && defaultSource == null ) ;
225
199
const [ flatStyle , _resizeMode , filter , tintColor ] = getFlatStyle (
226
200
style ,
227
201
blurRadius ,
228
202
filterRef . current
229
203
) ;
230
204
const resizeMode = props . resizeMode || _resizeMode || 'cover' ;
231
- const availableSource = getSourceToDisplay ( mainSource , fallbackSource ) ;
232
- const displayImageUri = ImageLoader . resolveUri ( availableSource . uri ) ;
233
- const imageSizeStyle = resolveAssetDimensions ( availableSource ) ;
205
+ const selected = shouldDisplaySource ? mainSource : fallbackSource ;
206
+ const displayImageUri = selected . source . uri ;
234
207
const backgroundImage = displayImageUri ? `url("${ displayImageUri } ")` : null ;
235
208
const backgroundSize = getBackgroundSize ( ) ;
236
209
@@ -283,7 +256,7 @@ const Image: React.AbstractComponent<
283
256
style = { [
284
257
styles . root ,
285
258
hasTextAncestor && styles . inline ,
286
- imageSizeStyle ,
259
+ { width : selected . source . width , height : selected . source . height } ,
287
260
flatStyle
288
261
] }
289
262
>
@@ -326,10 +299,7 @@ ImageWithStatics.queryCache = function (uris) {
326
299
/**
327
300
* Image loading/state management hook
328
301
*/
329
- const useSource = (
330
- callbacks : ImageLoadingProps ,
331
- source : ?Source
332
- ) : SourceState => {
302
+ const useSource = ( callbacks , source : ?Source ) => {
333
303
const [ resolvedSource , setResolvedSource ] = React . useState < ImageSource > ( ( ) =>
334
304
resolveSource ( source )
335
305
) ;
@@ -369,8 +339,9 @@ const useSource = (
369
339
return ;
370
340
}
371
341
342
+ // $FlowFixMe
372
343
const { onLoad, onLoadStart, onLoadEnd, onError } = callbackRefs . current ;
373
- function handleLoad ( result : ImageResult ) {
344
+ function handleLoad ( result ) {
374
345
if ( onLoad ) onLoad ( { nativeEvent : result } ) ;
375
346
if ( onLoadEnd ) onLoadEnd ( ) ;
376
347
@@ -398,7 +369,7 @@ const useSource = (
398
369
const requestId = ImageLoader . load ( resolvedSource , handleLoad , handleError ) ;
399
370
400
371
// Release resources on unmount or after starting a new request
401
- return ( ) => ImageLoader . release ( requestId ) ;
372
+ return ( ) => ImageLoader . abort ( requestId ) ;
402
373
} , [ resolvedSource ] ) ;
403
374
404
375
return { status, source : result } ;
0 commit comments