1#import <React/RCTImageSource.h>
2#import <React/RCTImageView.h>
3#import <UMCore/UMDefines.h>
4
5#import "EXKernel.h"
6#import "EXManagedAppSplashScreenConfiguration.h"
7#import "EXManagedAppSplashScreenConfigurationBuilder.h"
8#import "EXManagedAppSplashScreenViewProvider.h"
9#import "EXReactAppManager.h"
10
11@interface EXManagedAppSplashScreenViewProvider ()
12
13@property (nonatomic, weak) UIView *splashScreenView;
14@property (nonatomic, strong) EXManagedAppSplashScreenConfiguration *configuration;
15@property (nonatomic, strong, nullable) RCTImageView *splashImageView;
16
17@end
18
19@implementation EXManagedAppSplashScreenViewProvider
20
21- (instancetype)initWithManifest:(NSDictionary *)manifest
22{
23  if (self = [super init]) {
24    _configuration = [EXManagedAppSplashScreenConfigurationBuilder parseManifest:manifest];
25  }
26  return self;
27}
28
29- (void)updateSplashScreenViewWithManifest:(NSDictionary *)manifest
30{
31  EXManagedAppSplashScreenConfiguration *previousConfiguration = _configuration;
32  _configuration = [EXManagedAppSplashScreenConfigurationBuilder parseManifest:manifest];
33  if (_splashScreenView) {
34    [self configureSplashScreenView:_splashScreenView previousConfiguration:previousConfiguration];
35  }
36}
37
38- (UIView *)createSplashScreenView
39{
40  UIView *splashScreenView = [UIView new];
41  [self configureSplashScreenView:splashScreenView previousConfiguration:nil];
42  _splashScreenView = splashScreenView;
43  return splashScreenView;
44}
45
46- (void)configureSplashScreenView:(UIView *)splashScreenView previousConfiguration:(EXManagedAppSplashScreenConfiguration *)previousConfiguration
47{
48  UM_WEAKIFY(self);
49  dispatch_async(dispatch_get_main_queue(), ^{
50    UM_ENSURE_STRONGIFY(self);
51    splashScreenView.backgroundColor = self.configuration.backgroundColor;
52
53    if (self.configuration.imageUrl) {
54      EXKernelAppRecord *homeAppRecord = [EXKernel sharedInstance].appRegistry.homeAppRecord;
55
56      if (homeAppRecord.appManager.reactBridge) {
57        // Only re-create the splashImageView when the imageUrl or imageResizeMode changes
58        if (![previousConfiguration.imageUrl isEqualToString:self.configuration.imageUrl] ||
59            previousConfiguration.imageResizeMode != self.configuration.imageResizeMode) {
60          if (self.splashImageView) {
61            [self.splashImageView removeFromSuperview];
62          }
63          RCTImageSource *imageSource = [RCTConvert RCTImageSource:@{ @"uri": self.configuration.imageUrl }];
64
65          // splash image loading is taking some time that, what can result in no image visually presented during loading phase
66          // despite the fact the RCTImageView is mounted in the view hierarchy
67          self.splashImageView = [[RCTImageView alloc] initWithBridge:homeAppRecord.appManager.reactBridge];
68          self.splashImageView.frame = splashScreenView.bounds;
69          self.splashImageView.imageSources = @[imageSource];
70          self.splashImageView.resizeMode = self.configuration.imageResizeMode == EXSplashScreenImageResizeModeCover ? RCTResizeModeCover : RCTResizeModeContain;
71          [splashScreenView addSubview:self.splashImageView];
72        }
73      }
74    }
75  });
76}
77
78@end
79
80