react-native-tvos 0.85.2-0 → 0.85.3-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Components/ScrollView/ScrollView.d.ts +1 -1
- package/Libraries/Components/ScrollView/ScrollView.js +1 -1
- package/Libraries/Components/TV/TVViewPropTypes.js +9 -0
- package/Libraries/Components/View/View.js +7 -3
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/NativeComponent/TVViewConfig.js +1 -0
- package/Libraries/Utilities/HMRClient.js +28 -1
- package/README.md +13 -1
- package/React/Base/RCTVersion.m +2 -2
- package/React/CoreModules/RCTJscSafeUrl+Internal.h +23 -0
- package/React/CoreModules/RCTJscSafeUrl.mm +38 -0
- package/React/CoreModules/RCTRedBox+Internal.h +42 -0
- package/React/CoreModules/RCTRedBox.mm +30 -471
- package/React/CoreModules/RCTRedBox2AnsiParser+Internal.h +22 -0
- package/React/CoreModules/RCTRedBox2AnsiParser.mm +55 -0
- package/React/CoreModules/RCTRedBox2Controller+Internal.h +34 -0
- package/React/CoreModules/RCTRedBox2Controller.mm +764 -0
- package/React/CoreModules/RCTRedBox2ErrorParser+Internal.h +46 -0
- package/React/CoreModules/RCTRedBox2ErrorParser.mm +57 -0
- package/React/CoreModules/RCTRedBoxController+Internal.h +31 -0
- package/React/CoreModules/RCTRedBoxController.mm +447 -0
- package/React/CoreModules/RCTRedBoxHMRClient+Internal.h +26 -0
- package/React/CoreModules/RCTRedBoxHMRClient.mm +125 -0
- package/React/CoreModules/React-CoreModules.podspec +1 -0
- package/React/DevSupport/RCTFrameTimingsObserver.h +24 -0
- package/React/DevSupport/RCTFrameTimingsObserver.mm +298 -0
- package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +40 -0
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +35 -15
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/hermes-engine/build.gradle.kts +17 -0
- package/ReactAndroid/publish.gradle +20 -46
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/InspectorFlags.kt +4 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingSequence.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/FrameTimingsObserver.kt +127 -26
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +31 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +51 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +11 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +11 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +56 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +11 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/tracing/PerformanceTracer.kt +39 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.kt +50 -10
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +14 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +14 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt +46 -6
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt +5 -0
- package/ReactAndroid/src/main/jni/CMakeLists.txt +7 -0
- package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.cpp +22 -0
- package/ReactAndroid/src/main/jni/react/devsupport/JInspectorFlags.h +2 -0
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +71 -1
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +16 -1
- package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp +14 -0
- package/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h +18 -4
- package/ReactCommon/React-Fabric.podspec +6 -0
- package/ReactCommon/cxxreact/ReactNativeVersion.h +3 -3
- package/ReactCommon/jsinspector-modern/HostAgent.cpp +36 -0
- package/ReactCommon/jsinspector-modern/HostTarget.cpp +7 -1
- package/ReactCommon/jsinspector-modern/HostTarget.h +25 -0
- package/ReactCommon/jsinspector-modern/HostTargetTracing.cpp +1 -1
- package/ReactCommon/jsinspector-modern/HostTargetTracing.h +4 -4
- package/ReactCommon/jsinspector-modern/InspectorFlags.cpp +12 -0
- package/ReactCommon/jsinspector-modern/InspectorFlags.h +12 -0
- package/ReactCommon/jsinspector-modern/NetworkIOAgent.cpp +1 -1
- package/ReactCommon/jsinspector-modern/RuntimeAgent.cpp +19 -0
- package/ReactCommon/jsinspector-modern/RuntimeAgent.h +7 -0
- package/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +33 -0
- package/ReactCommon/jsinspector-modern/RuntimeTarget.h +6 -0
- package/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +12 -0
- package/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +3 -2
- package/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +1 -0
- package/ReactCommon/jsinspector-modern/tests/NetworkReporterTest.cpp +1 -1
- package/ReactCommon/jsinspector-modern/tests/TracingTest.cpp +1 -1
- package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +10 -0
- package/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +3 -1
- package/ReactCommon/jsinspector-modern/tracing/CMakeLists.txt +1 -0
- package/ReactCommon/jsinspector-modern/tracing/FrameTimingSequence.h +7 -3
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.cpp +52 -29
- package/ReactCommon/jsinspector-modern/tracing/HostTracingProfileSerializer.h +6 -6
- package/ReactCommon/jsinspector-modern/tracing/PerformanceTracerSection.h +113 -0
- package/ReactCommon/jsinspector-modern/tracing/React-jsinspectortracing.podspec +1 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.cpp +12 -5
- package/ReactCommon/jsinspector-modern/tracing/TraceEventGenerator.h +3 -1
- package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.cpp +42 -0
- package/ReactCommon/jsinspector-modern/tracing/TraceEventSerializer.h +7 -0
- package/ReactCommon/react/debug/CMakeLists.txt +2 -1
- package/ReactCommon/react/debug/React-debug.podspec +7 -1
- package/ReactCommon/react/debug/redbox/AnsiParser.cpp +139 -0
- package/ReactCommon/react/debug/redbox/AnsiParser.h +35 -0
- package/ReactCommon/react/debug/redbox/JscSafeUrl.cpp +179 -0
- package/ReactCommon/react/debug/redbox/JscSafeUrl.h +27 -0
- package/ReactCommon/react/debug/redbox/RedBoxErrorParser.cpp +171 -0
- package/ReactCommon/react/debug/redbox/RedBoxErrorParser.h +40 -0
- package/ReactCommon/react/debug/redbox/tests/AnsiParserTest.cpp +97 -0
- package/ReactCommon/react/debug/redbox/tests/JscSafeUrlTest.cpp +173 -0
- package/ReactCommon/react/debug/redbox/tests/RedBoxErrorParserTest.cpp +107 -0
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +21 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +26 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +135 -45
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +12 -2
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +21 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +46 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +6 -1
- package/ReactCommon/react/nativemodule/defaults/CMakeLists.txt +1 -0
- package/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp +7 -0
- package/ReactCommon/react/nativemodule/defaults/React-defaultsnativemodule.podspec +1 -0
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +26 -1
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +11 -1
- package/ReactCommon/react/nativemodule/mutationobserver/NativeMutationObserver.h +4 -0
- package/ReactCommon/react/nativemodule/mutationobserver/React-mutationobservernativemodule.podspec +66 -0
- package/ReactCommon/react/performance/timeline/PerformanceObserver.cpp +18 -6
- package/ReactCommon/react/performance/timeline/PerformanceObserver.h +2 -0
- package/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +7 -0
- package/ReactCommon/react/renderer/components/view/BaseViewProps.h +1 -0
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +18 -0
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h +1 -0
- package/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +115 -0
- package/ReactCommon/{jsinspector-modern → react/utils}/Base64.h +2 -2
- package/package.json +11 -11
- package/scripts/cocoapods/utils.rb +1 -0
- package/scripts/react_native_pods.rb +1 -0
- package/scripts/replace-rncore-version.js +72 -15
- package/src/private/featureflags/ReactNativeFeatureFlags.js +26 -1
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +6 -1
- package/src/private/setup/setUpDefaultReactNativeEnvironment.js +6 -0
- package/types/public/ReactNativeTVTypes.d.ts +9 -0
|
@@ -16,472 +16,15 @@
|
|
|
16
16
|
#import <React/RCTRedBoxExtraDataViewController.h>
|
|
17
17
|
#import <React/RCTReloadCommand.h>
|
|
18
18
|
#import <React/RCTUtils.h>
|
|
19
|
-
|
|
20
|
-
#import <objc/runtime.h>
|
|
19
|
+
#import <react/featureflags/ReactNativeFeatureFlags.h>
|
|
21
20
|
|
|
22
21
|
#import "CoreModulesPlugins.h"
|
|
22
|
+
#import "RCTRedBox+Internal.h"
|
|
23
|
+
#import "RCTRedBox2Controller+Internal.h"
|
|
24
|
+
#import "RCTRedBoxController+Internal.h"
|
|
23
25
|
|
|
24
26
|
#if RCT_DEV_MENU
|
|
25
27
|
|
|
26
|
-
@class RCTRedBoxController;
|
|
27
|
-
|
|
28
|
-
@interface UIButton (RCTRedBox)
|
|
29
|
-
|
|
30
|
-
@property (nonatomic) RCTRedBoxButtonPressHandler rct_handler;
|
|
31
|
-
|
|
32
|
-
- (void)rct_addBlock:(RCTRedBoxButtonPressHandler)handler forControlEvents:(UIControlEvents)controlEvents;
|
|
33
|
-
|
|
34
|
-
@end
|
|
35
|
-
|
|
36
|
-
@implementation UIButton (RCTRedBox)
|
|
37
|
-
|
|
38
|
-
- (RCTRedBoxButtonPressHandler)rct_handler
|
|
39
|
-
{
|
|
40
|
-
return objc_getAssociatedObject(self, @selector(rct_handler));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
- (void)setRct_handler:(RCTRedBoxButtonPressHandler)rct_handler
|
|
44
|
-
{
|
|
45
|
-
objc_setAssociatedObject(self, @selector(rct_handler), rct_handler, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
- (void)rct_callBlock
|
|
49
|
-
{
|
|
50
|
-
if (self.rct_handler) {
|
|
51
|
-
self.rct_handler();
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
- (void)rct_addBlock:(RCTRedBoxButtonPressHandler)handler forControlEvents:(UIControlEvents)controlEvents
|
|
56
|
-
{
|
|
57
|
-
self.rct_handler = handler;
|
|
58
|
-
[self addTarget:self action:@selector(rct_callBlock) forControlEvents:controlEvents];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
@end
|
|
62
|
-
|
|
63
|
-
@protocol RCTRedBoxControllerActionDelegate <NSObject>
|
|
64
|
-
|
|
65
|
-
- (void)redBoxController:(RCTRedBoxController *)redBoxController openStackFrameInEditor:(RCTJSStackFrame *)stackFrame;
|
|
66
|
-
- (void)reloadFromRedBoxController:(RCTRedBoxController *)redBoxController;
|
|
67
|
-
- (void)loadExtraDataViewController;
|
|
68
|
-
|
|
69
|
-
@end
|
|
70
|
-
|
|
71
|
-
@interface RCTRedBoxController : UIViewController <UITableViewDelegate, UITableViewDataSource>
|
|
72
|
-
@property (nonatomic, weak) id<RCTRedBoxControllerActionDelegate> actionDelegate;
|
|
73
|
-
@end
|
|
74
|
-
|
|
75
|
-
@implementation RCTRedBoxController {
|
|
76
|
-
UITableView *_stackTraceTableView;
|
|
77
|
-
NSString *_lastErrorMessage;
|
|
78
|
-
NSArray<RCTJSStackFrame *> *_lastStackTrace;
|
|
79
|
-
NSArray<NSString *> *_customButtonTitles;
|
|
80
|
-
NSArray<RCTRedBoxButtonPressHandler> *_customButtonHandlers;
|
|
81
|
-
int _lastErrorCookie;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
- (instancetype)initWithCustomButtonTitles:(NSArray<NSString *> *)customButtonTitles
|
|
85
|
-
customButtonHandlers:(NSArray<RCTRedBoxButtonPressHandler> *)customButtonHandlers
|
|
86
|
-
{
|
|
87
|
-
if (self = [super init]) {
|
|
88
|
-
_lastErrorCookie = -1;
|
|
89
|
-
_customButtonTitles = customButtonTitles;
|
|
90
|
-
_customButtonHandlers = customButtonHandlers;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return self;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
- (void)viewDidLoad
|
|
97
|
-
{
|
|
98
|
-
[super viewDidLoad];
|
|
99
|
-
self.view.backgroundColor = [UIColor blackColor];
|
|
100
|
-
|
|
101
|
-
const CGFloat buttonHeight = 60;
|
|
102
|
-
|
|
103
|
-
CGRect detailsFrame = self.view.bounds;
|
|
104
|
-
detailsFrame.size.height -= buttonHeight + (double)[self bottomSafeViewHeight];
|
|
105
|
-
|
|
106
|
-
_stackTraceTableView = [[UITableView alloc] initWithFrame:detailsFrame style:UITableViewStylePlain];
|
|
107
|
-
_stackTraceTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
108
|
-
_stackTraceTableView.delegate = self;
|
|
109
|
-
_stackTraceTableView.dataSource = self;
|
|
110
|
-
_stackTraceTableView.backgroundColor = [UIColor clearColor];
|
|
111
|
-
#if !TARGET_OS_TV
|
|
112
|
-
_stackTraceTableView.separatorColor = [UIColor colorWithWhite:1 alpha:0.3];
|
|
113
|
-
_stackTraceTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
|
114
|
-
#endif
|
|
115
|
-
_stackTraceTableView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
|
|
116
|
-
[self.view addSubview:_stackTraceTableView];
|
|
117
|
-
|
|
118
|
-
#if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST
|
|
119
|
-
NSString *reloadText = @"Reload\n(\u2318R)";
|
|
120
|
-
NSString *dismissText = @"Dismiss\n(ESC)";
|
|
121
|
-
NSString *copyText = @"Copy\n(\u2325\u2318C)";
|
|
122
|
-
NSString *extraText = @"Extra Info\n(\u2318E)";
|
|
123
|
-
#else
|
|
124
|
-
NSString *reloadText = @"Reload JS";
|
|
125
|
-
NSString *dismissText = @"Dismiss";
|
|
126
|
-
NSString *copyText = @"Copy";
|
|
127
|
-
NSString *extraText = @"Extra Info";
|
|
128
|
-
#endif
|
|
129
|
-
|
|
130
|
-
UIButton *dismissButton = [self redBoxButton:dismissText
|
|
131
|
-
accessibilityIdentifier:@"redbox-dismiss"
|
|
132
|
-
selector:@selector(dismiss)
|
|
133
|
-
block:nil];
|
|
134
|
-
UIButton *reloadButton = [self redBoxButton:reloadText
|
|
135
|
-
accessibilityIdentifier:@"redbox-reload"
|
|
136
|
-
selector:@selector(reload)
|
|
137
|
-
block:nil];
|
|
138
|
-
UIButton *copyButton = [self redBoxButton:copyText
|
|
139
|
-
accessibilityIdentifier:@"redbox-copy"
|
|
140
|
-
selector:@selector(copyStack)
|
|
141
|
-
block:nil];
|
|
142
|
-
UIButton *extraButton = [self redBoxButton:extraText
|
|
143
|
-
accessibilityIdentifier:@"redbox-extra"
|
|
144
|
-
selector:@selector(showExtraDataViewController)
|
|
145
|
-
block:nil];
|
|
146
|
-
|
|
147
|
-
[NSLayoutConstraint activateConstraints:@[
|
|
148
|
-
[dismissButton.heightAnchor constraintEqualToConstant:buttonHeight],
|
|
149
|
-
[reloadButton.heightAnchor constraintEqualToConstant:buttonHeight],
|
|
150
|
-
[copyButton.heightAnchor constraintEqualToConstant:buttonHeight],
|
|
151
|
-
[extraButton.heightAnchor constraintEqualToConstant:buttonHeight]
|
|
152
|
-
]];
|
|
153
|
-
|
|
154
|
-
UIStackView *buttonStackView = [[UIStackView alloc] init];
|
|
155
|
-
buttonStackView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
156
|
-
buttonStackView.axis = UILayoutConstraintAxisHorizontal;
|
|
157
|
-
buttonStackView.distribution = UIStackViewDistributionFillEqually;
|
|
158
|
-
buttonStackView.alignment = UIStackViewAlignmentTop;
|
|
159
|
-
buttonStackView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
|
|
160
|
-
|
|
161
|
-
[buttonStackView addArrangedSubview:dismissButton];
|
|
162
|
-
[buttonStackView addArrangedSubview:reloadButton];
|
|
163
|
-
[buttonStackView addArrangedSubview:copyButton];
|
|
164
|
-
[buttonStackView addArrangedSubview:extraButton];
|
|
165
|
-
|
|
166
|
-
[self.view addSubview:buttonStackView];
|
|
167
|
-
|
|
168
|
-
[NSLayoutConstraint activateConstraints:@[
|
|
169
|
-
[buttonStackView.heightAnchor constraintEqualToConstant:buttonHeight + [self bottomSafeViewHeight]],
|
|
170
|
-
[buttonStackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
|
|
171
|
-
[buttonStackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
|
|
172
|
-
[buttonStackView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]
|
|
173
|
-
]];
|
|
174
|
-
|
|
175
|
-
for (NSUInteger i = 0; i < [_customButtonTitles count]; i++) {
|
|
176
|
-
UIButton *button = [self redBoxButton:_customButtonTitles[i]
|
|
177
|
-
accessibilityIdentifier:@""
|
|
178
|
-
selector:nil
|
|
179
|
-
block:_customButtonHandlers[i]];
|
|
180
|
-
[button.heightAnchor constraintEqualToConstant:buttonHeight].active = YES;
|
|
181
|
-
[buttonStackView addArrangedSubview:button];
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
UIView *topBorder = [[UIView alloc] init];
|
|
185
|
-
topBorder.translatesAutoresizingMaskIntoConstraints = NO;
|
|
186
|
-
topBorder.backgroundColor = [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
|
|
187
|
-
[topBorder.heightAnchor constraintEqualToConstant:1].active = YES;
|
|
188
|
-
|
|
189
|
-
[self.view addSubview:topBorder];
|
|
190
|
-
|
|
191
|
-
[NSLayoutConstraint activateConstraints:@[
|
|
192
|
-
[topBorder.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
|
|
193
|
-
[topBorder.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
|
|
194
|
-
[topBorder.bottomAnchor constraintEqualToAnchor:buttonStackView.topAnchor],
|
|
195
|
-
]];
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
- (UIButton *)redBoxButton:(NSString *)title
|
|
199
|
-
accessibilityIdentifier:(NSString *)accessibilityIdentifier
|
|
200
|
-
selector:(SEL)selector
|
|
201
|
-
block:(RCTRedBoxButtonPressHandler)block
|
|
202
|
-
{
|
|
203
|
-
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
204
|
-
button.autoresizingMask =
|
|
205
|
-
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin;
|
|
206
|
-
button.accessibilityIdentifier = accessibilityIdentifier;
|
|
207
|
-
button.titleLabel.font = [UIFont systemFontOfSize:13];
|
|
208
|
-
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
209
|
-
button.titleLabel.textAlignment = NSTextAlignmentCenter;
|
|
210
|
-
button.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
|
|
211
|
-
[button setTitle:title forState:UIControlStateNormal];
|
|
212
|
-
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
|
213
|
-
[button setTitleColor:[UIColor colorWithWhite:1 alpha:0.5] forState:UIControlStateHighlighted];
|
|
214
|
-
if (selector) {
|
|
215
|
-
[button addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
|
|
216
|
-
} else if (block) {
|
|
217
|
-
[button rct_addBlock:block forControlEvents:UIControlEventTouchUpInside];
|
|
218
|
-
}
|
|
219
|
-
return button;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
- (NSInteger)bottomSafeViewHeight
|
|
223
|
-
{
|
|
224
|
-
#if TARGET_OS_MACCATALYST
|
|
225
|
-
return 0;
|
|
226
|
-
#else
|
|
227
|
-
return RCTKeyWindow().safeAreaInsets.bottom;
|
|
228
|
-
#endif
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
|
|
232
|
-
|
|
233
|
-
- (NSString *)stripAnsi:(NSString *)text
|
|
234
|
-
{
|
|
235
|
-
NSError *error = nil;
|
|
236
|
-
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\x1b\\[[0-9;]*m"
|
|
237
|
-
options:NSRegularExpressionCaseInsensitive
|
|
238
|
-
error:&error];
|
|
239
|
-
return [regex stringByReplacingMatchesInString:text options:0 range:NSMakeRange(0, [text length]) withTemplate:@""];
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
- (void)showErrorMessage:(NSString *)message
|
|
243
|
-
withStack:(NSArray<RCTJSStackFrame *> *)stack
|
|
244
|
-
isUpdate:(BOOL)isUpdate
|
|
245
|
-
errorCookie:(int)errorCookie
|
|
246
|
-
{
|
|
247
|
-
// Remove ANSI color codes from the message
|
|
248
|
-
NSString *messageWithoutAnsi = [self stripAnsi:message];
|
|
249
|
-
|
|
250
|
-
BOOL isRootViewControllerPresented = self.presentingViewController != nil;
|
|
251
|
-
// Show if this is a new message, or if we're updating the previous message
|
|
252
|
-
BOOL isNew = !isRootViewControllerPresented && !isUpdate;
|
|
253
|
-
BOOL isUpdateForSameMessage = !isNew &&
|
|
254
|
-
(isRootViewControllerPresented && isUpdate &&
|
|
255
|
-
((errorCookie == -1 && [_lastErrorMessage isEqualToString:messageWithoutAnsi]) ||
|
|
256
|
-
(errorCookie == _lastErrorCookie)));
|
|
257
|
-
if (isNew || isUpdateForSameMessage) {
|
|
258
|
-
_lastStackTrace = stack;
|
|
259
|
-
// message is displayed using UILabel, which is unable to render text of
|
|
260
|
-
// unlimited length, so we truncate it
|
|
261
|
-
_lastErrorMessage = [messageWithoutAnsi substringToIndex:MIN((NSUInteger)10000, messageWithoutAnsi.length)];
|
|
262
|
-
_lastErrorCookie = errorCookie;
|
|
263
|
-
|
|
264
|
-
[_stackTraceTableView reloadData];
|
|
265
|
-
|
|
266
|
-
if (!isRootViewControllerPresented) {
|
|
267
|
-
[_stackTraceTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
|
|
268
|
-
atScrollPosition:UITableViewScrollPositionTop
|
|
269
|
-
animated:NO];
|
|
270
|
-
[RCTKeyWindow().rootViewController presentViewController:self animated:YES completion:nil];
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
- (void)dismiss
|
|
276
|
-
{
|
|
277
|
-
[self dismissViewControllerAnimated:YES completion:nil];
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
- (void)reload
|
|
281
|
-
{
|
|
282
|
-
if (_actionDelegate != nil) {
|
|
283
|
-
[_actionDelegate reloadFromRedBoxController:self];
|
|
284
|
-
} else {
|
|
285
|
-
// In bridgeless mode `RCTRedBox` gets deallocated, we need to notify listeners anyway.
|
|
286
|
-
RCTTriggerReloadCommandListeners(@"Redbox");
|
|
287
|
-
[self dismiss];
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
- (void)showExtraDataViewController
|
|
292
|
-
{
|
|
293
|
-
[_actionDelegate loadExtraDataViewController];
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
- (void)copyStack
|
|
297
|
-
{
|
|
298
|
-
NSMutableString *fullStackTrace;
|
|
299
|
-
|
|
300
|
-
if (_lastErrorMessage != nil) {
|
|
301
|
-
fullStackTrace = [_lastErrorMessage mutableCopy];
|
|
302
|
-
[fullStackTrace appendString:@"\n\n"];
|
|
303
|
-
} else {
|
|
304
|
-
fullStackTrace = [NSMutableString string];
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
for (RCTJSStackFrame *stackFrame in _lastStackTrace) {
|
|
308
|
-
[fullStackTrace appendString:[NSString stringWithFormat:@"%@\n", stackFrame.methodName]];
|
|
309
|
-
if (stackFrame.file) {
|
|
310
|
-
[fullStackTrace appendFormat:@" %@\n", [self formatFrameSource:stackFrame]];
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
#if !TARGET_OS_TV
|
|
314
|
-
UIPasteboard *pb = [UIPasteboard generalPasteboard];
|
|
315
|
-
[pb setString:fullStackTrace];
|
|
316
|
-
#endif
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
- (NSString *)formatFrameSource:(RCTJSStackFrame *)stackFrame
|
|
320
|
-
{
|
|
321
|
-
NSString *fileName = RCTNilIfNull(stackFrame.file) ? [stackFrame.file lastPathComponent] : @"<unknown file>";
|
|
322
|
-
NSString *lineInfo = [NSString stringWithFormat:@"%@:%lld", fileName, (long long)stackFrame.lineNumber];
|
|
323
|
-
|
|
324
|
-
if (stackFrame.column != 0) {
|
|
325
|
-
lineInfo = [lineInfo stringByAppendingFormat:@":%lld", (long long)stackFrame.column];
|
|
326
|
-
}
|
|
327
|
-
return lineInfo;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
- (void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
|
|
331
|
-
{
|
|
332
|
-
UITableViewCell *previouslyFocusedItem = (UITableViewCell *)context.previouslyFocusedItem;
|
|
333
|
-
if ([previouslyFocusedItem isKindOfClass:[UITableViewCell class]]) {
|
|
334
|
-
[coordinator addCoordinatedUnfocusingAnimations:^(id<UIFocusAnimationContext> _Nonnull animationContext) {
|
|
335
|
-
previouslyFocusedItem.textLabel.textColor = [UIColor whiteColor];
|
|
336
|
-
} completion:nil];
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
UITableViewCell *nextFocusedItem = (UITableViewCell *)context.nextFocusedItem;
|
|
340
|
-
if ([nextFocusedItem isKindOfClass:[UITableViewCell class]]) {
|
|
341
|
-
[coordinator addCoordinatedFocusingAnimations:^(id<UIFocusAnimationContext> _Nonnull animationContext) {
|
|
342
|
-
nextFocusedItem.textLabel.textColor = [UIColor blackColor];
|
|
343
|
-
} completion:nil];
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
#pragma mark - TableView
|
|
348
|
-
|
|
349
|
-
- (NSInteger)numberOfSectionsInTableView:(__unused UITableView *)tableView
|
|
350
|
-
{
|
|
351
|
-
return 2;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
- (NSInteger)tableView:(__unused UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
|
355
|
-
{
|
|
356
|
-
return section == 0 ? 1 : _lastStackTrace.count;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
360
|
-
{
|
|
361
|
-
if (indexPath.section == 0) {
|
|
362
|
-
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"msg-cell"];
|
|
363
|
-
return [self reuseCell:cell forErrorMessage:_lastErrorMessage];
|
|
364
|
-
}
|
|
365
|
-
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
|
|
366
|
-
NSUInteger index = indexPath.row;
|
|
367
|
-
RCTJSStackFrame *stackFrame = _lastStackTrace[index];
|
|
368
|
-
return [self reuseCell:cell forStackFrame:stackFrame];
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
- (UITableViewCell *)reuseCell:(UITableViewCell *)cell forErrorMessage:(NSString *)message
|
|
372
|
-
{
|
|
373
|
-
if (!cell) {
|
|
374
|
-
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"msg-cell"];
|
|
375
|
-
cell.textLabel.accessibilityIdentifier = @"redbox-error";
|
|
376
|
-
cell.textLabel.textColor = [UIColor whiteColor];
|
|
377
|
-
|
|
378
|
-
// Prefer a monofont for formatting messages that were designed
|
|
379
|
-
// to be displayed in a terminal.
|
|
380
|
-
cell.textLabel.font = [UIFont monospacedSystemFontOfSize:14 weight:UIFontWeightBold];
|
|
381
|
-
|
|
382
|
-
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
383
|
-
cell.textLabel.numberOfLines = 0;
|
|
384
|
-
cell.detailTextLabel.textColor = [UIColor whiteColor];
|
|
385
|
-
cell.backgroundColor = [UIColor colorWithRed:0.82 green:0.10 blue:0.15 alpha:1.0];
|
|
386
|
-
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
cell.textLabel.text = message;
|
|
390
|
-
|
|
391
|
-
return cell;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
- (UITableViewCell *)reuseCell:(UITableViewCell *)cell forStackFrame:(RCTJSStackFrame *)stackFrame
|
|
395
|
-
{
|
|
396
|
-
if (!cell) {
|
|
397
|
-
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
|
|
398
|
-
cell.textLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:14];
|
|
399
|
-
cell.textLabel.lineBreakMode = NSLineBreakByCharWrapping;
|
|
400
|
-
cell.textLabel.numberOfLines = 2;
|
|
401
|
-
cell.detailTextLabel.textColor = [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
|
|
402
|
-
cell.detailTextLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:11];
|
|
403
|
-
cell.detailTextLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
|
|
404
|
-
cell.backgroundColor = [UIColor clearColor];
|
|
405
|
-
cell.selectedBackgroundView = [UIView new];
|
|
406
|
-
cell.selectedBackgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2];
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
cell.textLabel.text = stackFrame.methodName ?: @"(unnamed method)";
|
|
410
|
-
if (stackFrame.file) {
|
|
411
|
-
cell.detailTextLabel.text = [self formatFrameSource:stackFrame];
|
|
412
|
-
} else {
|
|
413
|
-
cell.detailTextLabel.text = @"";
|
|
414
|
-
}
|
|
415
|
-
cell.textLabel.textColor = stackFrame.collapse ? [UIColor lightGrayColor] : [UIColor whiteColor];
|
|
416
|
-
cell.detailTextLabel.textColor = stackFrame.collapse ? [UIColor colorWithRed:0.50 green:0.50 blue:0.50 alpha:1.0]
|
|
417
|
-
: [UIColor colorWithRed:0.70 green:0.70 blue:0.70 alpha:1.0];
|
|
418
|
-
return cell;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
422
|
-
{
|
|
423
|
-
if (indexPath.section == 0) {
|
|
424
|
-
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
|
425
|
-
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
|
|
426
|
-
|
|
427
|
-
NSDictionary *attributes =
|
|
428
|
-
@{NSFontAttributeName : [UIFont boldSystemFontOfSize:16], NSParagraphStyleAttributeName : paragraphStyle};
|
|
429
|
-
CGRect boundingRect =
|
|
430
|
-
[_lastErrorMessage boundingRectWithSize:CGSizeMake(tableView.frame.size.width - 30, CGFLOAT_MAX)
|
|
431
|
-
options:NSStringDrawingUsesLineFragmentOrigin
|
|
432
|
-
attributes:attributes
|
|
433
|
-
context:nil];
|
|
434
|
-
return ceil(boundingRect.size.height) + 40;
|
|
435
|
-
} else {
|
|
436
|
-
return 50;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
|
441
|
-
{
|
|
442
|
-
if (indexPath.section == 1) {
|
|
443
|
-
NSUInteger row = indexPath.row;
|
|
444
|
-
RCTJSStackFrame *stackFrame = _lastStackTrace[row];
|
|
445
|
-
[_actionDelegate redBoxController:self openStackFrameInEditor:stackFrame];
|
|
446
|
-
}
|
|
447
|
-
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
#pragma mark - Key commands
|
|
451
|
-
|
|
452
|
-
- (NSArray<UIKeyCommand *> *)keyCommands
|
|
453
|
-
{
|
|
454
|
-
// NOTE: We could use RCTKeyCommands for this, but since
|
|
455
|
-
// we control this window, we can use the standard, non-hacky
|
|
456
|
-
// mechanism instead
|
|
457
|
-
|
|
458
|
-
return @[
|
|
459
|
-
// Dismiss red box
|
|
460
|
-
[UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:0 action:@selector(dismiss)],
|
|
461
|
-
|
|
462
|
-
// Reload
|
|
463
|
-
[UIKeyCommand keyCommandWithInput:@"r" modifierFlags:UIKeyModifierCommand action:@selector(reload)],
|
|
464
|
-
|
|
465
|
-
// Copy = Cmd-Option C since Cmd-C in the simulator copies the pasteboard from
|
|
466
|
-
// the simulator to the desktop pasteboard.
|
|
467
|
-
[UIKeyCommand keyCommandWithInput:@"c"
|
|
468
|
-
modifierFlags:UIKeyModifierCommand | UIKeyModifierAlternate
|
|
469
|
-
action:@selector(copyStack)],
|
|
470
|
-
|
|
471
|
-
// Extra data
|
|
472
|
-
[UIKeyCommand keyCommandWithInput:@"e"
|
|
473
|
-
modifierFlags:UIKeyModifierCommand
|
|
474
|
-
action:@selector(showExtraDataViewController)]
|
|
475
|
-
];
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
- (BOOL)canBecomeFirstResponder
|
|
479
|
-
{
|
|
480
|
-
return YES;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
@end
|
|
484
|
-
|
|
485
28
|
@interface RCTRedBox () <
|
|
486
29
|
RCTInvalidating,
|
|
487
30
|
RCTRedBoxControllerActionDelegate,
|
|
@@ -490,7 +33,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
|
|
|
490
33
|
@end
|
|
491
34
|
|
|
492
35
|
@implementation RCTRedBox {
|
|
493
|
-
|
|
36
|
+
id<RCTRedBoxControlling> _controller;
|
|
494
37
|
NSMutableArray<id<RCTErrorCustomizer>> *_errorCustomizers;
|
|
495
38
|
RCTRedBoxExtraDataViewController *_extraDataViewController;
|
|
496
39
|
NSMutableArray<NSString *> *_customButtonTitles;
|
|
@@ -622,6 +165,14 @@ RCT_EXPORT_MODULE()
|
|
|
622
165
|
[self showErrorMessage:message withParsedStack:stack isUpdate:YES errorCookie:errorCookie];
|
|
623
166
|
}
|
|
624
167
|
|
|
168
|
+
- (id<RCTRedBox2Controlling>)_redBox2Controller
|
|
169
|
+
{
|
|
170
|
+
if ([_controller conformsToProtocol:@protocol(RCTRedBox2Controlling)]) {
|
|
171
|
+
return (id<RCTRedBox2Controlling>)_controller;
|
|
172
|
+
}
|
|
173
|
+
return nil;
|
|
174
|
+
}
|
|
175
|
+
|
|
625
176
|
- (void)showErrorMessage:(NSString *)message
|
|
626
177
|
withParsedStack:(NSArray<RCTJSStackFrame *> *)stack
|
|
627
178
|
isUpdate:(BOOL)isUpdate
|
|
@@ -638,14 +189,21 @@ RCT_EXPORT_MODULE()
|
|
|
638
189
|
[[self->_moduleRegistry moduleForName:"EventDispatcher"] sendDeviceEventWithName:@"collectRedBoxExtraData"
|
|
639
190
|
body:nil];
|
|
640
191
|
#pragma clang diagnostic pop
|
|
641
|
-
if (!self->_controller) {
|
|
642
|
-
self->_controller = [[RCTRedBoxController alloc] initWithCustomButtonTitles:self->_customButtonTitles
|
|
643
|
-
customButtonHandlers:self->_customButtonHandlers];
|
|
644
|
-
self->_controller.actionDelegate = self;
|
|
645
|
-
}
|
|
646
192
|
|
|
647
193
|
RCTErrorInfo *errorInfo = [[RCTErrorInfo alloc] initWithErrorMessage:message stack:stack];
|
|
648
194
|
errorInfo = [self _customizeError:errorInfo];
|
|
195
|
+
|
|
196
|
+
if (self->_controller == nullptr) {
|
|
197
|
+
if (facebook::react::ReactNativeFeatureFlags::redBoxV2IOS()) {
|
|
198
|
+
self->_controller = [[RCTRedBox2Controller alloc] initWithCustomButtonTitles:self->_customButtonTitles
|
|
199
|
+
customButtonHandlers:self->_customButtonHandlers];
|
|
200
|
+
} else {
|
|
201
|
+
self->_controller = [[RCTRedBoxController alloc] initWithCustomButtonTitles:self->_customButtonTitles
|
|
202
|
+
customButtonHandlers:self->_customButtonHandlers];
|
|
203
|
+
}
|
|
204
|
+
self->_controller.actionDelegate = self;
|
|
205
|
+
}
|
|
206
|
+
[self _redBox2Controller].bundleURL = self->_overrideBundleURL ?: self->_bundleManager.bundleURL;
|
|
649
207
|
[self->_controller showErrorMessage:errorInfo.errorMessage
|
|
650
208
|
withStack:errorInfo.stack
|
|
651
209
|
isUpdate:isUpdate
|
|
@@ -656,9 +214,10 @@ RCT_EXPORT_MODULE()
|
|
|
656
214
|
- (void)loadExtraDataViewController
|
|
657
215
|
{
|
|
658
216
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
217
|
+
UIViewController *controller = static_cast<UIViewController *>(self->_controller);
|
|
659
218
|
// Make sure the CMD+E shortcut doesn't call this twice
|
|
660
|
-
if (self->_extraDataViewController != nil &&
|
|
661
|
-
[
|
|
219
|
+
if (self->_extraDataViewController != nil && ([controller presentedViewController] == nullptr)) {
|
|
220
|
+
[controller presentViewController:self->_extraDataViewController animated:YES completion:nil];
|
|
662
221
|
}
|
|
663
222
|
});
|
|
664
223
|
}
|
|
@@ -680,7 +239,7 @@ RCT_EXPORT_METHOD(dismiss)
|
|
|
680
239
|
[self dismiss];
|
|
681
240
|
}
|
|
682
241
|
|
|
683
|
-
- (void)redBoxController:(__unused
|
|
242
|
+
- (void)redBoxController:(__unused UIViewController *)redBoxController
|
|
684
243
|
openStackFrameInEditor:(RCTJSStackFrame *)stackFrame
|
|
685
244
|
{
|
|
686
245
|
NSURL *const bundleURL = _overrideBundleURL ?: _bundleManager.bundleURL;
|
|
@@ -707,7 +266,7 @@ RCT_EXPORT_METHOD(dismiss)
|
|
|
707
266
|
[self reloadFromRedBoxController:nil];
|
|
708
267
|
}
|
|
709
268
|
|
|
710
|
-
- (void)reloadFromRedBoxController:(__unused
|
|
269
|
+
- (void)reloadFromRedBoxController:(__unused UIViewController *)redBoxController
|
|
711
270
|
{
|
|
712
271
|
if (_overrideReloadAction) {
|
|
713
272
|
_overrideReloadAction();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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 <UIKit/UIKit.h>
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parses ANSI escape sequences in text and produces an NSAttributedString
|
|
12
|
+
* with the corresponding foreground/background colors applied.
|
|
13
|
+
*
|
|
14
|
+
* Uses the Afterglow color theme (matching LogBox's AnsiHighlight.js).
|
|
15
|
+
*/
|
|
16
|
+
@interface RCTRedBox2AnsiParser : NSObject
|
|
17
|
+
|
|
18
|
+
+ (NSAttributedString *)attributedStringFromAnsiText:(NSString *)text
|
|
19
|
+
baseFont:(UIFont *)font
|
|
20
|
+
baseColor:(UIColor *)color;
|
|
21
|
+
|
|
22
|
+
@end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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 "RCTRedBox2AnsiParser+Internal.h"
|
|
9
|
+
|
|
10
|
+
#import <React/RCTDefines.h>
|
|
11
|
+
#import <react/debug/redbox/AnsiParser.h>
|
|
12
|
+
|
|
13
|
+
#if RCT_DEV_MENU
|
|
14
|
+
|
|
15
|
+
using facebook::react::unstable_redbox::AnsiColor;
|
|
16
|
+
using facebook::react::unstable_redbox::parseAnsi;
|
|
17
|
+
|
|
18
|
+
static UIColor *RCTUIColorFromAnsiColor(const AnsiColor &c)
|
|
19
|
+
{
|
|
20
|
+
return [UIColor colorWithRed:c.r / 255.0 green:c.g / 255.0 blue:c.b / 255.0 alpha:1.0];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@implementation RCTRedBox2AnsiParser
|
|
24
|
+
|
|
25
|
+
+ (NSAttributedString *)attributedStringFromAnsiText:(NSString *)text baseFont:(UIFont *)font baseColor:(UIColor *)color
|
|
26
|
+
{
|
|
27
|
+
if (text == nil) {
|
|
28
|
+
return [[NSAttributedString alloc] init];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
auto spans = parseAnsi(text.UTF8String);
|
|
32
|
+
NSMutableAttributedString *result =[NSMutableAttributedString new];
|
|
33
|
+
NSDictionary *baseAttributes = @{NSFontAttributeName : font, NSForegroundColorAttributeName : color};
|
|
34
|
+
|
|
35
|
+
for (const auto &span : spans) {
|
|
36
|
+
NSString *str = [NSString stringWithUTF8String:span.text.c_str()];
|
|
37
|
+
if (str == nil) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
NSMutableDictionary *attrs = [baseAttributes mutableCopy];
|
|
41
|
+
if (span.foregroundColor.has_value()) {
|
|
42
|
+
attrs[NSForegroundColorAttributeName] = RCTUIColorFromAnsiColor(*span.foregroundColor);
|
|
43
|
+
}
|
|
44
|
+
if (span.backgroundColor.has_value()) {
|
|
45
|
+
attrs[NSBackgroundColorAttributeName] = RCTUIColorFromAnsiColor(*span.backgroundColor);
|
|
46
|
+
}
|
|
47
|
+
[result appendAttributedString:[[NSAttributedString alloc] initWithString:str attributes:attrs]];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@end
|
|
54
|
+
|
|
55
|
+
#endif
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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/RCTDefines.h>
|
|
9
|
+
|
|
10
|
+
#import "RCTRedBox+Internal.h"
|
|
11
|
+
|
|
12
|
+
#if RCT_DEV_MENU
|
|
13
|
+
|
|
14
|
+
typedef void (^RCTRedBox2ButtonPressHandler)(void);
|
|
15
|
+
|
|
16
|
+
@interface RCTRedBox2Controller : UIViewController <RCTRedBox2Controlling, UITableViewDelegate, UITableViewDataSource>
|
|
17
|
+
|
|
18
|
+
@property (nonatomic, weak) id<RCTRedBoxControllerActionDelegate> actionDelegate;
|
|
19
|
+
|
|
20
|
+
- (instancetype)initWithCustomButtonTitles:(NSArray<NSString *> *)customButtonTitles
|
|
21
|
+
customButtonHandlers:(NSArray<RCTRedBox2ButtonPressHandler> *)customButtonHandlers;
|
|
22
|
+
|
|
23
|
+
- (void)showErrorMessage:(NSString *)message
|
|
24
|
+
withStack:(NSArray<RCTJSStackFrame *> *)stack
|
|
25
|
+
isUpdate:(BOOL)isUpdate
|
|
26
|
+
errorCookie:(int)errorCookie;
|
|
27
|
+
|
|
28
|
+
/// The bundle URL used by the app, for the native HMR connection.
|
|
29
|
+
@property (nonatomic, strong, nullable) NSURL *bundleURL;
|
|
30
|
+
|
|
31
|
+
- (void)dismiss;
|
|
32
|
+
@end
|
|
33
|
+
|
|
34
|
+
#endif
|