Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_controller.h" | 5 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_controller.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #import "base/mac/scoped_nsobject.h" | 8 #import "base/mac/scoped_nsobject.h" |
| 9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
| 10 #import "ios/chrome/browser/tabs/tab.h" | 10 #import "ios/chrome/browser/tabs/tab.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 } | 28 } |
| 29 | 29 |
| 30 } // namespace | 30 } // namespace |
| 31 | 31 |
| 32 @interface TabSwitcherPanelController ()<UICollectionViewDataSource, | 32 @interface TabSwitcherPanelController ()<UICollectionViewDataSource, |
| 33 SessionCellDelegate> { | 33 SessionCellDelegate> { |
| 34 ios::ChromeBrowserState* _browserState; // Weak. | 34 ios::ChromeBrowserState* _browserState; // Weak. |
| 35 base::scoped_nsobject<TabSwitcherPanelView> _panelView; | 35 base::scoped_nsobject<TabSwitcherPanelView> _panelView; |
| 36 base::scoped_nsobject<TabSwitcherModel> _model; | 36 base::scoped_nsobject<TabSwitcherModel> _model; |
| 37 std::string _sessionTag; | 37 std::string _sessionTag; |
| 38 ios_internal::SessionType _sessionType; | 38 SessionType _sessionType; |
| 39 base::scoped_nsobject<TabSwitcherCache> _cache; | 39 base::scoped_nsobject<TabSwitcherCache> _cache; |
| 40 base::scoped_nsobject<TabSwitcherPanelOverlayView> _overlayView; | 40 base::scoped_nsobject<TabSwitcherPanelOverlayView> _overlayView; |
| 41 std::unique_ptr<const synced_sessions::DistantSession> _distantSession; | 41 std::unique_ptr<const synced_sessions::DistantSession> _distantSession; |
| 42 std::unique_ptr<const TabModelSnapshot> _localSession; | 42 std::unique_ptr<const TabModelSnapshot> _localSession; |
| 43 } | 43 } |
| 44 | 44 |
| 45 // Changes the visibility of the zero tab state overlay view. | 45 // Changes the visibility of the zero tab state overlay view. |
| 46 - (void)setZeroTabStateOverlayVisible:(BOOL)show; | 46 - (void)setZeroTabStateOverlayVisible:(BOOL)show; |
| 47 | 47 |
| 48 @end | 48 @end |
| 49 | 49 |
| 50 @implementation TabSwitcherPanelController | 50 @implementation TabSwitcherPanelController |
| 51 | 51 |
| 52 @synthesize delegate = _delegate; | 52 @synthesize delegate = _delegate; |
| 53 @synthesize sessionType = _sessionType; | 53 @synthesize sessionType = _sessionType; |
| 54 | 54 |
| 55 - (instancetype)initWithModel:(TabSwitcherModel*)model | 55 - (instancetype)initWithModel:(TabSwitcherModel*)model |
| 56 forDistantSessionWithTag:(std::string const&)sessionTag | 56 forDistantSessionWithTag:(std::string const&)sessionTag |
| 57 browserState:(ios::ChromeBrowserState*)browserState { | 57 browserState:(ios::ChromeBrowserState*)browserState { |
| 58 self = [super init]; | 58 self = [super init]; |
| 59 if (self) { | 59 if (self) { |
| 60 DCHECK(model); | 60 DCHECK(model); |
| 61 _sessionType = ios_internal::SessionType::DISTANT_SESSION; | 61 _sessionType = SessionType::DISTANT_SESSION; |
| 62 _model.reset([model retain]); | 62 _model.reset([model retain]); |
| 63 _distantSession = [model distantSessionForTag:sessionTag]; | 63 _distantSession = [model distantSessionForTag:sessionTag]; |
| 64 _sessionTag = sessionTag; | 64 _sessionTag = sessionTag; |
| 65 _browserState = browserState; | 65 _browserState = browserState; |
| 66 [self loadView]; | 66 [self loadView]; |
| 67 } | 67 } |
| 68 return self; | 68 return self; |
| 69 } | 69 } |
| 70 | 70 |
| 71 - (instancetype)initWithModel:(TabSwitcherModel*)model | 71 - (instancetype)initWithModel:(TabSwitcherModel*)model |
| 72 forLocalSessionOfType:(ios_internal::SessionType)sessionType | 72 forLocalSessionOfType:(SessionType)sessionType |
| 73 withCache:(TabSwitcherCache*)cache | 73 withCache:(TabSwitcherCache*)cache |
| 74 browserState:(ios::ChromeBrowserState*)browserState { | 74 browserState:(ios::ChromeBrowserState*)browserState { |
| 75 self = [super init]; | 75 self = [super init]; |
| 76 if (self) { | 76 if (self) { |
| 77 DCHECK(model); | 77 DCHECK(model); |
| 78 _sessionType = sessionType; | 78 _sessionType = sessionType; |
| 79 _model.reset([model retain]); | 79 _model.reset([model retain]); |
| 80 _localSession = [model tabModelSnapshotForLocalSession:sessionType]; | 80 _localSession = [model tabModelSnapshotForLocalSession:sessionType]; |
| 81 _cache.reset([cache retain]); | 81 _cache.reset([cache retain]); |
| 82 _browserState = browserState; | 82 _browserState = browserState; |
| 83 [self loadView]; | 83 [self loadView]; |
| 84 } | 84 } |
| 85 return self; | 85 return self; |
| 86 } | 86 } |
| 87 | 87 |
| 88 - (TabSwitcherPanelView*)view { | 88 - (TabSwitcherPanelView*)view { |
| 89 return _panelView; | 89 return _panelView; |
| 90 } | 90 } |
| 91 | 91 |
| 92 - (std::string)sessionTag { | 92 - (std::string)sessionTag { |
| 93 return _sessionTag; | 93 return _sessionTag; |
| 94 } | 94 } |
| 95 | 95 |
| 96 - (void)setDelegate:(id<TabSwitcherPanelControllerDelegate>)delegate { | 96 - (void)setDelegate:(id<TabSwitcherPanelControllerDelegate>)delegate { |
| 97 _delegate = delegate; | 97 _delegate = delegate; |
| 98 [[_panelView collectionView] performBatchUpdates:nil completion:nil]; | 98 [[_panelView collectionView] performBatchUpdates:nil completion:nil]; |
| 99 } | 99 } |
| 100 | 100 |
| 101 - (BOOL)shouldShowNewTabButton { | 101 - (BOOL)shouldShowNewTabButton { |
| 102 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) { | 102 if (_sessionType == SessionType::DISTANT_SESSION) { |
| 103 return NO; | 103 return NO; |
| 104 } else { | 104 } else { |
| 105 return ![self isOverlayVisible]; | 105 return ![self isOverlayVisible]; |
| 106 } | 106 } |
| 107 } | 107 } |
| 108 | 108 |
| 109 - (void)updateCollectionViewIfNeeded { | 109 - (void)updateCollectionViewIfNeeded { |
| 110 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) { | 110 if (_sessionType == SessionType::DISTANT_SESSION) { |
| 111 UICollectionView* collectionView = [_panelView collectionView]; | 111 UICollectionView* collectionView = [_panelView collectionView]; |
| 112 // TODO(crbug.com/633928) Compute SessionChanges outside of the | 112 // TODO(crbug.com/633928) Compute SessionChanges outside of the |
| 113 // updateBlock. | 113 // updateBlock. |
| 114 auto updateBlock = ^{ | 114 auto updateBlock = ^{ |
| 115 std::unique_ptr<const synced_sessions::DistantSession> newDistantSession = | 115 std::unique_ptr<const synced_sessions::DistantSession> newDistantSession = |
| 116 [_model distantSessionForTag:_sessionTag]; | 116 [_model distantSessionForTag:_sessionTag]; |
| 117 std::vector<size_t> oldTabsHashes; | 117 std::vector<size_t> oldTabsHashes; |
| 118 std::vector<size_t> newTabsHashes; | 118 std::vector<size_t> newTabsHashes; |
| 119 FillVectorWithHashesUsingDistantSession(*_distantSession.get(), | 119 FillVectorWithHashesUsingDistantSession(*_distantSession.get(), |
| 120 &oldTabsHashes); | 120 &oldTabsHashes); |
| 121 FillVectorWithHashesUsingDistantSession(*newDistantSession.get(), | 121 FillVectorWithHashesUsingDistantSession(*newDistantSession.get(), |
| 122 &newTabsHashes); | 122 &newTabsHashes); |
| 123 ios_internal::SessionChanges changes(oldTabsHashes, newTabsHashes); | 123 SessionChanges changes(oldTabsHashes, newTabsHashes); |
| 124 if (changes.hasChanges()) { | 124 if (changes.hasChanges()) { |
| 125 _distantSession = std::move(newDistantSession); | 125 _distantSession = std::move(newDistantSession); |
| 126 [self applyChanges:changes toCollectionView:collectionView]; | 126 [self applyChanges:changes toCollectionView:collectionView]; |
| 127 } | 127 } |
| 128 }; | 128 }; |
| 129 [collectionView performBatchUpdates:updateBlock completion:nil]; | 129 [collectionView performBatchUpdates:updateBlock completion:nil]; |
| 130 } else { | 130 } else { |
| 131 UICollectionView* collectionView = [_panelView collectionView]; | 131 UICollectionView* collectionView = [_panelView collectionView]; |
| 132 auto updateBlock = ^{ | 132 auto updateBlock = ^{ |
| 133 std::unique_ptr<const TabModelSnapshot> newLocalSession = | 133 std::unique_ptr<const TabModelSnapshot> newLocalSession = |
| 134 [_model tabModelSnapshotForLocalSession:_sessionType]; | 134 [_model tabModelSnapshotForLocalSession:_sessionType]; |
| 135 ios_internal::SessionChanges changes(_localSession->hashes(), | 135 SessionChanges changes(_localSession->hashes(), |
| 136 newLocalSession->hashes()); | 136 newLocalSession->hashes()); |
| 137 if (changes.hasChanges()) { | 137 if (changes.hasChanges()) { |
| 138 _localSession = std::move(newLocalSession); | 138 _localSession = std::move(newLocalSession); |
| 139 [self applyChanges:changes toCollectionView:collectionView]; | 139 [self applyChanges:changes toCollectionView:collectionView]; |
| 140 } | 140 } |
| 141 }; | 141 }; |
| 142 [collectionView performBatchUpdates:updateBlock completion:nil]; | 142 [collectionView performBatchUpdates:updateBlock completion:nil]; |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 | 145 |
| 146 - (void)applyChanges:(ios_internal::SessionChanges&)changes | 146 - (void)applyChanges:(SessionChanges&)changes |
| 147 toCollectionView:(UICollectionView*)collectionView { | 147 toCollectionView:(UICollectionView*)collectionView { |
| 148 NSMutableArray* deletedIndexes = [NSMutableArray array]; | 148 NSMutableArray* deletedIndexes = [NSMutableArray array]; |
| 149 NSMutableArray* insertedIndexes = [NSMutableArray array]; | 149 NSMutableArray* insertedIndexes = [NSMutableArray array]; |
| 150 NSMutableArray* updatedIndexes = [NSMutableArray array]; | 150 NSMutableArray* updatedIndexes = [NSMutableArray array]; |
| 151 for (size_t i : changes.deletions()) { | 151 for (size_t i : changes.deletions()) { |
| 152 NSInteger deletedTabIndex = static_cast<NSInteger>(i); | 152 NSInteger deletedTabIndex = static_cast<NSInteger>(i); |
| 153 [deletedIndexes | 153 [deletedIndexes |
| 154 addObject:[NSIndexPath indexPathForItem:deletedTabIndex inSection:0]]; | 154 addObject:[NSIndexPath indexPathForItem:deletedTabIndex inSection:0]]; |
| 155 } | 155 } |
| 156 for (size_t i : changes.insertions()) { | 156 for (size_t i : changes.insertions()) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 195 | 195 |
| 196 - (UICollectionView*)collectionView { | 196 - (UICollectionView*)collectionView { |
| 197 return [_panelView collectionView]; | 197 return [_panelView collectionView]; |
| 198 } | 198 } |
| 199 | 199 |
| 200 #pragma mark - UICollectionViewDataSource | 200 #pragma mark - UICollectionViewDataSource |
| 201 | 201 |
| 202 - (NSInteger)collectionView:(UICollectionView*)collectionView | 202 - (NSInteger)collectionView:(UICollectionView*)collectionView |
| 203 numberOfItemsInSection:(NSInteger)section { | 203 numberOfItemsInSection:(NSInteger)section { |
| 204 DCHECK_EQ(section, 0); | 204 DCHECK_EQ(section, 0); |
| 205 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) { | 205 if (_sessionType == SessionType::DISTANT_SESSION) { |
| 206 CHECK(_distantSession); | 206 CHECK(_distantSession); |
| 207 return _distantSession->tabs.size(); | 207 return _distantSession->tabs.size(); |
| 208 } else { | 208 } else { |
| 209 CHECK(_localSession); | 209 CHECK(_localSession); |
| 210 NSInteger numberOfTabs = _localSession->tabs().size(); | 210 NSInteger numberOfTabs = _localSession->tabs().size(); |
| 211 [self setZeroTabStateOverlayVisible:numberOfTabs == 0]; | 211 [self setZeroTabStateOverlayVisible:numberOfTabs == 0]; |
| 212 return numberOfTabs; | 212 return numberOfTabs; |
| 213 } | 213 } |
| 214 } | 214 } |
| 215 | 215 |
| 216 - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView | 216 - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView |
| 217 cellForItemAtIndexPath:(NSIndexPath*)indexPath { | 217 cellForItemAtIndexPath:(NSIndexPath*)indexPath { |
| 218 UICollectionViewCell* cell = nil; | 218 UICollectionViewCell* cell = nil; |
| 219 NSUInteger tabIndex = indexPath.item; | 219 NSUInteger tabIndex = indexPath.item; |
| 220 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) { | 220 if (_sessionType == SessionType::DISTANT_SESSION) { |
| 221 cell = [collectionView | 221 cell = [collectionView |
| 222 dequeueReusableCellWithReuseIdentifier:[TabSwitcherDistantSessionCell | 222 dequeueReusableCellWithReuseIdentifier:[TabSwitcherDistantSessionCell |
| 223 identifier] | 223 identifier] |
| 224 forIndexPath:indexPath]; | 224 forIndexPath:indexPath]; |
| 225 DCHECK([cell isKindOfClass:[TabSwitcherDistantSessionCell class]]); | 225 DCHECK([cell isKindOfClass:[TabSwitcherDistantSessionCell class]]); |
| 226 TabSwitcherDistantSessionCell* panelCell = | 226 TabSwitcherDistantSessionCell* panelCell = |
| 227 static_cast<TabSwitcherDistantSessionCell*>(cell); | 227 static_cast<TabSwitcherDistantSessionCell*>(cell); |
| 228 CHECK(_distantSession); | 228 CHECK(_distantSession); |
| 229 const std::size_t distantSessionTabCount = _distantSession->tabs.size(); | 229 const std::size_t distantSessionTabCount = _distantSession->tabs.size(); |
| 230 LOG_ASSERT(tabIndex < distantSessionTabCount) | 230 LOG_ASSERT(tabIndex < distantSessionTabCount) |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 255 #pragma mark - SessionCellDelegate | 255 #pragma mark - SessionCellDelegate |
| 256 | 256 |
| 257 - (TabSwitcherCache*)tabSwitcherCache { | 257 - (TabSwitcherCache*)tabSwitcherCache { |
| 258 return _cache; | 258 return _cache; |
| 259 } | 259 } |
| 260 | 260 |
| 261 - (void)cellPressed:(UICollectionViewCell*)cell { | 261 - (void)cellPressed:(UICollectionViewCell*)cell { |
| 262 const NSInteger tabIndex = | 262 const NSInteger tabIndex = |
| 263 [[_panelView collectionView] indexPathForCell:cell].item; | 263 [[_panelView collectionView] indexPathForCell:cell].item; |
| 264 | 264 |
| 265 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) { | 265 if (_sessionType == SessionType::DISTANT_SESSION) { |
|
sdefresne
2017/01/03 16:04:30
nit: why not "if (!SessionTypeIsLocalSession(_sess
rohitrao (ping after 24h)
2017/01/04 13:36:37
Acknowledged.
| |
| 266 synced_sessions::DistantTab* tab = _distantSession->tabs[tabIndex].get(); | 266 synced_sessions::DistantTab* tab = _distantSession->tabs[tabIndex].get(); |
| 267 if (tab) | 267 if (tab) |
| 268 [self.delegate tabSwitcherPanelController:self didSelectDistantTab:tab]; | 268 [self.delegate tabSwitcherPanelController:self didSelectDistantTab:tab]; |
| 269 } else { | 269 } else { |
| 270 Tab* tab = _localSession->tabs()[tabIndex]; | 270 Tab* tab = _localSession->tabs()[tabIndex]; |
| 271 if (tab) | 271 if (tab) |
| 272 [self.delegate tabSwitcherPanelController:self didSelectLocalTab:tab]; | 272 [self.delegate tabSwitcherPanelController:self didSelectLocalTab:tab]; |
| 273 } | 273 } |
| 274 } | 274 } |
| 275 | 275 |
| 276 - (void)deleteButtonPressedForCell:(UICollectionViewCell*)cell { | 276 - (void)deleteButtonPressedForCell:(UICollectionViewCell*)cell { |
| 277 DCHECK(_sessionType != ios_internal::SessionType::DISTANT_SESSION); | 277 DCHECK(_sessionType != SessionType::DISTANT_SESSION); |
|
sdefresne
2017/01/03 16:04:30
nit: why not "DCHECK(SessionTypeIsLocalSession(_se
rohitrao (ping after 24h)
2017/01/04 13:36:37
Acknowledged.
| |
| 278 const NSInteger tabIndex = | 278 const NSInteger tabIndex = |
| 279 [[_panelView collectionView] indexPathForCell:cell].item; | 279 [[_panelView collectionView] indexPathForCell:cell].item; |
| 280 Tab* tab = _localSession->tabs()[tabIndex]; | 280 Tab* tab = _localSession->tabs()[tabIndex]; |
| 281 if (tab) | 281 if (tab) |
| 282 [self.delegate tabSwitcherPanelController:self didCloseLocalTab:tab]; | 282 [self.delegate tabSwitcherPanelController:self didCloseLocalTab:tab]; |
| 283 } | 283 } |
| 284 | 284 |
| 285 #pragma mark - Private | 285 #pragma mark - Private |
| 286 | 286 |
| 287 - (BOOL)isOverlayVisible { | 287 - (BOOL)isOverlayVisible { |
| 288 return _overlayView && [_overlayView alpha] != 0.0; | 288 return _overlayView && [_overlayView alpha] != 0.0; |
| 289 } | 289 } |
| 290 | 290 |
| 291 - (void)setZeroTabStateOverlayVisible:(BOOL)show { | 291 - (void)setZeroTabStateOverlayVisible:(BOOL)show { |
| 292 if (show == [self isOverlayVisible]) | 292 if (show == [self isOverlayVisible]) |
| 293 return; | 293 return; |
| 294 | 294 |
| 295 DCHECK(ios_internal::IsLocalSession(_sessionType)); | 295 DCHECK(SessionTypeIsLocalSession(_sessionType)); |
| 296 | 296 |
| 297 if (!_overlayView) { | 297 if (!_overlayView) { |
| 298 _overlayView.reset([[TabSwitcherPanelOverlayView alloc] | 298 _overlayView.reset([[TabSwitcherPanelOverlayView alloc] |
| 299 initWithFrame:[_panelView bounds] | 299 initWithFrame:[_panelView bounds] |
| 300 browserState:_browserState]); | 300 browserState:_browserState]); |
| 301 [_overlayView | 301 [_overlayView |
| 302 setOverlayType: | 302 setOverlayType:(_sessionType == SessionType::OFF_THE_RECORD_SESSION) |
| 303 (_sessionType == ios_internal::SessionType::OFF_THE_RECORD_SESSION) | 303 ? TabSwitcherPanelOverlayType:: |
| 304 ? TabSwitcherPanelOverlayType:: | 304 OVERLAY_PANEL_USER_NO_INCOGNITO_TABS |
| 305 OVERLAY_PANEL_USER_NO_INCOGNITO_TABS | 305 : TabSwitcherPanelOverlayType:: |
| 306 : TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_NO_OPEN_TABS]; | 306 OVERLAY_PANEL_USER_NO_OPEN_TABS]; |
| 307 | 307 |
| 308 [_overlayView setAlpha:0]; | 308 [_overlayView setAlpha:0]; |
| 309 [_overlayView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | | 309 [_overlayView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | |
| 310 UIViewAutoresizingFlexibleWidth]; | 310 UIViewAutoresizingFlexibleWidth]; |
| 311 [_panelView addSubview:_overlayView]; | 311 [_panelView addSubview:_overlayView]; |
| 312 [_overlayView setNeedsLayout]; | 312 [_overlayView setNeedsLayout]; |
| 313 } | 313 } |
| 314 | 314 |
| 315 [UIView | 315 [UIView |
| 316 animateWithDuration:0.25 | 316 animateWithDuration:0.25 |
| 317 animations:^{ | 317 animations:^{ |
| 318 [_overlayView setAlpha:show ? 1.0 : 0.0]; | 318 [_overlayView setAlpha:show ? 1.0 : 0.0]; |
| 319 [self.delegate | 319 [self.delegate |
| 320 tabSwitcherPanelControllerDidUpdateOverlayViewVisibility: | 320 tabSwitcherPanelControllerDidUpdateOverlayViewVisibility: |
| 321 self]; | 321 self]; |
| 322 }]; | 322 }]; |
| 323 } | 323 } |
| 324 | 324 |
| 325 - (void)loadView { | 325 - (void)loadView { |
| 326 _panelView.reset( | 326 _panelView.reset( |
| 327 [[TabSwitcherPanelView alloc] initWithSessionType:_sessionType]); | 327 [[TabSwitcherPanelView alloc] initWithSessionType:_sessionType]); |
| 328 _panelView.get().collectionView.dataSource = self; | 328 _panelView.get().collectionView.dataSource = self; |
| 329 } | 329 } |
| 330 | 330 |
| 331 - (synced_sessions::DistantSession const*)distantSession { | 331 - (synced_sessions::DistantSession const*)distantSession { |
| 332 return _distantSession.get(); | 332 return _distantSession.get(); |
| 333 } | 333 } |
| 334 | 334 |
| 335 @end | 335 @end |
| OLD | NEW |