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

Side by Side Diff: ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_controller.mm

Issue 2588733002: Upstream Chrome on iOS source code [9/11]. (Closed)
Patch Set: Created 4 years 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_controller.h"
6
7 #include "base/logging.h"
8 #import "base/mac/scoped_nsobject.h"
9 #include "base/strings/sys_string_conversions.h"
10 #import "ios/chrome/browser/tabs/tab.h"
11 #include "ios/chrome/browser/ui/ntp/recent_tabs/synced_sessions.h"
12 #import "ios/chrome/browser/ui/tab_switcher/session_changes.h"
13 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_cache.h"
14 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h"
15 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.h"
16 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_view.h"
17
18 namespace {
19
20 void FillVectorWithHashesUsingDistantSession(
21 synced_sessions::DistantSession const& session,
22 std::vector<size_t>* hashes) {
23 DCHECK(hashes);
24 DCHECK(hashes->empty());
25 for (size_t i = 0; i < session.tabs.size(); ++i) {
26 hashes->push_back(session.tabs[i]->hashOfUserVisibleProperties());
27 }
28 }
29
30 } // namespace
31
32 @interface TabSwitcherPanelController ()<UICollectionViewDataSource,
33 SessionCellDelegate> {
34 ios::ChromeBrowserState* _browserState; // Weak.
35 base::scoped_nsobject<TabSwitcherPanelView> _panelView;
36 base::scoped_nsobject<TabSwitcherModel> _model;
37 std::string _sessionTag;
38 ios_internal::SessionType _sessionType;
39 base::scoped_nsobject<TabSwitcherCache> _cache;
40 base::scoped_nsobject<TabSwitcherPanelOverlayView> _overlayView;
41 std::unique_ptr<const synced_sessions::DistantSession> _distantSession;
42 std::unique_ptr<const TabModelSnapshot> _localSession;
43 }
44
45 // Changes the visibility of the zero tab state overlay view.
46 - (void)setZeroTabStateOverlayVisible:(BOOL)show;
47
48 @end
49
50 @implementation TabSwitcherPanelController
51
52 @synthesize delegate = _delegate;
53 @synthesize sessionType = _sessionType;
54
55 - (instancetype)initWithModel:(TabSwitcherModel*)model
56 forDistantSessionWithTag:(std::string const&)sessionTag
57 browserState:(ios::ChromeBrowserState*)browserState {
58 self = [super init];
59 if (self) {
60 DCHECK(model);
61 _sessionType = ios_internal::SessionType::DISTANT_SESSION;
62 _model.reset([model retain]);
63 _distantSession = [model distantSessionForTag:sessionTag];
64 _sessionTag = sessionTag;
65 _browserState = browserState;
66 [self loadView];
67 }
68 return self;
69 }
70
71 - (instancetype)initWithModel:(TabSwitcherModel*)model
72 forLocalSessionOfType:(ios_internal::SessionType)sessionType
73 withCache:(TabSwitcherCache*)cache
74 browserState:(ios::ChromeBrowserState*)browserState {
75 self = [super init];
76 if (self) {
77 DCHECK(model);
78 _sessionType = sessionType;
79 _model.reset([model retain]);
80 _localSession = [model tabModelSnapshotForLocalSession:sessionType];
81 _cache.reset([cache retain]);
82 _browserState = browserState;
83 [self loadView];
84 }
85 return self;
86 }
87
88 - (TabSwitcherPanelView*)view {
89 return _panelView;
90 }
91
92 - (std::string)sessionTag {
93 return _sessionTag;
94 }
95
96 - (void)setDelegate:(id<TabSwitcherPanelControllerDelegate>)delegate {
97 _delegate = delegate;
98 [[_panelView collectionView] performBatchUpdates:nil completion:nil];
99 }
100
101 - (BOOL)shouldShowNewTabButton {
102 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
103 return NO;
104 } else {
105 return ![self isOverlayVisible];
106 }
107 }
108
109 - (void)updateCollectionViewIfNeeded {
110 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
111 UICollectionView* collectionView = [_panelView collectionView];
112 // TODO(crbug.com/633928) Compute SessionChanges outside of the
113 // updateBlock.
114 auto updateBlock = ^{
115 std::unique_ptr<const synced_sessions::DistantSession> newDistantSession =
116 [_model distantSessionForTag:_sessionTag];
117 std::vector<size_t> oldTabsHashes;
118 std::vector<size_t> newTabsHashes;
119 FillVectorWithHashesUsingDistantSession(*_distantSession.get(),
120 &oldTabsHashes);
121 FillVectorWithHashesUsingDistantSession(*newDistantSession.get(),
122 &newTabsHashes);
123 ios_internal::SessionChanges changes(oldTabsHashes, newTabsHashes);
124 if (changes.hasChanges()) {
125 _distantSession = std::move(newDistantSession);
126 [self applyChanges:changes toCollectionView:collectionView];
127 }
128 };
129 [collectionView performBatchUpdates:updateBlock completion:nil];
130 } else {
131 UICollectionView* collectionView = [_panelView collectionView];
132 auto updateBlock = ^{
133 std::unique_ptr<const TabModelSnapshot> newLocalSession =
134 [_model tabModelSnapshotForLocalSession:_sessionType];
135 ios_internal::SessionChanges changes(_localSession->hashes(),
136 newLocalSession->hashes());
137 if (changes.hasChanges()) {
138 _localSession = std::move(newLocalSession);
139 [self applyChanges:changes toCollectionView:collectionView];
140 }
141 };
142 [collectionView performBatchUpdates:updateBlock completion:nil];
143 }
144 }
145
146 - (void)applyChanges:(ios_internal::SessionChanges&)changes
147 toCollectionView:(UICollectionView*)collectionView {
148 NSMutableArray* deletedIndexes = [NSMutableArray array];
149 NSMutableArray* insertedIndexes = [NSMutableArray array];
150 NSMutableArray* updatedIndexes = [NSMutableArray array];
151 for (size_t i : changes.deletions()) {
152 NSInteger deletedTabIndex = static_cast<NSInteger>(i);
153 [deletedIndexes
154 addObject:[NSIndexPath indexPathForItem:deletedTabIndex inSection:0]];
155 }
156 for (size_t i : changes.insertions()) {
157 NSInteger insertedTabIndex = static_cast<NSInteger>(i);
158 [insertedIndexes
159 addObject:[NSIndexPath indexPathForItem:insertedTabIndex inSection:0]];
160 }
161 for (size_t i : changes.updates()) {
162 NSInteger updatedTabIndex = static_cast<NSInteger>(i);
163 [updatedIndexes
164 addObject:[NSIndexPath indexPathForItem:updatedTabIndex inSection:0]];
165 }
166 [collectionView deleteItemsAtIndexPaths:deletedIndexes];
167 [collectionView insertItemsAtIndexPaths:insertedIndexes];
168 [collectionView reloadItemsAtIndexPaths:updatedIndexes];
169 }
170
171 - (void)scrollTabIndexToVisible:(NSInteger)index triggerLayout:(BOOL)layout {
172 [[_panelView collectionView]
173 scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]
174 atScrollPosition:UICollectionViewScrollPositionTop
175 animated:NO];
176 if (layout)
177 [[_panelView collectionView] layoutIfNeeded];
178 }
179
180 - (TabSwitcherLocalSessionCell*)localSessionCellForTabAtIndex:(NSInteger)index {
181 return (TabSwitcherLocalSessionCell*)[[_panelView collectionView]
182 cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
183 }
184
185 - (CGRect)localSessionCellFrameForTabAtIndex:(NSInteger)index {
186 UICollectionViewLayoutAttributes* attributes = [[_panelView collectionView]
187 layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:index
188 inSection:0]];
189 return attributes.frame;
190 }
191
192 - (void)reload {
193 [[_panelView collectionView] reloadSections:[NSIndexSet indexSetWithIndex:0]];
194 }
195
196 - (UICollectionView*)collectionView {
197 return [_panelView collectionView];
198 }
199
200 #pragma mark - UICollectionViewDataSource
201
202 - (NSInteger)collectionView:(UICollectionView*)collectionView
203 numberOfItemsInSection:(NSInteger)section {
204 DCHECK_EQ(section, 0);
205 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
206 CHECK(_distantSession);
207 return _distantSession->tabs.size();
208 } else {
209 CHECK(_localSession);
210 NSInteger numberOfTabs = _localSession->tabs().size();
211 [self setZeroTabStateOverlayVisible:numberOfTabs == 0];
212 return numberOfTabs;
213 }
214 }
215
216 - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
217 cellForItemAtIndexPath:(NSIndexPath*)indexPath {
218 UICollectionViewCell* cell = nil;
219 NSUInteger tabIndex = indexPath.item;
220 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
221 cell = [collectionView
222 dequeueReusableCellWithReuseIdentifier:[TabSwitcherDistantSessionCell
223 identifier]
224 forIndexPath:indexPath];
225 DCHECK([cell isKindOfClass:[TabSwitcherDistantSessionCell class]]);
226 TabSwitcherDistantSessionCell* panelCell =
227 static_cast<TabSwitcherDistantSessionCell*>(cell);
228 CHECK(_distantSession);
229 const std::size_t distantSessionTabCount = _distantSession->tabs.size();
230 LOG_ASSERT(tabIndex < distantSessionTabCount)
231 << "tabIndex == " << tabIndex
232 << " _distantSession->tabs.size() == " << distantSessionTabCount;
233 synced_sessions::DistantTab* tab = _distantSession->tabs[tabIndex].get();
234 CHECK(tab);
235 [panelCell setTitle:SysUTF16ToNSString(tab->title)];
236 [panelCell setSessionGURL:tab->virtual_url
237 withBrowserState:[_model browserState]];
238 [panelCell setDelegate:self];
239 } else {
240 cell = [collectionView
241 dequeueReusableCellWithReuseIdentifier:[TabSwitcherLocalSessionCell
242 identifier]
243 forIndexPath:indexPath];
244 DCHECK([cell isKindOfClass:[TabSwitcherLocalSessionCell class]]);
245 TabSwitcherLocalSessionCell* panelCell =
246 static_cast<TabSwitcherLocalSessionCell*>(cell);
247 Tab* tab = _localSession->tabs()[tabIndex];
248 [panelCell setDelegate:self];
249 [panelCell setSessionType:_sessionType];
250 [panelCell setAppearanceForTab:tab cellSize:[_panelView cellSize]];
251 }
252 return cell;
253 }
254
255 #pragma mark - SessionCellDelegate
256
257 - (TabSwitcherCache*)tabSwitcherCache {
258 return _cache;
259 }
260
261 - (void)cellPressed:(UICollectionViewCell*)cell {
262 const NSInteger tabIndex =
263 [[_panelView collectionView] indexPathForCell:cell].item;
264
265 if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
266 synced_sessions::DistantTab* tab = _distantSession->tabs[tabIndex].get();
267 if (tab)
268 [self.delegate tabSwitcherPanelController:self didSelectDistantTab:tab];
269 } else {
270 Tab* tab = _localSession->tabs()[tabIndex];
271 if (tab)
272 [self.delegate tabSwitcherPanelController:self didSelectLocalTab:tab];
273 }
274 }
275
276 - (void)deleteButtonPressedForCell:(UICollectionViewCell*)cell {
277 DCHECK(_sessionType != ios_internal::SessionType::DISTANT_SESSION);
278 const NSInteger tabIndex =
279 [[_panelView collectionView] indexPathForCell:cell].item;
280 Tab* tab = _localSession->tabs()[tabIndex];
281 if (tab)
282 [self.delegate tabSwitcherPanelController:self didCloseLocalTab:tab];
283 }
284
285 #pragma mark - Private
286
287 - (BOOL)isOverlayVisible {
288 return _overlayView && [_overlayView alpha] != 0.0;
289 }
290
291 - (void)setZeroTabStateOverlayVisible:(BOOL)show {
292 if (show == [self isOverlayVisible])
293 return;
294
295 DCHECK(ios_internal::IsLocalSession(_sessionType));
296
297 if (!_overlayView) {
298 _overlayView.reset([[TabSwitcherPanelOverlayView alloc]
299 initWithFrame:[_panelView bounds]
300 browserState:_browserState]);
301 [_overlayView
302 setOverlayType:
303 (_sessionType == ios_internal::SessionType::OFF_THE_RECORD_SESSION)
304 ? TabSwitcherPanelOverlayType::
305 OVERLAY_PANEL_USER_NO_INCOGNITO_TABS
306 : TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_NO_OPEN_TABS];
307
308 [_overlayView setAlpha:0];
309 [_overlayView setAutoresizingMask:UIViewAutoresizingFlexibleHeight |
310 UIViewAutoresizingFlexibleWidth];
311 [_panelView addSubview:_overlayView];
312 [_overlayView setNeedsLayout];
313 }
314
315 [UIView
316 animateWithDuration:0.25
317 animations:^{
318 [_overlayView setAlpha:show ? 1.0 : 0.0];
319 [self.delegate
320 tabSwitcherPanelControllerDidUpdateOverlayViewVisibility:
321 self];
322 }];
323 }
324
325 - (void)loadView {
326 _panelView.reset(
327 [[TabSwitcherPanelView alloc] initWithSessionType:_sessionType]);
328 _panelView.get().collectionView.dataSource = self;
329 }
330
331 - (synced_sessions::DistantSession const*)distantSession {
332 return _distantSession.get();
333 }
334
335 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698