16
16
#import " RCTRedBoxExtraDataViewController.h"
17
17
#import " RCTUtils.h"
18
18
19
+ #import < objc/runtime.h>
20
+
19
21
#if RCT_DEV
20
22
static BOOL redBoxEnabled = YES ;
21
23
#else
@@ -34,6 +36,41 @@ BOOL RCTRedBoxGetEnabled() {
34
36
35
37
@class RCTRedBoxWindow;
36
38
39
+ @interface UIButton (RCTRedBox)
40
+
41
+ @property (nonatomic ) RCTRedBoxButtonPressHandler rct_handler;
42
+
43
+ - (void )rct_addBlock : (RCTRedBoxButtonPressHandler)handler forControlEvents : (UIControlEvents)controlEvents ;
44
+
45
+ @end
46
+
47
+ @implementation UIButton (RCTRedBox)
48
+
49
+ - (RCTRedBoxButtonPressHandler)rct_handler
50
+ {
51
+ return objc_getAssociatedObject (self, @selector (rct_handler ));
52
+ }
53
+
54
+ - (void )setRct_handler : (RCTRedBoxButtonPressHandler)rct_handler
55
+ {
56
+ objc_setAssociatedObject (self, @selector (rct_handler ), rct_handler, OBJC_ASSOCIATION_RETAIN_NONATOMIC );
57
+ }
58
+
59
+ - (void )rct_callBlock
60
+ {
61
+ if (self.rct_handler ) {
62
+ self.rct_handler ();
63
+ }
64
+ }
65
+
66
+ - (void )rct_addBlock : (RCTRedBoxButtonPressHandler)handler forControlEvents : (UIControlEvents)controlEvents
67
+ {
68
+ self.rct_handler = handler;
69
+ [self addTarget: self action: @selector (rct_callBlock ) forControlEvents: controlEvents];
70
+ }
71
+
72
+ @end
73
+
37
74
@protocol RCTRedBoxWindowActionDelegate <NSObject >
38
75
39
76
- (void )redBoxWindow : (RCTRedBoxWindow *)redBoxWindow openStackFrameInEditor : (RCTJSStackFrame *)stackFrame ;
@@ -54,7 +91,7 @@ @implementation RCTRedBoxWindow
54
91
int _lastErrorCookie;
55
92
}
56
93
57
- - (instancetype )initWithFrame : (CGRect )frame
94
+ - (instancetype )initWithFrame : (CGRect )frame customButtonTitles : ( NSArray <NSString *>*) customButtonTitles customButtonHandlers : ( NSArray <RCTRedBoxButtonPressHandler> *) customButtonHandlers
58
95
{
59
96
_lastErrorCookie = -1 ;
60
97
if ((self = [super initWithFrame: frame])) {
@@ -100,26 +137,32 @@ - (instancetype)initWithFrame:(CGRect)frame
100
137
NSString *extraText = @" Extra Info" ;
101
138
#endif
102
139
103
- UIButton *dismissButton = [self redBoxButton: dismissText accessibilityIdentifier: @" redbox-dismiss" selector: @selector (dismiss )];
104
- UIButton *reloadButton = [self redBoxButton: reloadText accessibilityIdentifier: @" redbox-reload" selector: @selector (reload )];
105
- UIButton *copyButton = [self redBoxButton: copyText accessibilityIdentifier: @" redbox-copy" selector: @selector (copyStack )];
106
- UIButton *extraButton = [self redBoxButton: extraText accessibilityIdentifier: @" redbox-extra" selector: @selector (showExtraDataViewController )];
140
+ UIButton *dismissButton = [self redBoxButton: dismissText accessibilityIdentifier: @" redbox-dismiss" selector: @selector (dismiss ) block: nil ];
141
+ UIButton *reloadButton = [self redBoxButton: reloadText accessibilityIdentifier: @" redbox-reload" selector: @selector (reload ) block: nil ];
142
+ UIButton *copyButton = [self redBoxButton: copyText accessibilityIdentifier: @" redbox-copy" selector: @selector (copyStack ) block: nil ];
143
+ UIButton *extraButton = [self redBoxButton: extraText accessibilityIdentifier: @" redbox-extra" selector: @selector (showExtraDataViewController ) block: nil ];
107
144
108
- CGFloat buttonWidth = self.bounds .size .width / 4 ;
145
+ CGFloat buttonWidth = self.bounds .size .width / ( 4 + [customButtonTitles count ]) ;
109
146
CGFloat bottomButtonHeight = self.bounds .size .height - buttonHeight - [self bottomSafeViewHeight ];
110
-
111
147
dismissButton.frame = CGRectMake (0 , bottomButtonHeight, buttonWidth, buttonHeight);
112
148
reloadButton.frame = CGRectMake (buttonWidth, bottomButtonHeight, buttonWidth, buttonHeight);
113
149
copyButton.frame = CGRectMake (buttonWidth * 2 , bottomButtonHeight, buttonWidth, buttonHeight);
114
150
extraButton.frame = CGRectMake (buttonWidth * 3 , bottomButtonHeight, buttonWidth, buttonHeight);
115
151
116
- UIView *topBorder = [[UIView alloc ] initWithFrame: CGRectMake (0 , bottomButtonHeight + 1 , rootView.frame.size.width, 1 )];
117
- topBorder.backgroundColor = [UIColor colorWithRed: 0.70 green: 0.70 blue: 0.70 alpha: 1.0 ];
118
-
119
152
[rootView addSubview: dismissButton];
120
153
[rootView addSubview: reloadButton];
121
154
[rootView addSubview: copyButton];
122
155
[rootView addSubview: extraButton];
156
+
157
+ for (NSUInteger i = 0 ; i < [customButtonTitles count ]; i++) {
158
+ UIButton *button = [self redBoxButton: customButtonTitles[i] accessibilityIdentifier: @" " selector: nil block: customButtonHandlers[i]];
159
+ button.frame = CGRectMake (buttonWidth * (4 + i), bottomButtonHeight, buttonWidth, buttonHeight);
160
+ [rootView addSubview: button];
161
+ }
162
+
163
+ UIView *topBorder = [[UIView alloc ] initWithFrame: CGRectMake (0 , bottomButtonHeight + 1 , rootView.frame.size.width, 1 )];
164
+ topBorder.backgroundColor = [UIColor colorWithRed: 0.70 green: 0.70 blue: 0.70 alpha: 1.0 ];
165
+
123
166
[rootView addSubview: topBorder];
124
167
125
168
UIView *bottomSafeView = [UIView new ];
@@ -131,7 +174,7 @@ - (instancetype)initWithFrame:(CGRect)frame
131
174
return self;
132
175
}
133
176
134
- - (UIButton *)redBoxButton : (NSString *)title accessibilityIdentifier : (NSString *)accessibilityIdentifier selector : (SEL )selector
177
+ - (UIButton *)redBoxButton : (NSString *)title accessibilityIdentifier : (NSString *)accessibilityIdentifier selector : (SEL )selector block : (RCTRedBoxButtonPressHandler) block
135
178
{
136
179
UIButton *button = [UIButton buttonWithType: UIButtonTypeCustom];
137
180
button.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin;
@@ -143,7 +186,11 @@ - (UIButton *)redBoxButton:(NSString *)title accessibilityIdentifier:(NSString *
143
186
[button setTitle: title forState: UIControlStateNormal];
144
187
[button setTitleColor: [UIColor whiteColor ] forState: UIControlStateNormal];
145
188
[button setTitleColor: [UIColor colorWithWhite: 1 alpha: 0.5 ] forState: UIControlStateHighlighted];
146
- [button addTarget: self action: selector forControlEvents: UIControlEventTouchUpInside];
189
+ if (selector) {
190
+ [button addTarget: self action: selector forControlEvents: UIControlEventTouchUpInside];
191
+ } else if (block) {
192
+ [button rct_addBlock: block forControlEvents: UIControlEventTouchUpInside];
193
+ }
147
194
return button;
148
195
}
149
196
@@ -399,6 +446,8 @@ @implementation RCTRedBox
399
446
RCTRedBoxWindow *_window;
400
447
NSMutableArray <id <RCTErrorCustomizer>> *_errorCustomizers;
401
448
RCTRedBoxExtraDataViewController *_extraDataViewController;
449
+ NSMutableArray <NSString *> *_customButtonTitles;
450
+ NSMutableArray <RCTRedBoxButtonPressHandler> *_customButtonHandlers;
402
451
}
403
452
404
453
@synthesize bridge = _bridge;
@@ -524,7 +573,7 @@ - (void)showErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSStack
524
573
#pragma clang diagnostic pop
525
574
526
575
if (!self->_window ) {
527
- self->_window = [[RCTRedBoxWindow alloc ] initWithFrame: [UIScreen mainScreen ].bounds];
576
+ self->_window = [[RCTRedBoxWindow alloc ] initWithFrame: [UIScreen mainScreen ].bounds customButtonTitles: self ->_customButtonTitles customButtonHandlers: self ->_customButtonHandlers ];
528
577
self->_window .actionDelegate = self;
529
578
}
530
579
@@ -599,6 +648,17 @@ - (void)reloadFromRedBoxWindow:(__unused RCTRedBoxWindow *)redBoxWindow
599
648
[self dismiss ];
600
649
}
601
650
651
+ - (void )addCustomButton : (NSString *)title onPressHandler : (RCTRedBoxButtonPressHandler)handler
652
+ {
653
+ if (!_customButtonTitles) {
654
+ _customButtonTitles = [NSMutableArray new ];
655
+ _customButtonHandlers = [NSMutableArray new ];
656
+ }
657
+
658
+ [_customButtonTitles addObject: title];
659
+ [_customButtonHandlers addObject: handler];
660
+ }
661
+
602
662
@end
603
663
604
664
@implementation RCTBridge (RCTRedBox)
@@ -632,6 +692,8 @@ - (void)updateErrorMessage:(NSString *)message withParsedStack:(NSArray<RCTJSSta
632
692
633
693
- (void )dismiss {}
634
694
695
+ - (void )addCustomButton : (NSString *)title onPressHandler : (RCTRedBoxButtonPressHandler)handler {}
696
+
635
697
@end
636
698
637
699
@implementation RCTBridge (RCTRedBox)
0 commit comments