Commit 7405f12a authored by gambard's avatar gambard Committed by Commit Bot

Add AccessibilityCustomAction to ContentSuggestions

In order to have the feature accessible, all the actions using gestures
(long press, swipe to dismiss) must have custom accessibility actions.
Also adds action sheet to Read Later cells.

Bug: 749131
Change-Id: I2c81f6443a49bdf0cdccc3ec747b0ffd42513ef1
Reviewed-on: https://chromium-review.googlesource.com/593652
Commit-Queue: Gauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarJean-François Geyelin <jif@chromium.org>
Cr-Commit-Position: refs/heads/master@{#490930}
parent 12af7241
......@@ -5,7 +5,6 @@
source_set("content_suggestions") {
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
"content_suggestions_alert_commands.h",
"content_suggestions_alert_factory.h",
"content_suggestions_alert_factory.mm",
"content_suggestions_category_wrapper.h",
......@@ -94,6 +93,7 @@ source_set("eg_tests") {
"//ios/chrome/browser/ui/alert_coordinator",
"//ios/chrome/browser/ui/alert_coordinator",
"//ios/chrome/browser/ui/collection_view/cells",
"//ios/chrome/browser/ui/content_suggestions/cells",
"//ios/chrome/browser/ui/util",
"//ios/chrome/test/earl_grey:test_support",
"//ui/strings",
......
......@@ -7,9 +7,9 @@
#import <EarlGrey/EarlGrey.h>
#import <XCTest/XCTest.h>
#import "ios/chrome/browser/content_suggestions/content_suggestions_alert_commands.h"
#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h"
#include "ios/chrome/browser/ui/ui_util.h"
#import "ios/chrome/browser/ui/util/top_view_controller.h"
#include "ios/chrome/grit/ios_strings.h"
......@@ -35,6 +35,7 @@
onViewController:viewController
atPoint:CGPointMake(50, 50)
atIndexPath:nil
readLaterAction:YES
commandHandler:nil];
[coordinator start];
......@@ -67,11 +68,11 @@
UIViewController* viewController =
top_view_controller::TopPresentedViewController();
AlertCoordinator* coordinator = [ContentSuggestionsAlertFactory
alertCoordinatorForSuggestionItem:nil
onViewController:viewController
atPoint:CGPointMake(50, 50)
atIndexPath:nil
commandHandler:nil];
alertCoordinatorForMostVisitedItem:nil
onViewController:viewController
atPoint:CGPointMake(50, 50)
atIndexPath:nil
commandHandler:nil];
[coordinator start];
[[EarlGrey
......
......@@ -8,8 +8,9 @@
#import <UIKit/UIKit.h>
@class AlertCoordinator;
@class CollectionViewItem;
@protocol ContentSuggestionsAlertCommands;
@class ContentSuggestionsItem;
@class ContentSuggestionsMostVisitedItem;
@protocol ContentSuggestionsGestureCommands;
// Factory for AlertCoordinators for ContentSuggestions.
@interface ContentSuggestionsAlertFactory : NSObject
......@@ -20,21 +21,22 @@
// |commandHandler| will receive callbacks when the user chooses one of the
// options displayed by the alert.
+ (AlertCoordinator*)
alertCoordinatorForSuggestionItem:(CollectionViewItem*)item
alertCoordinatorForSuggestionItem:(ContentSuggestionsItem*)item
onViewController:(UIViewController*)viewController
atPoint:(CGPoint)touchLocation
atIndexPath:(NSIndexPath*)indexPath
readLaterAction:(BOOL)readLaterAction
commandHandler:
(id<ContentSuggestionsAlertCommands>)commandHandler;
(id<ContentSuggestionsGestureCommands>)commandHandler;
// Same as above but for a MostVisited item.
+ (AlertCoordinator*)
alertCoordinatorForMostVisitedItem:(CollectionViewItem*)item
alertCoordinatorForMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item
onViewController:(UIViewController*)viewController
atPoint:(CGPoint)touchLocation
atIndexPath:(NSIndexPath*)indexPath
commandHandler:
(id<ContentSuggestionsAlertCommands>)commandHandler;
(id<ContentSuggestionsGestureCommands>)commandHandler;
@end
......
......@@ -4,9 +4,10 @@
#import "ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.h"
#import "ios/chrome/browser/content_suggestions/content_suggestions_alert_commands.h"
#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/strings/grit/ui_strings.h"
......@@ -18,12 +19,13 @@
@implementation ContentSuggestionsAlertFactory
+ (AlertCoordinator*)
alertCoordinatorForSuggestionItem:(CollectionViewItem*)item
alertCoordinatorForSuggestionItem:(ContentSuggestionsItem*)item
onViewController:(UIViewController*)viewController
atPoint:(CGPoint)touchLocation
atIndexPath:(NSIndexPath*)indexPath
readLaterAction:(BOOL)readLaterAction
commandHandler:
(id<ContentSuggestionsAlertCommands>)commandHandler {
(id<ContentSuggestionsGestureCommands>)commandHandler {
AlertCoordinator* alertCoordinator = [[ActionSheetCoordinator alloc]
initWithBaseViewController:viewController
title:nil
......@@ -32,15 +34,15 @@ alertCoordinatorForSuggestionItem:(CollectionViewItem*)item
0)
view:[viewController view]];
__weak CollectionViewItem* weakItem = item;
__weak id<ContentSuggestionsAlertCommands> weakCommandHandler =
__weak ContentSuggestionsItem* weakItem = item;
__weak id<ContentSuggestionsGestureCommands> weakCommandHandler =
commandHandler;
NSString* openInNewTabTitle =
l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB);
[alertCoordinator addItemWithTitle:openInNewTabTitle
action:^{
CollectionViewItem* strongItem = weakItem;
ContentSuggestionsItem* strongItem = weakItem;
if (strongItem) {
// TODO(crbug.com/691979): Add metrics.
[weakCommandHandler
......@@ -54,7 +56,7 @@ alertCoordinatorForSuggestionItem:(CollectionViewItem*)item
l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB);
[alertCoordinator addItemWithTitle:openInNewTabIncognitoTitle
action:^{
CollectionViewItem* strongItem = weakItem;
ContentSuggestionsItem* strongItem = weakItem;
if (strongItem) {
// TODO(crbug.com/691979): Add metrics.
[weakCommandHandler
......@@ -64,24 +66,26 @@ alertCoordinatorForSuggestionItem:(CollectionViewItem*)item
}
style:UIAlertActionStyleDefault];
NSString* readLaterTitle =
l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_ADDTOREADINGLIST);
[alertCoordinator
addItemWithTitle:readLaterTitle
action:^{
CollectionViewItem* strongItem = weakItem;
if (strongItem) {
// TODO(crbug.com/691979): Add metrics.
[weakCommandHandler addItemToReadingList:strongItem];
if (readLaterAction) {
NSString* readLaterTitle =
l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_ADDTOREADINGLIST);
[alertCoordinator
addItemWithTitle:readLaterTitle
action:^{
ContentSuggestionsItem* strongItem = weakItem;
if (strongItem) {
// TODO(crbug.com/691979): Add metrics.
[weakCommandHandler addItemToReadingList:strongItem];
}
}
}
style:UIAlertActionStyleDefault];
style:UIAlertActionStyleDefault];
}
NSString* deleteTitle =
l10n_util::GetNSString(IDS_IOS_CONTENT_SUGGESTIONS_REMOVE);
[alertCoordinator addItemWithTitle:deleteTitle
action:^{
CollectionViewItem* strongItem = weakItem;
ContentSuggestionsItem* strongItem = weakItem;
if (strongItem) {
// TODO(crbug.com/691979): Add metrics.
[weakCommandHandler
......@@ -100,12 +104,12 @@ alertCoordinatorForSuggestionItem:(CollectionViewItem*)item
}
+ (AlertCoordinator*)
alertCoordinatorForMostVisitedItem:(CollectionViewItem*)item
alertCoordinatorForMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item
onViewController:(UIViewController*)viewController
atPoint:(CGPoint)touchLocation
atIndexPath:(NSIndexPath*)indexPath
commandHandler:
(id<ContentSuggestionsAlertCommands>)commandHandler {
(id<ContentSuggestionsGestureCommands>)commandHandler {
AlertCoordinator* alertCoordinator = [[ActionSheetCoordinator alloc]
initWithBaseViewController:viewController
title:nil
......@@ -114,15 +118,15 @@ alertCoordinatorForMostVisitedItem:(CollectionViewItem*)item
0)
view:[viewController view]];
__weak CollectionViewItem* weakItem = item;
__weak id<ContentSuggestionsAlertCommands> weakCommandHandler =
__weak ContentSuggestionsMostVisitedItem* weakItem = item;
__weak id<ContentSuggestionsGestureCommands> weakCommandHandler =
commandHandler;
[alertCoordinator
addItemWithTitle:l10n_util::GetNSStringWithFixup(
IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)
action:^{
CollectionViewItem* strongItem = weakItem;
ContentSuggestionsMostVisitedItem* strongItem = weakItem;
if (strongItem) {
[weakCommandHandler
openNewTabWithMostVisitedItem:strongItem
......@@ -136,7 +140,7 @@ alertCoordinatorForMostVisitedItem:(CollectionViewItem*)item
addItemWithTitle:l10n_util::GetNSStringWithFixup(
IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB)
action:^{
CollectionViewItem* strongItem = weakItem;
ContentSuggestionsMostVisitedItem* strongItem = weakItem;
if (strongItem) {
[weakCommandHandler
openNewTabWithMostVisitedItem:strongItem
......@@ -150,7 +154,7 @@ alertCoordinatorForMostVisitedItem:(CollectionViewItem*)item
addItemWithTitle:l10n_util::GetNSStringWithFixup(
IDS_IOS_CONTENT_SUGGESTIONS_REMOVE)
action:^{
CollectionViewItem* strongItem = weakItem;
ContentSuggestionsMostVisitedItem* strongItem = weakItem;
if (strongItem) {
[weakCommandHandler removeMostVisited:strongItem];
}
......
......@@ -16,7 +16,6 @@
#include "components/reading_list/core/reading_list_model.h"
#include "components/strings/grit/components_strings.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/content_suggestions/content_suggestions_alert_commands.h"
#import "ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.h"
#import "ios/chrome/browser/content_suggestions/content_suggestions_header_view_controller.h"
#import "ios/chrome/browser/content_suggestions/content_suggestions_header_view_controller_delegate.h"
......@@ -34,6 +33,7 @@
#import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
#include "ios/chrome/browser/ui/commands/ios_command_ids.h"
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h"
......@@ -65,8 +65,8 @@ const char kNTPHelpURL[] = "https://support.google.com/chrome/?p=new_tab";
} // namespace
@interface ContentSuggestionsCoordinator ()<
ContentSuggestionsAlertCommands,
ContentSuggestionsCommands,
ContentSuggestionsGestureCommands,
ContentSuggestionsHeaderViewControllerCommandHandler,
ContentSuggestionsViewControllerAudience,
ContentSuggestionsViewControllerDelegate,
......@@ -211,14 +211,18 @@ const char kNTPHelpURL[] = "https://support.google.com/chrome/?p=new_tab";
rendererInitiated:NO];
}
- (void)displayContextMenuForArticle:(CollectionViewItem*)item
atPoint:(CGPoint)touchLocation
atIndexPath:(NSIndexPath*)indexPath {
- (void)displayContextMenuForSuggestion:(CollectionViewItem*)item
atPoint:(CGPoint)touchLocation
atIndexPath:(NSIndexPath*)indexPath
readLaterAction:(BOOL)readLaterAction {
ContentSuggestionsItem* suggestionsItem =
base::mac::ObjCCastStrict<ContentSuggestionsItem>(item);
self.alertCoordinator = [ContentSuggestionsAlertFactory
alertCoordinatorForSuggestionItem:item
alertCoordinatorForSuggestionItem:suggestionsItem
onViewController:self.suggestionsViewController
atPoint:touchLocation
atIndexPath:indexPath
readLaterAction:readLaterAction
commandHandler:self];
[self.alertCoordinator start];
......@@ -227,8 +231,10 @@ const char kNTPHelpURL[] = "https://support.google.com/chrome/?p=new_tab";
- (void)displayContextMenuForMostVisitedItem:(CollectionViewItem*)item
atPoint:(CGPoint)touchLocation
atIndexPath:(NSIndexPath*)indexPath {
ContentSuggestionsMostVisitedItem* mostVisitedItem =
base::mac::ObjCCastStrict<ContentSuggestionsMostVisitedItem>(item);
self.alertCoordinator = [ContentSuggestionsAlertFactory
alertCoordinatorForMostVisitedItem:item
alertCoordinatorForMostVisitedItem:mostVisitedItem
onViewController:self.suggestionsViewController
atPoint:touchLocation
atIndexPath:indexPath
......@@ -268,52 +274,54 @@ const char kNTPHelpURL[] = "https://support.google.com/chrome/?p=new_tab";
rendererInitiated:NO];
}
#pragma mark - ContentSuggestionsAlertCommands
#pragma mark - ContentSuggestionsGestureCommands
- (void)openNewTabWithSuggestionsItem:(CollectionViewItem*)item
- (void)openNewTabWithSuggestionsItem:(ContentSuggestionsItem*)item
incognito:(BOOL)incognito {
ContentSuggestionsItem* suggestionsItem =
base::mac::ObjCCastStrict<ContentSuggestionsItem>(item);
[self openNewTabWithURL:suggestionsItem.URL incognito:incognito];
[self openNewTabWithURL:item.URL incognito:incognito];
}
- (void)addItemToReadingList:(CollectionViewItem*)item {
ContentSuggestionsItem* suggestionsItem =
base::mac::ObjCCastStrict<ContentSuggestionsItem>(item);
- (void)addItemToReadingList:(ContentSuggestionsItem*)item {
base::RecordAction(base::UserMetricsAction("MobileReadingListAdd"));
ReadingListModel* readingModel =
ReadingListModelFactory::GetForBrowserState(self.browserState);
readingModel->AddEntry(suggestionsItem.URL,
base::SysNSStringToUTF8(suggestionsItem.title),
readingModel->AddEntry(item.URL, base::SysNSStringToUTF8(item.title),
reading_list::ADDED_VIA_CURRENT_APP);
}
- (void)dismissSuggestion:(CollectionViewItem*)item
- (void)dismissSuggestion:(ContentSuggestionsItem*)item
atIndexPath:(NSIndexPath*)indexPath {
ContentSuggestionsItem* suggestionsItem =
base::mac::ObjCCastStrict<ContentSuggestionsItem>(item);
NSIndexPath* itemIndexPath = indexPath;
if (!itemIndexPath) {
// If the caller uses a nil |indexPath|, find it from the model.
itemIndexPath = [self.suggestionsViewController.collectionViewModel
indexPathForItem:item];
}
// TODO(crbug.com/691979): Add metrics.
[self.contentSuggestionsMediator
dismissSuggestion:suggestionsItem.suggestionIdentifier];
[self.suggestionsViewController dismissEntryAtIndexPath:indexPath];
[self.contentSuggestionsMediator dismissSuggestion:item.suggestionIdentifier];
[self.suggestionsViewController dismissEntryAtIndexPath:itemIndexPath];
}
- (void)openNewTabWithMostVisitedItem:(CollectionViewItem*)item
- (void)openNewTabWithMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item
incognito:(BOOL)incognito
atIndex:(NSInteger)index {
ContentSuggestionsMostVisitedItem* mostVisitedItem =
base::mac::ObjCCastStrict<ContentSuggestionsMostVisitedItem>(item);
[self logMostVisitedOpening:mostVisitedItem atIndex:index];
[self openNewTabWithURL:mostVisitedItem.URL incognito:incognito];
[self logMostVisitedOpening:item atIndex:index];
[self openNewTabWithURL:item.URL incognito:incognito];
}
- (void)removeMostVisited:(CollectionViewItem*)item {
ContentSuggestionsMostVisitedItem* mostVisitedItem =
base::mac::ObjCCastStrict<ContentSuggestionsMostVisitedItem>(item);
- (void)openNewTabWithMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item
incognito:(BOOL)incognito {
NSInteger index =
[self.suggestionsViewController.collectionViewModel indexPathForItem:item]
.item;
[self openNewTabWithMostVisitedItem:item incognito:incognito atIndex:index];
}
- (void)removeMostVisited:(ContentSuggestionsMostVisitedItem*)item {
base::RecordAction(base::UserMetricsAction("MostVisited_UrlBlacklisted"));
[self.contentSuggestionsMediator blacklistMostVisitedURL:mostVisitedItem.URL];
[self showMostVisitedUndoForURL:mostVisitedItem.URL];
[self.contentSuggestionsMediator blacklistMostVisitedURL:item.URL];
[self showMostVisitedUndoForURL:item.URL];
}
#pragma mark - ContentSuggestionsViewControllerDelegate
......
......@@ -25,6 +25,7 @@ class MostVisitedSites;
}
@protocol ContentSuggestionsCommands;
@protocol ContentSuggestionsGestureCommands;
@protocol ContentSuggestionsHeaderProvider;
@class ContentSuggestionIdentifier;
class GURL;
......@@ -49,8 +50,9 @@ initWithContentService:
- (nullable instancetype)init NS_UNAVAILABLE;
// Command handler for the mediator.
@property(nonatomic, weak, nullable) id<ContentSuggestionsCommands>
commandHandler;
@property(nonatomic, weak, nullable)
id<ContentSuggestionsCommands, ContentSuggestionsGestureCommands>
commandHandler;
@property(nonatomic, weak, nullable) id<ContentSuggestionsHeaderProvider>
headerProvider;
......
......@@ -452,6 +452,7 @@ initWithContentService:(ntp_snippets::ContentSuggestionsService*)contentService
ContentSuggestionsItem* suggestion =
ConvertSuggestion(contentSuggestion, sectionInfo, category);
suggestion.delegate = self;
suggestion.commandHandler = self.commandHandler;
[self.faviconMediator fetchFaviconForSuggestions:suggestion
inCategory:category];
......
......@@ -64,6 +64,7 @@ ContentSuggestionsItem* ConvertSuggestion(
}
if (category.IsKnownCategory(ntp_snippets::KnownCategories::ARTICLES)) {
suggestion.hasImage = YES;
suggestion.readLaterAction = YES;
}
return suggestion;
......
......@@ -4,6 +4,7 @@
source_set("cells") {
sources = [
"content_suggestions_gesture_commands.h",
"content_suggestions_item.h",
"content_suggestions_item.mm",
"content_suggestions_most_visited_item.h",
......
......@@ -2,38 +2,49 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ALERT_COMMANDS_H_
#define IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ALERT_COMMANDS_H_
#ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_CONTENT_SUGGESTIONS_GESTURE_COMMANDS_H_
#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_CONTENT_SUGGESTIONS_GESTURE_COMMANDS_H_
#import <UIKit/UIKit.h>
@class CollectionViewItem;
@class ContentSuggestionsItem;
@class ContentSuggestionsMostVisitedItem;
// Command protocol for the ContentSuggestionsAlertFactory, handling the
// callbacks from the alerts.
@protocol ContentSuggestionsAlertCommands
// Command protocol for the interactions based on a gesture, handling the
// callbacks from the alerts and the accessibility custom actions.
@protocol ContentSuggestionsGestureCommands
// Opens the URL corresponding to the |item| in a new tab, |incognito| or not.
// The item has to be a suggestion item.
- (void)openNewTabWithSuggestionsItem:(nonnull CollectionViewItem*)item
- (void)openNewTabWithSuggestionsItem:(nonnull ContentSuggestionsItem*)item
incognito:(BOOL)incognito;
// Adds the |item| to the reading list. The item has to be a suggestion item.
- (void)addItemToReadingList:(nonnull CollectionViewItem*)item;
- (void)addItemToReadingList:(nonnull ContentSuggestionsItem*)item;
// Dismiss the |item| at |indexPath|. The item has to be a suggestion item.
- (void)dismissSuggestion:(nonnull CollectionViewItem*)item
atIndexPath:(nonnull NSIndexPath*)indexPath;
// If |indexPath| is nil, the commands handler will find the index path
// associated with the |item|.
- (void)dismissSuggestion:(nonnull ContentSuggestionsItem*)item
atIndexPath:(nullable NSIndexPath*)indexPath;
// Open the URL corresponding to the |item| in a new tab, |incognito| or not.
// The item has to be a Most Visited item.
- (void)openNewTabWithMostVisitedItem:(nonnull CollectionViewItem*)item
- (void)openNewTabWithMostVisitedItem:
(nonnull ContentSuggestionsMostVisitedItem*)item
incognito:(BOOL)incognito
atIndex:(NSInteger)mostVisitedIndex;
// Open the URL corresponding to the |item| in a new tab, |incognito| or not.
// The index of the item will be find by the command handler. The item has to
// be a Most Visited item.
- (void)openNewTabWithMostVisitedItem:
(nonnull ContentSuggestionsMostVisitedItem*)item
incognito:(BOOL)incognito;
// Removes the most visited |item|.
- (void)removeMostVisited:(nonnull CollectionViewItem*)item;
- (void)removeMostVisited:(nonnull ContentSuggestionsMostVisitedItem*)item;
@end
#endif // IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ALERT_COMMANDS_H_
#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_CONTENT_SUGGESTIONS_GESTURE_COMMANDS_H_
......@@ -16,6 +16,8 @@ class Time;
@class FaviconAttributes;
class GURL;
@protocol ContentSuggestionsGestureCommands;
// Delegate for SuggestedContent.
@protocol ContentSuggestionsItemDelegate
......@@ -48,6 +50,10 @@ class GURL;
@property(nonatomic, strong) FaviconAttributes* attributes;
// URL for the favicon, if different of |URL|.
@property(nonatomic, assign) GURL faviconURL;
// Whether this item should have an option to be read later.
@property(nonatomic, assign) BOOL readLaterAction;
// Command handler for the accessibility custom actions.
@property(nonatomic, weak) id<ContentSuggestionsGestureCommands> commandHandler;
@end
......
......@@ -7,6 +7,7 @@
#include "base/strings/sys_string_conversions.h"
#include "base/time/time.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion_identifier.h"
#import "ios/chrome/browser/ui/favicon/favicon_attributes.h"
#import "ios/chrome/browser/ui/favicon/favicon_view.h"
......@@ -46,6 +47,8 @@
@synthesize faviconURL = _faviconURL;
@synthesize hasImage = _hasImage;
@synthesize firstTimeWithImage = _firstTimeWithImage;
@synthesize readLaterAction = _readLaterAction;
@synthesize commandHandler = _commandHandler;
- (instancetype)initWithType:(NSInteger)type
title:(NSString*)title
......@@ -75,6 +78,7 @@
date:[self relativeDate]];
cell.isAccessibilityElement = YES;
cell.accessibilityLabel = [self accessibilityLabel];
cell.accessibilityCustomActions = [self customActions];
}
- (void)setImage:(UIImage*)image {
......@@ -121,4 +125,67 @@
base::SysNSStringToUTF16([self relativeDate]));
}
#pragma mark - AccessibilityCustomAction
// Custom action for a cell configured with this item.
- (NSArray<UIAccessibilityCustomAction*>*)customActions {
UIAccessibilityCustomAction* openInNewTab =
[[UIAccessibilityCustomAction alloc]
initWithName:l10n_util::GetNSString(
IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)
target:self
selector:@selector(openInNewTab)];
UIAccessibilityCustomAction* openInNewIncognitoTab =
[[UIAccessibilityCustomAction alloc]
initWithName:l10n_util::GetNSString(
IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB)
target:self
selector:@selector(openInNewIncognitoTab)];
NSMutableArray* customActions = [NSMutableArray
arrayWithObjects:openInNewTab, openInNewIncognitoTab, nil];
if (self.readLaterAction) {
UIAccessibilityCustomAction* readLater =
[[UIAccessibilityCustomAction alloc]
initWithName:l10n_util::GetNSString(
IDS_IOS_CONTENT_CONTEXT_ADDTOREADINGLIST)
target:self
selector:@selector(readLater)];
[customActions addObject:readLater];
}
UIAccessibilityCustomAction* removeSuggestion = [
[UIAccessibilityCustomAction alloc]
initWithName:l10n_util::GetNSString(IDS_IOS_CONTENT_SUGGESTIONS_REMOVE)
target:self
selector:@selector(removeSuggestion)];
[customActions addObject:removeSuggestion];
return customActions;
}
// Target for custom action.
- (BOOL)openInNewTab {
[self.commandHandler openNewTabWithSuggestionsItem:self incognito:NO];
return YES;
}
// Target for custom action.
- (BOOL)openInNewIncognitoTab {
[self.commandHandler openNewTabWithSuggestionsItem:self incognito:YES];
return YES;
}
// Target for custom action.
- (BOOL)readLater {
[self.commandHandler addItemToReadingList:self];
return YES;
}
// Target for custom action.
- (BOOL)removeSuggestion {
[self.commandHandler dismissSuggestion:self atIndexPath:nil];
return YES;
}
@end
......@@ -37,6 +37,7 @@ TEST(ContentSuggestionsItemTest, CellIsConfiguredWithoutImage) {
item.hasImage = YES;
item.publisher = publisher;
item.publishDate = publishTime;
item.readLaterAction = YES;
OCMExpect([delegateMock loadImageForSuggestedItem:item]);
ContentSuggestionsCell* cell = [[[item cellClass] alloc] init];
ASSERT_EQ([ContentSuggestionsCell class], [cell class]);
......@@ -54,6 +55,7 @@ TEST(ContentSuggestionsItemTest, CellIsConfiguredWithoutImage) {
EXPECT_OCMOCK_VERIFY(cellMock);
EXPECT_EQ(title, cell.titleLabel.text);
EXPECT_OCMOCK_VERIFY(delegateMock);
EXPECT_EQ(4U, [cell.accessibilityCustomActions count]);
}
// Tests that configureCell: does not call the delegate if it fetched the image
......@@ -139,4 +141,24 @@ TEST(ContentSuggestionsItemTest, ImageAnimatedOnlyTheFirstTime) {
EXPECT_OCMOCK_VERIFY(cell1);
EXPECT_OCMOCK_VERIFY(cell2);
}
// Tests the custom actions when there is no read later actions.
TEST(ContentSuggestionsItemTest, NoReadLaterAction) {
// Setup.
NSString* title = @"testTitle";
GURL url = GURL("http://chromium.org");
ContentSuggestionsItem* item =
[[ContentSuggestionsItem alloc] initWithType:0 title:title url:url];
item.readLaterAction = NO;
item.image = [[UIImage alloc] init];
ContentSuggestionsCell* cell = [[[item cellClass] alloc] init];
// Action.
[item configureCell:cell];
// Tests.
EXPECT_EQ(3U, [cell.accessibilityCustomActions count]);
}
} // namespace
......@@ -10,6 +10,7 @@
#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/suggested_content.h"
@protocol ContentSuggestionsGestureCommands;
@class FaviconAttributes;
class GURL;
......@@ -26,6 +27,9 @@ class GURL;
@property(nonatomic, assign) ntp_tiles::TileSource source;
// Attributes for favicon.
@property(nonatomic, strong, nullable) FaviconAttributes* attributes;
// Command handler for the accessibility custom actions.
@property(nonatomic, weak, nullable) id<ContentSuggestionsGestureCommands>
commandHandler;
- (ntp_tiles::TileVisualType)tileType;
......
......@@ -4,10 +4,13 @@
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.h"
#import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion_identifier.h"
#import "ios/chrome/browser/ui/favicon/favicon_attributes.h"
#import "ios/chrome/browser/ui/favicon/favicon_view.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
......@@ -21,6 +24,7 @@
@synthesize title = _title;
@synthesize URL = _URL;
@synthesize source = _source;
@synthesize commandHandler = _commandHandler;
- (instancetype)initWithType:(NSInteger)type {
self = [super initWithType:type];
......@@ -35,6 +39,7 @@
cell.titleLabel.text = self.title;
cell.accessibilityLabel = self.title;
[cell.faviconView configureWithAttributes:self.attributes];
cell.accessibilityCustomActions = [self customActions];
}
- (ntp_tiles::TileVisualType)tileType {
......@@ -52,4 +57,51 @@
return [ContentSuggestionsMostVisitedCell defaultSize].height;
}
#pragma mark - AccessibilityCustomAction
// Custom action for a cell configured with this item.
- (NSArray<UIAccessibilityCustomAction*>*)customActions {
UIAccessibilityCustomAction* openInNewTab =
[[UIAccessibilityCustomAction alloc]
initWithName:l10n_util::GetNSString(
IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)
target:self
selector:@selector(openInNewTab)];
UIAccessibilityCustomAction* openInNewIncognitoTab =
[[UIAccessibilityCustomAction alloc]
initWithName:l10n_util::GetNSString(
IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB)
target:self
selector:@selector(openInNewIncognitoTab)];
UIAccessibilityCustomAction* removeMostVisited = [
[UIAccessibilityCustomAction alloc]
initWithName:l10n_util::GetNSString(IDS_IOS_CONTENT_SUGGESTIONS_REMOVE)
target:self
selector:@selector(removeMostVisited)];
NSArray* customActions =
[NSArray arrayWithObjects:openInNewTab, openInNewIncognitoTab,
removeMostVisited, nil];
return customActions;
}
// Target for custom action.
- (BOOL)openInNewTab {
[self.commandHandler openNewTabWithMostVisitedItem:self incognito:NO];
return YES;
}
// Target for custom action.
- (BOOL)openInNewIncognitoTab {
[self.commandHandler openNewTabWithMostVisitedItem:self incognito:YES];
return YES;
}
// Target for custom action.
- (BOOL)removeMostVisited {
[self.commandHandler removeMostVisited:self];
return YES;
}
@end
......@@ -18,10 +18,12 @@
// Opens the Most Visited associated with this |item| at the |mostVisitedItem|.
- (void)openMostVisitedItem:(nonnull CollectionViewItem*)item
atIndex:(NSInteger)mostVisitedIndex;
// Displays a context menu for the |articleItem|.
- (void)displayContextMenuForArticle:(nonnull CollectionViewItem*)articleItem
atPoint:(CGPoint)touchLocation
atIndexPath:(nonnull NSIndexPath*)indexPath;
// Displays a context menu for the |suggestionItem|.
- (void)displayContextMenuForSuggestion:
(nonnull CollectionViewItem*)suggestionItem
atPoint:(CGPoint)touchLocation
atIndexPath:(nonnull NSIndexPath*)indexPath
readLaterAction:(BOOL)readLaterAction;
// Displays a context menu for the |mostVisitedItem|.
- (void)displayContextMenuForMostVisitedItem:
(nonnull CollectionViewItem*)mostVisitedItem
......
......@@ -471,9 +471,17 @@ BOOL ShouldCellsBeFullWidth(UITraitCollection* collection) {
switch (type) {
case ContentSuggestionTypeArticle:
[self.suggestionCommandHandler
displayContextMenuForArticle:touchedItem
atPoint:touchLocation
atIndexPath:touchedItemIndexPath];
displayContextMenuForSuggestion:touchedItem
atPoint:touchLocation
atIndexPath:touchedItemIndexPath
readLaterAction:YES];
break;
case ContentSuggestionTypeReadingList:
[self.suggestionCommandHandler
displayContextMenuForSuggestion:touchedItem
atPoint:touchLocation
atIndexPath:touchedItemIndexPath
readLaterAction:NO];
break;
case ContentSuggestionTypeMostVisited:
[self.suggestionCommandHandler
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment