269 lines
9.4 KiB
Mathematica
269 lines
9.4 KiB
Mathematica
|
/*
|
||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||
|
*
|
||
|
* This source code is licensed under the MIT license found in the
|
||
|
* LICENSE file in the root directory of this source tree.
|
||
|
*/
|
||
|
|
||
|
#import "RCTRedBoxExtraDataViewController.h"
|
||
|
#import "React/RCTUtils.h"
|
||
|
|
||
|
@interface RCTRedBoxExtraDataCell : UITableViewCell
|
||
|
|
||
|
@property (nonatomic, strong) UILabel *keyLabel;
|
||
|
@property (nonatomic, strong) UILabel *valueLabel;
|
||
|
|
||
|
@end
|
||
|
|
||
|
@implementation RCTRedBoxExtraDataCell
|
||
|
|
||
|
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
|
||
|
{
|
||
|
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
||
|
self.backgroundColor = [UIColor colorWithRed:0.8 green:0 blue:0 alpha:1];
|
||
|
UILayoutGuide *contentLayout = self.contentView.layoutMarginsGuide;
|
||
|
|
||
|
self.keyLabel = [UILabel new];
|
||
|
[self.contentView addSubview:self.keyLabel];
|
||
|
self.keyLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
||
|
[NSLayoutConstraint activateConstraints:@[
|
||
|
[self.keyLabel.leadingAnchor constraintEqualToAnchor:contentLayout.leadingAnchor],
|
||
|
[self.keyLabel.topAnchor constraintEqualToAnchor:contentLayout.topAnchor],
|
||
|
[self.keyLabel.bottomAnchor constraintEqualToAnchor:contentLayout.bottomAnchor],
|
||
|
[self.keyLabel.widthAnchor constraintEqualToAnchor:contentLayout.widthAnchor multiplier:0.3]
|
||
|
]];
|
||
|
self.keyLabel.textColor = [UIColor whiteColor];
|
||
|
self.keyLabel.numberOfLines = 0;
|
||
|
self.keyLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
||
|
self.keyLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:12.0f];
|
||
|
|
||
|
self.valueLabel = [UILabel new];
|
||
|
[self.contentView addSubview:self.valueLabel];
|
||
|
self.valueLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
||
|
[NSLayoutConstraint activateConstraints:@[
|
||
|
[self.valueLabel.leadingAnchor constraintEqualToAnchor:self.keyLabel.trailingAnchor constant:10.f],
|
||
|
[self.valueLabel.trailingAnchor constraintEqualToAnchor:contentLayout.trailingAnchor],
|
||
|
[self.valueLabel.topAnchor constraintEqualToAnchor:contentLayout.topAnchor],
|
||
|
[self.valueLabel.bottomAnchor constraintEqualToAnchor:contentLayout.bottomAnchor]
|
||
|
]];
|
||
|
self.valueLabel.textColor = [UIColor whiteColor];
|
||
|
self.valueLabel.numberOfLines = 0;
|
||
|
self.valueLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
||
|
self.valueLabel.font = [UIFont fontWithName:@"Menlo-Regular" size:12.0f];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
@end
|
||
|
|
||
|
@interface RCTRedBoxExtraDataViewController ()
|
||
|
|
||
|
@end
|
||
|
|
||
|
@implementation RCTRedBoxExtraDataViewController {
|
||
|
UITableView *_tableView;
|
||
|
NSMutableArray *_extraDataTitle;
|
||
|
NSMutableArray *_extraData;
|
||
|
}
|
||
|
|
||
|
@synthesize actionDelegate = _actionDelegate;
|
||
|
|
||
|
- (instancetype)init
|
||
|
{
|
||
|
if (self = [super init]) {
|
||
|
_extraData = [NSMutableArray new];
|
||
|
_extraDataTitle = [NSMutableArray new];
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
- (UIButton *)redBoxButtonWithTitle:(NSString *)title
|
||
|
accessibilityIdentifier:(NSString *)accessibilityIdentifier
|
||
|
action:(SEL)action
|
||
|
{
|
||
|
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
|
||
|
button.accessibilityIdentifier = accessibilityIdentifier;
|
||
|
|
||
|
button.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
|
||
|
|
||
|
button.titleLabel.font = [UIFont systemFontOfSize:13];
|
||
|
|
||
|
[button setTitle:title forState:UIControlStateNormal];
|
||
|
[button setTitleColor:[UIColor colorWithWhite:1 alpha:1] forState:UIControlStateNormal];
|
||
|
[button setTitleColor:[UIColor colorWithWhite:1 alpha:0.5] forState:UIControlStateHighlighted];
|
||
|
|
||
|
[button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
|
||
|
return button;
|
||
|
}
|
||
|
|
||
|
- (void)viewDidLoad
|
||
|
{
|
||
|
CGFloat bottomSafeAreaInset = RCTKeyWindow().safeAreaInsets.bottom;
|
||
|
|
||
|
CGFloat buttonHeight = 60;
|
||
|
CGFloat buttonWidth = self.view.bounds.size.width / 2;
|
||
|
|
||
|
_tableView = [UITableView new];
|
||
|
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
|
||
|
_tableView.delegate = self;
|
||
|
_tableView.dataSource = self;
|
||
|
_tableView.backgroundColor = [UIColor colorWithRed:0.8 green:0 blue:0 alpha:1];
|
||
|
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||
|
_tableView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
|
||
|
_tableView.allowsSelection = NO;
|
||
|
[self.view addSubview:_tableView];
|
||
|
|
||
|
#if TARGET_OS_SIMULATOR || TARGET_OS_MACCATALYST
|
||
|
NSString *reloadText = @"Reload JS (\u2318R)";
|
||
|
NSString *dismissText = @"Dismiss (ESC)";
|
||
|
#else
|
||
|
NSString *reloadText = @"Reload JS";
|
||
|
NSString *dismissText = @"Dismiss";
|
||
|
#endif
|
||
|
|
||
|
UIButton *dismissButton = [self redBoxButtonWithTitle:dismissText
|
||
|
accessibilityIdentifier:@"redbox-extra-data-dismiss"
|
||
|
action:@selector(dismiss)];
|
||
|
UIButton *reloadButton = [self redBoxButtonWithTitle:reloadText
|
||
|
accessibilityIdentifier:@"redbox-reload"
|
||
|
action:@selector(reload)];
|
||
|
|
||
|
UIStackView *buttonStackView = [[UIStackView alloc] init];
|
||
|
buttonStackView.translatesAutoresizingMaskIntoConstraints = NO;
|
||
|
buttonStackView.axis = UILayoutConstraintAxisHorizontal;
|
||
|
buttonStackView.distribution = UIStackViewDistributionFillEqually;
|
||
|
buttonStackView.alignment = UIStackViewAlignmentTop;
|
||
|
buttonStackView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1];
|
||
|
|
||
|
[buttonStackView addArrangedSubview:dismissButton];
|
||
|
[buttonStackView addArrangedSubview:reloadButton];
|
||
|
|
||
|
[self.view addSubview:buttonStackView];
|
||
|
|
||
|
[NSLayoutConstraint activateConstraints:@[
|
||
|
[_tableView.topAnchor constraintEqualToAnchor:self.view.topAnchor],
|
||
|
[_tableView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
|
||
|
[_tableView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
|
||
|
[_tableView.bottomAnchor constraintEqualToAnchor:buttonStackView.topAnchor],
|
||
|
|
||
|
[dismissButton.heightAnchor constraintEqualToConstant:buttonHeight],
|
||
|
[dismissButton.widthAnchor constraintEqualToConstant:buttonWidth],
|
||
|
[reloadButton.heightAnchor constraintEqualToConstant:buttonHeight],
|
||
|
[reloadButton.widthAnchor constraintEqualToConstant:buttonWidth],
|
||
|
[buttonStackView.heightAnchor constraintEqualToConstant:buttonHeight + bottomSafeAreaInset],
|
||
|
|
||
|
[buttonStackView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
|
||
|
[buttonStackView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
|
||
|
[buttonStackView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
|
||
|
]];
|
||
|
}
|
||
|
|
||
|
- (void)viewDidAppear:(BOOL)animated
|
||
|
{
|
||
|
[super viewDidAppear:animated];
|
||
|
[_tableView reloadData];
|
||
|
}
|
||
|
|
||
|
- (NSInteger)tableView:(__unused UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||
|
{
|
||
|
return [[_extraData objectAtIndex:section] count];
|
||
|
}
|
||
|
|
||
|
- (CGFloat)tableView:(__unused UITableView *)tableView heightForHeaderInSection:(__unused NSInteger)section
|
||
|
{
|
||
|
return 40;
|
||
|
}
|
||
|
|
||
|
- (UIView *)tableView:(__unused UITableView *)tableView viewForHeaderInSection:(NSInteger)section
|
||
|
{
|
||
|
UIView *header = [UIView new];
|
||
|
header.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
|
||
|
|
||
|
UILabel *headerLabel = [UILabel new];
|
||
|
[header addSubview:headerLabel];
|
||
|
|
||
|
headerLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
||
|
[NSLayoutConstraint activateConstraints:@[
|
||
|
[headerLabel.leadingAnchor constraintEqualToAnchor:header.leadingAnchor constant:5],
|
||
|
[headerLabel.trailingAnchor constraintEqualToAnchor:header.trailingAnchor],
|
||
|
[headerLabel.topAnchor constraintEqualToAnchor:header.topAnchor],
|
||
|
[headerLabel.bottomAnchor constraintEqualToAnchor:header.bottomAnchor],
|
||
|
]];
|
||
|
|
||
|
headerLabel.textColor = [UIColor whiteColor];
|
||
|
headerLabel.font = [UIFont fontWithName:@"Menlo-Bold" size:14.0f];
|
||
|
headerLabel.text = [_extraDataTitle[section] uppercaseString];
|
||
|
|
||
|
return header;
|
||
|
}
|
||
|
|
||
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||
|
{
|
||
|
static NSString *reuseIdentifier = @"RedBoxExtraData";
|
||
|
|
||
|
RCTRedBoxExtraDataCell *cell =
|
||
|
(RCTRedBoxExtraDataCell *)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
|
||
|
|
||
|
if (cell == nil) {
|
||
|
cell = [[RCTRedBoxExtraDataCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
|
||
|
}
|
||
|
|
||
|
NSArray *dataKVPair = _extraData[indexPath.section][indexPath.row];
|
||
|
cell.keyLabel.text = dataKVPair[0];
|
||
|
cell.valueLabel.text = dataKVPair[1];
|
||
|
|
||
|
return cell;
|
||
|
}
|
||
|
|
||
|
- (NSInteger)numberOfSectionsInTableView:(__unused UITableView *)tableView
|
||
|
{
|
||
|
return _extraDataTitle.count;
|
||
|
}
|
||
|
|
||
|
- (void)addExtraData:(NSDictionary *)data forIdentifier:(NSString *)identifier
|
||
|
{
|
||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||
|
NSMutableArray *newData = [NSMutableArray new];
|
||
|
for (id key in data) {
|
||
|
[newData addObject:@[
|
||
|
[NSString stringWithFormat:@"%@", key],
|
||
|
[NSString stringWithFormat:@"%@", [data objectForKey:key]]
|
||
|
]];
|
||
|
}
|
||
|
|
||
|
NSInteger idx = [self->_extraDataTitle indexOfObject:identifier];
|
||
|
if (idx == NSNotFound) {
|
||
|
[self->_extraDataTitle addObject:identifier];
|
||
|
[self->_extraData addObject:newData];
|
||
|
} else {
|
||
|
[self->_extraData replaceObjectAtIndex:idx withObject:newData];
|
||
|
}
|
||
|
|
||
|
[self->_tableView reloadData];
|
||
|
});
|
||
|
}
|
||
|
|
||
|
- (void)dismiss
|
||
|
{
|
||
|
[self dismissViewControllerAnimated:YES completion:nil];
|
||
|
}
|
||
|
|
||
|
- (void)reload
|
||
|
{
|
||
|
[_actionDelegate reload];
|
||
|
}
|
||
|
|
||
|
#pragma mark - Key commands
|
||
|
|
||
|
- (NSArray<UIKeyCommand *> *)keyCommands
|
||
|
{
|
||
|
return @[
|
||
|
// Dismiss
|
||
|
[UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:0 action:@selector(dismiss)],
|
||
|
// Reload
|
||
|
[UIKeyCommand keyCommandWithInput:@"r" modifierFlags:UIKeyModifierCommand action:@selector(reload)]
|
||
|
];
|
||
|
}
|
||
|
|
||
|
@end
|