| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 6 #error "This file requires ARC support." | |
| 7 #endif | |
| 8 | |
| 9 #import "remoting/client/ios/app/remoting_view_controller.h" | |
| 10 | |
| 11 #import "base/mac/bind_objc_block.h" | |
| 12 #import "ios/third_party/material_components_ios/src/components/AnimationTiming/
src/MaterialAnimationTiming.h" | |
| 13 #import "ios/third_party/material_components_ios/src/components/AppBar/src/Mater
ialAppBar.h" | |
| 14 #import "ios/third_party/material_components_ios/src/components/Dialogs/src/Mate
rialDialogs.h" | |
| 15 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/Mat
erialSnackbar.h" | |
| 16 #import "remoting/client/ios/app/client_connection_view_controller.h" | |
| 17 #import "remoting/client/ios/app/host_collection_view_controller.h" | |
| 18 #import "remoting/client/ios/app/host_view_controller.h" | |
| 19 #import "remoting/client/ios/app/remoting_settings_view_controller.h" | |
| 20 #import "remoting/client/ios/domain/client_session_details.h" | |
| 21 #import "remoting/client/ios/facade/remoting_authentication.h" | |
| 22 #import "remoting/client/ios/facade/remoting_service.h" | |
| 23 #import "remoting/client/ios/session/remoting_client.h" | |
| 24 | |
| 25 #include "base/strings/sys_string_conversions.h" | |
| 26 #include "remoting/base/oauth_token_getter.h" | |
| 27 #include "remoting/client/connect_to_host_info.h" | |
| 28 | |
| 29 static CGFloat kHostInset = 5.f; | |
| 30 | |
| 31 @interface RemotingViewController ()<HostCollectionViewControllerDelegate, | |
| 32 ClientConnectionViewControllerDelegate, | |
| 33 UIViewControllerAnimatedTransitioning, | |
| 34 UIViewControllerTransitioningDelegate> { | |
| 35 bool _isAuthenticated; | |
| 36 MDCDialogTransitionController* _dialogTransitionController; | |
| 37 MDCAppBar* _appBar; | |
| 38 HostCollectionViewController* _collectionViewController; | |
| 39 RemotingService* _remotingService; | |
| 40 RemotingClient* _client; | |
| 41 } | |
| 42 @end | |
| 43 | |
| 44 // TODO(nicholss): Localize this file. | |
| 45 // TODO(nicholss): This file is not finished with integration, the app flow is | |
| 46 // still pending development. | |
| 47 | |
| 48 @implementation RemotingViewController | |
| 49 | |
| 50 - (instancetype)init { | |
| 51 _isAuthenticated = NO; | |
| 52 UICollectionViewFlowLayout* layout = | |
| 53 [[UICollectionViewFlowLayout alloc] init]; | |
| 54 layout.minimumInteritemSpacing = 0; | |
| 55 CGFloat sectionInset = kHostInset * 2.f; | |
| 56 [layout setSectionInset:UIEdgeInsetsMake(sectionInset, sectionInset, | |
| 57 sectionInset, sectionInset)]; | |
| 58 HostCollectionViewController* collectionVC = [ | |
| 59 [HostCollectionViewController alloc] initWithCollectionViewLayout:layout]; | |
| 60 self = [super initWithContentViewController:collectionVC]; | |
| 61 if (self) { | |
| 62 _remotingService = [RemotingService SharedInstance]; | |
| 63 | |
| 64 _collectionViewController = collectionVC; | |
| 65 _collectionViewController.flexHeaderContainerViewController = self; | |
| 66 _collectionViewController.delegate = self; | |
| 67 | |
| 68 _appBar = [[MDCAppBar alloc] init]; | |
| 69 [self addChildViewController:_appBar.headerViewController]; | |
| 70 | |
| 71 _appBar.headerViewController.headerView.backgroundColor = | |
| 72 [UIColor clearColor]; | |
| 73 _appBar.navigationBar.tintColor = [UIColor whiteColor]; | |
| 74 | |
| 75 UIBarButtonItem* menuButton = | |
| 76 [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"Settings"] | |
| 77 style:UIBarButtonItemStyleDone | |
| 78 target:self | |
| 79 action:@selector(didSelectSettings)]; | |
| 80 self.navigationItem.leftBarButtonItem = menuButton; | |
| 81 | |
| 82 UIBarButtonItem* refreshButton = | |
| 83 [[UIBarButtonItem alloc] initWithTitle:@"Refresh" | |
| 84 style:UIBarButtonItemStyleDone | |
| 85 target:self | |
| 86 action:@selector(didSelectRefresh)]; | |
| 87 self.navigationItem.rightBarButtonItem = refreshButton; | |
| 88 | |
| 89 [[NSNotificationCenter defaultCenter] | |
| 90 addObserver:self | |
| 91 selector:@selector(hostSessionStatusChanged:) | |
| 92 name:kHostSessionStatusChanged | |
| 93 object:nil]; | |
| 94 } | |
| 95 return self; | |
| 96 } | |
| 97 | |
| 98 #pragma mark - UIViewController | |
| 99 | |
| 100 - (void)viewDidLoad { | |
| 101 [super viewDidLoad]; | |
| 102 [_appBar addSubviewsToParent]; | |
| 103 | |
| 104 [[NSNotificationCenter defaultCenter] | |
| 105 addObserver:self | |
| 106 selector:@selector(hostsDidUpdateNotification:) | |
| 107 name:kHostsDidUpdate | |
| 108 object:nil]; | |
| 109 [[NSNotificationCenter defaultCenter] | |
| 110 addObserver:self | |
| 111 selector:@selector(userDidUpdateNotification:) | |
| 112 name:kUserDidUpdate | |
| 113 object:nil]; | |
| 114 } | |
| 115 | |
| 116 - (void)viewWillAppear:(BOOL)animated { | |
| 117 [super viewWillAppear:animated]; | |
| 118 | |
| 119 [self nowAuthenticated:_remotingService.authentication.user.isAuthenticated]; | |
| 120 [self presentStatus]; | |
| 121 } | |
| 122 | |
| 123 - (void)viewDidAppear:(BOOL)animated { | |
| 124 [super viewDidAppear:animated]; | |
| 125 if (!_isAuthenticated) { | |
| 126 // TODO(nicholss): This is used as a demo of the app functionality for the | |
| 127 // moment but the real app will force the login flow if unauthenticated. | |
| 128 [self didSelectSettings]; | |
| 129 // [self didSelectRefresh]; | |
| 130 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; | |
| 131 message.text = @"Please login."; | |
| 132 [MDCSnackbarManager showMessage:message]; | |
| 133 } else { | |
| 134 [_remotingService requestHostListFetch]; | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 - (void)viewDidLayoutSubviews { | |
| 139 [super viewDidLayoutSubviews]; | |
| 140 | |
| 141 // Adjust the collection view's position and size so that it doesn't get | |
| 142 // overlayed by the navigation bar. | |
| 143 CGFloat collectionOffsetY = | |
| 144 _appBar.headerViewController.headerView.frame.size.height; | |
| 145 CGFloat collectionHeight = self.view.bounds.size.height - collectionOffsetY; | |
| 146 CGRect oldFrame = _collectionViewController.collectionView.frame; | |
| 147 _collectionViewController.collectionView.frame = | |
| 148 CGRectMake(oldFrame.origin.x, collectionOffsetY, oldFrame.size.width, | |
| 149 collectionHeight); | |
| 150 } | |
| 151 | |
| 152 #pragma mark - Remoting Service Notifications | |
| 153 | |
| 154 - (void)hostsDidUpdateNotification:(NSNotification*)notification { | |
| 155 [_collectionViewController.collectionView reloadData]; | |
| 156 } | |
| 157 | |
| 158 - (void)userDidUpdateNotification:(NSNotification*)notification { | |
| 159 [self nowAuthenticated:_remotingService.authentication.user.isAuthenticated]; | |
| 160 } | |
| 161 | |
| 162 #pragma mark - RemotingAuthenticationDelegate | |
| 163 | |
| 164 - (void)nowAuthenticated:(BOOL)authenticated { | |
| 165 if (authenticated) { | |
| 166 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; | |
| 167 message.text = @"Logged In!"; | |
| 168 [MDCSnackbarManager showMessage:message]; | |
| 169 } else { | |
| 170 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; | |
| 171 message.text = @"Not logged in."; | |
| 172 [MDCSnackbarManager showMessage:message]; | |
| 173 } | |
| 174 _isAuthenticated = authenticated; | |
| 175 [_collectionViewController.collectionView reloadData]; | |
| 176 } | |
| 177 | |
| 178 #pragma mark - RemotingHostListDelegate | |
| 179 | |
| 180 // TODO(nicholss): these need to be a stats change like "none, loading, | |
| 181 // updated"... | |
| 182 - (void)hostListUpdated { | |
| 183 [_collectionViewController.collectionView reloadData]; | |
| 184 } | |
| 185 | |
| 186 #pragma mark - ClientConnectionViewControllerDelegate | |
| 187 | |
| 188 - (void)clientConnected { | |
| 189 HostViewController* hostViewController = | |
| 190 [[HostViewController alloc] initWithClient:_client]; | |
| 191 [self presentViewController:hostViewController animated:YES completion:nil]; | |
| 192 } | |
| 193 | |
| 194 - (NSString*)getConnectingHostName { | |
| 195 if (_client) { | |
| 196 return _client.hostInfo.hostName; | |
| 197 } | |
| 198 return nil; | |
| 199 } | |
| 200 | |
| 201 #pragma mark - HostCollectionViewControllerDelegate | |
| 202 | |
| 203 - (void)didSelectCell:(HostCollectionViewCell*)cell | |
| 204 completion:(void (^)())completionBlock { | |
| 205 _client = [[RemotingClient alloc] init]; | |
| 206 | |
| 207 [_remotingService.authentication | |
| 208 callbackWithAccessToken:base::BindBlockArc(^( | |
| 209 remoting::OAuthTokenGetter::Status status, | |
| 210 const std::string& user_email, | |
| 211 const std::string& access_token) { | |
| 212 // TODO(nicholss): Check status. | |
| 213 HostInfo* hostInfo = cell.hostInfo; | |
| 214 [_client connectToHost:hostInfo | |
| 215 username:base::SysUTF8ToNSString(user_email) | |
| 216 accessToken:base::SysUTF8ToNSString(access_token)]; | |
| 217 })]; | |
| 218 | |
| 219 ClientConnectionViewController* clientConnectionViewController = | |
| 220 [[ClientConnectionViewController alloc] init]; | |
| 221 clientConnectionViewController.delegate = self; | |
| 222 [self presentViewController:clientConnectionViewController | |
| 223 animated:YES | |
| 224 completion:nil]; | |
| 225 completionBlock(); | |
| 226 } | |
| 227 | |
| 228 - (NSInteger)getHostCount { | |
| 229 return _remotingService.hosts.count; | |
| 230 } | |
| 231 | |
| 232 - (HostInfo*)getHostAtIndexPath:(NSIndexPath*)path { | |
| 233 return _remotingService.hosts[path.row]; | |
| 234 } | |
| 235 | |
| 236 #pragma mark - UIViewControllerTransitioningDelegate | |
| 237 | |
| 238 - (nullable id<UIViewControllerAnimatedTransitioning>) | |
| 239 animationControllerForPresentedController:(UIViewController*)presented | |
| 240 presentingController:(UIViewController*)presenting | |
| 241 sourceController:(UIViewController*)source { | |
| 242 // TODO(nicholss): Not implemented yet. | |
| 243 return nil; | |
| 244 } | |
| 245 | |
| 246 - (nullable id<UIViewControllerAnimatedTransitioning>) | |
| 247 animationControllerForDismissedController:(UIViewController*)dismissed { | |
| 248 return self; | |
| 249 } | |
| 250 | |
| 251 #pragma mark - UIViewControllerAnimatedTransitioning | |
| 252 | |
| 253 - (void)animateTransition: | |
| 254 (id<UIViewControllerContextTransitioning>)transitionContext { | |
| 255 } | |
| 256 | |
| 257 - (NSTimeInterval)transitionDuration: | |
| 258 (id<UIViewControllerContextTransitioning>)transitionContext { | |
| 259 return 0.2; | |
| 260 } | |
| 261 | |
| 262 #pragma mark - Private | |
| 263 | |
| 264 - (void)hostSessionStatusChanged:(NSNotification*)notification { | |
| 265 NSLog(@"hostSessionStatusChanged: %@", [notification userInfo]); | |
| 266 } | |
| 267 | |
| 268 - (void)closeViewController { | |
| 269 [self dismissViewControllerAnimated:true completion:nil]; | |
| 270 } | |
| 271 | |
| 272 - (void)didSelectRefresh { | |
| 273 // TODO(nicholss): Might want to rate limit this. Maybe remoting service | |
| 274 // controls that. | |
| 275 [_remotingService requestHostListFetch]; | |
| 276 } | |
| 277 | |
| 278 - (void)didSelectSettings { | |
| 279 RemotingSettingsViewController* settingsViewController = | |
| 280 [[RemotingSettingsViewController alloc] init]; | |
| 281 [self presentViewController:settingsViewController | |
| 282 animated:YES | |
| 283 completion:nil]; | |
| 284 } | |
| 285 | |
| 286 - (void)presentStatus { | |
| 287 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; | |
| 288 if (_isAuthenticated) { | |
| 289 message.text = [NSString | |
| 290 stringWithFormat:@"Currently signed in as %@.", | |
| 291 _remotingService.authentication.user.userEmail]; | |
| 292 [MDCSnackbarManager showMessage:message]; | |
| 293 } | |
| 294 } | |
| 295 | |
| 296 @end | |
| OLD | NEW |