OLD | NEW |
| (Empty) |
1 // Copyright 2014 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/bookmarks/bookmark_folder_collection_view.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/strings/sys_string_conversions.h" | |
9 #include "components/bookmarks/browser/bookmark_model.h" | |
10 #include "ios/chrome/browser/bookmarks/bookmarks_utils.h" | |
11 #include "ios/chrome/browser/experimental_flags.h" | |
12 #import "ios/chrome/browser/ui/authentication/signin_promo_view.h" | |
13 #import "ios/chrome/browser/ui/authentication/signin_promo_view_configurator.h" | |
14 #import "ios/chrome/browser/ui/authentication/signin_promo_view_consumer.h" | |
15 #import "ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h" | |
16 #import "ios/chrome/browser/ui/bookmarks/bookmark_collection_cells.h" | |
17 #import "ios/chrome/browser/ui/bookmarks/bookmark_promo_cell.h" | |
18 #import "ios/chrome/browser/ui/bookmarks/bookmark_signin_promo_cell.h" | |
19 #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" | |
20 | |
21 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
22 #error "This file requires ARC support." | |
23 #endif | |
24 | |
25 using bookmarks::BookmarkNode; | |
26 | |
27 namespace { | |
28 // Computes the cell size based on width. | |
29 CGSize PreferredCellSizeForWidth(UICollectionViewCell* cell, CGFloat width) { | |
30 CGRect cellFrame = cell.frame; | |
31 cellFrame.size.width = width; | |
32 cellFrame.size.height = CGFLOAT_MAX; | |
33 cell.frame = cellFrame; | |
34 [cell setNeedsLayout]; | |
35 [cell layoutIfNeeded]; | |
36 CGSize result = | |
37 [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize | |
38 withHorizontalFittingPriority:UILayoutPriorityRequired | |
39 verticalFittingPriority:UILayoutPriorityDefaultLow]; | |
40 cellFrame.size = result; | |
41 cell.frame = cellFrame; | |
42 return result; | |
43 } | |
44 } | |
45 | |
46 @interface BookmarkFolderCollectionView ()<BookmarkPromoCellDelegate, | |
47 SigninPromoViewConsumer> { | |
48 // A vector of folders to display in the collection view. | |
49 std::vector<const BookmarkNode*> _subFolders; | |
50 // A vector of bookmark urls to display in the collection view. | |
51 std::vector<const BookmarkNode*> _subItems; | |
52 | |
53 // True if the promo is visible. | |
54 BOOL _promoVisible; | |
55 | |
56 // Mediator, helper for the sign-in promo view. | |
57 SigninPromoViewMediator* _signinPromoViewMediator; | |
58 } | |
59 @property(nonatomic, assign) const bookmarks::BookmarkNode* folder; | |
60 | |
61 // Section indices. | |
62 @property(nonatomic, readonly, assign) NSInteger promoSection; | |
63 @property(nonatomic, readonly, assign) NSInteger folderSection; | |
64 @property(nonatomic, readonly, assign) NSInteger itemsSection; | |
65 @property(nonatomic, readonly, assign) NSInteger sectionCount; | |
66 | |
67 @end | |
68 | |
69 @implementation BookmarkFolderCollectionView | |
70 @synthesize delegate = _delegate; | |
71 @synthesize folder = _folder; | |
72 | |
73 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState | |
74 frame:(CGRect)frame { | |
75 self = [super initWithBrowserState:browserState frame:frame]; | |
76 if (self) { | |
77 [self updateCollectionView]; | |
78 } | |
79 return self; | |
80 } | |
81 | |
82 - (void)setDelegate:(id<BookmarkFolderCollectionViewDelegate>)delegate { | |
83 _delegate = delegate; | |
84 [self promoStateChangedAnimated:NO]; | |
85 } | |
86 | |
87 - (NSInteger)promoSection { | |
88 return [self shouldShowPromoCell] ? 0 : -1; | |
89 } | |
90 | |
91 - (NSInteger)folderSection { | |
92 return [self shouldShowPromoCell] ? 1 : 0; | |
93 } | |
94 | |
95 - (NSInteger)itemsSection { | |
96 return [self shouldShowPromoCell] ? 2 : 1; | |
97 } | |
98 | |
99 - (NSInteger)sectionCount { | |
100 return [self shouldShowPromoCell] ? 3 : 2; | |
101 } | |
102 | |
103 - (void)updateCollectionView { | |
104 if (!self.bookmarkModel->loaded()) | |
105 return; | |
106 | |
107 // Regenerate the list of all bookmarks. | |
108 _subFolders = std::vector<const BookmarkNode*>(); | |
109 _subItems = std::vector<const BookmarkNode*>(); | |
110 | |
111 if (self.folder) { | |
112 int childCount = self.folder->child_count(); | |
113 for (int i = 0; i < childCount; ++i) { | |
114 const BookmarkNode* node = self.folder->GetChild(i); | |
115 if (node->is_folder()) | |
116 _subFolders.push_back(node); | |
117 else | |
118 _subItems.push_back(node); | |
119 } | |
120 | |
121 bookmark_utils_ios::SortFolders(&_subFolders); | |
122 } | |
123 | |
124 [self cancelAllFaviconLoads]; | |
125 [self.collectionView reloadData]; | |
126 } | |
127 | |
128 #pragma mark - BookmarkModelBridgeObserver Callbacks | |
129 | |
130 - (void)bookmarkModelLoaded { | |
131 [self updateCollectionView]; | |
132 } | |
133 | |
134 - (void)bookmarkNodeChanged:(const BookmarkNode*)bookmarkNode { | |
135 // The base folder changed. Do nothing. | |
136 if (bookmarkNode == self.folder) | |
137 return; | |
138 | |
139 // A specific cell changed. Reload that cell. | |
140 NSIndexPath* indexPath = [self indexPathForNode:bookmarkNode]; | |
141 | |
142 if (indexPath) { | |
143 // TODO(crbug.com/603661): Ideally, we would only reload the relevant index | |
144 // path. However, calling reloadItemsAtIndexPaths:(0,0) immediately after | |
145 // reloadData results in a exception: NSInternalInconsistencyException | |
146 // 'request for index path for global index 2147483645 ...' | |
147 // One solution would be to keep track of whether we've just called | |
148 // reloadData, but that requires experimentation to determine how long we | |
149 // have to wait before we can safely call reloadItemsAtIndexPaths. | |
150 [self updateCollectionView]; | |
151 } | |
152 } | |
153 | |
154 - (void)bookmarkNodeFaviconChanged: | |
155 (const bookmarks::BookmarkNode*)bookmarkNode { | |
156 // Only urls have favicons. | |
157 DCHECK(bookmarkNode->is_url()); | |
158 | |
159 // Update image of corresponding cell. | |
160 NSIndexPath* indexPath = [self indexPathForNode:bookmarkNode]; | |
161 | |
162 if (!indexPath) | |
163 return; | |
164 | |
165 // Check that this cell is visible. | |
166 NSArray* visiblePaths = [self.collectionView indexPathsForVisibleItems]; | |
167 if (![visiblePaths containsObject:indexPath]) | |
168 return; | |
169 | |
170 [self loadFaviconAtIndexPath:indexPath]; | |
171 } | |
172 | |
173 - (NSIndexPath*)indexPathForNode:(const bookmarks::BookmarkNode*)bookmarkNode { | |
174 NSIndexPath* indexPath = nil; | |
175 if (bookmarkNode->is_folder()) { | |
176 std::vector<const BookmarkNode*>::iterator it = | |
177 std::find(_subFolders.begin(), _subFolders.end(), bookmarkNode); | |
178 if (it != _subFolders.end()) { | |
179 ptrdiff_t index = std::distance(_subFolders.begin(), it); | |
180 indexPath = | |
181 [NSIndexPath indexPathForRow:index inSection:self.folderSection]; | |
182 } | |
183 } else if (bookmarkNode->is_url()) { | |
184 std::vector<const BookmarkNode*>::iterator it = | |
185 std::find(_subItems.begin(), _subItems.end(), bookmarkNode); | |
186 if (it != _subItems.end()) { | |
187 ptrdiff_t index = std::distance(_subItems.begin(), it); | |
188 indexPath = | |
189 [NSIndexPath indexPathForRow:index inSection:self.itemsSection]; | |
190 } | |
191 } | |
192 return indexPath; | |
193 } | |
194 | |
195 - (void)bookmarkNodeDeleted:(const BookmarkNode*)node | |
196 fromFolder:(const BookmarkNode*)folder { | |
197 if (self.folder == node) { | |
198 self.folder = nil; | |
199 [self updateCollectionView]; | |
200 } | |
201 } | |
202 | |
203 - (void)bookmarkNodeChildrenChanged:(const BookmarkNode*)bookmarkNode { | |
204 // The base folder's children changed. Reload everything. | |
205 if (bookmarkNode == self.folder) { | |
206 [self updateCollectionView]; | |
207 return; | |
208 } | |
209 | |
210 // A subfolder's children changed. Reload that cell. | |
211 std::vector<const BookmarkNode*>::iterator it = | |
212 std::find(_subFolders.begin(), _subFolders.end(), bookmarkNode); | |
213 if (it != _subFolders.end()) { | |
214 // TODO(crbug.com/603661): Ideally, we would only reload the relevant index | |
215 // path. However, calling reloadItemsAtIndexPaths:(0,0) immediately after | |
216 // reloadData results in a exception: NSInternalInconsistencyException | |
217 // 'request for index path for global index 2147483645 ...' | |
218 // One solution would be to keep track of whether we've just called | |
219 // reloadData, but that requires experimentation to determine how long we | |
220 // have to wait before we can safely call reloadItemsAtIndexPaths. | |
221 [self updateCollectionView]; | |
222 } | |
223 } | |
224 | |
225 - (void)bookmarkNode:(const BookmarkNode*)bookmarkNode | |
226 movedFromParent:(const BookmarkNode*)oldParent | |
227 toParent:(const BookmarkNode*)newParent { | |
228 if (oldParent == self.folder || newParent == self.folder) { | |
229 // A folder was added or removed from the base folder. | |
230 [self updateCollectionView]; | |
231 } | |
232 } | |
233 | |
234 - (void)bookmarkModelRemovedAllNodes { | |
235 self.folder = nil; | |
236 [self updateCollectionView]; | |
237 } | |
238 | |
239 #pragma mark - Parent class overrides that affect functionality | |
240 | |
241 - (void)collectionView:(UICollectionView*)collectionView | |
242 willDisplayCell:(UICollectionViewCell*)cell | |
243 forItemAtIndexPath:(NSIndexPath*)indexPath { | |
244 if (indexPath.section == self.itemsSection) { | |
245 [self loadFaviconAtIndexPath:indexPath]; | |
246 } | |
247 } | |
248 | |
249 - (void)didAddCellForEditingAtIndexPath:(NSIndexPath*)indexPath { | |
250 const BookmarkNode* node = [self nodeAtIndexPath:indexPath]; | |
251 UICollectionViewCell* cell = | |
252 [self.collectionView cellForItemAtIndexPath:indexPath]; | |
253 [self.delegate bookmarkCollectionView:self cell:cell addNodeForEditing:node]; | |
254 } | |
255 | |
256 - (void)didRemoveCellForEditingAtIndexPath:(NSIndexPath*)indexPath { | |
257 const BookmarkNode* node = [self nodeAtIndexPath:indexPath]; | |
258 UICollectionViewCell* cell = | |
259 [self.collectionView cellForItemAtIndexPath:indexPath]; | |
260 [self.delegate bookmarkCollectionView:self | |
261 cell:cell | |
262 removeNodeForEditing:node]; | |
263 } | |
264 | |
265 - (void)didTapCellAtIndexPath:(NSIndexPath*)indexPath { | |
266 if (indexPath.section == self.promoSection) { | |
267 // User tapped inside promo cell but not on one of the buttons. Ignore it. | |
268 return; | |
269 } | |
270 | |
271 const BookmarkNode* node = [self nodeAtIndexPath:indexPath]; | |
272 DCHECK(node); | |
273 | |
274 if (indexPath.section == self.folderSection) { | |
275 [self.delegate bookmarkFolderCollectionView:self | |
276 selectedFolderForNavigation:node]; | |
277 } else { | |
278 RecordBookmarkLaunch(BOOKMARK_LAUNCH_LOCATION_FOLDER); | |
279 [self.delegate bookmarkCollectionView:self | |
280 selectedUrlForNavigation:node->url()]; | |
281 } | |
282 } | |
283 | |
284 - (void)didTapMenuButtonAtIndexPath:(NSIndexPath*)indexPath | |
285 onView:(UIView*)view | |
286 forCell:(BookmarkItemCell*)cell { | |
287 [self.delegate bookmarkCollectionView:self | |
288 wantsMenuForBookmark:[self nodeAtIndexPath:indexPath] | |
289 onView:view | |
290 forCell:cell]; | |
291 } | |
292 | |
293 - (bookmark_cell::ButtonType)buttonTypeForCellAtIndexPath: | |
294 (NSIndexPath*)indexPath { | |
295 return self.editing ? bookmark_cell::ButtonNone : bookmark_cell::ButtonMenu; | |
296 } | |
297 | |
298 - (BOOL)allowLongPressForCellAtIndexPath:(NSIndexPath*)indexPath { | |
299 return !self.editing; | |
300 } | |
301 | |
302 - (void)didLongPressCell:(UICollectionViewCell*)cell | |
303 atIndexPath:(NSIndexPath*)indexPath { | |
304 if (indexPath.section == self.promoSection) { | |
305 // User long-pressed inside promo cell. Ignore it. | |
306 return; | |
307 } | |
308 | |
309 [self.delegate bookmarkCollectionView:self | |
310 didLongPressCell:cell | |
311 forBookmark:[self nodeAtIndexPath:indexPath]]; | |
312 } | |
313 | |
314 - (BOOL)shouldSelectCellAtIndexPath:(NSIndexPath*)indexPath { | |
315 return YES; | |
316 } | |
317 | |
318 - (BOOL)cellIsSelectedForEditingAtIndexPath:(NSIndexPath*)indexPath { | |
319 const BookmarkNode* node = [self nodeAtIndexPath:indexPath]; | |
320 const std::set<const BookmarkNode*>& editingNodes = | |
321 [self.delegate nodesBeingEdited]; | |
322 return editingNodes.find(node) != editingNodes.end(); | |
323 } | |
324 | |
325 - (const BookmarkNode*)nodeAtIndexPath:(NSIndexPath*)indexPath { | |
326 if (indexPath.section == self.folderSection) | |
327 return _subFolders[indexPath.row]; | |
328 if (indexPath.section == self.itemsSection) | |
329 return _subItems[indexPath.row]; | |
330 | |
331 NOTREACHED(); | |
332 return nullptr; | |
333 } | |
334 | |
335 - (void)resetFolder:(const BookmarkNode*)folder { | |
336 DCHECK(folder->is_folder()); | |
337 self.folder = folder; | |
338 [self updateCollectionView]; | |
339 } | |
340 | |
341 - (CGFloat)interitemSpacingForSectionAtIndex:(NSInteger)section { | |
342 CGFloat interitemSpacing = 0; | |
343 SEL minimumInteritemSpacingSelector = @selector(collectionView: | |
344 layout: | |
345 minimumInteritemSpacingForSectionAtIndex:); | |
346 if ([self.collectionView.delegate | |
347 respondsToSelector:minimumInteritemSpacingSelector]) { | |
348 id collectionViewDelegate = static_cast<id>(self.collectionView.delegate); | |
349 interitemSpacing = | |
350 [collectionViewDelegate collectionView:self.collectionView | |
351 layout:self.collectionView | |
352 .collectionViewLayout | |
353 minimumInteritemSpacingForSectionAtIndex:section]; | |
354 } else if ([self.collectionView.collectionViewLayout | |
355 isKindOfClass:[UICollectionViewFlowLayout class]]) { | |
356 UICollectionViewFlowLayout* flowLayout = | |
357 static_cast<UICollectionViewFlowLayout*>( | |
358 self.collectionView.collectionViewLayout); | |
359 interitemSpacing = flowLayout.minimumInteritemSpacing; | |
360 } | |
361 return interitemSpacing; | |
362 } | |
363 | |
364 // Parent class override. | |
365 - (UIEdgeInsets)insetForSectionAtIndex:(NSInteger)section { | |
366 UIEdgeInsets insets = [super insetForSectionAtIndex:section]; | |
367 if (section == self.folderSection) | |
368 insets.bottom = [self interitemSpacingForSectionAtIndex:section] / 2.; | |
369 else if (section == self.itemsSection) | |
370 insets.top = [self interitemSpacingForSectionAtIndex:section] / 2.; | |
371 else if (section == self.promoSection) | |
372 (void)0; // No insets to update. | |
373 else | |
374 NOTREACHED(); | |
375 return insets; | |
376 } | |
377 | |
378 // Parent class override. | |
379 - (CGSize)cellSizeForIndexPath:(NSIndexPath*)indexPath { | |
380 if ([self isPromoSection:indexPath.section]) { | |
381 UICollectionViewCell* cell = | |
382 [self.collectionView cellForItemAtIndexPath:indexPath]; | |
383 if (!cell) { | |
384 // -[UICollectionView | |
385 // dequeueReusableCellWithReuseIdentifier:forIndexPath:] cannot be used | |
386 // here since this method is called by -[id<UICollectionViewDelegate> | |
387 // collectionView:layout:sizeForItemAtIndexPath:]. This would generate | |
388 // crash: SIGFPE, EXC_I386_DIV. | |
389 if (experimental_flags::IsSigninPromoEnabled()) { | |
390 DCHECK(_signinPromoViewMediator); | |
391 BookmarkSigninPromoCell* signinPromoCell = | |
392 [[BookmarkSigninPromoCell alloc] | |
393 initWithFrame:CGRectMake(0, 0, 1000, 1000)]; | |
394 [[_signinPromoViewMediator createConfigurator] | |
395 configureSigninPromoView:signinPromoCell.signinPromoView]; | |
396 cell = signinPromoCell; | |
397 } else { | |
398 cell = [[BookmarkPromoCell alloc] init]; | |
399 } | |
400 } | |
401 return PreferredCellSizeForWidth(cell, CGRectGetWidth(self.bounds)); | |
402 } | |
403 return [super cellSizeForIndexPath:indexPath]; | |
404 } | |
405 | |
406 // Parent class override. | |
407 - (UICollectionViewCell*)cellAtIndexPath:(NSIndexPath*)indexPath { | |
408 if (indexPath.section == self.promoSection) { | |
409 if (experimental_flags::IsSigninPromoEnabled()) { | |
410 BookmarkSigninPromoCell* signinPromoCell = [self.collectionView | |
411 dequeueReusableCellWithReuseIdentifier:[BookmarkSigninPromoCell | |
412 reuseIdentifier] | |
413 forIndexPath:indexPath]; | |
414 signinPromoCell.signinPromoView.delegate = _signinPromoViewMediator; | |
415 [[_signinPromoViewMediator createConfigurator] | |
416 configureSigninPromoView:signinPromoCell.signinPromoView]; | |
417 __weak BookmarkFolderCollectionView* weakSelf = self; | |
418 signinPromoCell.closeButtonAction = ^() { | |
419 [weakSelf.delegate bookmarkCollectionViewDismissPromo:self]; | |
420 }; | |
421 return signinPromoCell; | |
422 } else { | |
423 BookmarkPromoCell* promoCell = [self.collectionView | |
424 dequeueReusableCellWithReuseIdentifier:[BookmarkPromoCell | |
425 reuseIdentifier] | |
426 forIndexPath:indexPath]; | |
427 promoCell.delegate = self; | |
428 return promoCell; | |
429 } | |
430 } | |
431 const BookmarkNode* node = [self nodeAtIndexPath:indexPath]; | |
432 | |
433 if (indexPath.section == self.folderSection) | |
434 return [self cellForFolder:node indexPath:indexPath]; | |
435 | |
436 BookmarkItemCell* cell = [self cellForBookmark:node indexPath:indexPath]; | |
437 return cell; | |
438 } | |
439 | |
440 - (BOOL)needsSectionHeaderForSection:(NSInteger)section { | |
441 // Only show header when there is at least one element in the previous | |
442 // section. | |
443 if (section == 0) | |
444 return NO; | |
445 | |
446 if ([self numberOfItemsInSection:(section - 1)] == 0) | |
447 return NO; | |
448 | |
449 return YES; | |
450 } | |
451 | |
452 // Parent class override. | |
453 - (CGSize)headerSizeForSection:(NSInteger)section { | |
454 if ([self needsSectionHeaderForSection:section]) | |
455 return CGSizeMake(self.bounds.size.width, | |
456 [BookmarkHeaderSeparatorView preferredHeight]); | |
457 | |
458 return CGSizeZero; | |
459 } | |
460 | |
461 // Parent class override. | |
462 - (UICollectionReusableView*)headerAtIndexPath:(NSIndexPath*)indexPath { | |
463 if (![self needsSectionHeaderForSection:indexPath.section]) | |
464 return nil; | |
465 | |
466 BookmarkHeaderSeparatorView* view = [self.collectionView | |
467 dequeueReusableSupplementaryViewOfKind: | |
468 UICollectionElementKindSectionHeader | |
469 withReuseIdentifier:[BookmarkHeaderSeparatorView | |
470 reuseIdentifier] | |
471 forIndexPath:indexPath]; | |
472 view.backgroundColor = [UIColor colorWithWhite:1 alpha:1]; | |
473 return view; | |
474 } | |
475 | |
476 - (NSInteger)numberOfItemsInSection:(NSInteger)section { | |
477 if (section == self.folderSection) | |
478 return _subFolders.size(); | |
479 if (section == self.itemsSection) | |
480 return _subItems.size(); | |
481 if (section == self.promoSection) | |
482 return 1; | |
483 | |
484 NOTREACHED(); | |
485 return -1; | |
486 } | |
487 | |
488 - (NSInteger)numberOfSections { | |
489 return self.sectionCount; | |
490 } | |
491 | |
492 - (void)collectionViewScrolled { | |
493 [self.delegate bookmarkCollectionViewDidScroll:self]; | |
494 } | |
495 | |
496 - (void)setEditing:(BOOL)editing animated:(BOOL)animated { | |
497 [super setEditing:editing animated:animated]; | |
498 [self promoStateChangedAnimated:animated]; | |
499 } | |
500 | |
501 - (void)promoStateChangedAnimated:(BOOL)animate { | |
502 BOOL newPromoState = | |
503 !self.editing && self.folder && | |
504 self.folder->type() == BookmarkNode::MOBILE && | |
505 [self.delegate bookmarkCollectionViewShouldShowPromoCell:self]; | |
506 if (newPromoState != _promoVisible) { | |
507 // This is awful, but until the old code to do the refresh when switching | |
508 // in and out of edit mode is fixed, this is probably the cleanest thing to | |
509 // do. | |
510 _promoVisible = newPromoState; | |
511 if (experimental_flags::IsSigninPromoEnabled()) { | |
512 if (!_promoVisible) { | |
513 _signinPromoViewMediator.consumer = nil; | |
514 _signinPromoViewMediator = nil; | |
515 } else { | |
516 _signinPromoViewMediator = [[SigninPromoViewMediator alloc] init]; | |
517 _signinPromoViewMediator.consumer = self; | |
518 _signinPromoViewMediator.accessPoint = | |
519 signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER; | |
520 } | |
521 } | |
522 [self.collectionView reloadData]; | |
523 } | |
524 } | |
525 | |
526 #pragma mark - BookmarkPromoCellDelegate | |
527 | |
528 - (void)bookmarkPromoCellDidTapSignIn:(BookmarkPromoCell*)bookmarkPromoCell { | |
529 [self.delegate bookmarkCollectionViewShowSignIn:self]; | |
530 } | |
531 | |
532 - (void)bookmarkPromoCellDidTapDismiss:(BookmarkPromoCell*)bookmarkPromoCell { | |
533 [self.delegate bookmarkCollectionViewDismissPromo:self]; | |
534 } | |
535 | |
536 #pragma mark - Promo Cell | |
537 | |
538 - (BOOL)shouldShowPromoCell { | |
539 return _promoVisible; | |
540 } | |
541 | |
542 #pragma mark - SigninPromoViewConsumer | |
543 | |
544 - (void)configureSigninPromoWithConfigurator: | |
545 (SigninPromoViewConfigurator*)configurator | |
546 identityChanged:(BOOL)identityChanged { | |
547 DCHECK(_signinPromoViewMediator); | |
548 NSIndexPath* indexPath = | |
549 [NSIndexPath indexPathForRow:0 inSection:self.promoSection]; | |
550 BookmarkSigninPromoCell* signinPromoCell = | |
551 static_cast<BookmarkSigninPromoCell*>( | |
552 [self.collectionView cellForItemAtIndexPath:indexPath]); | |
553 if (!signinPromoCell) | |
554 return; | |
555 // Should always reconfigure the cell size even if it has to be reloaded. | |
556 // -[BookmarkFolderCollectionView cellSizeForIndexPath:] uses the current | |
557 // cell to compute its height. | |
558 [configurator configureSigninPromoView:signinPromoCell.signinPromoView]; | |
559 if (identityChanged) { | |
560 // The section should be reload to update the cell height. | |
561 NSIndexSet* indexSet = [NSIndexSet indexSetWithIndex:self.promoSection]; | |
562 [self.collectionView reloadSections:indexSet]; | |
563 } | |
564 } | |
565 | |
566 @end | |
OLD | NEW |