Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/content_suggestions/content_suggestions_collectio n_updater.h" | 5 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collectio n_updater.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/mac/foundation_util.h" | 8 #include "base/mac/foundation_util.h" |
| 9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| 11 #include "components/strings/grit/components_strings.h" | 11 #include "components/strings/grit/components_strings.h" |
| 12 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h " | 12 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h " |
| 13 #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" | 13 #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" |
| 14 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" | 14 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" |
| 15 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_art icle_item.h" | |
| 16 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_foo ter_item.h" | 15 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_foo ter_item.h" |
| 16 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_ite m.h" | |
| 17 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_mos t_visited_item.h" | 17 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_mos t_visited_item.h" |
| 18 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_rea ding_list_item.h" | |
| 19 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tex t_item.h" | 18 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tex t_item.h" |
| 20 #import "ios/chrome/browser/ui/content_suggestions/content_suggestion.h" | 19 #import "ios/chrome/browser/ui/content_suggestions/content_suggestion.h" |
| 21 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sink .h" | 20 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sink .h" |
| 22 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sour ce.h" | 21 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sour ce.h" |
| 23 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_image_fet cher.h" | 22 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_image_fet cher.h" |
| 24 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_cont roller.h" | 23 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_cont roller.h" |
| 25 #import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion _identifier.h" | 24 #import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion _identifier.h" |
| 26 #import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion s_section_information.h" | 25 #import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion s_section_information.h" |
| 27 #import "ios/chrome/browser/ui/favicon/favicon_attributes.h" | 26 #import "ios/chrome/browser/ui/favicon/favicon_attributes.h" |
| 28 #include "ui/base/l10n/l10n_util.h" | 27 #include "ui/base/l10n/l10n_util.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 return SectionIdentifierMostVisited; | 97 return SectionIdentifierMostVisited; |
| 99 | 98 |
| 100 case ContentSuggestionsSectionUnknown: | 99 case ContentSuggestionsSectionUnknown: |
| 101 return SectionIdentifierDefault; | 100 return SectionIdentifierDefault; |
| 102 } | 101 } |
| 103 } | 102 } |
| 104 | 103 |
| 105 } // namespace | 104 } // namespace |
| 106 | 105 |
| 107 @interface ContentSuggestionsCollectionUpdater ()< | 106 @interface ContentSuggestionsCollectionUpdater ()< |
| 108 ContentSuggestionsArticleItemDelegate, | 107 ContentSuggestionsItemDelegate, |
| 109 ContentSuggestionsDataSink> | 108 ContentSuggestionsDataSink> |
| 110 | 109 |
| 111 @property(nonatomic, weak) id<ContentSuggestionsDataSource> dataSource; | 110 @property(nonatomic, weak) id<ContentSuggestionsDataSource> dataSource; |
| 112 @property(nonatomic, strong) | 111 @property(nonatomic, strong) |
| 113 NSMutableDictionary<NSNumber*, ContentSuggestionsSectionInformation*>* | 112 NSMutableDictionary<NSNumber*, ContentSuggestionsSectionInformation*>* |
| 114 sectionInfoBySectionIdentifier; | 113 sectionInfoBySectionIdentifier; |
| 115 | 114 |
| 116 @end | 115 @end |
| 117 | 116 |
| 118 @implementation ContentSuggestionsCollectionUpdater | 117 @implementation ContentSuggestionsCollectionUpdater |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 264 sectionIdentifier]] == 0) { | 263 sectionIdentifier]] == 0) { |
| 265 CSCollectionViewItem* item = | 264 CSCollectionViewItem* item = |
| 266 [self emptyItemForSectionInfo:sectionInfo]; | 265 [self emptyItemForSectionInfo:sectionInfo]; |
| 267 NSIndexPath* addedIndexPath = | 266 NSIndexPath* addedIndexPath = |
| 268 [self addItem:item toSectionWithIdentifier:sectionIdentifier]; | 267 [self addItem:item toSectionWithIdentifier:sectionIdentifier]; |
| 269 [indexPaths addObject:addedIndexPath]; | 268 [indexPaths addObject:addedIndexPath]; |
| 270 } | 269 } |
| 271 break; | 270 break; |
| 272 } | 271 } |
| 273 case ContentSuggestionTypeArticle: { | 272 case ContentSuggestionTypeArticle: { |
| 274 ContentSuggestionsArticleItem* articleItem = | 273 ContentSuggestionsItem* articleItem = |
| 275 [self articleItemForSuggestion:suggestion]; | 274 [self suggestionItemForSuggestion:suggestion]; |
| 275 | |
| 276 articleItem.hasImage = YES; | |
| 277 | |
| 278 __weak ContentSuggestionsItem* weakItem = articleItem; | |
| 279 [self fetchFaviconForItem:articleItem | |
| 280 withURL:articleItem.URL | |
| 281 callback:^void(FaviconAttributes* attributes) { | |
| 282 weakItem.attributes = attributes; | |
| 283 }]; | |
| 284 | |
| 285 __weak ContentSuggestionsCollectionUpdater* weakSelf = self; | |
| 286 [self.dataSource | |
| 287 fetchFaviconImageForSuggestion:articleItem.suggestionIdentifier | |
| 288 completion:^void(UIImage* favicon) { | |
| 289 if (!weakItem || !weakSelf) | |
| 290 return; | |
| 291 | |
| 292 ContentSuggestionsCollectionUpdater* | |
| 293 strongSelf = weakSelf; | |
|
jif
2017/05/10 09:36:11
strongSelf and strongItem should be the first thin
gambard
2017/05/10 12:17:13
Done.
| |
| 294 ContentSuggestionsItem* strongItem = weakItem; | |
| 295 strongItem.attributes = [FaviconAttributes | |
| 296 attributesWithImage:favicon]; | |
| 297 [strongSelf.collectionViewController | |
| 298 reconfigureCellsForItems:@[ strongItem ]]; | |
| 299 }]; | |
| 276 | 300 |
| 277 NSIndexPath* addedIndexPath = [self addItem:articleItem | 301 NSIndexPath* addedIndexPath = [self addItem:articleItem |
| 278 toSectionWithIdentifier:sectionIdentifier]; | 302 toSectionWithIdentifier:sectionIdentifier]; |
| 279 [indexPaths addObject:addedIndexPath]; | 303 [indexPaths addObject:addedIndexPath]; |
| 280 break; | 304 break; |
| 281 } | 305 } |
| 282 case ContentSuggestionTypeReadingList: { | 306 case ContentSuggestionTypeReadingList: { |
| 283 ContentSuggestionsReadingListItem* readingListItem = | 307 ContentSuggestionsItem* readingListItem = |
| 284 [self readingListItemForSuggestion:suggestion]; | 308 [self suggestionItemForSuggestion:suggestion]; |
| 309 | |
| 310 __weak ContentSuggestionsItem* weakItem = readingListItem; | |
| 311 [self fetchFaviconForItem:readingListItem | |
| 312 withURL:readingListItem.URL | |
| 313 callback:^void(FaviconAttributes* attributes) { | |
| 314 weakItem.attributes = attributes; | |
| 315 }]; | |
| 285 | 316 |
| 286 NSIndexPath* addedIndexPath = [self addItem:readingListItem | 317 NSIndexPath* addedIndexPath = [self addItem:readingListItem |
| 287 toSectionWithIdentifier:sectionIdentifier]; | 318 toSectionWithIdentifier:sectionIdentifier]; |
| 288 [indexPaths addObject:addedIndexPath]; | 319 [indexPaths addObject:addedIndexPath]; |
| 289 break; | 320 break; |
| 290 } | 321 } |
| 291 case ContentSuggestionTypeMostVisited: { | 322 case ContentSuggestionTypeMostVisited: { |
| 292 ContentSuggestionsMostVisitedItem* mostVisitedItem = | 323 ContentSuggestionsMostVisitedItem* mostVisitedItem = |
| 293 [[ContentSuggestionsMostVisitedItem alloc] | 324 [[ContentSuggestionsMostVisitedItem alloc] |
| 294 initWithType:ItemTypeMostVisited]; | 325 initWithType:ItemTypeMostVisited]; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 CSCollectionViewModel* model = | 366 CSCollectionViewModel* model = |
| 336 self.collectionViewController.collectionViewModel; | 367 self.collectionViewController.collectionViewModel; |
| 337 NSInteger sectionIdentifier = [model sectionIdentifierForSection:section]; | 368 NSInteger sectionIdentifier = [model sectionIdentifierForSection:section]; |
| 338 ContentSuggestionsSectionInformation* sectionInfo = | 369 ContentSuggestionsSectionInformation* sectionInfo = |
| 339 self.sectionInfoBySectionIdentifier[@(sectionIdentifier)]; | 370 self.sectionInfoBySectionIdentifier[@(sectionIdentifier)]; |
| 340 | 371 |
| 341 CSCollectionViewItem* item = [self emptyItemForSectionInfo:sectionInfo]; | 372 CSCollectionViewItem* item = [self emptyItemForSectionInfo:sectionInfo]; |
| 342 return [self addItem:item toSectionWithIdentifier:sectionIdentifier]; | 373 return [self addItem:item toSectionWithIdentifier:sectionIdentifier]; |
| 343 } | 374 } |
| 344 | 375 |
| 345 #pragma mark - ContentSuggestionsArticleItemDelegate | 376 #pragma mark - ContentSuggestionsItemDelegate |
| 346 | 377 |
| 347 - (void)loadImageForArticleItem:(ContentSuggestionsArticleItem*)articleItem { | 378 - (void)loadImageForSuggestionItem:(ContentSuggestionsItem*)suggestionItem { |
| 348 __weak ContentSuggestionsCollectionUpdater* weakSelf = self; | 379 __weak ContentSuggestionsCollectionUpdater* weakSelf = self; |
| 349 __weak ContentSuggestionsArticleItem* weakArticle = articleItem; | 380 __weak ContentSuggestionsItem* weakArticle = suggestionItem; |
| 350 | 381 |
| 351 void (^imageFetchedCallback)(UIImage*) = ^(UIImage* image) { | 382 void (^imageFetchedCallback)(UIImage*) = ^(UIImage* image) { |
| 352 ContentSuggestionsCollectionUpdater* strongSelf = weakSelf; | 383 ContentSuggestionsCollectionUpdater* strongSelf = weakSelf; |
| 353 ContentSuggestionsArticleItem* strongArticle = weakArticle; | 384 ContentSuggestionsItem* strongArticle = weakArticle; |
| 354 if (!strongSelf || !strongArticle) { | 385 if (!strongSelf || !strongArticle) { |
| 355 return; | 386 return; |
| 356 } | 387 } |
| 357 | 388 |
| 358 strongArticle.image = image; | 389 strongArticle.image = image; |
| 359 [strongSelf.collectionViewController | 390 [strongSelf.collectionViewController |
| 360 reconfigureCellsForItems:@[ strongArticle ]]; | 391 reconfigureCellsForItems:@[ strongArticle ]]; |
| 361 }; | 392 }; |
| 362 | 393 |
| 363 [self.dataSource.imageFetcher | 394 [self.dataSource.imageFetcher |
| 364 fetchImageForSuggestion:articleItem.suggestionIdentifier | 395 fetchImageForSuggestion:suggestionItem.suggestionIdentifier |
| 365 callback:imageFetchedCallback]; | 396 callback:imageFetchedCallback]; |
| 366 } | 397 } |
| 367 | 398 |
| 368 #pragma mark - Private methods | 399 #pragma mark - Private methods |
| 369 | 400 |
| 370 // Adds a footer to the section identified by |sectionInfo| if there is none | 401 // Adds a footer to the section identified by |sectionInfo| if there is none |
| 371 // present and the section info contains a title for it. | 402 // present and the section info contains a title for it. |
| 372 - (void)addFooterIfNeeded:(ContentSuggestionsSectionInformation*)sectionInfo { | 403 - (void)addFooterIfNeeded:(ContentSuggestionsSectionInformation*)sectionInfo { |
| 373 NSInteger sectionIdentifier = SectionIdentifierForInfo(sectionInfo); | 404 NSInteger sectionIdentifier = SectionIdentifierForInfo(sectionInfo); |
| 374 | 405 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 448 - (CSCollectionViewItem*)emptyItemForSectionInfo: | 479 - (CSCollectionViewItem*)emptyItemForSectionInfo: |
| 449 (ContentSuggestionsSectionInformation*)sectionInfo { | 480 (ContentSuggestionsSectionInformation*)sectionInfo { |
| 450 ContentSuggestionsTextItem* item = | 481 ContentSuggestionsTextItem* item = |
| 451 [[ContentSuggestionsTextItem alloc] initWithType:ItemTypeEmpty]; | 482 [[ContentSuggestionsTextItem alloc] initWithType:ItemTypeEmpty]; |
| 452 item.text = l10n_util::GetNSString(IDS_NTP_TITLE_NO_SUGGESTIONS); | 483 item.text = l10n_util::GetNSString(IDS_NTP_TITLE_NO_SUGGESTIONS); |
| 453 item.detailText = sectionInfo.emptyText; | 484 item.detailText = sectionInfo.emptyText; |
| 454 | 485 |
| 455 return item; | 486 return item; |
| 456 } | 487 } |
| 457 | 488 |
| 458 // Returns an article built with the |suggestion|. | 489 // Returns a suggestion item built with the |suggestion|. |
| 459 - (ContentSuggestionsArticleItem*)articleItemForSuggestion: | 490 - (ContentSuggestionsItem*)suggestionItemForSuggestion: |
| 460 (ContentSuggestion*)suggestion { | 491 (ContentSuggestion*)suggestion { |
| 461 ContentSuggestionsArticleItem* articleItem = | 492 ContentSuggestionsItem* suggestionItem = [[ContentSuggestionsItem alloc] |
| 462 [[ContentSuggestionsArticleItem alloc] | 493 initWithType:ItemTypeForContentSuggestionType(suggestion.type) |
| 463 initWithType:ItemTypeForContentSuggestionType(suggestion.type) | 494 title:suggestion.title |
| 464 title:suggestion.title | 495 subtitle:suggestion.text |
| 465 subtitle:suggestion.text | 496 delegate:self |
| 466 delegate:self | 497 url:suggestion.url]; |
| 467 url:suggestion.url]; | |
| 468 | 498 |
| 469 articleItem.publisher = suggestion.publisher; | 499 suggestionItem.publisher = suggestion.publisher; |
| 470 articleItem.publishDate = suggestion.publishDate; | 500 suggestionItem.publishDate = suggestion.publishDate; |
| 501 suggestionItem.availableOffline = suggestion.availableOffline; | |
| 471 | 502 |
| 472 articleItem.suggestionIdentifier = suggestion.suggestionIdentifier; | 503 suggestionItem.suggestionIdentifier = suggestion.suggestionIdentifier; |
| 473 | 504 |
| 474 __weak ContentSuggestionsArticleItem* weakItem = articleItem; | 505 return suggestionItem; |
| 475 [self fetchFaviconForItem:articleItem | |
| 476 withURL:articleItem.articleURL | |
| 477 callback:^void(FaviconAttributes* attributes) { | |
| 478 weakItem.attributes = attributes; | |
| 479 }]; | |
| 480 | |
| 481 __weak ContentSuggestionsCollectionUpdater* weakSelf = self; | |
| 482 [self.dataSource | |
| 483 fetchFaviconImageForSuggestion:articleItem.suggestionIdentifier | |
| 484 completion:^void(UIImage* favicon) { | |
| 485 if (!weakItem || !weakSelf) | |
| 486 return; | |
| 487 | |
| 488 weakItem.attributes = | |
| 489 [FaviconAttributes attributesWithImage:favicon]; | |
| 490 [weakSelf.collectionViewController | |
| 491 reconfigureCellsForItems:@[ weakItem ]]; | |
| 492 }]; | |
| 493 | |
| 494 return articleItem; | |
| 495 } | |
| 496 | |
| 497 // Returns a reading list item built with the |suggestion|. | |
| 498 - (ContentSuggestionsReadingListItem*)readingListItemForSuggestion: | |
| 499 (ContentSuggestion*)suggestion { | |
| 500 ContentSuggestionsReadingListItem* readingListItem = | |
| 501 [[ContentSuggestionsReadingListItem alloc] | |
| 502 initWithType:ItemTypeReadingList | |
| 503 url:suggestion.url | |
| 504 distillationState:suggestion.readingListExtra.status]; | |
| 505 | |
| 506 readingListItem.title = suggestion.title; | |
| 507 readingListItem.subtitle = suggestion.publisher; | |
| 508 | |
| 509 readingListItem.suggestionIdentifier = suggestion.suggestionIdentifier; | |
| 510 | |
| 511 __weak ContentSuggestionsReadingListItem* weakItem = readingListItem; | |
| 512 [self fetchFaviconForItem:readingListItem | |
| 513 withURL:readingListItem.url | |
| 514 callback:^void(FaviconAttributes* attributes) { | |
| 515 weakItem.attributes = attributes; | |
| 516 }]; | |
| 517 | |
| 518 return readingListItem; | |
| 519 } | 506 } |
| 520 | 507 |
| 521 // Fetches the favicon associated with the |URL|, call the |callback| with the | 508 // Fetches the favicon associated with the |URL|, call the |callback| with the |
| 522 // attributes then reconfigure the |item|. | 509 // attributes then reconfigure the |item|. |
| 523 - (void)fetchFaviconForItem:(CSCollectionViewItem*)item | 510 - (void)fetchFaviconForItem:(CSCollectionViewItem*)item |
| 524 withURL:(const GURL&)URL | 511 withURL:(const GURL&)URL |
| 525 callback:(void (^)(FaviconAttributes*))callback { | 512 callback:(void (^)(FaviconAttributes*))callback { |
| 526 if (!callback) | 513 if (!callback) |
| 527 return; | 514 return; |
| 528 | 515 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 552 CSCollectionViewModel* model = | 539 CSCollectionViewModel* model = |
| 553 self.collectionViewController.collectionViewModel; | 540 self.collectionViewController.collectionViewModel; |
| 554 NSInteger section = [model sectionForSectionIdentifier:sectionIdentifier]; | 541 NSInteger section = [model sectionForSectionIdentifier:sectionIdentifier]; |
| 555 NSInteger itemNumber = [model numberOfItemsInSection:section]; | 542 NSInteger itemNumber = [model numberOfItemsInSection:section]; |
| 556 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; | 543 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; |
| 557 | 544 |
| 558 return [NSIndexPath indexPathForItem:itemNumber inSection:section]; | 545 return [NSIndexPath indexPathForItem:itemNumber inSection:section]; |
| 559 } | 546 } |
| 560 | 547 |
| 561 @end | 548 @end |
| OLD | NEW |