1*bf47c682SAndroid Build Coastguard Worker/* 2*bf47c682SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project 3*bf47c682SAndroid Build Coastguard Worker * 4*bf47c682SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*bf47c682SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*bf47c682SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*bf47c682SAndroid Build Coastguard Worker * 8*bf47c682SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*bf47c682SAndroid Build Coastguard Worker * 10*bf47c682SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*bf47c682SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*bf47c682SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*bf47c682SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*bf47c682SAndroid Build Coastguard Worker * limitations under the License. 15*bf47c682SAndroid Build Coastguard Worker */ 16*bf47c682SAndroid Build Coastguard Worker 17*bf47c682SAndroid Build Coastguard Worker#import "MenuController.h" 18*bf47c682SAndroid Build Coastguard Worker 19*bf47c682SAndroid Build Coastguard Worker#import "UIAlertView+Extensions.h" 20*bf47c682SAndroid Build Coastguard Worker#import "WALTLogger.h" 21*bf47c682SAndroid Build Coastguard Worker#import "WALTAppDelegate.h" 22*bf47c682SAndroid Build Coastguard Worker#import "WALTClient.h" 23*bf47c682SAndroid Build Coastguard Worker 24*bf47c682SAndroid Build Coastguard Worker@implementation MenuController { 25*bf47c682SAndroid Build Coastguard Worker WALTClient *_client; 26*bf47c682SAndroid Build Coastguard Worker UIActivityIndicatorView *_spinner; 27*bf47c682SAndroid Build Coastguard Worker} 28*bf47c682SAndroid Build Coastguard Worker 29*bf47c682SAndroid Build Coastguard Worker- (void)viewDidLoad { 30*bf47c682SAndroid Build Coastguard Worker [super viewDidLoad]; 31*bf47c682SAndroid Build Coastguard Worker 32*bf47c682SAndroid Build Coastguard Worker _spinner = 33*bf47c682SAndroid Build Coastguard Worker [[UIActivityIndicatorView alloc] 34*bf47c682SAndroid Build Coastguard Worker initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 35*bf47c682SAndroid Build Coastguard Worker 36*bf47c682SAndroid Build Coastguard Worker _client = ((WALTAppDelegate *)[UIApplication sharedApplication].delegate).client; 37*bf47c682SAndroid Build Coastguard Worker} 38*bf47c682SAndroid Build Coastguard Worker 39*bf47c682SAndroid Build Coastguard Worker- (void)viewDidAppear:(BOOL)animated { 40*bf47c682SAndroid Build Coastguard Worker [super viewDidAppear:animated]; 41*bf47c682SAndroid Build Coastguard Worker 42*bf47c682SAndroid Build Coastguard Worker [_client addObserver:self 43*bf47c682SAndroid Build Coastguard Worker forKeyPath:@"connected" 44*bf47c682SAndroid Build Coastguard Worker options:NSKeyValueObservingOptionInitial 45*bf47c682SAndroid Build Coastguard Worker context:NULL]; 46*bf47c682SAndroid Build Coastguard Worker} 47*bf47c682SAndroid Build Coastguard Worker 48*bf47c682SAndroid Build Coastguard Worker- (void)dealloc { 49*bf47c682SAndroid Build Coastguard Worker [_client removeObserver:self forKeyPath:@"connected"]; 50*bf47c682SAndroid Build Coastguard Worker} 51*bf47c682SAndroid Build Coastguard Worker 52*bf47c682SAndroid Build Coastguard Worker- (void)observeValueForKeyPath:(NSString *)keyPath 53*bf47c682SAndroid Build Coastguard Worker ofObject:(id)object 54*bf47c682SAndroid Build Coastguard Worker change:(NSDictionary *)change 55*bf47c682SAndroid Build Coastguard Worker context:(void *)context { 56*bf47c682SAndroid Build Coastguard Worker if (_client.isConnected) { 57*bf47c682SAndroid Build Coastguard Worker [_spinner stopAnimating]; 58*bf47c682SAndroid Build Coastguard Worker self.syncCell.accessoryView = nil; // Display a checkmark. 59*bf47c682SAndroid Build Coastguard Worker [[WALTLogger sessionLogger] appendString:@"WALT\tCONNECTED\n"]; 60*bf47c682SAndroid Build Coastguard Worker [[WALTLogger sessionLogger] appendFormat:@"SYNC\t%lld\t%lld\n", 61*bf47c682SAndroid Build Coastguard Worker _client.minError, _client.maxError]; 62*bf47c682SAndroid Build Coastguard Worker } else { 63*bf47c682SAndroid Build Coastguard Worker self.syncCell.accessoryView = _spinner; 64*bf47c682SAndroid Build Coastguard Worker [_spinner startAnimating]; 65*bf47c682SAndroid Build Coastguard Worker [[WALTLogger sessionLogger] appendString:@"WALT\tDISCONNECTED\n"]; 66*bf47c682SAndroid Build Coastguard Worker 67*bf47c682SAndroid Build Coastguard Worker // Return to this view controller. 68*bf47c682SAndroid Build Coastguard Worker UINavigationController *navigationController = self.navigationController; 69*bf47c682SAndroid Build Coastguard Worker if (navigationController.visibleViewController != self) { 70*bf47c682SAndroid Build Coastguard Worker [navigationController popToRootViewControllerAnimated:YES]; 71*bf47c682SAndroid Build Coastguard Worker 72*bf47c682SAndroid Build Coastguard Worker UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"WALT Connection Error" 73*bf47c682SAndroid Build Coastguard Worker message:@"WALT disconnected." 74*bf47c682SAndroid Build Coastguard Worker delegate:nil 75*bf47c682SAndroid Build Coastguard Worker cancelButtonTitle:@"Dismiss" 76*bf47c682SAndroid Build Coastguard Worker otherButtonTitles:nil]; 77*bf47c682SAndroid Build Coastguard Worker [alert show]; 78*bf47c682SAndroid Build Coastguard Worker } 79*bf47c682SAndroid Build Coastguard Worker } 80*bf47c682SAndroid Build Coastguard Worker 81*bf47c682SAndroid Build Coastguard Worker [self.tableView reloadData]; // Update accessory types. 82*bf47c682SAndroid Build Coastguard Worker} 83*bf47c682SAndroid Build Coastguard Worker 84*bf47c682SAndroid Build Coastguard Worker- (void)shareLog:(id)sender { 85*bf47c682SAndroid Build Coastguard Worker NSFileManager *fileManager = [NSFileManager defaultManager]; 86*bf47c682SAndroid Build Coastguard Worker NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; 87*bf47c682SAndroid Build Coastguard Worker 88*bf47c682SAndroid Build Coastguard Worker if (urls.count > 0) { 89*bf47c682SAndroid Build Coastguard Worker NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 90*bf47c682SAndroid Build Coastguard Worker formatter.dateFormat = @"yyyy-MM-dd'T'HH-mm-ss"; 91*bf47c682SAndroid Build Coastguard Worker 92*bf47c682SAndroid Build Coastguard Worker // Save the log to a file (which also allows it to be retrieved in iTunes/Xcode). 93*bf47c682SAndroid Build Coastguard Worker NSString *logName = [NSString stringWithFormat:@"walt_%@.log", 94*bf47c682SAndroid Build Coastguard Worker [formatter stringFromDate:[NSDate date]]]; 95*bf47c682SAndroid Build Coastguard Worker NSURL *logURL = [urls.firstObject URLByAppendingPathComponent:logName]; 96*bf47c682SAndroid Build Coastguard Worker 97*bf47c682SAndroid Build Coastguard Worker WALTLogger *logger = [WALTLogger sessionLogger]; 98*bf47c682SAndroid Build Coastguard Worker NSError *error = nil; 99*bf47c682SAndroid Build Coastguard Worker if ([logger writeToURL:logURL error:&error]) { 100*bf47c682SAndroid Build Coastguard Worker // Open a share sheet for the URL. 101*bf47c682SAndroid Build Coastguard Worker UIActivityViewController *activityController = 102*bf47c682SAndroid Build Coastguard Worker [[UIActivityViewController alloc] initWithActivityItems:@[logURL] 103*bf47c682SAndroid Build Coastguard Worker applicationActivities:nil]; 104*bf47c682SAndroid Build Coastguard Worker [self presentViewController:activityController animated:YES completion:NULL]; 105*bf47c682SAndroid Build Coastguard Worker } else { 106*bf47c682SAndroid Build Coastguard Worker UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Log Write Error" 107*bf47c682SAndroid Build Coastguard Worker error:error]; 108*bf47c682SAndroid Build Coastguard Worker [alert show]; 109*bf47c682SAndroid Build Coastguard Worker } 110*bf47c682SAndroid Build Coastguard Worker } else { 111*bf47c682SAndroid Build Coastguard Worker UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Log Write Error" 112*bf47c682SAndroid Build Coastguard Worker message:@"Could not locate document directory." 113*bf47c682SAndroid Build Coastguard Worker delegate:nil 114*bf47c682SAndroid Build Coastguard Worker cancelButtonTitle:@"Dismiss" 115*bf47c682SAndroid Build Coastguard Worker otherButtonTitles:nil]; 116*bf47c682SAndroid Build Coastguard Worker [alert show]; 117*bf47c682SAndroid Build Coastguard Worker } 118*bf47c682SAndroid Build Coastguard Worker} 119*bf47c682SAndroid Build Coastguard Worker 120*bf47c682SAndroid Build Coastguard Worker#pragma mark - UITableView Delegate 121*bf47c682SAndroid Build Coastguard Worker 122*bf47c682SAndroid Build Coastguard Worker- (void)tableView:(UITableView *)tableView 123*bf47c682SAndroid Build Coastguard Worker willDisplayCell:(UITableViewCell *)cell 124*bf47c682SAndroid Build Coastguard WorkerforRowAtIndexPath:(NSIndexPath *)indexPath { 125*bf47c682SAndroid Build Coastguard Worker if (indexPath.section == 1) { 126*bf47c682SAndroid Build Coastguard Worker // Show/hide the disclosure indicator on the "Measure Latency" cells. 127*bf47c682SAndroid Build Coastguard Worker cell.accessoryType = (_client.isConnected ? 128*bf47c682SAndroid Build Coastguard Worker UITableViewCellAccessoryDisclosureIndicator : 129*bf47c682SAndroid Build Coastguard Worker UITableViewCellAccessoryNone); 130*bf47c682SAndroid Build Coastguard Worker } 131*bf47c682SAndroid Build Coastguard Worker} 132*bf47c682SAndroid Build Coastguard Worker 133*bf47c682SAndroid Build Coastguard Worker- (NSIndexPath *)tableView:(UITableView *)tableView 134*bf47c682SAndroid Build Coastguard Worker willSelectRowAtIndexPath:(NSIndexPath *)indexPath { 135*bf47c682SAndroid Build Coastguard Worker if (indexPath.section == 0 && indexPath.row == 0) { 136*bf47c682SAndroid Build Coastguard Worker // "Clock Sync" 137*bf47c682SAndroid Build Coastguard Worker NSError *error = nil; 138*bf47c682SAndroid Build Coastguard Worker if (![_client checkConnectionWithError:&error] || 139*bf47c682SAndroid Build Coastguard Worker ![_client syncClocksWithError:&error]) { 140*bf47c682SAndroid Build Coastguard Worker UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"WALT Connection Error" 141*bf47c682SAndroid Build Coastguard Worker error:error]; 142*bf47c682SAndroid Build Coastguard Worker [alert show]; 143*bf47c682SAndroid Build Coastguard Worker } 144*bf47c682SAndroid Build Coastguard Worker [[WALTLogger sessionLogger] appendFormat:@"SYNC\t%lld\t%lld\n", 145*bf47c682SAndroid Build Coastguard Worker _client.minError, _client.maxError]; 146*bf47c682SAndroid Build Coastguard Worker return nil; 147*bf47c682SAndroid Build Coastguard Worker } else if (indexPath.section == 1 && !_client.isConnected) { 148*bf47c682SAndroid Build Coastguard Worker // "Measure Latency" 149*bf47c682SAndroid Build Coastguard Worker return nil; 150*bf47c682SAndroid Build Coastguard Worker } 151*bf47c682SAndroid Build Coastguard Worker 152*bf47c682SAndroid Build Coastguard Worker return indexPath; 153*bf47c682SAndroid Build Coastguard Worker} 154*bf47c682SAndroid Build Coastguard Worker@end 155