Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1028)

Side by Side Diff: remoting/ios/app/client_connection_view_controller.mm

Issue 2971903002: Adding error handling to the connection flow. (Closed)
Patch Set: Trying out activateConstraints. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/ios/app/client_connection_view_controller.h ('k') | remoting/ios/app/pin_entry_view.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if !defined(__has_feature) || !__has_feature(objc_arc) 5 #if !defined(__has_feature) || !__has_feature(objc_arc)
6 #error "This file requires ARC support." 6 #error "This file requires ARC support."
7 #endif 7 #endif
8 8
9 #import "remoting/ios/app/client_connection_view_controller.h" 9 #import "remoting/ios/app/client_connection_view_controller.h"
10 10
11 #import "base/mac/bind_objc_block.h" 11 #import "base/mac/bind_objc_block.h"
12 #import "ios/third_party/material_components_ios/src/components/ActivityIndicato r/src/MDCActivityIndicator.h" 12 #import "ios/third_party/material_components_ios/src/components/ActivityIndicato r/src/MDCActivityIndicator.h"
13 #import "ios/third_party/material_components_ios/src/components/Buttons/src/Mate rialButtons.h" 13 #import "ios/third_party/material_components_ios/src/components/Buttons/src/Mate rialButtons.h"
14 #import "ios/third_party/material_components_ios/src/components/NavigationBar/sr c/MaterialNavigationBar.h" 14 #import "ios/third_party/material_components_ios/src/components/NavigationBar/sr c/MaterialNavigationBar.h"
15 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/Mat erialSnackbar.h"
15 #import "remoting/ios/app/host_view_controller.h" 16 #import "remoting/ios/app/host_view_controller.h"
16 #import "remoting/ios/app/pin_entry_view.h" 17 #import "remoting/ios/app/pin_entry_view.h"
17 #import "remoting/ios/app/remoting_theme.h" 18 #import "remoting/ios/app/remoting_theme.h"
19 #import "remoting/ios/app/session_reconnect_view.h"
18 #import "remoting/ios/domain/client_session_details.h" 20 #import "remoting/ios/domain/client_session_details.h"
19 #import "remoting/ios/domain/host_info.h" 21 #import "remoting/ios/domain/host_info.h"
20 #import "remoting/ios/facade/remoting_authentication.h" 22 #import "remoting/ios/facade/remoting_authentication.h"
21 #import "remoting/ios/facade/remoting_service.h" 23 #import "remoting/ios/facade/remoting_service.h"
22 #import "remoting/ios/session/remoting_client.h" 24 #import "remoting/ios/session/remoting_client.h"
23 25
24 #include "base/strings/sys_string_conversions.h" 26 #include "base/strings/sys_string_conversions.h"
25 #include "remoting/protocol/client_authentication_config.h" 27 #include "remoting/protocol/client_authentication_config.h"
26 28
27 static const CGFloat kIconRadius = 30.f; 29 static const CGFloat kIconRadius = 30.f;
28 static const CGFloat kActivityIndicatorStrokeWidth = 3.f; 30 static const CGFloat kActivityIndicatorStrokeWidth = 3.f;
29 static const CGFloat kActivityIndicatorRadius = 33.f; 31 static const CGFloat kActivityIndicatorRadius = 33.f;
30 32
31 static const CGFloat kPinEntryViewWidth = 240.f; 33 static const CGFloat kPinEntryViewWidth = 240.f;
32 static const CGFloat kPinEntryViewHeight = 90.f; 34 static const CGFloat kPinEntryViewHeight = 90.f;
33 35
34 static const CGFloat kCenterShift = -80.f; 36 static const CGFloat kReconnectViewWidth = 120.f;
37 static const CGFloat kReconnectViewHeight = 90.f;
38
39 static const CGFloat kTopPadding = 240.f;
35 static const CGFloat kPadding = 20.f; 40 static const CGFloat kPadding = 20.f;
36 static const CGFloat kMargin = 20.f; 41 static const CGFloat kMargin = 20.f;
37 42
38 static const CGFloat kBarHeight = 58.f; 43 static const CGFloat kBarHeight = 58.f;
39 44
40 static const CGFloat kKeyboardAnimationTime = 0.3; 45 static const CGFloat kKeyboardAnimationTime = 0.3;
41 46
42 @interface ClientConnectionViewController ()<PinEntryDelegate> { 47 @interface ClientConnectionViewController ()<PinEntryDelegate,
48 SessionReconnectViewDelegate> {
43 UIImageView* _iconView; 49 UIImageView* _iconView;
44 MDCActivityIndicator* _activityIndicator; 50 MDCActivityIndicator* _activityIndicator;
51 NSLayoutConstraint* _activityIndicatorTopConstraintFull;
52 NSLayoutConstraint* _activityIndicatorTopConstraintKeyboard;
45 UILabel* _statusLabel; 53 UILabel* _statusLabel;
46 MDCNavigationBar* _navBar; 54 MDCNavigationBar* _navBar;
47 PinEntryView* _pinEntryView; 55 PinEntryView* _pinEntryView;
56 SessionReconnectView* _reconnectView;
48 NSString* _remoteHostName; 57 NSString* _remoteHostName;
49 RemotingClient* _client; 58 RemotingClient* _client;
59 SessionErrorCode _lastError;
60 HostInfo* _hostInfo;
50 } 61 }
51 @end 62 @end
52 63
53 @implementation ClientConnectionViewController 64 @implementation ClientConnectionViewController
54 65
55 @synthesize state = _state; 66 @synthesize state = _state;
56 67
57 - (instancetype)initWithHostInfo:(HostInfo*)hostInfo { 68 - (instancetype)initWithHostInfo:(HostInfo*)hostInfo {
58 self = [super init]; 69 self = [super init];
59 if (self) { 70 if (self) {
60 _client = [[RemotingClient alloc] init]; 71 _hostInfo = hostInfo;
61
62 __weak RemotingClient* weakClient = _client;
63 [RemotingService.instance.authentication
64 callbackWithAccessToken:^(RemotingAuthenticationStatus status,
65 NSString* userEmail, NSString* accessToken) {
66 [weakClient connectToHost:hostInfo
67 username:userEmail
68 accessToken:accessToken];
69 }];
70
71 _remoteHostName = hostInfo.hostName; 72 _remoteHostName = hostInfo.hostName;
72 73
73 // TODO(yuweih): This logic may be reused by other views. 74 // TODO(yuweih): This logic may be reused by other views.
74 UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeSystem]; 75 UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeSystem];
75 [cancelButton setTitle:@"CANCEL" forState:UIControlStateNormal]; 76 [cancelButton setTitle:@"CANCEL" forState:UIControlStateNormal];
76 [cancelButton 77 [cancelButton
77 setImage:[RemotingTheme 78 setImage:[RemotingTheme
78 .backIcon imageFlippedForRightToLeftLayoutDirection] 79 .backIcon imageFlippedForRightToLeftLayoutDirection]
79 forState:UIControlStateNormal]; 80 forState:UIControlStateNormal];
80 [cancelButton addTarget:self 81 [cancelButton addTarget:self
(...skipping 14 matching lines...) Expand all
95 96
96 // Attach navBar to the top of the view. 97 // Attach navBar to the top of the view.
97 [NSLayoutConstraint activateConstraints:@[ 98 [NSLayoutConstraint activateConstraints:@[
98 [[_navBar topAnchor] constraintEqualToAnchor:[self.view topAnchor]], 99 [[_navBar topAnchor] constraintEqualToAnchor:[self.view topAnchor]],
99 [[_navBar leadingAnchor] 100 [[_navBar leadingAnchor]
100 constraintEqualToAnchor:[self.view leadingAnchor]], 101 constraintEqualToAnchor:[self.view leadingAnchor]],
101 [[_navBar trailingAnchor] 102 [[_navBar trailingAnchor]
102 constraintEqualToAnchor:[self.view trailingAnchor]], 103 constraintEqualToAnchor:[self.view trailingAnchor]],
103 [[_navBar heightAnchor] constraintEqualToConstant:kBarHeight], 104 [[_navBar heightAnchor] constraintEqualToConstant:kBarHeight],
104 ]]; 105 ]];
106
107 [self attemptConnectionToHost];
105 } 108 }
106 return self; 109 return self;
107 } 110 }
108 111
109 #pragma mark - UIViewController 112 #pragma mark - UIViewController
110 113
111 - (void)loadView { 114 - (void)viewDidLoad {
112 [super loadView]; 115 [super viewDidLoad];
113
114 self.view.backgroundColor = RemotingTheme.connectionViewBackgroundColor; 116 self.view.backgroundColor = RemotingTheme.connectionViewBackgroundColor;
115 117
116 _activityIndicator = [[MDCActivityIndicator alloc] initWithFrame:CGRectZero]; 118 _activityIndicator = [[MDCActivityIndicator alloc] initWithFrame:CGRectZero];
119 _activityIndicator.radius = kActivityIndicatorRadius;
120 _activityIndicator.trackEnabled = YES;
121 _activityIndicator.strokeWidth = kActivityIndicatorStrokeWidth;
122 _activityIndicator.cycleColors = @[ UIColor.whiteColor ];
123 _activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;
117 [self.view addSubview:_activityIndicator]; 124 [self.view addSubview:_activityIndicator];
118 125
119 _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 126 _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero];
127 _statusLabel.numberOfLines = 1;
128 _statusLabel.lineBreakMode = NSLineBreakByTruncatingTail;
129 _statusLabel.textColor = [UIColor whiteColor];
130 _statusLabel.textAlignment = NSTextAlignmentCenter;
131 _statusLabel.translatesAutoresizingMaskIntoConstraints = NO;
120 [self.view addSubview:_statusLabel]; 132 [self.view addSubview:_statusLabel];
121 133
122 _iconView = [[UIImageView alloc] initWithFrame:CGRectZero]; 134 _iconView = [[UIImageView alloc] initWithFrame:CGRectZero];
123 [self.view addSubview:_iconView];
124
125 _pinEntryView = [[PinEntryView alloc] init];
126 [self.view addSubview:_pinEntryView];
127 _pinEntryView.delegate = self;
128 }
129
130 - (void)viewDidLoad {
131 [super viewDidLoad];
132
133 _iconView.contentMode = UIViewContentModeCenter; 135 _iconView.contentMode = UIViewContentModeCenter;
134 _iconView.alpha = 0.87f; 136 _iconView.alpha = 0.87f;
135 _iconView.backgroundColor = RemotingTheme.onlineHostColor; 137 _iconView.backgroundColor = RemotingTheme.onlineHostColor;
136 _iconView.layer.cornerRadius = kIconRadius; 138 _iconView.layer.cornerRadius = kIconRadius;
137 _iconView.layer.masksToBounds = YES; 139 _iconView.layer.masksToBounds = YES;
138 _iconView.image = RemotingTheme.desktopIcon; 140 _iconView.image = RemotingTheme.desktopIcon;
141 _iconView.translatesAutoresizingMaskIntoConstraints = NO;
142 [self.view addSubview:_iconView];
139 143
140 _activityIndicator.radius = kActivityIndicatorRadius; 144 _reconnectView = [[SessionReconnectView alloc] initWithFrame:CGRectZero];
141 _activityIndicator.trackEnabled = YES; 145 _reconnectView.hidden = YES;
142 _activityIndicator.strokeWidth = kActivityIndicatorStrokeWidth; 146 _reconnectView.translatesAutoresizingMaskIntoConstraints = NO;
143 _activityIndicator.cycleColors = @[ UIColor.whiteColor ]; 147 [self.view addSubview:_reconnectView];
148 _reconnectView.delegate = self;
144 149
145 _statusLabel.numberOfLines = 1; 150 _pinEntryView = [[PinEntryView alloc] init];
146 _statusLabel.lineBreakMode = NSLineBreakByTruncatingTail; 151 _pinEntryView.hidden = YES;
147 _statusLabel.textColor = [UIColor whiteColor]; 152 _pinEntryView.translatesAutoresizingMaskIntoConstraints = NO;
148 _statusLabel.textAlignment = NSTextAlignmentCenter; 153 [self.view addSubview:_pinEntryView];
154 _pinEntryView.delegate = self;
149 155
150 _pinEntryView.hidden = YES; 156 [self
157 initializeLayoutConstraintsWithViews:NSDictionaryOfVariableBindings(
158 _activityIndicator, _statusLabel,
159 _iconView, _reconnectView,
160 _pinEntryView)];
151 } 161 }
152 162
153 - (void)viewWillLayoutSubviews { 163 - (void)initializeLayoutConstraintsWithViews:(NSDictionary*)views {
154 [super viewWillLayoutSubviews]; 164 // Metrics to use in visual format strings.
165 NSDictionary* layoutMetrics = @{
166 @"padding" : @(kPadding),
167 @"margin" : @(kMargin),
168 @"topPadding" : @(kTopPadding),
169 @"iconDiameter" : @(kIconRadius * 2),
170 @"pinEntryViewWidth" : @(kPinEntryViewWidth),
171 @"pinEntryViewHeight" : @(kPinEntryViewHeight),
172 @"reconnectViewWidth" : @(kReconnectViewWidth),
173 @"reconnectViewHeight" : @(kReconnectViewHeight),
174 };
175 [_activityIndicator sizeToFit];
176 NSString* f;
155 177
156 _iconView.frame = CGRectMake(0, 0, kIconRadius * 2, kIconRadius * 2.f); 178 // Horizontal constraints:
157 _iconView.center =
158 CGPointMake(self.view.center.x, self.view.center.y + kCenterShift);
159 179
160 [_activityIndicator sizeToFit]; 180 [self.view addConstraints:
161 _activityIndicator.center = _iconView.center; 181 [NSLayoutConstraint
182 constraintsWithVisualFormat:@"H:[_iconView(iconDiameter)]"
183 options:0
184 metrics:layoutMetrics
185 views:views]];
162 186
163 _statusLabel.frame = 187 [self.view addConstraints:[NSLayoutConstraint
164 CGRectMake(kMargin, _activityIndicator.center.y + kIconRadius + kPadding, 188 constraintsWithVisualFormat:
165 self.view.frame.size.width - kMargin * 2.f, 189 @"H:|-margin-[_statusLabel]-margin-|"
166 _statusLabel.font.pointSize * _statusLabel.numberOfLines); 190 options:0
191 metrics:layoutMetrics
192 views:views]];
167 193
168 _pinEntryView.frame = CGRectMake( 194 [self.view addConstraints:[NSLayoutConstraint
169 (self.view.frame.size.width - kPinEntryViewWidth) / 2.f, 195 constraintsWithVisualFormat:
170 _statusLabel.frame.origin.y + _statusLabel.frame.size.height + kPadding, 196 @"H:[_pinEntryView(pinEntryViewWidth)]"
171 kPinEntryViewWidth, kPinEntryViewHeight); 197 options:0
198 metrics:layoutMetrics
199 views:views]];
200
201 [self.view addConstraints:[NSLayoutConstraint
202 constraintsWithVisualFormat:
203 @"H:[_reconnectView(reconnectViewWidth)]"
204 options:0
205 metrics:layoutMetrics
206 views:views]];
207
208 // Anchors:
209
210 _activityIndicatorTopConstraintFull =
211 [_activityIndicator.topAnchor constraintEqualToAnchor:self.view.topAnchor
212 constant:kTopPadding];
213 _activityIndicatorTopConstraintFull.active = YES;
214
215 [_iconView.centerYAnchor
216 constraintEqualToAnchor:_activityIndicator.centerYAnchor]
217 .active = YES;
218
219 // Vertical constraints:
220
221 [self.view addConstraints:
222 [NSLayoutConstraint
223 constraintsWithVisualFormat:@"V:[_iconView(iconDiameter)]"
224 options:0
225 metrics:layoutMetrics
226 views:views]];
227
228 [self.view addConstraints:
229 [NSLayoutConstraint
230 constraintsWithVisualFormat:
231 @"V:[_activityIndicator]-(padding)-[_statusLabel]"
232 options:NSLayoutFormatAlignAllCenterX
233 metrics:layoutMetrics
234 views:views]];
235
236 [self.view addConstraints:
237 [NSLayoutConstraint
238 constraintsWithVisualFormat:
239 @"V:[_iconView]-(padding)-[_statusLabel]"
240 options:NSLayoutFormatAlignAllCenterX
241 metrics:layoutMetrics
242 views:views]];
243
244 f = @"V:[_statusLabel]-(padding)-[_pinEntryView(pinEntryViewHeight)]";
245 [self.view addConstraints:
246 [NSLayoutConstraint
247 constraintsWithVisualFormat:f
248 options:NSLayoutFormatAlignAllCenterX
249 metrics:layoutMetrics
250 views:views]];
251
252 f = @"V:[_statusLabel]-padding-[_reconnectView(reconnectViewHeight)]";
253 [self.view addConstraints:
254 [NSLayoutConstraint
255 constraintsWithVisualFormat:f
256 options:NSLayoutFormatAlignAllCenterX
257 metrics:layoutMetrics
258 views:views]];
259
260 [self.view setNeedsUpdateConstraints];
172 } 261 }
173 262
174 - (void)viewWillAppear:(BOOL)animated { 263 - (void)viewWillAppear:(BOOL)animated {
175 [super viewWillAppear:animated]; 264 [super viewWillAppear:animated];
176 [self.navigationController setNavigationBarHidden:YES animated:animated]; 265 [self.navigationController setNavigationBarHidden:YES animated:animated];
177 266
178 [[NSNotificationCenter defaultCenter] 267 [[NSNotificationCenter defaultCenter]
179 addObserver:self 268 addObserver:self
180 selector:@selector(hostSessionStatusChanged:) 269 selector:@selector(hostSessionStatusChanged:)
181 name:kHostSessionStatusChanged 270 name:kHostSessionStatusChanged
(...skipping 28 matching lines...) Expand all
210 } 299 }
211 300
212 #pragma mark - Keyboard 301 #pragma mark - Keyboard
213 302
214 - (void)keyboardWillShow:(NSNotification*)notification { 303 - (void)keyboardWillShow:(NSNotification*)notification {
215 CGSize keyboardSize = 304 CGSize keyboardSize =
216 [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] 305 [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey]
217 CGRectValue] 306 CGRectValue]
218 .size; 307 .size;
219 308
220 [UIView 309 CGFloat newHeight = self.view.frame.size.height - keyboardSize.height;
221 animateWithDuration:kKeyboardAnimationTime 310 CGFloat overlap = newHeight - (_pinEntryView.frame.origin.y +
222 animations:^{ 311 _pinEntryView.frame.size.height + kPadding);
223 CGRect f = self.view.frame; 312 if (overlap > 0) {
224 CGFloat newHeight = 313 overlap = 0;
225 self.view.frame.size.height - keyboardSize.height; 314 }
226 CGFloat overlap = 315 _activityIndicatorTopConstraintKeyboard.active = NO;
227 newHeight - (_pinEntryView.frame.origin.y + 316 _activityIndicatorTopConstraintKeyboard = [_activityIndicator.topAnchor
228 _pinEntryView.frame.size.height + kPadding); 317 constraintEqualToAnchor:self.view.topAnchor
229 if (overlap < 0) { 318 constant:kTopPadding + overlap];
230 f.origin.y = overlap; 319 _activityIndicatorTopConstraintFull.active = NO;
231 // TODO(yuweih): This may push the navigation bar off screen. 320 _activityIndicatorTopConstraintKeyboard.active = YES;
232 self.view.frame = f; 321 [UIView animateWithDuration:kKeyboardAnimationTime
233 } 322 animations:^{
234 }]; 323 [self.view layoutIfNeeded];
324 }];
235 } 325 }
236 326
237 - (void)keyboardWillHide:(NSNotification*)notification { 327 - (void)keyboardWillHide:(NSNotification*)notification {
328 _activityIndicatorTopConstraintKeyboard.active = NO;
329 _activityIndicatorTopConstraintFull.active = YES;
238 [UIView animateWithDuration:kKeyboardAnimationTime 330 [UIView animateWithDuration:kKeyboardAnimationTime
239 animations:^{ 331 animations:^{
240 CGRect f = self.view.frame; 332 [self.view layoutIfNeeded];
241 f.origin.y = 0.f;
242 self.view.frame = f;
243 }]; 333 }];
244 } 334 }
245 335
246 #pragma mark - Properties 336 #pragma mark - Properties
247 337
248 - (void)setState:(ClientConnectionViewState)state { 338 - (void)setState:(ClientConnectionViewState)state {
249 _state = state; 339 _state = state;
250 switch (_state) { 340 switch (_state) {
251 case ClientViewConnecting: 341 case ClientViewConnecting:
252 [self showConnectingState]; 342 [self showConnectingState];
253 break; 343 break;
254 case ClientViewPinPrompt: 344 case ClientViewPinPrompt:
255 [self showPinPromptState]; 345 [self showPinPromptState];
256 break; 346 break;
257 case ClientViewConnected: 347 case ClientViewConnected:
258 [self showConnectedState]; 348 [self showConnectedState];
259 break; 349 break;
260 case ClientViewClosed: 350 case ClientViewClosed:
261 [self dismissViewControllerAnimated:YES completion:nil]; 351 [self.navigationController popToRootViewControllerAnimated:YES];
352 break;
353 case ClientViewError:
354 [self showError];
262 break; 355 break;
263 } 356 }
264 } 357 }
265 358
359 #pragma mark - SessionReconnectViewDelegate
360
361 - (void)didTapReconnect {
362 [self attemptConnectionToHost];
363 }
364
266 #pragma mark - Private 365 #pragma mark - Private
267 366
367 - (void)attemptConnectionToHost {
368 _client = [[RemotingClient alloc] init];
369 __weak RemotingClient* weakClient = _client;
370 __weak HostInfo* weakHostInfo = _hostInfo;
371 [RemotingService.instance.authentication
372 callbackWithAccessToken:^(RemotingAuthenticationStatus status,
373 NSString* userEmail, NSString* accessToken) {
374 [weakClient connectToHost:weakHostInfo
375 username:userEmail
376 accessToken:accessToken];
377 }];
378 [self setState:ClientViewConnecting];
379 }
380
268 - (void)showConnectingState { 381 - (void)showConnectingState {
269 [_pinEntryView endEditing:YES]; 382 [_pinEntryView endEditing:YES];
270 _statusLabel.text = 383 _statusLabel.text =
271 [NSString stringWithFormat:@"Connecting to %@", _remoteHostName]; 384 [NSString stringWithFormat:@"Connecting to %@", _remoteHostName];
272 [_activityIndicator stopAnimating]; 385 [_activityIndicator stopAnimating];
273 _activityIndicator.cycleColors = @[ [UIColor whiteColor] ]; 386 _activityIndicator.cycleColors = @[ [UIColor whiteColor] ];
274 _activityIndicator.indicatorMode = MDCActivityIndicatorModeIndeterminate; 387 _activityIndicator.indicatorMode = MDCActivityIndicatorModeIndeterminate;
275 _activityIndicator.hidden = NO; 388 _activityIndicator.hidden = NO;
276 _pinEntryView.hidden = YES; 389 _pinEntryView.hidden = YES;
390 _reconnectView.hidden = YES;
277 [_activityIndicator startAnimating]; 391 [_activityIndicator startAnimating];
278 } 392 }
279 393
280 - (void)showPinPromptState { 394 - (void)showPinPromptState {
281 _statusLabel.text = [NSString stringWithFormat:@"%@", _remoteHostName]; 395 _statusLabel.text = [NSString stringWithFormat:@"%@", _remoteHostName];
282 [_activityIndicator stopAnimating]; 396 [_activityIndicator stopAnimating];
283 _activityIndicator.hidden = YES; 397 _activityIndicator.hidden = YES;
284 _pinEntryView.hidden = NO; 398 _pinEntryView.hidden = NO;
399 _reconnectView.hidden = YES;
285 400
286 // TODO(yuweih): This may be called before viewDidAppear and miss the keyboard 401 // TODO(yuweih): This may be called before viewDidAppear and miss the keyboard
287 // callback. 402 // callback.
288 [_pinEntryView becomeFirstResponder]; 403 [_pinEntryView becomeFirstResponder];
289 } 404 }
290 405
291 - (void)showConnectedState { 406 - (void)showConnectedState {
292 [_pinEntryView endEditing:YES]; 407 [_pinEntryView endEditing:YES];
293 _statusLabel.text = 408 _statusLabel.text =
294 [NSString stringWithFormat:@"Connected to %@", _remoteHostName]; 409 [NSString stringWithFormat:@"Connected to %@", _remoteHostName];
295 _activityIndicator.progress = 0.0; 410 _activityIndicator.progress = 0.0;
296 _pinEntryView.hidden = YES; 411 _pinEntryView.hidden = YES;
297 _activityIndicator.hidden = NO; 412 _activityIndicator.hidden = NO;
298 _activityIndicator.indicatorMode = MDCActivityIndicatorModeDeterminate; 413 _activityIndicator.indicatorMode = MDCActivityIndicatorModeDeterminate;
299 _activityIndicator.cycleColors = @[ [UIColor greenColor] ]; 414 _activityIndicator.cycleColors = @[ [UIColor greenColor] ];
300 [_activityIndicator startAnimating]; 415 [_activityIndicator startAnimating];
301 _activityIndicator.progress = 1.0; 416 _activityIndicator.progress = 1.0;
417 _reconnectView.hidden = YES;
302 418
303 HostViewController* hostViewController = 419 HostViewController* hostViewController =
304 [[HostViewController alloc] initWithClient:_client]; 420 [[HostViewController alloc] initWithClient:_client];
305 _client = nil; 421 _client = nil;
306 422
307 // Replaces current (topmost) view controller with |hostViewController|. 423 // Replaces current (topmost) view controller with |hostViewController|.
308 NSMutableArray* controllers = 424 NSMutableArray* controllers =
309 [self.navigationController.viewControllers mutableCopy]; 425 [self.navigationController.viewControllers mutableCopy];
310 [controllers removeLastObject]; 426 [controllers removeLastObject];
311 [controllers addObject:hostViewController]; 427 [controllers addObject:hostViewController];
312 [self.navigationController setViewControllers:controllers animated:NO]; 428 [self.navigationController setViewControllers:controllers animated:NO];
313 } 429 }
314 430
431 - (void)showError {
432 _statusLabel.text =
433 [NSString stringWithFormat:@"Error connecting to %@", _remoteHostName];
434 _activityIndicator.progress = 0.0;
435 _pinEntryView.hidden = YES;
436 _activityIndicator.hidden = NO;
437 _activityIndicator.indicatorMode = MDCActivityIndicatorModeDeterminate;
438 _activityIndicator.cycleColors = @[ [UIColor redColor] ];
439 [_activityIndicator startAnimating];
440 _activityIndicator.progress = 1.0;
441 _reconnectView.hidden = NO;
442
443 MDCSnackbarMessage* message = nil;
444 switch (_lastError) {
445 case SessionErrorOk:
446 // Do nothing.
447 break;
448 case SessionErrorPeerIsOffline:
449 message = [MDCSnackbarMessage
450 messageWithText:@"Error: SessionErrorPeerIsOffline."];
451 break;
452 case SessionErrorSessionRejected:
453 message = [MDCSnackbarMessage
454 messageWithText:@"Error: SessionErrorSessionRejected."];
455 break;
456 case SessionErrorIncompatibleProtocol:
457 message = [MDCSnackbarMessage
458 messageWithText:@"Error: SessionErrorIncompatibleProtocol."];
459 break;
460 case SessionErrorAuthenticationFailed:
461 message = [MDCSnackbarMessage messageWithText:@"Error: Invalid Pin."];
462 [_pinEntryView clearPinEntry];
463 break;
464 case SessionErrorInvalidAccount:
465 message = [MDCSnackbarMessage
466 messageWithText:@"Error: SessionErrorInvalidAccount."];
467 break;
468 case SessionErrorChannelConnectionError:
469 message = [MDCSnackbarMessage
470 messageWithText:@"Error: SessionErrorChannelConnectionError."];
471 break;
472 case SessionErrorSignalingError:
473 message = [MDCSnackbarMessage
474 messageWithText:@"Error: SessionErrorSignalingError."];
475 break;
476 case SessionErrorSignalingTimeout:
477 message = [MDCSnackbarMessage
478 messageWithText:@"Error: SessionErrorSignalingTimeout."];
479 break;
480 case SessionErrorHostOverload:
481 message = [MDCSnackbarMessage
482 messageWithText:@"Error: SessionErrorHostOverload."];
483 break;
484 case SessionErrorMaxSessionLength:
485 message = [MDCSnackbarMessage
486 messageWithText:@"Error: SessionErrorMaxSessionLength."];
487 break;
488 case SessionErrorHostConfigurationError:
489 message = [MDCSnackbarMessage
490 messageWithText:@"Error: SessionErrorHostConfigurationError."];
491 break;
492 case SessionErrorUnknownError:
493 message = [MDCSnackbarMessage
494 messageWithText:@"Error: SessionErrorUnknownError."];
495 break;
496 }
497 if (message.text) {
498 [MDCSnackbarManager showMessage:message];
499 }
500 }
501
315 - (void)didProvidePin:(NSString*)pin createPairing:(BOOL)createPairing { 502 - (void)didProvidePin:(NSString*)pin createPairing:(BOOL)createPairing {
316 // TODO(nicholss): There is an open question if createPairing is supported on 503 // TODO(nicholss): There is an open question if createPairing is supported on
317 // iOS. Need to fingure this out. 504 // iOS. Need to fingure this out.
318 [[NSNotificationCenter defaultCenter] 505 [[NSNotificationCenter defaultCenter]
319 postNotificationName:kHostSessionPinProvided 506 postNotificationName:kHostSessionPinProvided
320 object:self 507 object:self
321 userInfo:[NSDictionary dictionaryWithObject:pin 508 userInfo:[NSDictionary dictionaryWithObject:pin
322 forKey:kHostSessionPin]]; 509 forKey:kHostSessionPin]];
323 } 510 }
324 511
(...skipping 15 matching lines...) Expand all
340 case SessionConnecting: 527 case SessionConnecting:
341 state = ClientViewConnecting; 528 state = ClientViewConnecting;
342 break; 529 break;
343 case SessionPinPrompt: 530 case SessionPinPrompt:
344 state = ClientViewPinPrompt; 531 state = ClientViewPinPrompt;
345 break; 532 break;
346 case SessionConnected: 533 case SessionConnected:
347 state = ClientViewConnected; 534 state = ClientViewConnected;
348 break; 535 break;
349 case SessionFailed: 536 case SessionFailed:
350 // TODO(nicholss): Implement an error screen. 537 state = ClientViewError;
538 break;
351 case SessionClosed: 539 case SessionClosed:
352 state = ClientViewClosed; 540 state = ClientViewClosed;
353 break; 541 break;
354 default: 542 default:
355 LOG(ERROR) << "Unknown State for Session, " << sessionDetails.state; 543 LOG(ERROR) << "Unknown State for Session, " << sessionDetails.state;
356 return; 544 return;
357 } 545 }
546 _lastError = sessionDetails.error;
358 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 547 [[NSOperationQueue mainQueue] addOperationWithBlock:^{
359 [self setState:state]; 548 [self setState:state];
360 }]; 549 }];
361 } 550 }
362 551
363 @end 552 @end
OLDNEW
« no previous file with comments | « remoting/ios/app/client_connection_view_controller.h ('k') | remoting/ios/app/pin_entry_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698