UNPKG

5.16 kBPlain TextView Raw
1/*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#import <React/RCTDevLoadingView.h>
9
10#import <QuartzCore/QuartzCore.h>
11
12#import <React/RCTBridge.h>
13#import <React/RCTDefines.h>
14#import <React/RCTModalHostViewController.h>
15#import <React/RCTUtils.h>
16
17#if RCT_DEV | RCT_ENABLE_LOADING_VIEW
18
19static BOOL isEnabled = YES;
20
21@implementation RCTDevLoadingView
22{
23 UIWindow *_window;
24 UILabel *_label;
25 NSDate *_showDate;
26}
27
28@synthesize bridge = _bridge;
29
30RCT_EXPORT_MODULE()
31
32+ (void)setEnabled:(BOOL)enabled
33{
34 isEnabled = enabled;
35}
36
37+ (BOOL)requiresMainQueueSetup
38{
39 return YES;
40}
41
42- (void)setBridge:(RCTBridge *)bridge
43{
44 _bridge = bridge;
45
46 [[NSNotificationCenter defaultCenter] addObserver:self
47 selector:@selector(hide)
48 name:RCTJavaScriptDidLoadNotification
49 object:nil];
50 [[NSNotificationCenter defaultCenter] addObserver:self
51 selector:@selector(hide)
52 name:RCTJavaScriptDidFailToLoadNotification
53 object:nil];
54
55 if (bridge.loading) {
56 [self showWithURL:bridge.bundleURL];
57 }
58}
59
60RCT_EXPORT_METHOD(showMessage:(NSString *)message color:(UIColor *)color backgroundColor:(UIColor *)backgroundColor)
61{
62 if (!isEnabled) {
63 return;
64 }
65
66 dispatch_async(dispatch_get_main_queue(), ^{
67 self->_showDate = [NSDate date];
68 if (!self->_window && !RCTRunningInTestEnvironment()) {
69 CGSize screenSize = [UIScreen mainScreen].bounds.size;
70
71 if (@available(iOS 11.0, *)) {
72 UIWindow *window = RCTSharedApplication().keyWindow;
73 self->_window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, window.safeAreaInsets.top + 30)];
74 self->_label = [[UILabel alloc] initWithFrame:CGRectMake(0, window.safeAreaInsets.top, screenSize.width, 30)];
75 } else {
76 self->_window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, 22)];
77 self->_label = [[UILabel alloc] initWithFrame:self->_window.bounds];
78 }
79 [self->_window addSubview:self->_label];
80#if TARGET_OS_TV
81 self->_window.windowLevel = UIWindowLevelNormal + 1;
82#else
83 self->_window.windowLevel = UIWindowLevelStatusBar + 1;
84#endif
85 // set a root VC so rotation is supported
86 self->_window.rootViewController = [UIViewController new];
87
88 self->_label.font = [UIFont monospacedDigitSystemFontOfSize:12.0
89 weight:UIFontWeightRegular];
90 self->_label.textAlignment = NSTextAlignmentCenter;
91 }
92
93 self->_label.text = message;
94 self->_label.textColor = color;
95 self->_window.backgroundColor = backgroundColor;
96 self->_window.hidden = NO;
97 });
98}
99
100RCT_EXPORT_METHOD(hide)
101{
102 if (!isEnabled) {
103 return;
104 }
105
106 dispatch_async(dispatch_get_main_queue(), ^{
107 const NSTimeInterval MIN_PRESENTED_TIME = 0.6;
108 NSTimeInterval presentedTime = [[NSDate date] timeIntervalSinceDate:self->_showDate];
109 NSTimeInterval delay = MAX(0, MIN_PRESENTED_TIME - presentedTime);
110 CGRect windowFrame = self->_window.frame;
111 [UIView animateWithDuration:0.25
112 delay:delay
113 options:0
114 animations:^{
115 self->_window.frame = CGRectOffset(windowFrame, 0, -windowFrame.size.height);
116 } completion:^(__unused BOOL finished) {
117 self->_window.frame = windowFrame;
118 self->_window.hidden = YES;
119 self->_window = nil;
120 }];
121 });
122}
123
124- (void)showWithURL:(NSURL *)URL
125{
126 UIColor *color;
127 UIColor *backgroundColor;
128 NSString *message;
129 if (URL.fileURL) {
130 // If dev mode is not enabled, we don't want to show this kind of notification
131#if !RCT_DEV
132 return;
133#endif
134 color = [UIColor whiteColor];
135 backgroundColor = [UIColor blackColor];
136 message = [NSString stringWithFormat:@"Connect to %@ to develop JavaScript.", RCT_PACKAGER_NAME];
137 } else {
138 color = [UIColor whiteColor];
139 backgroundColor = [UIColor colorWithHue:1./3 saturation:1 brightness:.35 alpha:1];
140 message = [NSString stringWithFormat:@"Loading from %@:%@...", URL.host, URL.port];
141 }
142
143 [self showMessage:message
144 color:color
145 backgroundColor:backgroundColor];
146}
147
148- (void)updateProgress:(RCTLoadingProgress *)progress
149{
150 if (!progress) {
151 return;
152 }
153 dispatch_async(dispatch_get_main_queue(), ^{
154 self->_label.text = [progress description];
155 });
156}
157
158@end
159
160#else
161
162@implementation RCTDevLoadingView
163
164+ (NSString *)moduleName { return nil; }
165+ (void)setEnabled:(BOOL)enabled { }
166- (void)showMessage:(NSString *)message color:(UIColor *)color backgroundColor:(UIColor *)backgroundColor { }
167- (void)showWithURL:(NSURL *)URL { }
168- (void)updateProgress:(RCTLoadingProgress *)progress { }
169- (void)hide { }
170
171@end
172
173#endif