1*232917c1SKudo Chien#import "EXAppLoadingProgressWindowController.h" 2*232917c1SKudo Chien 3*232917c1SKudo Chien#import <React/React-Core-umbrella.h> // Keeps this import to fix the error from building React module: `error: definition of 'RCTBridge' must be imported from module 'React' before it is required` 4*232917c1SKudo Chien 5efd75decSTomasz Sapeta#import <ExpoModulesCore/EXDefines.h> 69ef743bcSBartłomiej Bukowski 7bab1112dSTomasz Sapeta#if !defined(EX_DETACHED) 8c46d5aaeSBartłomiej Bukowski#import "Expo_Go-Swift.h" 9bab1112dSTomasz Sapeta#endif // !defined(EX_DETACHED) 101236efb4STomasz Sapeta 119ef743bcSBartłomiej Bukowski#import "EXUtil.h" 129ef743bcSBartłomiej Bukowski 139ef743bcSBartłomiej Bukowski@interface EXAppLoadingProgressWindowController () 149ef743bcSBartłomiej Bukowski 159ef743bcSBartłomiej Bukowski@property (nonatomic, assign) BOOL enabled; 169ef743bcSBartłomiej Bukowski@property (nonatomic, strong) UIWindow *window; 179ef743bcSBartłomiej Bukowski@property (nonatomic, strong) UILabel *textLabel; 189ef743bcSBartłomiej Bukowski 199ef743bcSBartłomiej Bukowski@end 209ef743bcSBartłomiej Bukowski 219ef743bcSBartłomiej Bukowski@implementation EXAppLoadingProgressWindowController 229ef743bcSBartłomiej Bukowski 239ef743bcSBartłomiej Bukowski- (instancetype)initWithEnabled:(BOOL)enabled 249ef743bcSBartłomiej Bukowski{ 259ef743bcSBartłomiej Bukowski if (self = [super init]) { 269ef743bcSBartłomiej Bukowski _enabled = enabled; 279ef743bcSBartłomiej Bukowski } 289ef743bcSBartłomiej Bukowski return self; 299ef743bcSBartłomiej Bukowski} 309ef743bcSBartłomiej Bukowski 319ef743bcSBartłomiej Bukowski- (void)show 329ef743bcSBartłomiej Bukowski{ 33bab1112dSTomasz Sapeta#if !defined(EX_DETACHED) 349ef743bcSBartłomiej Bukowski if (!_enabled) { 359ef743bcSBartłomiej Bukowski return; 369ef743bcSBartłomiej Bukowski } 379ef743bcSBartłomiej Bukowski 38efd75decSTomasz Sapeta EX_WEAKIFY(self); 399ef743bcSBartłomiej Bukowski dispatch_async(dispatch_get_main_queue(), ^{ 40efd75decSTomasz Sapeta EX_ENSURE_STRONGIFY(self); 419ef743bcSBartłomiej Bukowski if (!self.window) { 429ef743bcSBartłomiej Bukowski CGSize screenSize = [UIScreen mainScreen].bounds.size; 439ef743bcSBartłomiej Bukowski 4471ebd28eSCharlie Cruzan int bottomInsets = EXSharedApplication().keyWindow.safeAreaInsets.bottom; 4576b4fe7aSBartłomiej Bukowski self.window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 4676b4fe7aSBartłomiej Bukowski screenSize.height - 36 - bottomInsets, 4776b4fe7aSBartłomiej Bukowski screenSize.width, 48892d420fSEric Samelson 36 + bottomInsets)]; 499ef743bcSBartłomiej Bukowski self.window.windowLevel = UIWindowLevelStatusBar + 1; 50c46d5aaeSBartłomiej Bukowski self.window.rootViewController = [EXAppLoadingProgressWindowViewController new]; 51892d420fSEric Samelson self.window.backgroundColor = [EXUtil colorWithRGB:0xfafafa]; 529ef743bcSBartłomiej Bukowski 539ef743bcSBartłomiej Bukowski UIView *containerView = [UIView new]; 549ef743bcSBartłomiej Bukowski [self.window addSubview:containerView]; 559ef743bcSBartłomiej Bukowski 569ef743bcSBartłomiej Bukowski CALayer *topBorderLayer = [CALayer layer]; 579ef743bcSBartłomiej Bukowski topBorderLayer.frame = CGRectMake(0, 0, screenSize.width, 1); 589ef743bcSBartłomiej Bukowski topBorderLayer.backgroundColor = [EXUtil colorWithRGB:0xe3e3e3].CGColor; 599ef743bcSBartłomiej Bukowski [containerView.layer addSublayer:topBorderLayer]; 609ef743bcSBartłomiej Bukowski 619ef743bcSBartłomiej Bukowski self.textLabel = [UILabel new]; 629ef743bcSBartłomiej Bukowski self.textLabel.frame = CGRectMake(10, 0, screenSize.width - 20, 36); 639ef743bcSBartłomiej Bukowski self.textLabel.font = [UIFont systemFontOfSize:12]; 649ef743bcSBartłomiej Bukowski self.textLabel.textAlignment = NSTextAlignmentLeft; 659ef743bcSBartłomiej Bukowski self.textLabel.textColor = [EXUtil colorWithRGB:0xa7a7a7]; 669ef743bcSBartłomiej Bukowski [containerView addSubview:self.textLabel]; 679ef743bcSBartłomiej Bukowski } 689ef743bcSBartłomiej Bukowski self.textLabel.text = @"Waiting for server ..."; 699ef743bcSBartłomiej Bukowski self.window.hidden = NO; 709ef743bcSBartłomiej Bukowski }); 71bab1112dSTomasz Sapeta#endif // !defined(EX_DETACHED) 729ef743bcSBartłomiej Bukowski} 739ef743bcSBartłomiej Bukowski 749ef743bcSBartłomiej Bukowski- (void)hide 759ef743bcSBartłomiej Bukowski{ 76bab1112dSTomasz Sapeta#if !defined(EX_DETACHED) 779ef743bcSBartłomiej Bukowski if (!_enabled) { 789ef743bcSBartłomiej Bukowski return; 799ef743bcSBartłomiej Bukowski } 809ef743bcSBartłomiej Bukowski 81efd75decSTomasz Sapeta EX_WEAKIFY(self); 8237ed3460SEric Samelson dispatch_async(dispatch_get_main_queue(), ^{ 83efd75decSTomasz Sapeta EX_ENSURE_STRONGIFY(self); 8464c37d52SBartłomiej Bukowski if (self.window) { 859ef743bcSBartłomiej Bukowski self.window.hidden = YES; 86c46d5aaeSBartłomiej Bukowski // remove this window altogther to hand over the command over StatusBar rotation 87c46d5aaeSBartłomiej Bukowski self.window = nil; 889ef743bcSBartłomiej Bukowski } 8937ed3460SEric Samelson }); 90bab1112dSTomasz Sapeta#endif // !defined(EX_DETACHED) 9164c37d52SBartłomiej Bukowski} 929ef743bcSBartłomiej Bukowski 939ef743bcSBartłomiej Bukowski- (void)updateStatusWithProgress:(EXLoadingProgress *)progress 949ef743bcSBartłomiej Bukowski{ 95bab1112dSTomasz Sapeta#if !defined(EX_DETACHED) 969ef743bcSBartłomiej Bukowski if (!_enabled) { 979ef743bcSBartłomiej Bukowski return; 989ef743bcSBartłomiej Bukowski } 999ef743bcSBartłomiej Bukowski 10064c37d52SBartłomiej Bukowski [self show]; 10164c37d52SBartłomiej Bukowski 102efd75decSTomasz Sapeta EX_WEAKIFY(self); 1039ef743bcSBartłomiej Bukowski dispatch_async(dispatch_get_main_queue(), ^{ 104efd75decSTomasz Sapeta EX_ENSURE_STRONGIFY(self); 1059ef743bcSBartłomiej Bukowski float progressPercent = ([progress.done floatValue] / [progress.total floatValue]); 1069ef743bcSBartłomiej Bukowski self.textLabel.text = [NSString stringWithFormat:@"%@ %.2f%%", progress.status, progressPercent * 100]; 1079ef743bcSBartłomiej Bukowski [self.textLabel setNeedsDisplay]; 1089ef743bcSBartłomiej Bukowski 1099ef743bcSBartłomiej Bukowski // TODO: (@bbarthec) maybe it's better to show/hide this based on other thing than progress status reported by the fetcher? 1109ef743bcSBartłomiej Bukowski self.window.hidden = !(progress.total.floatValue > 0); 1119ef743bcSBartłomiej Bukowski }); 112bab1112dSTomasz Sapeta#endif // !defined(EX_DETACHED) 1139ef743bcSBartłomiej Bukowski} 1149ef743bcSBartłomiej Bukowski 11557bba33fSEric Samelson- (void)updateStatus:(EXAppLoaderRemoteUpdateStatus)status 11657bba33fSEric Samelson{ 117bab1112dSTomasz Sapeta#if !defined(EX_DETACHED) 11857bba33fSEric Samelson if (!_enabled) { 11957bba33fSEric Samelson return; 12057bba33fSEric Samelson } 12157bba33fSEric Samelson 12257bba33fSEric Samelson NSString *statusText = [[self class] _loadingViewTextForStatus:status]; 12357bba33fSEric Samelson if (!statusText) { 12457bba33fSEric Samelson return; 12557bba33fSEric Samelson } 12657bba33fSEric Samelson 12757bba33fSEric Samelson [self show]; 12857bba33fSEric Samelson 129efd75decSTomasz Sapeta EX_WEAKIFY(self); 13057bba33fSEric Samelson dispatch_async(dispatch_get_main_queue(), ^{ 131efd75decSTomasz Sapeta EX_ENSURE_STRONGIFY(self); 13257bba33fSEric Samelson self.textLabel.text = statusText; 13357bba33fSEric Samelson [self.textLabel setNeedsDisplay]; 13457bba33fSEric Samelson }); 135bab1112dSTomasz Sapeta#endif // !defined(EX_DETACHED) 13657bba33fSEric Samelson} 13757bba33fSEric Samelson 13857bba33fSEric Samelson+ (nullable NSString *)_loadingViewTextForStatus:(EXAppLoaderRemoteUpdateStatus)status 13957bba33fSEric Samelson{ 14057bba33fSEric Samelson if (status == kEXAppLoaderRemoteUpdateStatusChecking) { 14157bba33fSEric Samelson return @"Checking for new update..."; 14257bba33fSEric Samelson } else if (status == kEXAppLoaderRemoteUpdateStatusDownloading) { 14357bba33fSEric Samelson return @"New update available, downloading..."; 14457bba33fSEric Samelson } else { 14557bba33fSEric Samelson return nil; 14657bba33fSEric Samelson } 14757bba33fSEric Samelson} 1489ef743bcSBartłomiej Bukowski 1499ef743bcSBartłomiej Bukowski@end 150