Chromium Code Reviews| Index: remoting/ios/app/client_connection_view_controller.mm |
| diff --git a/remoting/ios/app/client_connection_view_controller.mm b/remoting/ios/app/client_connection_view_controller.mm |
| index 888ee2c358ea998c6de2cf1d4f89f90508397ad5..e7ab872550c650742fb2b12d775724e106d3bd42 100644 |
| --- a/remoting/ios/app/client_connection_view_controller.mm |
| +++ b/remoting/ios/app/client_connection_view_controller.mm |
| @@ -12,9 +12,11 @@ |
| #import "ios/third_party/material_components_ios/src/components/ActivityIndicator/src/MDCActivityIndicator.h" |
| #import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" |
| #import "ios/third_party/material_components_ios/src/components/NavigationBar/src/MaterialNavigationBar.h" |
| +#import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h" |
| #import "remoting/ios/app/host_view_controller.h" |
| #import "remoting/ios/app/pin_entry_view.h" |
| #import "remoting/ios/app/remoting_theme.h" |
| +#import "remoting/ios/app/session_error_view.h" |
| #import "remoting/ios/domain/client_session_details.h" |
| #import "remoting/ios/domain/host_info.h" |
| #import "remoting/ios/facade/remoting_authentication.h" |
| @@ -31,6 +33,9 @@ static const CGFloat kActivityIndicatorRadius = 33.f; |
| static const CGFloat kPinEntryViewWidth = 240.f; |
| static const CGFloat kPinEntryViewHeight = 90.f; |
| +static const CGFloat kErrorViewWidth = 120.f; |
| +static const CGFloat kErrorViewHeight = 90.f; |
| + |
| static const CGFloat kCenterShift = -80.f; |
| static const CGFloat kPadding = 20.f; |
| static const CGFloat kMargin = 20.f; |
| @@ -39,14 +44,18 @@ static const CGFloat kBarHeight = 58.f; |
| static const CGFloat kKeyboardAnimationTime = 0.3; |
| -@interface ClientConnectionViewController ()<PinEntryDelegate> { |
| +@interface ClientConnectionViewController ()<PinEntryDelegate, |
| + SessionErrorViewDelegate> { |
| UIImageView* _iconView; |
| MDCActivityIndicator* _activityIndicator; |
| UILabel* _statusLabel; |
| MDCNavigationBar* _navBar; |
| PinEntryView* _pinEntryView; |
| + SessionErrorView* _errorView; |
| NSString* _remoteHostName; |
| RemotingClient* _client; |
| + SessionErrorCode _lastError; |
| + HostInfo* _hostInfo; |
| } |
| @end |
| @@ -57,17 +66,7 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| - (instancetype)initWithHostInfo:(HostInfo*)hostInfo { |
| self = [super init]; |
| if (self) { |
| - _client = [[RemotingClient alloc] init]; |
| - |
| - __weak RemotingClient* weakClient = _client; |
| - [RemotingService.instance.authentication |
| - callbackWithAccessToken:^(RemotingAuthenticationStatus status, |
| - NSString* userEmail, NSString* accessToken) { |
| - [weakClient connectToHost:hostInfo |
| - username:userEmail |
| - accessToken:accessToken]; |
| - }]; |
| - |
| + _hostInfo = hostInfo; |
| _remoteHostName = hostInfo.hostName; |
| // TODO(yuweih): This logic may be reused by other views. |
| @@ -102,6 +101,8 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| constraintEqualToAnchor:[self.view trailingAnchor]], |
| [[_navBar heightAnchor] constraintEqualToConstant:kBarHeight], |
| ]]; |
| + |
| + [self attemptConnectionToHost]; |
| } |
| return self; |
| } |
| @@ -122,6 +123,10 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| _iconView = [[UIImageView alloc] initWithFrame:CGRectZero]; |
| [self.view addSubview:_iconView]; |
| + _errorView = [[SessionErrorView alloc] initWithFrame:CGRectZero]; |
| + [self.view addSubview:_errorView]; |
| + _errorView.delegate = self; |
| + |
| _pinEntryView = [[PinEntryView alloc] init]; |
| [self.view addSubview:_pinEntryView]; |
| _pinEntryView.delegate = self; |
| @@ -148,6 +153,8 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| _statusLabel.textAlignment = NSTextAlignmentCenter; |
| _pinEntryView.hidden = YES; |
| + |
| + _errorView.hidden = YES; |
| } |
| - (void)viewWillLayoutSubviews { |
| @@ -160,15 +167,21 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| [_activityIndicator sizeToFit]; |
| _activityIndicator.center = _iconView.center; |
| - _statusLabel.frame = |
| - CGRectMake(kMargin, _activityIndicator.center.y + kIconRadius + kPadding, |
| - self.view.frame.size.width - kMargin * 2.f, |
| - _statusLabel.font.pointSize * _statusLabel.numberOfLines); |
| + _statusLabel.frame = CGRectMake( |
| + kMargin, _activityIndicator.center.y + kIconRadius + kPadding, |
| + self.view.frame.size.width - kMargin * 2.f, |
| + _statusLabel.font.pointSize * _statusLabel.numberOfLines * 1.1); |
|
Yuwei
2017/07/05 21:43:42
What is this 1.1 doing?
nicholss
2017/07/06 20:49:01
The bottom of the g was getting cut off, I guess
Yuwei
2017/07/06 21:52:39
I think point is a unit different than pixels. UIF
|
| _pinEntryView.frame = CGRectMake( |
| (self.view.frame.size.width - kPinEntryViewWidth) / 2.f, |
| _statusLabel.frame.origin.y + _statusLabel.frame.size.height + kPadding, |
| kPinEntryViewWidth, kPinEntryViewHeight); |
| + |
| + _errorView.frame = CGRectMake( |
| + (self.view.frame.size.width - kErrorViewWidth) / 2.f, |
| + _statusLabel.frame.origin.y + _statusLabel.frame.size.height + kPadding, |
| + kErrorViewWidth, kErrorViewHeight); |
| + [_errorView setNeedsLayout]; |
| } |
| - (void)viewWillAppear:(BOOL)animated { |
| @@ -260,11 +273,34 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| case ClientViewClosed: |
| [self dismissViewControllerAnimated:YES completion:nil]; |
|
Yuwei
2017/07/05 21:43:42
Since you are here could you change this to [self.
nicholss
2017/07/06 20:49:02
Done.
|
| break; |
| + case ClientViewError: |
| + [self showError]; |
| + break; |
| } |
| } |
| +#pragma mark - SessionErrorViewDelegate |
| + |
| +- (void)didTapReconnect { |
| + [self attemptConnectionToHost]; |
| +} |
| + |
| #pragma mark - Private |
| +- (void)attemptConnectionToHost { |
| + _client = [[RemotingClient alloc] init]; |
| + __weak RemotingClient* weakClient = _client; |
| + __weak HostInfo* weakHostInfo = _hostInfo; |
| + [RemotingService.instance.authentication |
| + callbackWithAccessToken:^(RemotingAuthenticationStatus status, |
| + NSString* userEmail, NSString* accessToken) { |
| + [weakClient connectToHost:weakHostInfo |
| + username:userEmail |
| + accessToken:accessToken]; |
| + }]; |
| + [self setState:ClientViewConnecting]; |
| +} |
| + |
| - (void)showConnectingState { |
| [_pinEntryView endEditing:YES]; |
| _statusLabel.text = |
| @@ -274,6 +310,7 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| _activityIndicator.indicatorMode = MDCActivityIndicatorModeIndeterminate; |
| _activityIndicator.hidden = NO; |
| _pinEntryView.hidden = YES; |
| + _errorView.hidden = YES; |
| [_activityIndicator startAnimating]; |
| } |
| @@ -282,6 +319,7 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| [_activityIndicator stopAnimating]; |
| _activityIndicator.hidden = YES; |
| _pinEntryView.hidden = NO; |
| + _errorView.hidden = YES; |
| // TODO(yuweih): This may be called before viewDidAppear and miss the keyboard |
| // callback. |
| @@ -299,6 +337,7 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| _activityIndicator.cycleColors = @[ [UIColor greenColor] ]; |
| [_activityIndicator startAnimating]; |
| _activityIndicator.progress = 1.0; |
| + _errorView.hidden = YES; |
| HostViewController* hostViewController = |
| [[HostViewController alloc] initWithClient:_client]; |
| @@ -312,6 +351,77 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| [self.navigationController setViewControllers:controllers animated:NO]; |
| } |
| +- (void)showError { |
| + _statusLabel.text = |
| + [NSString stringWithFormat:@"Error connecting to %@", _remoteHostName]; |
| + _activityIndicator.progress = 0.0; |
| + _pinEntryView.hidden = YES; |
| + _activityIndicator.hidden = NO; |
| + _activityIndicator.indicatorMode = MDCActivityIndicatorModeDeterminate; |
| + _activityIndicator.cycleColors = @[ [UIColor redColor] ]; |
| + [_activityIndicator startAnimating]; |
| + _activityIndicator.progress = 1.0; |
| + _errorView.hidden = NO; |
| + |
| + MDCSnackbarMessage* message = nil; |
| + switch (_lastError) { |
| + case SessionErrorOk: |
| + // Do nothing. |
| + break; |
| + case SessionErrorPeerIsOffline: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorPeerIsOffline."]; |
| + break; |
| + case SessionErrorSessionRejected: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorSessionRejected."]; |
| + break; |
| + case SessionErrorIncompatibleProtocol: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorIncompatibleProtocol."]; |
| + break; |
| + case SessionErrorAuthenticationFailed: |
| + message = [MDCSnackbarMessage messageWithText:@"Error: Invalid Pin."]; |
| + [_pinEntryView clearPinEntry]; |
| + break; |
| + case SessionErrorInvalidAccount: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorInvalidAccount."]; |
| + break; |
| + case SessionErrorChannelConnectionError: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorChannelConnectionError."]; |
| + break; |
| + case SessionErrorSignalingError: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorSignalingError."]; |
| + break; |
| + case SessionErrorSignalingTimeout: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorSignalingTimeout."]; |
| + break; |
| + case SessionErrorHostOverload: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorHostOverload."]; |
| + break; |
| + case SessionErrorMaxSessionLength: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorMaxSessionLength."]; |
| + break; |
| + case SessionErrorHostConfigurationError: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorHostConfigurationError."]; |
| + break; |
| + case SessionErrorUnknownError: |
| + message = [MDCSnackbarMessage |
| + messageWithText:@"Error: SessionErrorUnknownError."]; |
| + break; |
| + } |
| + if (message.text) { |
| + [MDCSnackbarManager showMessage:message]; |
| + } |
| +} |
| + |
| - (void)didProvidePin:(NSString*)pin createPairing:(BOOL)createPairing { |
| // TODO(nicholss): There is an open question if createPairing is supported on |
| // iOS. Need to fingure this out. |
| @@ -347,7 +457,8 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| state = ClientViewConnected; |
| break; |
| case SessionFailed: |
| - // TODO(nicholss): Implement an error screen. |
| + state = ClientViewError; |
| + break; |
| case SessionClosed: |
| state = ClientViewClosed; |
| break; |
| @@ -355,6 +466,7 @@ static const CGFloat kKeyboardAnimationTime = 0.3; |
| LOG(ERROR) << "Unknown State for Session, " << sessionDetails.state; |
| return; |
| } |
| + _lastError = sessionDetails.error; |
| [[NSOperationQueue mainQueue] addOperationWithBlock:^{ |
| [self setState:state]; |
| }]; |