1// Copyright 2015-present 650 Industries. All rights reserved. 2 3#import <React/RCTAssert.h> 4 5#import <EXDevLauncher/EXDevLauncherRedBox.h> 6#import <EXDevLauncher/EXDevLauncherController.h> 7 8#if __has_include(<EXDevLauncher/EXDevLauncher-Swift.h>) 9// For cocoapods framework, the generated swift header will be inside EXDevLauncher module 10#import <EXDevLauncher/EXDevLauncher-Swift.h> 11#else 12#import <EXDevLauncher-Swift.h> 13#endif 14 15@interface EXDevLauncherRedBox () 16 17@property (nonatomic, weak) RCTLogBox *logBox; 18 19@end 20 21@implementation EXDevLauncherRedBox 22 23@synthesize overrideBundleURL; 24@synthesize overrideReloadAction; 25 26- (void)registerLogBox:(RCTLogBox * _Nullable)logBox 27{ 28 self.logBox = logBox; 29} 30 31- (void)addCustomButton:(NSString *)title onPressHandler:(RCTRedBoxButtonPressHandler)handler { 32 33} 34 35- (void)dismiss { 36 37} 38 39- (void)registerErrorCustomizer:(id<RCTErrorCustomizer>)errorCustomizer { 40 41} 42 43- (void)showError:(NSError *)error 44{ 45 [self showErrorMessage:error.localizedDescription 46 withDetails:error.localizedFailureReason 47 stack:error.userInfo[RCTJSStackTraceKey] 48 errorCookie:-1]; 49} 50 51- (void)showErrorMessage:(NSString *)message 52{ 53 [self showErrorMessage:message withParsedStack:nil isUpdate:NO errorCookie:-1]; 54} 55 56- (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details 57{ 58 [self showErrorMessage:message withDetails:details stack:nil errorCookie:-1]; 59} 60 61- (void)showErrorMessage:(NSString *)message 62 withDetails:(NSString *)details 63 stack:(NSArray<RCTJSStackFrame *> *)stack 64 errorCookie:(int)errorCookie 65{ 66 NSString *combinedMessage = message; 67 if (details) { 68 combinedMessage = [NSString stringWithFormat:@"%@\n\n%@", message, details]; 69 } 70 [self showErrorMessage:combinedMessage withParsedStack:stack isUpdate:NO errorCookie:errorCookie]; 71} 72 73- (void)showErrorMessage:(NSString *)message withRawStack:(NSString *)rawStack 74{ 75 [self showErrorMessage:message withRawStack:rawStack errorCookie:-1]; 76} 77 78- (void)showErrorMessage:(NSString *)message withRawStack:(NSString *)rawStack errorCookie:(int)errorCookie 79{ 80 NSArray<RCTJSStackFrame *> *stack = [RCTJSStackFrame stackFramesWithLines:rawStack]; 81 [self showErrorMessage:message withParsedStack:stack isUpdate:NO errorCookie:errorCookie]; 82} 83 84- (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack 85{ 86 [self showErrorMessage:message withStack:stack errorCookie:-1]; 87} 88 89- (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack 90{ 91 [self updateErrorMessage:message withStack:stack errorCookie:-1]; 92} 93 94- (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack errorCookie:(int)errorCookie 95{ 96 [self showErrorMessage:message 97 withParsedStack:[RCTJSStackFrame stackFramesWithDictionaries:stack] 98 isUpdate:NO 99 errorCookie:errorCookie]; 100} 101 102- (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack errorCookie:(int)errorCookie 103{ 104 [self showErrorMessage:message 105 withParsedStack:[RCTJSStackFrame stackFramesWithDictionaries:stack] 106 isUpdate:YES 107 errorCookie:errorCookie]; 108} 109 110- (void)showErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSStackFrame *> *)stack 111{ 112 [self showErrorMessage:message withParsedStack:stack errorCookie:-1]; 113} 114 115- (void)updateErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSStackFrame *> *)stack 116{ 117 [self updateErrorMessage:message withParsedStack:stack errorCookie:-1]; 118} 119 120- (void)showErrorMessage:(NSString *)message 121 withParsedStack:(NSArray<RCTJSStackFrame *> *)stack 122 errorCookie:(int)errorCookie 123{ 124 [self showErrorMessage:message withParsedStack:stack isUpdate:NO errorCookie:errorCookie]; 125} 126 127- (void)updateErrorMessage:(NSString *)message 128 withParsedStack:(NSArray<RCTJSStackFrame *> *)stack 129 errorCookie:(int)errorCookie 130{ 131 [self showErrorMessage:message withParsedStack:stack isUpdate:YES errorCookie:errorCookie]; 132} 133 134- (void)showErrorMessage:(NSString *)message 135 withParsedStack:(NSArray<RCTJSStackFrame *> *)stack 136 isUpdate:(BOOL)isUpdate 137 errorCookie:(int)errorCookie 138{ 139 if (isUpdate || errorCookie != -1) { 140 // These errors should be handled by LogBox 141 return; 142 } 143 144 // hide method was removed from the RCTLogBox interface in RN 0.64 145 if ([self.logBox respondsToSelector:@selector(hide)]) { 146 [self.logBox performSelector:@selector(hide)]; 147 } 148 149 dispatch_async(dispatch_get_main_queue(), ^{ 150 EXDevLauncherAppError *appError = [[EXDevLauncherAppError alloc] initWithMessage:[self stripAnsi:message] stack:stack]; 151 [[EXDevLauncherController sharedInstance].errorManager showError:appError]; 152 }); 153} 154 155- (RCTRedBox *)unsafe_castToRCTRedBox { 156 return (RCTRedBox *)self; 157} 158 159- (NSString *)stripAnsi:(NSString *)text 160{ 161 NSError *error = nil; 162 NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\x1b\\[[0-9;]*m" 163 options:NSRegularExpressionCaseInsensitive 164 error:&error]; 165 return [regex stringByReplacingMatchesInString:text options:0 range:NSMakeRange(0, [text length]) withTemplate:@""]; 166} 167 168@end 169