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