Commit 76d7d8ce authored by Ewann's avatar Ewann Committed by Commit Bot

[iOS] Basic ContentSuggestions Entry Context Menu

 - Adds a new Context Menu with a "Copy" action.
 - Wraps the old implementation with a feature flag check.
 - Adds metrics for the new context menu and its action.

Bug: 1093302
Change-Id: Ib814b1c16b18f2855a6cc8ad6d9f425a230ce8be
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2325172
Commit-Queue: Ewann Pellé <ewannpv@chromium.org>
Reviewed-by: default avatarSebastien Lalancette <seblalancette@chromium.org>
Reviewed-by: default avatarSylvain Defresne <sdefresne@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#793174}
parent 4d2068e0
......@@ -68,6 +68,7 @@ source_set("content_suggestions") {
"//ios/chrome/browser/ui/content_suggestions/identifier",
"//ios/chrome/browser/ui/coordinators:chrome_coordinators",
"//ios/chrome/browser/ui/favicon",
"//ios/chrome/browser/ui/menu",
"//ios/chrome/browser/ui/ntp",
"//ios/chrome/browser/ui/ntp:ntp_internal",
"//ios/chrome/browser/ui/overscroll_actions",
......@@ -120,6 +121,7 @@ source_set("content_suggestions_ui") {
"content_suggestions_header_view_controller_delegate.h",
"content_suggestions_layout.h",
"content_suggestions_layout.mm",
"content_suggestions_menu_provider.h",
"content_suggestions_metrics_recording.h",
"content_suggestions_view_controller.h",
"content_suggestions_view_controller.mm",
......@@ -142,6 +144,7 @@ source_set("content_suggestions_ui") {
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/collection_view",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/content_suggestions/cells",
"//ios/chrome/browser/ui/content_suggestions/cells:cells_ui",
"//ios/chrome/browser/ui/content_suggestions/identifier",
"//ios/chrome/browser/ui/elements",
......
......@@ -33,11 +33,13 @@
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sink.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_menu_provider.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h"
......@@ -46,6 +48,8 @@
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.h"
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_metrics.h"
#import "ios/chrome/browser/ui/content_suggestions/theme_change_delegate.h"
#import "ios/chrome/browser/ui/menu/action_factory.h"
#import "ios/chrome/browser/ui/menu/menu_histograms.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h"
#import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h"
#import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
......@@ -64,6 +68,7 @@
#endif
@interface ContentSuggestionsCoordinator () <
ContentSuggestionsMenuProvider,
ContentSuggestionsViewControllerAudience,
DiscoverFeedMenuCommands,
OverscrollActionsControllerDelegate,
......@@ -216,6 +221,10 @@
self.suggestionsViewController.dispatcher = dispatcher;
self.suggestionsViewController.discoverFeedMenuHandler = self;
if (@available(iOS 13.0, *)) {
self.suggestionsViewController.menuProvider = self;
}
self.NTPMediator.consumer = self.headerController;
// TODO(crbug.com/1045047): Use HandlerForProtocol after commands protocol
// clean up.
......@@ -419,4 +428,26 @@
[self.NTPMediator locationBarDidResignFirstResponder];
}
#pragma mark - ThemeChangeDelegate
- (UIContextMenuConfiguration*)contextMenuConfigurationForItem:
(ContentSuggestionsMostVisitedItem*)item API_AVAILABLE(ios(13.0)) {
return [UIContextMenuConfiguration
configurationWithIdentifier:nil
previewProvider:nil
actionProvider:^(NSArray<UIMenuElement*>* suggestedActions) {
// Record that this context menu was shown to the user.
RecordMenuShown(MenuScenario::kContentSuggestionsEntry);
ActionFactory* actionFactory = [[ActionFactory alloc]
initWithScenario:MenuScenario::
kContentSuggestionsEntry];
UIAction* copyAction =
[actionFactory actionToCopyURL:item.URL];
return [UIMenu menuWithTitle:@"" children:@[ copyAction ]];
}];
}
@end
// Copyright 2020 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.
#ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_MENU_PROVIDER_H_
#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_MENU_PROVIDER_H_
@class ContentSuggestionsMostVisitedItem;
// Protocol for instances that will provide menus to ContentSuggestions
// components.
@protocol ContentSuggestionsMenuProvider
// Creates a context menu configuration instance for the given |item|, which is
// represented on the UI by |view|.
- (UIContextMenuConfiguration*)contextMenuConfigurationForItem:
(ContentSuggestionsMostVisitedItem*)item API_AVAILABLE(ios(13.0));
@end
#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_MENU_PROVIDER_H_
......@@ -14,6 +14,7 @@
@protocol ContentSuggestionsCommands;
@protocol ContentSuggestionsDataSource;
@protocol ContentSuggestionsHeaderSynchronizing;
@protocol ContentSuggestionsMenuProvider;
@protocol ContentSuggestionsMetricsRecording;
@protocol ContentSuggestionsViewControllerAudience;
@protocol DiscoverFeedMenuCommands;
......@@ -54,6 +55,10 @@ extern NSString* const
@property(nonatomic, weak) id<ContentSuggestionsMetricsRecording>
metricsRecorder;
// Provider of menu configurations for the contentSuggestions component.
@property(nonatomic, weak) id<ContentSuggestionsMenuProvider> menuProvider
API_AVAILABLE(ios(13.0));
- (void)setDataSource:(id<ContentSuggestionsDataSource>)dataSource;
- (void)setDispatcher:(id<SnackbarCommands>)dispatcher;
......
......@@ -14,6 +14,7 @@
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_discover_header_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_discover_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/suggested_content.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h"
......@@ -21,6 +22,7 @@
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizing.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_menu_provider.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recording.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h"
#import "ios/chrome/browser/ui/content_suggestions/discover_feed_menu_commands.h"
......@@ -31,10 +33,12 @@
#import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
#import "ios/chrome/browser/ui/toolbar/public/toolbar_utils.h"
#import "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/chrome/browser/ui/util/menu_util.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -236,12 +240,14 @@ NSString* const kContentSuggestionsMostVisitedAccessibilityIdentifierPrefix =
ApplyVisualConstraints(@[ @"V:|[collection]|", @"H:|[collection]|" ],
@{@"collection" : self.collectionView});
UILongPressGestureRecognizer* longPressRecognizer =
[[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:@selector(handleLongPress:)];
longPressRecognizer.delegate = self;
[self.collectionView addGestureRecognizer:longPressRecognizer];
if (!IsNativeContextMenuEnabled()) {
UILongPressGestureRecognizer* longPressRecognizer =
[[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:@selector(handleLongPress:)];
longPressRecognizer.delegate = self;
[self.collectionView addGestureRecognizer:longPressRecognizer];
}
self.overscrollActionsController = [[OverscrollActionsController alloc]
initWithScrollView:self.collectionView];
......@@ -424,6 +430,29 @@ NSString* const kContentSuggestionsMostVisitedAccessibilityIdentifierPrefix =
return cell;
}
- (UIContextMenuConfiguration*)collectionView:(UICollectionView*)collectionView
contextMenuConfigurationForItemAtIndexPath:(NSIndexPath*)indexPath
point:(CGPoint)point
API_AVAILABLE(ios(13.0)) {
if (!IsNativeContextMenuEnabled()) {
// Returning nil will allow the gesture to be captured and show the old
// context menus.
return nil;
}
CollectionViewItem* item =
[self.collectionViewModel itemAtIndexPath:indexPath];
if (![item isKindOfClass:[ContentSuggestionsMostVisitedItem class]])
return nil;
ContentSuggestionsMostVisitedItem* contentSuggestionsItem =
base::mac::ObjCCastStrict<ContentSuggestionsMostVisitedItem>(item);
return [self.menuProvider
contextMenuConfigurationForItem:contentSuggestionsItem];
}
#pragma mark - UICollectionViewDataSource
- (UICollectionReusableView*)collectionView:(UICollectionView*)collectionView
......
......@@ -13,7 +13,8 @@ enum class MenuScenario {
kBookmarkEntry = 1,
kReadingListEntry = 2,
kRecentTabsEntry = 3,
kMaxValue = kRecentTabsEntry
kContentSuggestionsEntry = 4,
kMaxValue = kContentSuggestionsEntry
};
// Records a menu shown histogram metric for the |scenario|.
......
......@@ -23,6 +23,8 @@ const char ReadingListEntryActionsHistogram[] =
"Mobile.ContextMenu.ReadingListEntry.Actions";
const char RecentTabsEntryActionsHistogram[] =
"Mobile.ContextMenu.RecentTabsEntry.Actions";
const char ContentSuggestionsEntryActionsHistogram[] =
"Mobile.ContextMenu.ContentSuggestionsEntry.Actions";
} // namespace
void RecordMenuShown(MenuScenario scenario) {
......@@ -39,5 +41,7 @@ const char* GetActionsHistogramName(MenuScenario scenario) {
return ReadingListEntryActionsHistogram;
case MenuScenario::kRecentTabsEntry:
return RecentTabsEntryActionsHistogram;
case MenuScenario::kContentSuggestionsEntry:
return ContentSuggestionsEntryActionsHistogram;
}
}
......@@ -37118,6 +37118,7 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="1" label="Bookmark Entry"/>
<int value="2" label="ReadingList Entry"/>
<int value="3" label="RecentTabs Entry"/>
<int value="4" label="ContentSuggestions Entry"/>
</enum>
<enum name="IOSNTPImpression">
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