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 TabSwitcherSessionType _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 = TabSwitcherSessionType::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:(TabSwitcherSessionType)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 == TabSwitcherSessionType::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 == TabSwitcherSessionType::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 == TabSwitcherSessionType::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 == TabSwitcherSessionType::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 == TabSwitcherSessionType::DISTANT_SESSION) { |
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 != TabSwitcherSessionType::DISTANT_SESSION); |
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(TabSwitcherSessionTypeIsLocalSession(_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: |
303 (_sessionType == ios_internal::SessionType::OFF_THE_RECORD_SESSION) | 303 (_sessionType == TabSwitcherSessionType::OFF_THE_RECORD_SESSION) |
304 ? TabSwitcherPanelOverlayType:: | 304 ? TabSwitcherPanelOverlayType:: |
305 OVERLAY_PANEL_USER_NO_INCOGNITO_TABS | 305 OVERLAY_PANEL_USER_NO_INCOGNITO_TABS |
306 : TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_NO_OPEN_TABS]; | 306 : TabSwitcherPanelOverlayType::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 } |
(...skipping 12 matching lines...) Expand all Loading... |
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 |