OLD | NEW |
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/remoting_view_controller.h" | 9 #import "remoting/ios/app/remoting_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/AnimationTiming/
src/MaterialAnimationTiming.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" | 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" | 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/ShadowElevations
/src/MaterialShadowElevations.h" |
| 16 #import "ios/third_party/material_components_ios/src/components/ShadowLayer/src/
MaterialShadowLayer.h" |
15 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/Mat
erialSnackbar.h" | 17 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/Mat
erialSnackbar.h" |
16 #import "remoting/ios/app/app_delegate.h" | 18 #import "remoting/ios/app/app_delegate.h" |
17 #import "remoting/ios/app/client_connection_view_controller.h" | 19 #import "remoting/ios/app/client_connection_view_controller.h" |
18 #import "remoting/ios/app/host_collection_view_controller.h" | 20 #import "remoting/ios/app/host_collection_view_controller.h" |
| 21 #import "remoting/ios/app/host_setup_view_controller.h" |
19 #import "remoting/ios/app/host_view_controller.h" | 22 #import "remoting/ios/app/host_view_controller.h" |
20 #import "remoting/ios/app/remoting_menu_view_controller.h" | 23 #import "remoting/ios/app/remoting_menu_view_controller.h" |
21 #import "remoting/ios/app/remoting_theme.h" | 24 #import "remoting/ios/app/remoting_theme.h" |
22 #import "remoting/ios/domain/client_session_details.h" | 25 #import "remoting/ios/domain/client_session_details.h" |
23 #import "remoting/ios/facade/remoting_authentication.h" | 26 #import "remoting/ios/facade/remoting_authentication.h" |
24 #import "remoting/ios/facade/remoting_service.h" | 27 #import "remoting/ios/facade/remoting_service.h" |
25 | 28 |
26 #include "base/strings/sys_string_conversions.h" | 29 #include "base/strings/sys_string_conversions.h" |
27 #include "remoting/base/oauth_token_getter.h" | 30 #include "remoting/base/oauth_token_getter.h" |
28 #include "remoting/client/connect_to_host_info.h" | 31 #include "remoting/client/connect_to_host_info.h" |
29 | 32 |
30 static CGFloat kHostInset = 5.f; | 33 static CGFloat kHostInset = 5.f; |
31 | 34 |
32 @interface RemotingViewController ()<HostCollectionViewControllerDelegate, | 35 @interface RemotingViewController ()<HostCollectionViewControllerDelegate, |
33 UIViewControllerAnimatedTransitioning, | 36 UIViewControllerAnimatedTransitioning, |
34 UIViewControllerTransitioningDelegate> { | 37 UIViewControllerTransitioningDelegate> { |
35 bool _isAuthenticated; | 38 bool _isAuthenticated; |
36 MDCDialogTransitionController* _dialogTransitionController; | 39 MDCDialogTransitionController* _dialogTransitionController; |
37 MDCAppBar* _appBar; | 40 MDCAppBar* _appBar; |
38 HostCollectionViewController* _collectionViewController; | 41 HostCollectionViewController* _collectionViewController; |
| 42 HostSetupViewController* _setupViewController; |
39 RemotingService* _remotingService; | 43 RemotingService* _remotingService; |
40 } | 44 } |
41 @end | 45 @end |
42 | 46 |
43 // TODO(nicholss): Localize this file. | 47 // TODO(nicholss): Localize this file. |
44 // TODO(nicholss): This file is not finished with integration, the app flow is | 48 // TODO(nicholss): This file is not finished with integration, the app flow is |
45 // still pending development. | 49 // still pending development. |
46 | 50 |
47 @implementation RemotingViewController | 51 @implementation RemotingViewController |
48 | 52 |
49 - (instancetype)init { | 53 - (instancetype)init { |
50 _isAuthenticated = NO; | 54 _isAuthenticated = NO; |
51 UICollectionViewFlowLayout* layout = | 55 UICollectionViewFlowLayout* layout = |
52 [[MDCCollectionViewFlowLayout alloc] init]; | 56 [[MDCCollectionViewFlowLayout alloc] init]; |
53 layout.minimumInteritemSpacing = 0; | 57 layout.minimumInteritemSpacing = 0; |
54 CGFloat sectionInset = kHostInset * 2.f; | 58 CGFloat sectionInset = kHostInset * 2.f; |
55 [layout setSectionInset:UIEdgeInsetsMake(sectionInset, sectionInset, | 59 [layout setSectionInset:UIEdgeInsetsMake(sectionInset, sectionInset, |
56 sectionInset, sectionInset)]; | 60 sectionInset, sectionInset)]; |
57 HostCollectionViewController* collectionVC = [ | 61 self = [super init]; |
58 [HostCollectionViewController alloc] initWithCollectionViewLayout:layout]; | |
59 self = [super initWithContentViewController:collectionVC]; | |
60 if (self) { | 62 if (self) { |
61 _remotingService = RemotingService.instance; | 63 _remotingService = RemotingService.instance; |
62 | 64 |
63 _collectionViewController = collectionVC; | 65 _collectionViewController = [[HostCollectionViewController alloc] |
64 _collectionViewController.flexHeaderContainerViewController = self; | 66 initWithCollectionViewLayout:layout]; |
65 _collectionViewController.delegate = self; | 67 _collectionViewController.delegate = self; |
| 68 _collectionViewController.scrollViewDelegate = self.headerViewController; |
| 69 |
| 70 _setupViewController = [[HostSetupViewController alloc] init]; |
| 71 _setupViewController.scrollViewDelegate = self.headerViewController; |
66 | 72 |
67 _appBar = [[MDCAppBar alloc] init]; | 73 _appBar = [[MDCAppBar alloc] init]; |
68 [self addChildViewController:_appBar.headerViewController]; | 74 [self addChildViewController:_appBar.headerViewController]; |
69 | 75 |
70 self.navigationItem.title = @"Chrome Remote Desktop"; | 76 self.navigationItem.title = @"chrome remote desktop"; |
71 | 77 |
72 UIBarButtonItem* menuButton = | 78 UIBarButtonItem* menuButton = |
73 [[UIBarButtonItem alloc] initWithImage:RemotingTheme.menuIcon | 79 [[UIBarButtonItem alloc] initWithImage:RemotingTheme.menuIcon |
74 style:UIBarButtonItemStyleDone | 80 style:UIBarButtonItemStyleDone |
75 target:self | 81 target:self |
76 action:@selector(didSelectMenu)]; | 82 action:@selector(didSelectMenu)]; |
77 self.navigationItem.leftBarButtonItem = menuButton; | 83 self.navigationItem.leftBarButtonItem = menuButton; |
78 | 84 |
79 UIBarButtonItem* refreshButton = | 85 UIBarButtonItem* refreshButton = |
80 [[UIBarButtonItem alloc] initWithImage:RemotingTheme.refreshIcon | 86 [[UIBarButtonItem alloc] initWithImage:RemotingTheme.refreshIcon |
81 style:UIBarButtonItemStyleDone | 87 style:UIBarButtonItemStyleDone |
82 target:self | 88 target:self |
83 action:@selector(didSelectRefresh)]; | 89 action:@selector(didSelectRefresh)]; |
84 self.navigationItem.rightBarButtonItem = refreshButton; | 90 self.navigationItem.rightBarButtonItem = refreshButton; |
85 | 91 |
86 _appBar.headerViewController.headerView.backgroundColor = | 92 _appBar.headerViewController.headerView.backgroundColor = |
87 RemotingTheme.hostListBackgroundColor; | 93 RemotingTheme.hostListBackgroundColor; |
88 _appBar.navigationBar.backgroundColor = | 94 _appBar.navigationBar.backgroundColor = |
89 RemotingTheme.hostListBackgroundColor; | 95 RemotingTheme.hostListBackgroundColor; |
90 MDCNavigationBarTextColorAccessibilityMutator* mutator = | 96 MDCNavigationBarTextColorAccessibilityMutator* mutator = |
91 [[MDCNavigationBarTextColorAccessibilityMutator alloc] init]; | 97 [[MDCNavigationBarTextColorAccessibilityMutator alloc] init]; |
92 [mutator mutate:_appBar.navigationBar]; | 98 [mutator mutate:_appBar.navigationBar]; |
| 99 |
| 100 MDCFlexibleHeaderView* headerView = self.headerViewController.headerView; |
| 101 headerView.backgroundColor = [UIColor clearColor]; |
| 102 |
| 103 // Use a custom shadow under the flexible header. |
| 104 MDCShadowLayer* shadowLayer = [MDCShadowLayer layer]; |
| 105 [headerView setShadowLayer:shadowLayer |
| 106 intensityDidChangeBlock:^(CALayer* layer, CGFloat intensity) { |
| 107 CGFloat elevation = MDCShadowElevationAppBar * intensity; |
| 108 [(MDCShadowLayer*)layer setElevation:elevation]; |
| 109 }]; |
93 } | 110 } |
94 return self; | 111 return self; |
95 } | 112 } |
96 | 113 |
97 #pragma mark - UIViewController | 114 #pragma mark - UIViewController |
98 | 115 |
99 - (void)viewDidLoad { | 116 - (void)viewDidLoad { |
100 [super viewDidLoad]; | 117 [super viewDidLoad]; |
101 | 118 |
102 UIImage* image = [UIImage imageNamed:@"Background"]; | 119 UIImage* image = [UIImage imageNamed:@"Background"]; |
103 UIImageView* imageView = [[UIImageView alloc] initWithImage:image]; | 120 UIImageView* imageView = [[UIImageView alloc] initWithImage:image]; |
104 [self.view addSubview:imageView]; | 121 [self.view addSubview:imageView]; |
105 [self.view sendSubviewToBack:imageView]; | 122 [self.view sendSubviewToBack:imageView]; |
106 | 123 |
107 imageView.translatesAutoresizingMaskIntoConstraints = NO; | 124 imageView.translatesAutoresizingMaskIntoConstraints = NO; |
108 [NSLayoutConstraint activateConstraints:@[ | 125 [NSLayoutConstraint activateConstraints:@[ |
109 [[imageView widthAnchor] | 126 [[imageView widthAnchor] |
110 constraintGreaterThanOrEqualToAnchor:[self.view widthAnchor]], | 127 constraintGreaterThanOrEqualToAnchor:[self.view widthAnchor]], |
111 [[imageView heightAnchor] | 128 [[imageView heightAnchor] |
112 constraintGreaterThanOrEqualToAnchor:[self.view heightAnchor]], | 129 constraintGreaterThanOrEqualToAnchor:[self.view heightAnchor]], |
113 ]]; | 130 ]]; |
114 | 131 |
115 [_appBar addSubviewsToParent]; | 132 [_appBar addSubviewsToParent]; |
116 | 133 |
117 [[NSNotificationCenter defaultCenter] | 134 [[NSNotificationCenter defaultCenter] |
118 addObserver:self | 135 addObserver:self |
119 selector:@selector(hostsDidUpdateNotification:) | 136 selector:@selector(hostListStateDidChangeNotification:) |
120 name:kHostsDidUpdate | 137 name:kHostListStateDidChange |
121 object:nil]; | 138 object:nil]; |
122 [[NSNotificationCenter defaultCenter] | 139 [[NSNotificationCenter defaultCenter] |
123 addObserver:self | 140 addObserver:self |
124 selector:@selector(userDidUpdateNotification:) | 141 selector:@selector(userDidUpdateNotification:) |
125 name:kUserDidUpdate | 142 name:kUserDidUpdate |
126 object:nil]; | 143 object:nil]; |
127 } | 144 } |
128 | 145 |
129 - (void)viewWillAppear:(BOOL)animated { | 146 - (void)viewWillAppear:(BOOL)animated { |
130 [super viewWillAppear:animated]; | 147 [super viewWillAppear:animated]; |
(...skipping 13 matching lines...) Expand all Loading... |
144 [_remotingService requestHostListFetch]; | 161 [_remotingService requestHostListFetch]; |
145 } | 162 } |
146 } | 163 } |
147 | 164 |
148 - (UIStatusBarStyle)preferredStatusBarStyle { | 165 - (UIStatusBarStyle)preferredStatusBarStyle { |
149 return UIStatusBarStyleLightContent; | 166 return UIStatusBarStyleLightContent; |
150 } | 167 } |
151 | 168 |
152 #pragma mark - Remoting Service Notifications | 169 #pragma mark - Remoting Service Notifications |
153 | 170 |
154 - (void)hostsDidUpdateNotification:(NSNotification*)notification { | 171 - (void)hostListStateDidChangeNotification:(NSNotification*)notification { |
155 [_collectionViewController.collectionView reloadData]; | 172 [self refreshContent]; |
156 } | 173 } |
157 | 174 |
158 - (void)userDidUpdateNotification:(NSNotification*)notification { | 175 - (void)userDidUpdateNotification:(NSNotification*)notification { |
159 [self nowAuthenticated:_remotingService.authentication.user.isAuthenticated]; | 176 [self nowAuthenticated:_remotingService.authentication.user.isAuthenticated]; |
160 } | 177 } |
161 | 178 |
162 #pragma mark - RemotingAuthenticationDelegate | 179 #pragma mark - RemotingAuthenticationDelegate |
163 | 180 |
164 - (void)nowAuthenticated:(BOOL)authenticated { | 181 - (void)nowAuthenticated:(BOOL)authenticated { |
165 if (authenticated) { | 182 if (authenticated) { |
166 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; | 183 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; |
167 message.text = @"Logged In!"; | 184 message.text = @"Logged In!"; |
168 [MDCSnackbarManager showMessage:message]; | 185 [MDCSnackbarManager showMessage:message]; |
169 } else { | 186 } else { |
170 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; | 187 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; |
171 message.text = @"Not logged in."; | 188 message.text = @"Not logged in."; |
172 [MDCSnackbarManager showMessage:message]; | 189 [MDCSnackbarManager showMessage:message]; |
173 } | 190 } |
174 _isAuthenticated = authenticated; | 191 _isAuthenticated = authenticated; |
175 [_collectionViewController.collectionView reloadData]; | 192 [self refreshContent]; |
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 } | 193 } |
185 | 194 |
186 #pragma mark - HostCollectionViewControllerDelegate | 195 #pragma mark - HostCollectionViewControllerDelegate |
187 | 196 |
188 - (void)didSelectCell:(HostCollectionViewCell*)cell | 197 - (void)didSelectCell:(HostCollectionViewCell*)cell |
189 completion:(void (^)())completionBlock { | 198 completion:(void (^)())completionBlock { |
190 if (![cell.hostInfo isOnline]) { | 199 if (![cell.hostInfo isOnline]) { |
191 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; | 200 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; |
192 message.text = @"Host is offline."; | 201 message.text = @"Host is offline."; |
193 [MDCSnackbarManager showMessage:message]; | 202 [MDCSnackbarManager showMessage:message]; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 - (void)presentStatus { | 264 - (void)presentStatus { |
256 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; | 265 MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init]; |
257 if (_isAuthenticated) { | 266 if (_isAuthenticated) { |
258 message.text = [NSString | 267 message.text = [NSString |
259 stringWithFormat:@"Currently signed in as %@.", | 268 stringWithFormat:@"Currently signed in as %@.", |
260 _remotingService.authentication.user.userEmail]; | 269 _remotingService.authentication.user.userEmail]; |
261 [MDCSnackbarManager showMessage:message]; | 270 [MDCSnackbarManager showMessage:message]; |
262 } | 271 } |
263 } | 272 } |
264 | 273 |
| 274 - (void)refreshContent { |
| 275 if (_remotingService.hostListState == HostListStateNotFetched) { |
| 276 self.contentViewController = nil; |
| 277 return; |
| 278 } |
| 279 |
| 280 if (_remotingService.hostListState == HostListStateFetching) { |
| 281 NSLog(@"Fetching host list... TODO: Show fetching UI here."); |
| 282 return; |
| 283 } |
| 284 |
| 285 DCHECK(_remotingService.hostListState == HostListStateFetched); |
| 286 |
| 287 if (_remotingService.hosts.count > 0) { |
| 288 [_collectionViewController.collectionView reloadData]; |
| 289 self.headerViewController.headerView.trackingScrollView = |
| 290 _collectionViewController.collectionView; |
| 291 self.contentViewController = _collectionViewController; |
| 292 } else { |
| 293 self.contentViewController = _setupViewController; |
| 294 self.headerViewController.headerView.trackingScrollView = |
| 295 _setupViewController.collectionView; |
| 296 } |
| 297 self.contentViewController.view.frame = self.view.bounds; |
| 298 } |
| 299 |
265 @end | 300 @end |
OLD | NEW |