react-native-fast-image 8.6.41 → 8.6.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  #import "FFFastImageView.h"
2
2
  #import <SDWebImage/UIImage+MultiFormat.h>
3
3
  #import <SDWebImage/UIView+WebCache.h>
4
+ #import <React/RCTUtils.h>
4
5
 
5
6
  @interface FFFastImageView ()
6
7
 
@@ -14,11 +15,31 @@
14
15
  // The image before tinting, kept while a tint is applied so the tint can be
15
16
  // changed or removed. nil when there's no tint (super.image is untinted).
16
17
  @property(nonatomic, strong) UIImage* untintedImage;
18
+ // Whether the current load was already restarted after the app came back
19
+ // from the background (see downloadImage:).
20
+ @property(nonatomic, assign) BOOL retriedAfterBackground;
21
+ // Waits for the app to be active again, to restart a load.
22
+ @property(nonatomic, strong) id activeObserver;
17
23
 
18
24
  @end
19
25
 
26
+ // When the app last went to the background (CACurrentMediaTime), or 0.
27
+ static CFTimeInterval FFFEnteredBackgroundAt = 0;
28
+
20
29
  @implementation FFFastImageView
21
30
 
31
+ + (void) initialize {
32
+ if (self != [FFFastImageView class]) {
33
+ return;
34
+ }
35
+ [[NSNotificationCenter defaultCenter] addObserverForName: UIApplicationDidEnterBackgroundNotification
36
+ object: nil
37
+ queue: [NSOperationQueue mainQueue]
38
+ usingBlock: ^(NSNotification* notification) {
39
+ FFFEnteredBackgroundAt = CACurrentMediaTime();
40
+ }];
41
+ }
42
+
22
43
  - (id) init {
23
44
  self = [super init];
24
45
  self.resizeMode = RCTResizeModeCover;
@@ -29,10 +50,34 @@
29
50
  - (void) setResizeMode: (RCTResizeMode)resizeMode {
30
51
  if (_resizeMode != resizeMode) {
31
52
  _resizeMode = resizeMode;
32
- self.contentMode = (UIViewContentMode) resizeMode;
53
+ [self updateContentMode];
54
+ }
55
+ }
56
+
57
+ // The content mode for resizeMode. `center` scales an image larger than the
58
+ // view down to fit, as React Native's Image and Android do (#866); only a
59
+ // smaller one is shown at its own size. UIViewContentModeCenter alone showed
60
+ // large images at full size, cropped. So it depends on the image and the
61
+ // view's size.
62
+ - (void) updateContentMode {
63
+ UIViewContentMode contentMode = (UIViewContentMode) _resizeMode;
64
+ if (_resizeMode == RCTResizeModeCenter) {
65
+ CGSize imageSize = super.image.size;
66
+ CGSize viewSize = self.bounds.size;
67
+ if (imageSize.width > viewSize.width || imageSize.height > viewSize.height) {
68
+ contentMode = UIViewContentModeScaleAspectFit;
69
+ }
70
+ }
71
+ if (self.contentMode != contentMode) {
72
+ self.contentMode = contentMode;
33
73
  }
34
74
  }
35
75
 
76
+ - (void) layoutSubviews {
77
+ [super layoutSubviews];
78
+ [self updateContentMode];
79
+ }
80
+
36
81
  - (void) setOnFastImageLoadEnd: (RCTDirectEventBlock)onFastImageLoadEnd {
37
82
  _onFastImageLoadEnd = onFastImageLoadEnd;
38
83
  if (self.hasCompleted && _onFastImageLoadEnd) {
@@ -121,6 +166,7 @@
121
166
  self.untintedImage = nil;
122
167
  super.image = image;
123
168
  }
169
+ [self updateContentMode];
124
170
  }
125
171
 
126
172
  - (void) sendOnLoad: (UIImage*)image {
@@ -232,6 +278,8 @@
232
278
  }
233
279
  self.hasCompleted = NO;
234
280
  self.hasErrored = NO;
281
+ self.retriedAfterBackground = NO;
282
+ [self stopWaitingForActive];
235
283
 
236
284
  [self downloadImage: _source options: options context: context];
237
285
  } else if (_defaultSource) {
@@ -267,6 +315,7 @@
267
315
  });
268
316
  };
269
317
  }
318
+ CFTimeInterval startedAt = CACurrentMediaTime();
270
319
  [self sd_setImageWithURL: _source.url
271
320
  placeholderImage: _defaultSource
272
321
  options: options
@@ -276,6 +325,18 @@
276
325
  NSError* _Nullable error,
277
326
  SDImageCacheType cacheType,
278
327
  NSURL* _Nullable imageURL) {
328
+ // The download was running when the app went to the
329
+ // background, and failed: iOS suspends it there, and its
330
+ // timeout keeps counting, so it times out as the app comes
331
+ // back (NSURLErrorTimedOut), or loses its connection. Load it
332
+ // again once the app is active, as Android does (#758).
333
+ if (error && [error.domain isEqualToString: NSURLErrorDomain] &&
334
+ FFFEnteredBackgroundAt > startedAt && !weakSelf.retriedAfterBackground &&
335
+ weakSelf.source == source) {
336
+ weakSelf.retriedAfterBackground = YES;
337
+ [weakSelf downloadWhenActive: source options: options context: context];
338
+ return;
339
+ }
279
340
  if (error) {
280
341
  weakSelf.hasErrored = YES;
281
342
  if (weakSelf.onFastImageError) {
@@ -294,7 +355,37 @@
294
355
  }];
295
356
  }
296
357
 
358
+ // Downloads the source now if the app is active, or once it is (unless
359
+ // another load started meanwhile).
360
+ - (void) downloadWhenActive: (FFFastImageSource*)source options: (SDWebImageOptions)options context: (SDWebImageContext*)context {
361
+ // nil in app extensions, which don't get these notifications.
362
+ UIApplication* application = RCTSharedApplication();
363
+ if (!application || application.applicationState == UIApplicationStateActive) {
364
+ [self downloadImage: source options: options context: context];
365
+ return;
366
+ }
367
+ [self stopWaitingForActive];
368
+ __weak typeof(self) weakSelf = self;
369
+ self.activeObserver = [[NSNotificationCenter defaultCenter] addObserverForName: UIApplicationDidBecomeActiveNotification
370
+ object: nil
371
+ queue: [NSOperationQueue mainQueue]
372
+ usingBlock: ^(NSNotification* notification) {
373
+ [weakSelf stopWaitingForActive];
374
+ if (weakSelf.source == source) {
375
+ [weakSelf downloadImage: source options: options context: context];
376
+ }
377
+ }];
378
+ }
379
+
380
+ - (void) stopWaitingForActive {
381
+ if (self.activeObserver) {
382
+ [[NSNotificationCenter defaultCenter] removeObserver: self.activeObserver];
383
+ self.activeObserver = nil;
384
+ }
385
+ }
386
+
297
387
  - (void) dealloc {
388
+ [self stopWaitingForActive];
298
389
  [self sd_cancelCurrentImageLoad];
299
390
  }
300
391
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-fast-image",
3
- "version": "8.6.41",
3
+ "version": "8.6.43",
4
4
  "description": "🚩 FastImage, performant React Native image component.",
5
5
  "keywords": [
6
6
  "cache",