PHP 7.4.33
Preview: RCTImageCache.mm Size: 5.74 KB
/var/www/uibuilder.cmshelp.dk/httpdocs/node_modules/react-native/Libraries/Image/RCTImageCache.mm
/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#import <React/RCTImageCache.h>

#import <objc/runtime.h>

#import <ImageIO/ImageIO.h>

#import <React/RCTConvert.h>
#import <React/RCTNetworking.h>
#import <React/RCTResizeMode.h>
#import <React/RCTUtils.h>

#import <React/RCTImageUtils.h>

static NSUInteger RCTMaxCacheableDecodedImageSizeInBytes = 2 * 1024 * 1024;
static NSUInteger RCTImageCacheTotalCostLimit = 20 * 1024 * 1024;

void RCTSetImageCacheLimits(NSUInteger maxCacheableDecodedImageSizeInBytes, NSUInteger imageCacheTotalCostLimit)
{
  RCTMaxCacheableDecodedImageSizeInBytes = maxCacheableDecodedImageSizeInBytes;
  RCTImageCacheTotalCostLimit = imageCacheTotalCostLimit;
}

static NSString *RCTCacheKeyForImage(NSString *imageTag, CGSize size, CGFloat scale, RCTResizeMode resizeMode)
{
  return
      [NSString stringWithFormat:@"%@|%g|%g|%g|%lld", imageTag, size.width, size.height, scale, (long long)resizeMode];
}

@implementation RCTImageCache {
  NSOperationQueue *_imageDecodeQueue;
  NSCache *_decodedImageCache;
  NSMutableDictionary *_cacheStaleTimes;
}

- (instancetype)init
{
  if (self = [super init]) {
    _decodedImageCache = [NSCache new];
    _decodedImageCache.totalCostLimit = RCTImageCacheTotalCostLimit;
    _cacheStaleTimes = [NSMutableDictionary new];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(clearCache)
                                                 name:UIApplicationDidReceiveMemoryWarningNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(clearCache)
                                                 name:UIApplicationWillResignActiveNotification
                                               object:nil];
  }

  return self;
}

- (void)clearCache
{
  [_decodedImageCache removeAllObjects];
  @synchronized(_cacheStaleTimes) {
    [_cacheStaleTimes removeAllObjects];
  }
}

- (void)addImageToCache:(UIImage *)image forKey:(NSString *)cacheKey
{
  if (!image) {
    return;
  }
  NSInteger bytes = image.reactDecodedImageBytes;
  if (bytes <= RCTMaxCacheableDecodedImageSizeInBytes) {
    [self->_decodedImageCache setObject:image forKey:cacheKey cost:bytes];
  }
}

- (UIImage *)imageForUrl:(NSString *)url size:(CGSize)size scale:(CGFloat)scale resizeMode:(RCTResizeMode)resizeMode
{
  NSString *cacheKey = RCTCacheKeyForImage(url, size, scale, resizeMode);
  @synchronized(_cacheStaleTimes) {
    id staleTime = _cacheStaleTimes[cacheKey];
    if (staleTime) {
      if ([[NSDate new] compare:(NSDate *)staleTime] == NSOrderedDescending) {
        // cached image has expired, clear it out to make room for others
        [_cacheStaleTimes removeObjectForKey:cacheKey];
        [_decodedImageCache removeObjectForKey:cacheKey];
        return nil;
      }
    }
  }
  return [_decodedImageCache objectForKey:cacheKey];
}

- (void)addImageToCache:(UIImage *)image
                    URL:(NSString *)url
                   size:(CGSize)size
                  scale:(CGFloat)scale
             resizeMode:(RCTResizeMode)resizeMode
               response:(NSURLResponse *)response
{
  if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
    NSString *cacheKey = RCTCacheKeyForImage(url, size, scale, resizeMode);
    BOOL shouldCache = YES;
    NSString *responseDate = ((NSHTTPURLResponse *)response).allHeaderFields[@"Date"];
    NSDate *originalDate = [self dateWithHeaderString:responseDate];
    NSString *cacheControl = ((NSHTTPURLResponse *)response).allHeaderFields[@"Cache-Control"];
    NSDate *staleTime;
    NSArray<NSString *> *components = [cacheControl componentsSeparatedByString:@","];
    for (NSString *component in components) {
      if ([component containsString:@"no-cache"] || [component containsString:@"no-store"] ||
          [component hasSuffix:@"max-age=0"]) {
        shouldCache = NO;
        break;
      } else {
        NSRange range = [component rangeOfString:@"max-age="];
        if (range.location != NSNotFound) {
          NSInteger seconds = [[component substringFromIndex:range.location + range.length] integerValue];
          staleTime = [originalDate dateByAddingTimeInterval:(NSTimeInterval)seconds];
        }
      }
    }
    if (shouldCache) {
      if (!staleTime && originalDate) {
        NSString *expires = ((NSHTTPURLResponse *)response).allHeaderFields[@"Expires"];
        NSString *lastModified = ((NSHTTPURLResponse *)response).allHeaderFields[@"Last-Modified"];
        if (expires) {
          staleTime = [self dateWithHeaderString:expires];
        } else if (lastModified) {
          NSDate *lastModifiedDate = [self dateWithHeaderString:lastModified];
          if (lastModifiedDate) {
            NSTimeInterval interval = [originalDate timeIntervalSinceDate:lastModifiedDate] / 10;
            staleTime = [originalDate dateByAddingTimeInterval:interval];
          }
        }
      }
      if (staleTime) {
        @synchronized(_cacheStaleTimes) {
          _cacheStaleTimes[cacheKey] = staleTime;
        }
      }
      return [self addImageToCache:image forKey:cacheKey];
    }
  }
}

- (NSDate *)dateWithHeaderString:(NSString *)headerDateString
{
  static NSDateFormatter *formatter;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    formatter = [NSDateFormatter new];
    formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    formatter.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";
    formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
  });

  return [formatter dateFromString:headerDateString];
}

@end

Directory Contents

Dirs: 0 × Files: 70
Name Size Perms Modified Actions
305 B lrw-r--r-- 2025-03-28 11:04:42
Edit Download
6.37 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
1.24 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
10.57 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
10.79 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
7.92 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
306 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
465 B lrw-r--r-- 2025-03-28 11:04:42
Edit Download
3.14 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
2.52 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
7.11 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
1.47 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
1.12 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
2.81 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
3.94 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
2.36 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
2.20 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
595 B lrw-r--r-- 2025-03-28 11:04:42
Edit Download
4.93 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
406 B lrw-r--r-- 2025-03-28 11:04:42
Edit Download
440 B lrw-r--r-- 2025-03-28 11:04:42
Edit Download
424 B lrw-r--r-- 2025-03-28 11:04:42
Edit Download
1.69 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
430 B lrw-r--r-- 2025-03-28 11:04:42
Edit Download
414 B lrw-r--r-- 2025-03-28 11:04:42
Edit Download
609 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
4.76 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
302 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
2.16 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
569 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
841 B lrw-r--r-- 2025-03-28 11:04:43
Edit Download
299 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
1.51 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
364 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
3.58 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
1.20 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
5.74 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
1.85 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
295 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
4.38 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
1.42 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
51.56 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
816 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
6.15 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
2.01 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
1.10 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
1.04 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
276 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
380 B lrw-r--r-- 2025-03-28 11:04:43
Edit Download
1.69 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
8.35 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
3.13 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
2.84 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
707 B lrw-r--r-- 2025-03-28 11:04:43
Edit Download
3.50 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
12.22 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
844 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
15.24 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
279 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
4.53 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
362 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
2.16 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
1.53 KB lrw-r--r-- 2025-03-28 11:04:41
Edit Download
623 B lrw-r--r-- 2025-03-28 11:04:43
Edit Download
310 B lrw-r--r-- 2025-03-28 11:04:41
Edit Download
10.67 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
2.43 KB lrw-r--r-- 2025-03-28 11:04:43
Edit Download
710 B lrw-r--r-- 2025-03-28 11:04:42
Edit Download
4.22 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
1.30 KB lrw-r--r-- 2025-03-28 11:04:42
Edit Download
If ZipArchive is unavailable, a .tar will be created (no compression).