1#import <React/RCTImageSource.h> 2#import <React/RCTImageView.h> 3#import <ExpoModulesCore/EXDefines.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:(EXManifestsManifest *)manifest 22{ 23 if (self = [super init]) { 24 _configuration = [EXManagedAppSplashScreenConfigurationBuilder parseManifest:manifest]; 25 } 26 return self; 27} 28 29- (void)updateSplashScreenViewWithManifest:(EXManifestsManifest *)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 EX_WEAKIFY(self); 49 dispatch_async(dispatch_get_main_queue(), ^{ 50 EX_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