| 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/time/time.h" | 9 #include "base/time/time.h" |
| 10 #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" | 10 #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 | 80 |
| 81 @interface ContentSuggestionsCollectionUpdater ()< | 81 @interface ContentSuggestionsCollectionUpdater ()< |
| 82 ContentSuggestionsArticleItemDelegate, | 82 ContentSuggestionsArticleItemDelegate, |
| 83 ContentSuggestionsDataSink> | 83 ContentSuggestionsDataSink> |
| 84 | 84 |
| 85 @property(nonatomic, weak) id<ContentSuggestionsDataSource> dataSource; | 85 @property(nonatomic, weak) id<ContentSuggestionsDataSource> dataSource; |
| 86 @property(nonatomic, strong) | 86 @property(nonatomic, strong) |
| 87 NSMutableDictionary<NSNumber*, ContentSuggestionsSectionInformation*>* | 87 NSMutableDictionary<NSNumber*, ContentSuggestionsSectionInformation*>* |
| 88 sectionInfoBySectionIdentifier; | 88 sectionInfoBySectionIdentifier; |
| 89 | 89 |
| 90 // Adds a new section if needed and returns the section identifier. | |
| 91 - (NSInteger)addSectionIfNeeded: | |
| 92 (ContentSuggestionsSectionInformation*)sectionInformation; | |
| 93 // Resets the models, removing the current CollectionViewItem and the | |
| 94 // SectionInfo. | |
| 95 - (void)resetModels; | |
| 96 | |
| 97 @end | 90 @end |
| 98 | 91 |
| 99 @implementation ContentSuggestionsCollectionUpdater | 92 @implementation ContentSuggestionsCollectionUpdater |
| 100 | 93 |
| 101 @synthesize collectionViewController = _collectionViewController; | 94 @synthesize collectionViewController = _collectionViewController; |
| 102 @synthesize dataSource = _dataSource; | 95 @synthesize dataSource = _dataSource; |
| 103 @synthesize sectionInfoBySectionIdentifier = _sectionInfoBySectionIdentifier; | 96 @synthesize sectionInfoBySectionIdentifier = _sectionInfoBySectionIdentifier; |
| 104 | 97 |
| 105 - (instancetype)initWithDataSource: | 98 - (instancetype)initWithDataSource: |
| 106 (id<ContentSuggestionsDataSource>)dataSource { | 99 (id<ContentSuggestionsDataSource>)dataSource { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 128 SectionIdentifier sectionIdentifier = SectionIdentifierForInfo(sectionInfo); | 121 SectionIdentifier sectionIdentifier = SectionIdentifierForInfo(sectionInfo); |
| 129 | 122 |
| 130 CollectionViewModel* model = | 123 CollectionViewModel* model = |
| 131 self.collectionViewController.collectionViewModel; | 124 self.collectionViewController.collectionViewModel; |
| 132 if ([model hasSectionForSectionIdentifier:sectionIdentifier] && | 125 if ([model hasSectionForSectionIdentifier:sectionIdentifier] && |
| 133 [model itemsInSectionWithIdentifier:sectionIdentifier].count > 0) { | 126 [model itemsInSectionWithIdentifier:sectionIdentifier].count > 0) { |
| 134 // Do not dismiss the presented items. | 127 // Do not dismiss the presented items. |
| 135 return; | 128 return; |
| 136 } | 129 } |
| 137 | 130 |
| 138 [self addSuggestions:[self.dataSource suggestionsForSection:sectionInfo]]; | 131 [self.collectionViewController |
| 132 addSuggestions:[self.dataSource suggestionsForSection:sectionInfo]]; |
| 139 } | 133 } |
| 140 | 134 |
| 141 - (void)clearSuggestion:(ContentSuggestionIdentifier*)suggestionIdentifier { | 135 - (void)clearSuggestion:(ContentSuggestionIdentifier*)suggestionIdentifier { |
| 142 SectionIdentifier sectionIdentifier = | 136 SectionIdentifier sectionIdentifier = |
| 143 SectionIdentifierForInfo(suggestionIdentifier.sectionInfo); | 137 SectionIdentifierForInfo(suggestionIdentifier.sectionInfo); |
| 144 if (![self.collectionViewController.collectionViewModel | 138 if (![self.collectionViewController.collectionViewModel |
| 145 hasSectionForSectionIdentifier:sectionIdentifier]) { | 139 hasSectionForSectionIdentifier:sectionIdentifier]) { |
| 146 return; | 140 return; |
| 147 } | 141 } |
| 148 | 142 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 163 return; | 157 return; |
| 164 | 158 |
| 165 NSIndexPath* indexPath = [self.collectionViewController.collectionViewModel | 159 NSIndexPath* indexPath = [self.collectionViewController.collectionViewModel |
| 166 indexPathForItem:correspondingItem | 160 indexPathForItem:correspondingItem |
| 167 inSectionWithIdentifier:sectionIdentifier]; | 161 inSectionWithIdentifier:sectionIdentifier]; |
| 168 [self.collectionViewController dismissEntryAtIndexPath:indexPath]; | 162 [self.collectionViewController dismissEntryAtIndexPath:indexPath]; |
| 169 } | 163 } |
| 170 | 164 |
| 171 - (void)reloadAllData { | 165 - (void)reloadAllData { |
| 172 [self resetModels]; | 166 [self resetModels]; |
| 173 [self addSuggestions:[self.dataSource allSuggestions]]; | 167 [self.collectionViewController |
| 168 addSuggestions:[self.dataSource allSuggestions]]; |
| 174 } | 169 } |
| 175 | 170 |
| 176 - (void)clearSection:(ContentSuggestionsSectionInformation*)sectionInfo { | 171 - (void)clearSection:(ContentSuggestionsSectionInformation*)sectionInfo { |
| 177 SectionIdentifier sectionIdentifier = SectionIdentifierForInfo(sectionInfo); | 172 SectionIdentifier sectionIdentifier = SectionIdentifierForInfo(sectionInfo); |
| 178 NSInteger section = [self.collectionViewController.collectionViewModel | 173 NSInteger section = [self.collectionViewController.collectionViewModel |
| 179 sectionIdentifierForSection:sectionIdentifier]; | 174 sectionIdentifierForSection:sectionIdentifier]; |
| 180 | 175 |
| 181 [self.collectionViewController dismissSection:section]; | 176 [self.collectionViewController dismissSection:section]; |
| 182 } | 177 } |
| 183 | 178 |
| 184 #pragma mark - Public methods | 179 #pragma mark - Public methods |
| 185 | 180 |
| 186 - (BOOL)shouldUseCustomStyleForSection:(NSInteger)section { | 181 - (BOOL)shouldUseCustomStyleForSection:(NSInteger)section { |
| 187 NSNumber* identifier = @([self.collectionViewController.collectionViewModel | 182 NSNumber* identifier = @([self.collectionViewController.collectionViewModel |
| 188 sectionIdentifierForSection:section]); | 183 sectionIdentifierForSection:section]); |
| 189 ContentSuggestionsSectionInformation* sectionInformation = | 184 ContentSuggestionsSectionInformation* sectionInformation = |
| 190 self.sectionInfoBySectionIdentifier[identifier]; | 185 self.sectionInfoBySectionIdentifier[identifier]; |
| 191 return sectionInformation.layout == ContentSuggestionsSectionLayoutCustom; | 186 return sectionInformation.layout == ContentSuggestionsSectionLayoutCustom; |
| 192 } | 187 } |
| 193 | 188 |
| 194 - (ContentSuggestionType)contentSuggestionTypeForItem: | 189 - (ContentSuggestionType)contentSuggestionTypeForItem: |
| 195 (CollectionViewItem*)item { | 190 (CollectionViewItem*)item { |
| 196 return ContentSuggestionTypeForItemType(item.type); | 191 return ContentSuggestionTypeForItemType(item.type); |
| 197 } | 192 } |
| 198 | 193 |
| 199 #pragma mark - ContentSuggestionsArticleItemDelegate | 194 - (NSArray<NSIndexPath*>*)addSuggestionsToModel: |
| 200 | 195 (NSArray<ContentSuggestion*>*)suggestions { |
| 201 - (void)loadImageForArticleItem:(ContentSuggestionsArticleItem*)articleItem { | |
| 202 NSInteger sectionIdentifier = | |
| 203 SectionIdentifierForInfo(articleItem.suggestionIdentifier.sectionInfo); | |
| 204 | |
| 205 __weak ContentSuggestionsCollectionUpdater* weakSelf = self; | |
| 206 __weak ContentSuggestionsArticleItem* weakArticle = articleItem; | |
| 207 void (^imageFetchedCallback)(const gfx::Image&) = ^(const gfx::Image& image) { | |
| 208 if (image.IsEmpty()) { | |
| 209 return; | |
| 210 } | |
| 211 | |
| 212 ContentSuggestionsCollectionUpdater* strongSelf = weakSelf; | |
| 213 ContentSuggestionsArticleItem* strongArticle = weakArticle; | |
| 214 if (!strongSelf || !strongArticle) { | |
| 215 return; | |
| 216 } | |
| 217 | |
| 218 strongArticle.image = image.CopyUIImage(); | |
| 219 [strongSelf.collectionViewController | |
| 220 reconfigureCellsForItems:@[ strongArticle ] | |
| 221 inSectionWithIdentifier:sectionIdentifier]; | |
| 222 }; | |
| 223 | |
| 224 [self.dataSource.imageFetcher | |
| 225 fetchImageForSuggestion:articleItem.suggestionIdentifier | |
| 226 callback:imageFetchedCallback]; | |
| 227 } | |
| 228 | |
| 229 #pragma mark - Private methods | |
| 230 | |
| 231 // Add the |suggestions| to the model and reload the data. | |
| 232 - (void)addSuggestions:(NSArray<ContentSuggestion*>*)suggestions { | |
| 233 if (suggestions.count == 0) { | 196 if (suggestions.count == 0) { |
| 234 return; | 197 return [NSArray array]; |
| 235 } | 198 } |
| 236 | 199 |
| 237 CollectionViewModel* model = | 200 CollectionViewModel* model = |
| 238 self.collectionViewController.collectionViewModel; | 201 self.collectionViewController.collectionViewModel; |
| 239 | 202 |
| 203 NSMutableArray<NSIndexPath*>* indexPaths = [NSMutableArray array]; |
| 240 for (ContentSuggestion* suggestion in suggestions) { | 204 for (ContentSuggestion* suggestion in suggestions) { |
| 241 NSInteger sectionIdentifier = | 205 NSInteger sectionIdentifier = |
| 242 [self addSectionIfNeeded:suggestion.suggestionIdentifier.sectionInfo]; | 206 SectionIdentifierForInfo(suggestion.suggestionIdentifier.sectionInfo); |
| 207 |
| 243 ContentSuggestionsArticleItem* articleItem = | 208 ContentSuggestionsArticleItem* articleItem = |
| 244 [[ContentSuggestionsArticleItem alloc] | 209 [[ContentSuggestionsArticleItem alloc] |
| 245 initWithType:ItemTypeForContentSuggestionType(suggestion.type) | 210 initWithType:ItemTypeForContentSuggestionType(suggestion.type) |
| 246 title:suggestion.title | 211 title:suggestion.title |
| 247 subtitle:suggestion.text | 212 subtitle:suggestion.text |
| 248 delegate:self | 213 delegate:self |
| 249 url:suggestion.url]; | 214 url:suggestion.url]; |
| 250 | 215 |
| 251 articleItem.publisher = suggestion.publisher; | 216 articleItem.publisher = suggestion.publisher; |
| 252 articleItem.publishDate = suggestion.publishDate; | 217 articleItem.publishDate = suggestion.publishDate; |
| 253 | 218 |
| 254 articleItem.suggestionIdentifier = suggestion.suggestionIdentifier; | 219 articleItem.suggestionIdentifier = suggestion.suggestionIdentifier; |
| 255 | 220 |
| 221 NSInteger section = [model sectionForSectionIdentifier:sectionIdentifier]; |
| 222 NSInteger itemNumber = [model numberOfItemsInSection:section]; |
| 256 [model addItem:articleItem toSectionWithIdentifier:sectionIdentifier]; | 223 [model addItem:articleItem toSectionWithIdentifier:sectionIdentifier]; |
| 224 |
| 225 [indexPaths |
| 226 addObject:[NSIndexPath indexPathForItem:itemNumber inSection:section]]; |
| 257 } | 227 } |
| 258 | 228 |
| 259 if ([self.collectionViewController isViewLoaded]) { | 229 return indexPaths; |
| 260 [self.collectionViewController.collectionView reloadData]; | |
| 261 } | |
| 262 } | 230 } |
| 263 | 231 |
| 264 - (NSInteger)addSectionIfNeeded: | 232 - (NSIndexSet*)addSectionsForSuggestionsToModel: |
| 265 (ContentSuggestionsSectionInformation*)sectionInformation { | 233 (NSArray<ContentSuggestion*>*)suggestions { |
| 266 NSInteger sectionIdentifier = SectionIdentifierForInfo(sectionInformation); | 234 NSMutableIndexSet* indexSet = [NSMutableIndexSet indexSet]; |
| 267 | 235 |
| 268 CollectionViewModel* model = | 236 CollectionViewModel* model = |
| 269 self.collectionViewController.collectionViewModel; | 237 self.collectionViewController.collectionViewModel; |
| 270 if (![model hasSectionForSectionIdentifier:sectionIdentifier]) { | 238 for (ContentSuggestion* suggestion in suggestions) { |
| 271 [model addSectionWithIdentifier:sectionIdentifier]; | 239 ContentSuggestionsSectionInformation* sectionInfo = |
| 272 self.sectionInfoBySectionIdentifier[@(sectionIdentifier)] = | 240 suggestion.suggestionIdentifier.sectionInfo; |
| 273 sectionInformation; | 241 NSInteger sectionIdentifier = SectionIdentifierForInfo(sectionInfo); |
| 274 [self.sectionInfoBySectionIdentifier setObject:sectionInformation | 242 |
| 275 forKey:@(sectionIdentifier)]; | 243 if (![model hasSectionForSectionIdentifier:sectionIdentifier]) { |
| 244 [model addSectionWithIdentifier:sectionIdentifier]; |
| 245 self.sectionInfoBySectionIdentifier[@(sectionIdentifier)] = sectionInfo; |
| 246 [indexSet addIndex:[model sectionForSectionIdentifier:sectionIdentifier]]; |
| 247 } |
| 276 } | 248 } |
| 277 return sectionIdentifier; | 249 return indexSet; |
| 278 } | 250 } |
| 279 | 251 |
| 252 #pragma mark - ContentSuggestionsArticleItemDelegate |
| 253 |
| 254 - (void)loadImageForArticleItem:(ContentSuggestionsArticleItem*)articleItem { |
| 255 NSInteger sectionIdentifier = |
| 256 SectionIdentifierForInfo(articleItem.suggestionIdentifier.sectionInfo); |
| 257 |
| 258 __weak ContentSuggestionsCollectionUpdater* weakSelf = self; |
| 259 __weak ContentSuggestionsArticleItem* weakArticle = articleItem; |
| 260 void (^imageFetchedCallback)(const gfx::Image&) = ^(const gfx::Image& image) { |
| 261 if (image.IsEmpty()) { |
| 262 return; |
| 263 } |
| 264 |
| 265 ContentSuggestionsCollectionUpdater* strongSelf = weakSelf; |
| 266 ContentSuggestionsArticleItem* strongArticle = weakArticle; |
| 267 if (!strongSelf || !strongArticle) { |
| 268 return; |
| 269 } |
| 270 |
| 271 strongArticle.image = image.CopyUIImage(); |
| 272 [strongSelf.collectionViewController |
| 273 reconfigureCellsForItems:@[ strongArticle ] |
| 274 inSectionWithIdentifier:sectionIdentifier]; |
| 275 }; |
| 276 |
| 277 [self.dataSource.imageFetcher |
| 278 fetchImageForSuggestion:articleItem.suggestionIdentifier |
| 279 callback:imageFetchedCallback]; |
| 280 } |
| 281 |
| 282 #pragma mark - Private methods |
| 283 |
| 284 // Resets the models, removing the current CollectionViewItem and the |
| 285 // SectionInfo. |
| 280 - (void)resetModels { | 286 - (void)resetModels { |
| 281 [self.collectionViewController loadModel]; | 287 [self.collectionViewController loadModel]; |
| 282 self.sectionInfoBySectionIdentifier = [[NSMutableDictionary alloc] init]; | 288 self.sectionInfoBySectionIdentifier = [[NSMutableDictionary alloc] init]; |
| 283 } | 289 } |
| 284 | 290 |
| 285 @end | 291 @end |
| OLD | NEW |