mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
45a43241cd
Summary: This diff adds a NativeLogBox module implementation on iOS to manage rendering LogBox the way we render RedBox, except rendering a React Native component instead of a native view. The strategy here is: - initialize: will create a hidden window (the way redbox does) and render the LogBox to it - show: will show the window - hide: will hide the window Most of this is copied from the way RedBox works, the difference here is that we eagerly initialize the window with the `initialize` function so that it's warm by the time LogBox needs to render. Changelog: [Internal] Reviewed By: RSNara Differential Revision: D18750008 fbshipit-source-id: 013e55ded55c8572bb08e0219ff4cd0060ebe0da
163 lines
3.4 KiB
Plaintext
163 lines
3.4 KiB
Plaintext
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#import "RCTLogBox.h"
|
|
|
|
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
|
#import <React/RCTBridge.h>
|
|
#import <React/RCTRootView.h>
|
|
#import <React/RCTConvert.h>
|
|
#import <React/RCTDefines.h>
|
|
#import <React/RCTErrorInfo.h>
|
|
#import <React/RCTEventDispatcher.h>
|
|
#import <React/RCTJSStackFrame.h>
|
|
#import <React/RCTReloadCommand.h>
|
|
#import <React/RCTUtils.h>
|
|
|
|
#import <objc/runtime.h>
|
|
|
|
#import "CoreModulesPlugins.h"
|
|
|
|
#if RCT_DEV_MENU
|
|
|
|
@class RCTLogBoxWindow;
|
|
|
|
@protocol RCTLogBoxWindowActionDelegate <NSObject>
|
|
|
|
- (void)logBoxWindow:(RCTLogBoxWindow *)logBoxWindow openStackFrameInEditor:(RCTJSStackFrame *)stackFrame;
|
|
- (void)reloadFromlogBoxWindow:(RCTLogBoxWindow *)logBoxWindow;
|
|
- (void)loadExtraDataViewController;
|
|
|
|
@end
|
|
|
|
@interface RCTLogBoxWindow : UIWindow <UITableViewDelegate>
|
|
@property (nonatomic, weak) id<RCTLogBoxWindowActionDelegate> actionDelegate;
|
|
@end
|
|
|
|
@implementation RCTLogBoxWindow
|
|
{
|
|
UITableView *_stackTraceTableView;
|
|
NSString *_lastErrorMessage;
|
|
NSArray<RCTJSStackFrame *> *_lastStackTrace;
|
|
int _lastErrorCookie;
|
|
}
|
|
|
|
- (instancetype)initWithFrame:(CGRect)frame bridge:(RCTBridge *)bridge
|
|
{
|
|
_lastErrorCookie = -1;
|
|
if ((self = [super initWithFrame:frame])) {
|
|
#if TARGET_OS_TV
|
|
self.windowLevel = UIWindowLevelAlert + 1000;
|
|
#else
|
|
self.windowLevel = UIWindowLevelStatusBar - 1;
|
|
#endif
|
|
self.backgroundColor = [UIColor clearColor];
|
|
self.hidden = YES;
|
|
|
|
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"LogBox" initialProperties:nil];
|
|
|
|
UIViewController *rootViewController = [UIViewController new];
|
|
rootViewController.view = rootView;
|
|
self.rootViewController = rootViewController;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
- (void)show
|
|
{
|
|
[self becomeFirstResponder];
|
|
[self makeKeyAndVisible];
|
|
}
|
|
|
|
- (void)dismiss
|
|
{
|
|
self.hidden = YES;
|
|
[self resignFirstResponder];
|
|
[RCTSharedApplication().delegate.window makeKeyWindow];
|
|
}
|
|
|
|
@end
|
|
|
|
@interface RCTLogBox () <NativeLogBoxSpec>
|
|
@end
|
|
|
|
@implementation RCTLogBox
|
|
{
|
|
RCTLogBoxWindow *_window;
|
|
}
|
|
|
|
@synthesize bridge = _bridge;
|
|
|
|
RCT_EXPORT_MODULE()
|
|
|
|
+ (BOOL)requiresMainQueueSetup
|
|
{
|
|
return YES;
|
|
}
|
|
|
|
- (void)setBridge:(RCTBridge *)bridge
|
|
{
|
|
_bridge = bridge;
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
self->_window = [[RCTLogBoxWindow alloc] initWithFrame:[UIScreen mainScreen].bounds bridge: self->_bridge];
|
|
});
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(show)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[self->_window show];
|
|
});
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(hide)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[self->_window dismiss];
|
|
});
|
|
}
|
|
|
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
|
{
|
|
return std::make_shared<facebook::react::NativeLogBoxSpecJSI>(self, jsInvoker);
|
|
}
|
|
|
|
@end
|
|
|
|
#else // Disabled
|
|
|
|
@interface RCTLogBox() <NativeLogBoxSpec>
|
|
@end
|
|
|
|
@implementation RCTLogBox
|
|
|
|
+ (NSString *)moduleName
|
|
{
|
|
return nil;
|
|
}
|
|
|
|
- (void)show {
|
|
// noop
|
|
}
|
|
|
|
- (void)hide {
|
|
// noop
|
|
}
|
|
|
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
|
{
|
|
return std::make_shared<facebook::react::NativeLogBoxSpecJSI>(self, jsInvoker);
|
|
}
|
|
@end
|
|
|
|
#endif
|
|
|
|
Class RCTLogBoxCls(void) {
|
|
return RCTLogBox.class;
|
|
}
|