| Index: ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
|
| diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
|
| index ebdb7007a1e70f306d318cbdad9728e0a65ea54c..3165db95b76ae5dcbb6f64f1b20ee182bc595e3b 100644
|
| --- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
|
| +++ b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
|
| @@ -85,6 +85,11 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| AlertCoordinator* _actionSheet;
|
| std::unique_ptr<ReadingListModelBridge> _modelBridge;
|
| UIView* _emptyCollectionBackground;
|
| +
|
| + // Whether the model modifications should be taken into account.
|
| + BOOL _shouldMonitorModel;
|
| + // Whether the model has pending modifications.
|
| + BOOL _modelHasBeenModified;
|
| }
|
|
|
| // Lazily instantiated.
|
| @@ -101,9 +106,21 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| // of the map key.
|
| - (void)loadItemsFromMap:(const ItemsMapByDate&)map
|
| toSection:(SectionIdentifier)sectionIdentifier;
|
| +// Whether the model has changed.
|
| +- (BOOL)hasModelChanged;
|
| +// Returns whether there is a difference between the elements contained in the
|
| +// |sectionIdentifier| and those in the |map|.
|
| +- (BOOL)section:(SectionIdentifier)sectionIdentifier
|
| + isDifferentOfMap:(ItemsMapByDate&)map;
|
| +// Reloads the data if a changed occured during editing
|
| +- (void)applyPendingUpdates;
|
| // Convenience method to create cell items for reading list entries.
|
| - (ReadingListCollectionViewItem*)cellItemForReadingListEntry:
|
| (const ReadingListEntry&)entry;
|
| +// Fills the |unread_map| and the |read_map| with the corresponding
|
| +// ReadingListCollectionViewItem from the readingListModel.
|
| +- (void)fillUnreadMap:(ItemsMapByDate&)unread_map
|
| + readMap:(ItemsMapByDate&)read_map;
|
| // Returns whether there are elements in the section identified by
|
| // |sectionIdentifier|.
|
| - (BOOL)hasItemInSection:(SectionIdentifier)sectionIdentifier;
|
| @@ -135,7 +152,8 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| // Applies |action| to every cell in the section |identifier|.
|
| - (void)updateItemsInSectionIdentifier:(SectionIdentifier)identifier
|
| usingEntryUpdater:(EntryUpdater)updater;
|
| -// Applies |action| to every selected element of collection view.
|
| +// Applies |action| to every selected element of collection view. The monitoring
|
| +// of the model updates is stopped during this time.
|
| - (void)updateSelectedItemsWithEntryUpdater:(EntryUpdater)updater;
|
| // Logs the deletions histograms for the entry with |url|.
|
| - (void)logDeletionHistogramsForEntry:(const GURL&)url;
|
| @@ -187,6 +205,9 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| _readingListDownloadService = readingListDownloadService;
|
| _emptyCollectionBackground = [self emptyCollectionBackground];
|
|
|
| + _shouldMonitorModel = YES;
|
| + _modelHasBeenModified = NO;
|
| +
|
| _modelBridge.reset(new ReadingListModelBridge(self, model));
|
| }
|
| return self;
|
| @@ -312,22 +333,33 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| }
|
|
|
| - (void)readingListModelDidApplyChanges:(const ReadingListModel*)model {
|
| - // Ignore model updates when the view controller is being edited or doing
|
| - // batch updates.
|
| - if (model->IsPerformingBatchUpdates() || [self.editor isEditing]) {
|
| + if (!_shouldMonitorModel) {
|
| + return;
|
| + }
|
| +
|
| + // If we are editing and monitoring the model updates, set a flag to reload
|
| + // the data at the end of the editing.
|
| + if ([self.editor isEditing]) {
|
| + _modelHasBeenModified = YES;
|
| return;
|
| }
|
|
|
| - [self reloadData];
|
| + // Ignore model updates when the view controller is doing batch updates.
|
| + if (model->IsPerformingBatchUpdates()) {
|
| + return;
|
| + }
|
| +
|
| + if ([self hasModelChanged])
|
| + [self reloadData];
|
| }
|
|
|
| - (void)readingListModelCompletedBatchUpdates:(const ReadingListModel*)model {
|
| - // Ignore model updates when the view controller is being edited.
|
| - if ([self.editor isEditing]) {
|
| + if (!_shouldMonitorModel) {
|
| return;
|
| }
|
|
|
| - [self reloadData];
|
| + if ([self hasModelChanged])
|
| + [self reloadData];
|
| }
|
|
|
| #pragma mark - private methods
|
| @@ -485,6 +517,16 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| - (void)loadItems {
|
| ItemsMapByDate read_map;
|
| ItemsMapByDate unread_map;
|
| + [self fillUnreadMap:unread_map readMap:read_map];
|
| + [self loadItemsFromMap:unread_map toSection:SectionIdentifierUnread];
|
| + [self loadItemsFromMap:read_map toSection:SectionIdentifierRead];
|
| +
|
| + BOOL hasRead = read_map.size() > 0;
|
| + [_toolbar setHasReadItem:hasRead];
|
| +}
|
| +
|
| +- (void)fillUnreadMap:(ItemsMapByDate&)unread_map
|
| + readMap:(ItemsMapByDate&)read_map {
|
| for (const auto& url : self.readingListModel->Keys()) {
|
| const ReadingListEntry* entry = self.readingListModel->GetEntryByURL(url);
|
| ReadingListCollectionViewItem* item =
|
| @@ -495,11 +537,6 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| unread_map.insert(std::make_pair(entry->UpdateTime(), item));
|
| }
|
| }
|
| - [self loadItemsFromMap:unread_map toSection:SectionIdentifierUnread];
|
| - [self loadItemsFromMap:read_map toSection:SectionIdentifierRead];
|
| -
|
| - BOOL hasRead = read_map.size() > 0;
|
| - [_toolbar setHasReadItem:hasRead];
|
| }
|
|
|
| - (void)reloadData {
|
| @@ -509,6 +546,55 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| }
|
| }
|
|
|
| +- (void)applyPendingUpdates {
|
| + if (_modelHasBeenModified) {
|
| + [self reloadData];
|
| + }
|
| +}
|
| +
|
| +- (BOOL)hasModelChanged {
|
| + ItemsMapByDate read_map;
|
| + ItemsMapByDate unread_map;
|
| + [self fillUnreadMap:unread_map readMap:read_map];
|
| +
|
| + if ([self section:SectionIdentifierRead isDifferentOfMap:read_map])
|
| + return YES;
|
| + if ([self section:SectionIdentifierUnread isDifferentOfMap:unread_map])
|
| + return YES;
|
| +
|
| + return NO;
|
| +}
|
| +
|
| +- (BOOL)section:(SectionIdentifier)sectionIdentifier
|
| + isDifferentOfMap:(ItemsMapByDate&)map {
|
| + if (![self.collectionViewModel
|
| + hasSectionForSectionIdentifier:sectionIdentifier]) {
|
| + return !map.empty();
|
| + }
|
| +
|
| + NSArray* items =
|
| + [self.collectionViewModel itemsInSectionWithIdentifier:sectionIdentifier];
|
| + if ([items count] != map.size())
|
| + return NO;
|
| +
|
| + NSInteger index = 0;
|
| + ItemsMapByDate::const_reverse_iterator iterator = map.rbegin();
|
| + for (; iterator != map.rend(); iterator++) {
|
| + ReadingListCollectionViewItem* oldItem =
|
| + base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(items[index]);
|
| + ReadingListCollectionViewItem* newItem = iterator->second;
|
| + if (oldItem.url == newItem.url) {
|
| + oldItem.text = newItem.text;
|
| + oldItem.distillationState = newItem.distillationState;
|
| + }
|
| + if (![oldItem isEqual:newItem]) {
|
| + return YES;
|
| + }
|
| + index++;
|
| + }
|
| + return NO;
|
| +}
|
| +
|
| - (ReadingListCollectionViewItem*)cellItemForReadingListEntry:
|
| (const ReadingListEntry&)entry {
|
| GURL url = entry.URL();
|
| @@ -761,7 +847,7 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| }
|
| completion:^(BOOL) {
|
| // Reload data to take into account possible sync events.
|
| - [self reloadData];
|
| + [self applyPendingUpdates];
|
| }];
|
| // As we modified the section in the batch update block, remove the section in
|
| // another block.
|
| @@ -785,7 +871,7 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| }
|
| completion:^(BOOL) {
|
| // Reload data to take into account possible sync events.
|
| - [self reloadData];
|
| + [self applyPendingUpdates];
|
| }];
|
| // As we modified the section in the batch update block, remove the section in
|
| // another block.
|
| @@ -806,6 +892,7 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| }
|
|
|
| - (void)updateSelectedItemsWithEntryUpdater:(EntryUpdater)updater {
|
| + _shouldMonitorModel = NO;
|
| auto token = self.readingListModel->BeginBatchUpdates();
|
| for (NSIndexPath* index in self.collectionView.indexPathsForSelectedItems) {
|
| CollectionViewItem* cell = [self.collectionViewModel itemAtIndexPath:index];
|
| @@ -814,6 +901,9 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| if (updater)
|
| updater(readingListItem.url);
|
| }
|
| + // Leave the batch update while it is not monitored.
|
| + token.reset();
|
| + _shouldMonitorModel = YES;
|
| }
|
|
|
| - (void)logDeletionHistogramsForEntry:(const GURL&)url {
|
| @@ -873,7 +963,7 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| }
|
| completion:^(BOOL) {
|
| // Reload data to take into account possible sync events.
|
| - [self reloadData];
|
| + [self applyPendingUpdates];
|
| }];
|
| // As we modified the section in the batch update block, remove the section in
|
| // another block.
|
| @@ -920,7 +1010,7 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>;
|
| }
|
| completion:^(BOOL) {
|
| // Reload data to take into account possible sync events.
|
| - [self reloadData];
|
| + [self applyPendingUpdates];
|
| }];
|
| // As we modified the section in the batch update block, remove the section in
|
| // another block.
|
|
|