[RN] Add loading view for development mode

Summary:
It's very useful to know where the app is being loaded from and
can help debug various issues.
This commit is contained in:
Alex Kotliarskyi 2015-07-28 11:07:45 -07:00
parent 7d19ff3dcb
commit e964e741ef
6 changed files with 174 additions and 0 deletions

View File

@ -281,6 +281,9 @@ RCT_NOT_IMPLEMENTED(-initWithBundleURL:(__unused NSURL *)bundleURL
});
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptWillStartLoadingNotification
object:self
userInfo:@{ @"bridge": self }];
RCTProfileBeginEvent();
RCTPerformanceLoggerStart(RCTPLScriptDownload);
RCTJavaScriptLoader *loader = [[RCTJavaScriptLoader alloc] initWithBridge:self];

View File

@ -23,6 +23,11 @@
*/
RCT_EXTERN NSString *const RCTReloadNotification;
/**
* This notification fires when the bridge starts loading.
*/
RCT_EXTERN NSString *const RCTJavaScriptWillStartLoadingNotification;
/**
* This notification fires when the bridge has finished loading.
*/

View File

@ -18,6 +18,7 @@
#import "RCTUtils.h"
NSString *const RCTReloadNotification = @"RCTReloadNotification";
NSString *const RCTJavaScriptWillStartLoadingNotification = @"RCTJavaScriptWillStartLoadingNotification";
NSString *const RCTJavaScriptDidLoadNotification = @"RCTJavaScriptDidLoadNotification";
NSString *const RCTJavaScriptDidFailToLoadNotification = @"RCTJavaScriptDidFailToLoadNotification";
NSString *const RCTDidCreateNativeModules = @"RCTDidCreateNativeModules";

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface RCTDevLoadingView : NSObject
+ (instancetype)sharedInstance;
- (void)showWithURL:(NSURL *)URL;
- (void)hide;
@end

View File

@ -0,0 +1,139 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <QuartzCore/QuartzCore.h>
#import "RCTBridge.h"
#import "RCTDevLoadingView.h"
#import "RCTDefines.h"
#if RCT_DEV
@implementation RCTDevLoadingView
{
UIWindow *_window;
UILabel *_label;
NSDate *_showDate;
}
__attribute__((constructor))
static void RCTDevLoadingViewSetup()
{
[RCTDevLoadingView sharedInstance];
}
+ (instancetype)sharedInstance
{
static dispatch_once_t onceToken;
static RCTDevLoadingView *instance;
dispatch_once(&onceToken, ^{
instance = [[RCTDevLoadingView alloc] init];
});
return instance;
}
- (instancetype)init
{
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(willStartLoading:)
name:RCTJavaScriptWillStartLoadingNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didFinishLoading:)
name:RCTJavaScriptDidLoadNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didFinishLoading:)
name:RCTJavaScriptDidFailToLoadNotification
object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)willStartLoading:(NSNotification *)notification
{
NSURL *url = [[notification object] bundleURL];
dispatch_async(dispatch_get_main_queue(), ^{
[self showWithURL:url];
});
}
- (void)didFinishLoading:(__unused NSNotification *)notification
{
dispatch_async(dispatch_get_main_queue(), ^{
[self hide];
});
}
- (void)showWithURL:(NSURL *)URL
{
_showDate = [NSDate date];
if (!_window) {
CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
_window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, screenWidth, 22)];
_window.backgroundColor = [UIColor blackColor];
_window.windowLevel = UIWindowLevelStatusBar + 1;
_label = [[UILabel alloc] initWithFrame:_window.bounds];
_label.font = [UIFont systemFontOfSize:12.0];
_label.textColor = [UIColor grayColor];
_label.textAlignment = NSTextAlignmentCenter;
[_window addSubview:_label];
[_window makeKeyAndVisible];
}
NSString *source;
if ([URL isFileURL]) {
source = @"pre-bundled file";
} else {
source = [NSString stringWithFormat:@"%@:%@", [URL host], [URL port]];
}
_label.text = [NSString stringWithFormat:@"Loading from %@...", source];
_window.hidden = NO;
}
- (void)hide
{
const NSTimeInterval MIN_PRESENTED_TIME = 0.6;
NSTimeInterval presentedTime = [[NSDate date] timeIntervalSinceDate:_showDate];
NSTimeInterval delay = MAX(0, MIN_PRESENTED_TIME - presentedTime);
CGRect windowFrame = _window.frame;
[UIView animateWithDuration:0.25
delay:delay
options:0
animations:^{
_window.frame = CGRectOffset(windowFrame, 0, -windowFrame.size.height);
} completion:^(__unused BOOL finished) {
_window.frame = windowFrame;
_window.hidden = YES;
}];
}
@end
#else
@implementation RCTDevLoadingView
+ (instancetype)sharedInstance { return nil; }
- (void)showWithURL:(NSURL *)URL {}
- (void)hide {}
@end
#endif

View File

@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
000E6CEB1AB0E980000CDF4D /* RCTSourceCode.m in Sources */ = {isa = PBXBuildFile; fileRef = 000E6CEA1AB0E980000CDF4D /* RCTSourceCode.m */; };
00C1A2B31AC0B7E000E89A1C /* RCTDevMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 00C1A2B21AC0B7E000E89A1C /* RCTDevMenu.m */; };
00EAC16C1B62E089003B7CEE /* RCTDevLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 00EAC16B1B62E089003B7CEE /* RCTDevLoadingView.m */; };
131B6AF41AF1093D00FFC3E0 /* RCTSegmentedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 131B6AF11AF1093D00FFC3E0 /* RCTSegmentedControl.m */; };
131B6AF51AF1093D00FFC3E0 /* RCTSegmentedControlManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 131B6AF31AF1093D00FFC3E0 /* RCTSegmentedControlManager.m */; };
13456E931ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 13456E921ADAD2DE009F94A7 /* RCTConvert+CoreLocation.m */; };
@ -98,6 +99,8 @@
000E6CEA1AB0E980000CDF4D /* RCTSourceCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSourceCode.m; sourceTree = "<group>"; };
00C1A2B11AC0B7E000E89A1C /* RCTDevMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDevMenu.h; sourceTree = "<group>"; };
00C1A2B21AC0B7E000E89A1C /* RCTDevMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDevMenu.m; sourceTree = "<group>"; };
00EAC16A1B62E089003B7CEE /* RCTDevLoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTDevLoadingView.h; sourceTree = "<group>"; };
00EAC16B1B62E089003B7CEE /* RCTDevLoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTDevLoadingView.m; sourceTree = "<group>"; };
131B6AF01AF1093D00FFC3E0 /* RCTSegmentedControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSegmentedControl.h; sourceTree = "<group>"; };
131B6AF11AF1093D00FFC3E0 /* RCTSegmentedControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSegmentedControl.m; sourceTree = "<group>"; };
131B6AF21AF1093D00FFC3E0 /* RCTSegmentedControlManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSegmentedControlManager.h; sourceTree = "<group>"; };
@ -439,6 +442,8 @@
13AF1F851AE6E777005F5298 /* RCTDefines.h */,
00C1A2B11AC0B7E000E89A1C /* RCTDevMenu.h */,
00C1A2B21AC0B7E000E89A1C /* RCTDevMenu.m */,
00EAC16A1B62E089003B7CEE /* RCTDevLoadingView.h */,
00EAC16B1B62E089003B7CEE /* RCTDevLoadingView.m */,
83CBBA651A601EF300E9B192 /* RCTEventDispatcher.h */,
83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */,
146459241B06C49500B389AA /* RCTFPSGraph.h */,
@ -585,6 +590,7 @@
83CBBA511A601E3B00E9B192 /* RCTAssert.m in Sources */,
13AF20451AE707F9005F5298 /* RCTSlider.m in Sources */,
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */,
00EAC16C1B62E089003B7CEE /* RCTDevLoadingView.m in Sources */,
832348161A77A5AA00B55238 /* Layout.c in Sources */,
14F4D38B1AE1B7E40049C042 /* RCTProfile.m in Sources */,
13513F3C1B1F43F400FCE529 /* RCTProgressViewManager.m in Sources */,