From f99ef6996ef73bfd2f2e81ded4e467e9afdb96e9 Mon Sep 17 00:00:00 2001 From: John Knox Date: Tue, 28 Aug 2018 04:04:29 -0700 Subject: [PATCH] Summarise state in iOS diagnostics Summary: V1 ios diagnostics complete. This change adds a new section to the ios diagnostics screen that shows the current state of each step required to get sonar working. The logs (transitions between states) are displayed below it. SonarClient.mm is technically involved in the UI, by converting enums to emojis, I don't like this but didn't get obj-C working with C enums so have left it like this for now. Reviewed By: priteshrnandgaonkar Differential Revision: D9378212 fbshipit-source-id: 091ce00e898a8038c680555123640b90d753fc09 --- .../FlipperDiagnosticsViewController.h | 10 ++- .../FlipperDiagnosticsViewController.m | 76 ++++++++++++++----- iOS/SonarKit/SonarClient.h | 12 ++- iOS/SonarKit/SonarClient.mm | 31 ++++++++ 4 files changed, 109 insertions(+), 20 deletions(-) diff --git a/iOS/SonarKit/FlipperDiagnosticsViewController.h b/iOS/SonarKit/FlipperDiagnosticsViewController.h index 58854c43c..cc11595fe 100644 --- a/iOS/SonarKit/FlipperDiagnosticsViewController.h +++ b/iOS/SonarKit/FlipperDiagnosticsViewController.h @@ -10,9 +10,17 @@ #include "FlipperStateUpdateListener.h" #import +@interface StateTableDataSource : NSObject +@property (strong, nonatomic) NSArray *elements; +@end + @interface FlipperDiagnosticsViewController : UIViewController -@property(strong, nonatomic) UIScrollView *scrollView; +@property(strong, nonatomic) StateTableDataSource *tableDataSource; @property(strong, nonatomic) UILabel *stateLabel; +@property(strong, nonatomic) UITableView *stateTable; +@property(strong, nonatomic) UIScrollView *scrollView; +@property(strong, nonatomic) UILabel *logLabel; + - (void)onUpdate; @end diff --git a/iOS/SonarKit/FlipperDiagnosticsViewController.m b/iOS/SonarKit/FlipperDiagnosticsViewController.m index 0d0c3ff48..ae79c05ee 100644 --- a/iOS/SonarKit/FlipperDiagnosticsViewController.m +++ b/iOS/SonarKit/FlipperDiagnosticsViewController.m @@ -3,22 +3,54 @@ #import "FlipperDiagnosticsViewController.h" #import "SonarClient.h" +#define STATE_VIEW_HEIGHT 300 + +static NSString *const kSKCellIdentifier = @"FlipperDiagnosticStateTableStableCellIdentifier"; + +@implementation StateTableDataSource +- (instancetype)initWithElements:(NSArray *)elements { + self = [super init]; + if (self) { + _elements = elements; + } + return self; +} + +- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { + NSInteger row = indexPath.row; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kSKCellIdentifier forIndexPath:indexPath]; + cell.textLabel.font = [UIFont fontWithName:@"Arial" size:10]; + cell.textLabel.text = [self.elements[row][@"state"] stringByAppendingString:self.elements[row][@"name"]]; + return cell; +} + +- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.elements count]; +} + +@end + @implementation FlipperDiagnosticsViewController - (void)viewDidLoad { [super viewDidLoad]; - UILabel *text = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)]; - text.text = @"Flipper Diagnostics"; - [self.view addSubview:text]; + self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, STATE_VIEW_HEIGHT, self.view.frame.size.width, self.view.frame.size.height - 100 - STATE_VIEW_HEIGHT)]; + self.logLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.scrollView.frame.size.height)]; + self.logLabel.numberOfLines = 0; + self.logLabel.font = [UIFont fontWithName:@"Arial" size:10]; + [self.scrollView addSubview:self.logLabel]; - self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 50, self.view.frame.size.width, self.view.frame.size.height - 100)]; - self.stateLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 1000)]; + self.stateTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, STATE_VIEW_HEIGHT)]; + [self.stateTable registerClass:[UITableViewCell class] forCellReuseIdentifier:kSKCellIdentifier]; + self.stateTable.rowHeight = 14; + self.tableDataSource = [[StateTableDataSource alloc] initWithElements:[[SonarClient sharedClient] getStateElements]]; + self.stateTable.dataSource = self.tableDataSource; - self.stateLabel.numberOfLines = 0; - self.stateLabel.text = [[SonarClient sharedClient] getState]; - [self.scrollView addSubview:self.stateLabel]; - self.scrollView.contentSize = self.stateLabel.frame.size; + [self updateLogView]; + + [self.view addSubview:self.stateTable]; [self.view addSubview:self.scrollView]; self.view.backgroundColor = [UIColor whiteColor]; } @@ -26,17 +58,27 @@ - (void)onUpdate { FlipperDiagnosticsViewController __weak *weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ - FlipperDiagnosticsViewController *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - NSString *state = [[SonarClient sharedClient] getState]; - strongSelf.stateLabel.text = state; - [strongSelf.stateLabel sizeToFit]; - strongSelf.scrollView.contentSize = strongSelf.stateLabel.frame.size; + [weakSelf updateStateTable]; + [weakSelf updateLogView]; }); } +- (void)updateStateTable { + self.tableDataSource.elements = [[SonarClient sharedClient] getStateElements]; + [self.stateTable reloadData]; +} + +- (void)updateLogView { + NSString *state = [[SonarClient sharedClient] getState]; + self.logLabel.text = state; + [self.logLabel sizeToFit]; + self.scrollView.contentSize = self.logLabel.frame.size; + + // Scroll to bottom + CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height); + [self.scrollView setContentOffset:bottomOffset animated:YES]; +} + - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; id weakSelf = self; diff --git a/iOS/SonarKit/SonarClient.h b/iOS/SonarKit/SonarClient.h index d44da890b..790359595 100644 --- a/iOS/SonarKit/SonarClient.h +++ b/iOS/SonarKit/SonarClient.h @@ -5,8 +5,9 @@ * file in the root directory of this source tree. * */ -#import +#ifdef FB_SONARKIT_ENABLED +#import #import "SonarPlugin.h" #import "FlipperStateUpdateListener.h" @@ -47,10 +48,15 @@ Stop the connection to the Sonar desktop. - (void)stop; /** -Get the current state of the sonar client +Get the log of state changes from the sonar client */ - (NSString *)getState; +/** + Get the current summarized state of the sonar client + */ +- (NSArray *)getStateElements; + /** Subscribe a ViewController to state update change notifications */ @@ -61,3 +67,5 @@ Subscribe a ViewController to state update change notifications + (instancetype)new NS_UNAVAILABLE; @end + +#endif diff --git a/iOS/SonarKit/SonarClient.mm b/iOS/SonarKit/SonarClient.mm index e5bf17e6f..8ff766cce 100644 --- a/iOS/SonarKit/SonarClient.mm +++ b/iOS/SonarKit/SonarClient.mm @@ -127,6 +127,37 @@ using WrapperPlugin = facebook::sonar::SonarCppWrapperPlugin; return @(_cppClient->getState().c_str()); } +- (NSArray *)getStateElements { + NSMutableArray*> *const array = [NSMutableArray array]; + + for (facebook::sonar::StateElement element: _cppClient->getStateElements()) { + facebook::sonar::State state = element.state_; + NSString *stateString; + switch (state) { + case facebook::sonar::in_progress: + stateString = @"⏳ "; + break; + + case facebook::sonar::success: + stateString = @"✅ "; + break; + + case facebook::sonar::failed: + stateString = @"❌ "; + break; + + default: + stateString = @"❓ "; + break; + } + [array addObject:@{ + @"name": [NSString stringWithUTF8String:element.name_.c_str()], + @"state": stateString + }]; + } + return array; +} + - (void)subscribeForUpdates:(id)controller { auto stateListener = std::make_shared(controller); _cppClient->setStateListener(stateListener);