Index: ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm |
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm |
index 627c577169fa88d4241d353db93dd0513a9e0b30..45ddedcb46aa2cbe98740f295fb18d39eb02665a 100644 |
--- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm |
+++ b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm |
@@ -25,10 +25,12 @@ |
#import "ios/chrome/browser/ui/favicon_view.h" |
#import "ios/chrome/browser/ui/material_components/utils.h" |
#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" |
+#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item_accessibility_delegate.h" |
#import "ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h" |
#import "ios/chrome/browser/ui/reading_list/reading_list_toolbar.h" |
#import "ios/chrome/browser/ui/uikit_ui_util.h" |
#include "ios/chrome/browser/ui/url_loader.h" |
+#import "ios/chrome/browser/ui/util/pasteboard_util.h" |
#include "ios/chrome/grit/ios_strings.h" |
#import "ios/third_party/material_components_ios/src/components/AppBar/src/MaterialAppBar.h" |
#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" |
@@ -65,7 +67,8 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>; |
} |
@interface ReadingListCollectionViewController ()< |
- ReadingListModelBridgeObserver> { |
+ ReadingListModelBridgeObserver, |
+ ReadingListCollectionViewItemAccessibilityDelegate> { |
// Toolbar with the actions. |
ReadingListToolbar* _toolbar; |
// Action sheet presenting the subactions of the toolbar. |
@@ -116,6 +119,10 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>; |
- (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer; |
// Stops observing the ReadingListModel. |
- (void)stopObservingReadingListModel; |
+// Returns the ReadingListEntry associated with the |item|. If there is not such |
+// an entry, returns nullptr and reloads the UI. |
+- (const ReadingListEntry*)readingListEntryForItem: |
+ (ReadingListCollectionViewItem*)item; |
// Updates the toolbar state according to the selected items. |
- (void)updateToolbarState; |
// Displays an action sheet to let the user choose to mark all the elements as |
@@ -134,7 +141,7 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>; |
- (void)markItemsUnreadAtIndexPath:(NSArray*)indexPaths; |
// Deletes all the read items. |
- (void)deleteAllReadItems; |
-// Deletes all the items at |indexPaths|. |
+// Deletes all the items at |indexPath|. |
- (void)deleteItemsAtIndexPaths:(NSArray*)indexPaths; |
// Initializes |_actionSheet| with |self| as base view controller, and the |
// toolbar's mark button as anchor point. |
@@ -392,6 +399,100 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>; |
[_actionSheet stop]; |
} |
+#pragma mark - ReadingListCollectionViewItemAccessibilityDelegate |
+ |
+- (BOOL)isEntryRead:(ReadingListCollectionViewItem*)entry { |
+ const ReadingListEntry* readingListEntry = |
+ [self readingListEntryForItem:entry]; |
+ |
+ if (!readingListEntry) { |
+ return NO; |
+ } |
+ |
+ return readingListEntry->IsRead(); |
+} |
+ |
+- (void)deleteEntry:(ReadingListCollectionViewItem*)entry { |
+ const ReadingListEntry* readingListEntry = |
+ [self readingListEntryForItem:entry]; |
+ |
+ if (!readingListEntry) { |
+ return; |
+ } |
+ |
+ SectionIdentifier sectionIdentifier = SectionIdentifierUnread; |
+ if (readingListEntry->IsRead()) { |
+ sectionIdentifier = SectionIdentifierRead; |
+ } |
+ if (![self.collectionViewModel hasItem:entry |
+ inSectionWithIdentifier:sectionIdentifier]) { |
+ return; |
+ } |
+ |
+ [self |
+ deleteItemsAtIndexPaths:@[ [self.collectionViewModel |
+ indexPathForItem:entry |
+ inSectionWithIdentifier:sectionIdentifier] ]]; |
+} |
+ |
+- (void)openEntryInNewTab:(ReadingListCollectionViewItem*)entry { |
+ [self.delegate readingListCollectionViewController:self |
+ openNewTabWithURL:entry.url |
+ incognito:NO]; |
+} |
+ |
+- (void)openEntryInNewIncognitoTab:(ReadingListCollectionViewItem*)entry { |
+ [self.delegate readingListCollectionViewController:self |
+ openNewTabWithURL:entry.url |
+ incognito:YES]; |
+} |
+ |
+- (void)copyEntryURL:(ReadingListCollectionViewItem*)entry { |
+ StoreURLInPasteboard(entry.url); |
+} |
+ |
+- (void)openEntryOffline:(ReadingListCollectionViewItem*)entry { |
+ const ReadingListEntry* readingListEntry = |
+ [self readingListEntryForItem:entry]; |
+ |
+ if (!readingListEntry) { |
+ return; |
+ } |
+ |
+ if (readingListEntry->DistilledState() == ReadingListEntry::PROCESSED) { |
+ const GURL entryURL = readingListEntry->URL(); |
+ GURL offlineURL = reading_list::OfflineURLForPath( |
+ readingListEntry->DistilledPath(), entryURL, |
+ readingListEntry->DistilledURL()); |
+ |
+ [self.delegate readingListCollectionViewController:self |
+ openOfflineURL:offlineURL |
+ correspondingEntryURL:entryURL]; |
+ } |
+} |
+ |
+- (void)markEntryRead:(ReadingListCollectionViewItem*)entry { |
+ if (![self.collectionViewModel hasItem:entry |
+ inSectionWithIdentifier:SectionIdentifierUnread]) { |
+ return; |
+ } |
+ [self markItemsReadAtIndexPath:@[ |
+ [self.collectionViewModel indexPathForItem:entry |
+ inSectionWithIdentifier:SectionIdentifierUnread] |
+ ]]; |
+} |
+ |
+- (void)markEntryUnread:(ReadingListCollectionViewItem*)entry { |
+ if (![self.collectionViewModel hasItem:entry |
+ inSectionWithIdentifier:SectionIdentifierRead]) { |
+ return; |
+ } |
+ [self markItemsUnreadAtIndexPath:@[ |
+ [self.collectionViewModel indexPathForItem:entry |
+ inSectionWithIdentifier:SectionIdentifierRead] |
+ ]]; |
+} |
+ |
#pragma mark - Private methods |
- (void)donePressed { |
@@ -451,6 +552,7 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>; |
const ReadingListEntry* entry = self.readingListModel->GetEntryByURL(url); |
ReadingListCollectionViewItem* item = |
[self cellItemForReadingListEntry:*entry]; |
+ item.accessibilityDelegate = self; |
if (entry->IsRead()) { |
read_map.insert(std::make_pair(entry->UpdateTime(), item)); |
} else { |
@@ -588,6 +690,20 @@ using ItemsMapByDate = std::multimap<int64_t, ReadingListCollectionViewItem*>; |
_modelBridge.reset(); |
} |
+- (const ReadingListEntry*)readingListEntryForItem: |
+ (ReadingListCollectionViewItem*)item { |
+ const ReadingListEntry* readingListEntry = |
+ self.readingListModel->GetEntryByURL(item.url); |
+ |
+ if (!readingListEntry) { |
+ // The entry has been removed from the model, reload all data to synchronize |
+ // the UI with the model. |
+ [self reloadData]; |
+ } |
+ |
+ return readingListEntry; |
+} |
+ |
#pragma mark - ReadingListToolbarDelegate |
- (void)markPressed { |