react-native-fast-image 8.6.41 → 8.6.42
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;
|
|
@@ -232,6 +253,8 @@
|
|
|
232
253
|
}
|
|
233
254
|
self.hasCompleted = NO;
|
|
234
255
|
self.hasErrored = NO;
|
|
256
|
+
self.retriedAfterBackground = NO;
|
|
257
|
+
[self stopWaitingForActive];
|
|
235
258
|
|
|
236
259
|
[self downloadImage: _source options: options context: context];
|
|
237
260
|
} else if (_defaultSource) {
|
|
@@ -267,6 +290,7 @@
|
|
|
267
290
|
});
|
|
268
291
|
};
|
|
269
292
|
}
|
|
293
|
+
CFTimeInterval startedAt = CACurrentMediaTime();
|
|
270
294
|
[self sd_setImageWithURL: _source.url
|
|
271
295
|
placeholderImage: _defaultSource
|
|
272
296
|
options: options
|
|
@@ -276,6 +300,18 @@
|
|
|
276
300
|
NSError* _Nullable error,
|
|
277
301
|
SDImageCacheType cacheType,
|
|
278
302
|
NSURL* _Nullable imageURL) {
|
|
303
|
+
// The download was running when the app went to the
|
|
304
|
+
// background, and failed: iOS suspends it there, and its
|
|
305
|
+
// timeout keeps counting, so it times out as the app comes
|
|
306
|
+
// back (NSURLErrorTimedOut), or loses its connection. Load it
|
|
307
|
+
// again once the app is active, as Android does (#758).
|
|
308
|
+
if (error && [error.domain isEqualToString: NSURLErrorDomain] &&
|
|
309
|
+
FFFEnteredBackgroundAt > startedAt && !weakSelf.retriedAfterBackground &&
|
|
310
|
+
weakSelf.source == source) {
|
|
311
|
+
weakSelf.retriedAfterBackground = YES;
|
|
312
|
+
[weakSelf downloadWhenActive: source options: options context: context];
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
279
315
|
if (error) {
|
|
280
316
|
weakSelf.hasErrored = YES;
|
|
281
317
|
if (weakSelf.onFastImageError) {
|
|
@@ -294,7 +330,37 @@
|
|
|
294
330
|
}];
|
|
295
331
|
}
|
|
296
332
|
|
|
333
|
+
// Downloads the source now if the app is active, or once it is (unless
|
|
334
|
+
// another load started meanwhile).
|
|
335
|
+
- (void) downloadWhenActive: (FFFastImageSource*)source options: (SDWebImageOptions)options context: (SDWebImageContext*)context {
|
|
336
|
+
// nil in app extensions, which don't get these notifications.
|
|
337
|
+
UIApplication* application = RCTSharedApplication();
|
|
338
|
+
if (!application || application.applicationState == UIApplicationStateActive) {
|
|
339
|
+
[self downloadImage: source options: options context: context];
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
[self stopWaitingForActive];
|
|
343
|
+
__weak typeof(self) weakSelf = self;
|
|
344
|
+
self.activeObserver = [[NSNotificationCenter defaultCenter] addObserverForName: UIApplicationDidBecomeActiveNotification
|
|
345
|
+
object: nil
|
|
346
|
+
queue: [NSOperationQueue mainQueue]
|
|
347
|
+
usingBlock: ^(NSNotification* notification) {
|
|
348
|
+
[weakSelf stopWaitingForActive];
|
|
349
|
+
if (weakSelf.source == source) {
|
|
350
|
+
[weakSelf downloadImage: source options: options context: context];
|
|
351
|
+
}
|
|
352
|
+
}];
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
- (void) stopWaitingForActive {
|
|
356
|
+
if (self.activeObserver) {
|
|
357
|
+
[[NSNotificationCenter defaultCenter] removeObserver: self.activeObserver];
|
|
358
|
+
self.activeObserver = nil;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
297
362
|
- (void) dealloc {
|
|
363
|
+
[self stopWaitingForActive];
|
|
298
364
|
[self sd_cancelCurrentImageLoad];
|
|
299
365
|
}
|
|
300
366
|
|