1#import <ExpoModulesCore/EXDefines.h> 2 3#if __has_include("Expo_Go-Swift.h") 4#import "Expo_Go-Swift.h" 5#else 6#import "ExpoKitApp-Swift.h" 7#endif 8 9#import "EXAppLoadingProgressWindowController.h" 10#import "EXUtil.h" 11 12@interface EXAppLoadingProgressWindowController () 13 14@property (nonatomic, assign) BOOL enabled; 15@property (nonatomic, strong) UIWindow *window; 16@property (nonatomic, strong) UILabel *textLabel; 17 18@end 19 20@implementation EXAppLoadingProgressWindowController 21 22- (instancetype)initWithEnabled:(BOOL)enabled 23{ 24 if (self = [super init]) { 25 _enabled = enabled; 26 } 27 return self; 28} 29 30- (void)show 31{ 32 if (!_enabled) { 33 return; 34 } 35 36 EX_WEAKIFY(self); 37 dispatch_async(dispatch_get_main_queue(), ^{ 38 EX_ENSURE_STRONGIFY(self); 39 if (!self.window) { 40 CGSize screenSize = [UIScreen mainScreen].bounds.size; 41 42 int bottomInsets = EXSharedApplication().keyWindow.safeAreaInsets.bottom; 43 self.window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 44 screenSize.height - 36 - bottomInsets, 45 screenSize.width, 46 36 + bottomInsets)]; 47 self.window.windowLevel = UIWindowLevelStatusBar + 1; 48 self.window.rootViewController = [EXAppLoadingProgressWindowViewController new]; 49 self.window.backgroundColor = [EXUtil colorWithRGB:0xfafafa]; 50 51 UIView *containerView = [UIView new]; 52 [self.window addSubview:containerView]; 53 54 CALayer *topBorderLayer = [CALayer layer]; 55 topBorderLayer.frame = CGRectMake(0, 0, screenSize.width, 1); 56 topBorderLayer.backgroundColor = [EXUtil colorWithRGB:0xe3e3e3].CGColor; 57 [containerView.layer addSublayer:topBorderLayer]; 58 59 self.textLabel = [UILabel new]; 60 self.textLabel.frame = CGRectMake(10, 0, screenSize.width - 20, 36); 61 self.textLabel.font = [UIFont systemFontOfSize:12]; 62 self.textLabel.textAlignment = NSTextAlignmentLeft; 63 self.textLabel.textColor = [EXUtil colorWithRGB:0xa7a7a7]; 64 [containerView addSubview:self.textLabel]; 65 } 66 self.textLabel.text = @"Waiting for server ..."; 67 self.window.hidden = NO; 68 }); 69} 70 71- (void)hide 72{ 73 if (!_enabled) { 74 return; 75 } 76 77 EX_WEAKIFY(self); 78 dispatch_async(dispatch_get_main_queue(), ^{ 79 EX_ENSURE_STRONGIFY(self); 80 if (self.window) { 81 self.window.hidden = YES; 82 // remove this window altogther to hand over the command over StatusBar rotation 83 self.window = nil; 84 } 85 }); 86} 87 88- (void)updateStatusWithProgress:(EXLoadingProgress *)progress 89{ 90 if (!_enabled) { 91 return; 92 } 93 94 [self show]; 95 96 EX_WEAKIFY(self); 97 dispatch_async(dispatch_get_main_queue(), ^{ 98 EX_ENSURE_STRONGIFY(self); 99 float progressPercent = ([progress.done floatValue] / [progress.total floatValue]); 100 self.textLabel.text = [NSString stringWithFormat:@"%@ %.2f%%", progress.status, progressPercent * 100]; 101 [self.textLabel setNeedsDisplay]; 102 103 // TODO: (@bbarthec) maybe it's better to show/hide this based on other thing than progress status reported by the fetcher? 104 self.window.hidden = !(progress.total.floatValue > 0); 105 }); 106} 107 108- (void)updateStatus:(EXAppLoaderRemoteUpdateStatus)status 109{ 110 if (!_enabled) { 111 return; 112 } 113 114 NSString *statusText = [[self class] _loadingViewTextForStatus:status]; 115 if (!statusText) { 116 return; 117 } 118 119 [self show]; 120 121 EX_WEAKIFY(self); 122 dispatch_async(dispatch_get_main_queue(), ^{ 123 EX_ENSURE_STRONGIFY(self); 124 self.textLabel.text = statusText; 125 [self.textLabel setNeedsDisplay]; 126 }); 127} 128 129+ (nullable NSString *)_loadingViewTextForStatus:(EXAppLoaderRemoteUpdateStatus)status 130{ 131 if (status == kEXAppLoaderRemoteUpdateStatusChecking) { 132 return @"Checking for new update..."; 133 } else if (status == kEXAppLoaderRemoteUpdateStatusDownloading) { 134 return @"New update available, downloading..."; 135 } else { 136 return nil; 137 } 138} 139 140@end 141