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