blob: 210b089ec4282ddceda7c66e2e8a75572a3e6b6f [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h"
#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/time/time.h"
#import "ios/chrome/browser/ui/collection_view/collection_view_controller.h"
#import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestion.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_article_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sink.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_source.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_expandable_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_favicon_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_section_information.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_stack_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_text_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Enum defining the ItemType of this ContentSuggestionsCollectionUpdater.
typedef NS_ENUM(NSInteger, ItemType) {
ItemTypeText = kItemTypeEnumZero,
ItemTypeArticle,
ItemTypeExpand,
ItemTypeStack,
ItemTypeFavicon,
};
typedef NS_ENUM(NSInteger, SectionIdentifier) {
SectionIdentifierBookmarks = kSectionIdentifierEnumZero,
SectionIdentifierArticles,
SectionIdentifierDefault,
};
ItemType ItemTypeForContentSuggestionType(ContentSuggestionType type) {
switch (type) {
case ContentSuggestionTypeArticle:
return ItemTypeArticle;
}
}
ContentSuggestionType ContentSuggestionTypeForItemType(NSInteger type) {
if (type == ItemTypeArticle)
return ContentSuggestionTypeArticle;
// Add new type here
// Default type.
return ContentSuggestionTypeArticle;
}
// Returns the section identifier corresponding to the section |info|.
SectionIdentifier SectionIdentifierForInfo(
ContentSuggestionsSectionInformation* info) {
switch (info.sectionID) {
case ContentSuggestionsSectionBookmarks:
return SectionIdentifierBookmarks;
case ContentSuggestionsSectionArticles:
return SectionIdentifierArticles;
case ContentSuggestionsSectionUnknown:
return SectionIdentifierDefault;
}
}
} // namespace
@interface ContentSuggestionsCollectionUpdater ()<ContentSuggestionsDataSink>
@property(nonatomic, weak) id<ContentSuggestionsDataSource> dataSource;
@property(nonatomic, strong)
NSMutableDictionary<NSNumber*, ContentSuggestionsSectionInformation*>*
sectionInfoBySectionIdentifier;
// Reloads all the data from the data source, deleting all the current items.
- (void)reloadData;
// Adds a new section if needed and returns the section identifier.
- (NSInteger)addSectionIfNeeded:
(ContentSuggestionsSectionInformation*)sectionInformation;
// Resets the models, removing the current CollectionViewItem and the
// SectionInfo.
- (void)resetModels;
@end
@implementation ContentSuggestionsCollectionUpdater
@synthesize collectionViewController = _collectionViewController;
@synthesize dataSource = _dataSource;
@synthesize sectionInfoBySectionIdentifier = _sectionInfoBySectionIdentifier;
- (instancetype)initWithDataSource:
(id<ContentSuggestionsDataSource>)dataSource {
self = [super init];
if (self) {
_dataSource = dataSource;
_dataSource.dataSink = self;
}
return self;
}
#pragma mark - Properties
- (void)setCollectionViewController:
(ContentSuggestionsViewController*)collectionViewController {
_collectionViewController = collectionViewController;
[self reloadData];
}
#pragma mark - ContentSuggestionsDataSink
- (void)dataAvailable {
[self reloadData];
}
#pragma mark - Public methods
- (BOOL)shouldUseCustomStyleForSection:(NSInteger)section {
NSNumber* identifier = @([self.collectionViewController.collectionViewModel
sectionIdentifierForSection:section]);
ContentSuggestionsSectionInformation* sectionInformation =
self.sectionInfoBySectionIdentifier[identifier];
return sectionInformation.layout == ContentSuggestionsSectionLayoutCustom;
}
- (ContentSuggestionType)contentSuggestionTypeForItem:
(CollectionViewItem*)item {
return ContentSuggestionTypeForItemType(item.type);
}
#pragma mark - Private methods
- (void)reloadData {
[self resetModels];
CollectionViewModel* model =
self.collectionViewController.collectionViewModel;
NSArray<ContentSuggestion*>* suggestions = [self.dataSource allSuggestions];
for (ContentSuggestion* suggestion in suggestions) {
NSInteger sectionIdentifier = [self addSectionIfNeeded:suggestion.section];
ContentSuggestionsArticleItem* articleItem =
[[ContentSuggestionsArticleItem alloc]
initWithType:ItemTypeForContentSuggestionType(suggestion.type)
title:suggestion.title
subtitle:suggestion.text
image:suggestion.image
url:suggestion.url];
articleItem.publisher = suggestion.publisher;
articleItem.publishDate = suggestion.publishDate;
[model addItem:articleItem toSectionWithIdentifier:sectionIdentifier];
}
if ([self.collectionViewController isViewLoaded]) {
[self.collectionViewController.collectionView reloadData];
}
}
- (NSInteger)addSectionIfNeeded:
(ContentSuggestionsSectionInformation*)sectionInformation {
NSInteger sectionIdentifier = SectionIdentifierForInfo(sectionInformation);
CollectionViewModel* model =
self.collectionViewController.collectionViewModel;
if (![model hasSectionForSectionIdentifier:sectionIdentifier]) {
[model addSectionWithIdentifier:sectionIdentifier];
self.sectionInfoBySectionIdentifier[@(sectionIdentifier)] =
sectionInformation;
[self.sectionInfoBySectionIdentifier setObject:sectionInformation
forKey:@(sectionIdentifier)];
}
return sectionIdentifier;
}
- (void)resetModels {
[self.collectionViewController loadModel];
self.sectionInfoBySectionIdentifier = [[NSMutableDictionary alloc] init];
}
@end