Commit f1d5c4b5 authored by Gauthier Ambard's avatar Gauthier Ambard Committed by Commit Bot

Re-reland "Add blink effect to the PopupMenu"

This CL adds an effect to make the "New Incognito Tab" row of the tools
menu blink a selected state when the in product help requires it.

TBR=edchin@chromium.org

Bug: 829344
Cq-Include-Trybots: luci.chromium.try:ios-simulator-full-configs;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: Ic2e6fe63f5e2233f70ffaa0747c332778370132c
Reviewed-on: https://chromium-review.googlesource.com/1068044
Commit-Queue: Gauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#561006}
parent f2d78c30
...@@ -2300,6 +2300,8 @@ applicationCommandEndpoint:(id<ApplicationCommands>)applicationCommandEndpoint { ...@@ -2300,6 +2300,8 @@ applicationCommandEndpoint:(id<ApplicationCommands>)applicationCommandEndpoint {
self.popupMenuCoordinator = [[PopupMenuCoordinator alloc] self.popupMenuCoordinator = [[PopupMenuCoordinator alloc]
initWithBaseViewController:self initWithBaseViewController:self
browserState:self.browserState]; browserState:self.browserState];
self.popupMenuCoordinator.incognitoTabTipPresenter =
self.incognitoTabTipBubblePresenter;
self.popupMenuCoordinator.dispatcher = _dispatcher; self.popupMenuCoordinator.dispatcher = _dispatcher;
self.popupMenuCoordinator.webStateList = [_model webStateList]; self.popupMenuCoordinator.webStateList = [_model webStateList];
self.popupMenuCoordinator.UIUpdater = _toolbarCoordinatorAdaptor; self.popupMenuCoordinator.UIUpdater = _toolbarCoordinatorAdaptor;
...@@ -2826,6 +2828,7 @@ bubblePresenterForFeature:(const base::Feature&)feature ...@@ -2826,6 +2828,7 @@ bubblePresenterForFeature:(const base::Feature&)feature
return; return;
self.incognitoTabTipBubblePresenter = presenter; self.incognitoTabTipBubblePresenter = presenter;
self.popupMenuCoordinator.incognitoTabTipPresenter = presenter;
[self.incognitoTabTipBubblePresenter [self.incognitoTabTipBubblePresenter
presentInViewController:self presentInViewController:self
......
...@@ -25,6 +25,7 @@ source_set("popup_menu") { ...@@ -25,6 +25,7 @@ source_set("popup_menu") {
"//ios/chrome/browser/ui", "//ios/chrome/browser/ui",
"//ios/chrome/browser/ui/activity_services", "//ios/chrome/browser/ui/activity_services",
"//ios/chrome/browser/ui/bookmarks", "//ios/chrome/browser/ui/bookmarks",
"//ios/chrome/browser/ui/bubble",
"//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
"//ios/chrome/browser/ui/popup_menu/cells", "//ios/chrome/browser/ui/popup_menu/cells",
...@@ -127,7 +128,9 @@ source_set("unit_tests") { ...@@ -127,7 +128,9 @@ source_set("unit_tests") {
"//ios/chrome/browser/web_state_list", "//ios/chrome/browser/web_state_list",
"//ios/chrome/browser/web_state_list:test_support", "//ios/chrome/browser/web_state_list:test_support",
"//ios/chrome/test:test_support", "//ios/chrome/test:test_support",
"//ios/public/provider/chrome/browser",
"//ios/public/provider/chrome/browser:test_support", "//ios/public/provider/chrome/browser:test_support",
"//ios/public/provider/chrome/browser/user_feedback",
"//ios/web", "//ios/web",
"//ios/web/public/test", "//ios/web/public/test",
"//ios/web/public/test/fakes", "//ios/web/public/test/fakes",
......
...@@ -13,5 +13,7 @@ extern NSString* const kPopupMenuNavigationTableViewId; ...@@ -13,5 +13,7 @@ extern NSString* const kPopupMenuNavigationTableViewId;
// Alpha for the background color of the highlighted items. // Alpha for the background color of the highlighted items.
extern const CGFloat kSelectedItemBackgroundAlpha; extern const CGFloat kSelectedItemBackgroundAlpha;
// Duration of the highlight animation of the popup menu.
extern const CGFloat kHighlightAnimationDuration;
#endif // IOS_CHROME_BROWSER_UI_POPUP_MENU_POPUP_MENU_CONSTANTS_H_ #endif // IOS_CHROME_BROWSER_UI_POPUP_MENU_POPUP_MENU_CONSTANTS_H_
...@@ -14,3 +14,4 @@ NSString* const kPopupMenuNavigationTableViewId = ...@@ -14,3 +14,4 @@ NSString* const kPopupMenuNavigationTableViewId =
@"kPopupMenuNavigationTableViewId"; @"kPopupMenuNavigationTableViewId";
const CGFloat kSelectedItemBackgroundAlpha = 0.05; const CGFloat kSelectedItemBackgroundAlpha = 0.05;
const CGFloat kHighlightAnimationDuration = 0.5;
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
@class BubbleViewControllerPresenter;
@class CommandDispatcher; @class CommandDispatcher;
@protocol PopupMenuUIUpdating; @protocol PopupMenuUIUpdating;
class WebStateList; class WebStateList;
...@@ -22,6 +23,9 @@ class WebStateList; ...@@ -22,6 +23,9 @@ class WebStateList;
@property(nonatomic, assign) WebStateList* webStateList; @property(nonatomic, assign) WebStateList* webStateList;
// UI updater. // UI updater.
@property(nonatomic, weak) id<PopupMenuUIUpdating> UIUpdater; @property(nonatomic, weak) id<PopupMenuUIUpdating> UIUpdater;
// Bubble view presenter for the incognito tip.
@property(nonatomic, weak)
BubbleViewControllerPresenter* incognitoTabTipPresenter;
// Returns whether this coordinator is showing a popup menu. // Returns whether this coordinator is showing a popup menu.
- (BOOL)isShowingPopupMenu; - (BOOL)isShowingPopupMenu;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/feature_engagement/tracker_factory.h" #include "ios/chrome/browser/feature_engagement/tracker_factory.h"
#include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
#import "ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/commands/popup_menu_commands.h" #import "ios/chrome/browser/ui/commands/popup_menu_commands.h"
...@@ -54,6 +55,7 @@ PopupMenuCommandType CommandTypeFromPopupType(PopupMenuType type) { ...@@ -54,6 +55,7 @@ PopupMenuCommandType CommandTypeFromPopupType(PopupMenuType type) {
@synthesize requestStartTime = _requestStartTime; @synthesize requestStartTime = _requestStartTime;
@synthesize UIUpdater = _UIUpdater; @synthesize UIUpdater = _UIUpdater;
@synthesize webStateList = _webStateList; @synthesize webStateList = _webStateList;
@synthesize incognitoTabTipPresenter = _incognitoTabTipPresenter;
#pragma mark - ChromeCoordinator #pragma mark - ChromeCoordinator
...@@ -166,11 +168,19 @@ PopupMenuCommandType CommandTypeFromPopupType(PopupMenuType type) { ...@@ -166,11 +168,19 @@ PopupMenuCommandType CommandTypeFromPopupType(PopupMenuType type) {
static_cast<id<ApplicationCommands, BrowserCommands>>(self.dispatcher); static_cast<id<ApplicationCommands, BrowserCommands>>(self.dispatcher);
tableViewController.baseViewController = self.baseViewController; tableViewController.baseViewController = self.baseViewController;
BOOL triggerNewIncognitoTabTip = NO;
if (type == PopupMenuTypeToolsMenu) {
triggerNewIncognitoTabTip =
self.incognitoTabTipPresenter.triggerFollowUpAction;
self.incognitoTabTipPresenter.triggerFollowUpAction = NO;
}
self.mediator = [[PopupMenuMediator alloc] self.mediator = [[PopupMenuMediator alloc]
initWithType:type initWithType:type
isIncognito:self.browserState->IsOffTheRecord() isIncognito:self.browserState->IsOffTheRecord()
readingListModel:ReadingListModelFactory::GetForBrowserState( readingListModel:ReadingListModelFactory::GetForBrowserState(
self.browserState)]; self.browserState)
triggerNewIncognitoTabTip:triggerNewIncognitoTabTip];
self.mediator.engagementTracker = self.mediator.engagementTracker =
feature_engagement::TrackerFactory::GetForBrowserState(self.browserState); feature_engagement::TrackerFactory::GetForBrowserState(self.browserState);
self.mediator.webStateList = self.webStateList; self.mediator.webStateList = self.webStateList;
......
...@@ -24,9 +24,13 @@ class WebStateList; ...@@ -24,9 +24,13 @@ class WebStateList;
// updating the items of the popup menu. // updating the items of the popup menu.
@interface PopupMenuMediator : NSObject @interface PopupMenuMediator : NSObject
// Initializes the mediator with a |type| of popup menu, whether it
// |isIncognito|, a |readingListModel| used to display the badge for the reading
// list entry, and whether the mediator should |triggerNewIncognitoTabTip|.
- (instancetype)initWithType:(PopupMenuType)type - (instancetype)initWithType:(PopupMenuType)type
isIncognito:(BOOL)isIncognito isIncognito:(BOOL)isIncognito
readingListModel:(ReadingListModel*)readingListModel readingListModel:(ReadingListModel*)readingListModel
triggerNewIncognitoTabTip:(BOOL)triggerNewIncognitoTabTip
NS_DESIGNATED_INITIALIZER; NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
......
...@@ -89,8 +89,12 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID, ...@@ -89,8 +89,12 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID,
// Items notifying this items of changes happening to the ReadingList model. // Items notifying this items of changes happening to the ReadingList model.
@property(nonatomic, strong) ReadingListMenuNotifier* readingListMenuNotifier; @property(nonatomic, strong) ReadingListMenuNotifier* readingListMenuNotifier;
// Whether the hint for the "New Incognito Tab" item should be triggered.
@property(nonatomic, assign) BOOL triggerNewIncognitoTabTip;
#pragma mark*** Specific Items *** #pragma mark*** Specific Items ***
@property(nonatomic, strong) PopupMenuToolsItem* openNewIncognitoTabItem;
@property(nonatomic, strong) PopupMenuToolsItem* reloadStopItem; @property(nonatomic, strong) PopupMenuToolsItem* reloadStopItem;
@property(nonatomic, strong) PopupMenuToolsItem* readLaterItem; @property(nonatomic, strong) PopupMenuToolsItem* readLaterItem;
@property(nonatomic, strong) PopupMenuToolsItem* bookmarkItem; @property(nonatomic, strong) PopupMenuToolsItem* bookmarkItem;
...@@ -113,9 +117,11 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID, ...@@ -113,9 +117,11 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID,
@synthesize dispatcher = _dispatcher; @synthesize dispatcher = _dispatcher;
@synthesize engagementTracker = _engagementTracker; @synthesize engagementTracker = _engagementTracker;
@synthesize readingListMenuNotifier = _readingListMenuNotifier; @synthesize readingListMenuNotifier = _readingListMenuNotifier;
@synthesize triggerNewIncognitoTabTip = _triggerNewIncognitoTabTip;
@synthesize type = _type; @synthesize type = _type;
@synthesize webState = _webState; @synthesize webState = _webState;
@synthesize webStateList = _webStateList; @synthesize webStateList = _webStateList;
@synthesize openNewIncognitoTabItem = _openNewIncognitoTabItem;
@synthesize reloadStopItem = _reloadStopItem; @synthesize reloadStopItem = _reloadStopItem;
@synthesize readLaterItem = _readLaterItem; @synthesize readLaterItem = _readLaterItem;
@synthesize bookmarkItem = _bookmarkItem; @synthesize bookmarkItem = _bookmarkItem;
...@@ -129,8 +135,9 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID, ...@@ -129,8 +135,9 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID,
#pragma mark - Public #pragma mark - Public
- (instancetype)initWithType:(PopupMenuType)type - (instancetype)initWithType:(PopupMenuType)type
isIncognito:(BOOL)isIncognito isIncognito:(BOOL)isIncognito
readingListModel:(ReadingListModel*)readingListModel { readingListModel:(ReadingListModel*)readingListModel
triggerNewIncognitoTabTip:(BOOL)triggerNewIncognitoTabTip {
self = [super init]; self = [super init];
if (self) { if (self) {
_isIncognito = isIncognito; _isIncognito = isIncognito;
...@@ -139,6 +146,7 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID, ...@@ -139,6 +146,7 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID,
[[ReadingListMenuNotifier alloc] initWithReadingList:readingListModel]; [[ReadingListMenuNotifier alloc] initWithReadingList:readingListModel];
_webStateObserver = std::make_unique<web::WebStateObserverBridge>(self); _webStateObserver = std::make_unique<web::WebStateObserverBridge>(self);
_webStateListObserver = std::make_unique<WebStateListObserverBridge>(self); _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self);
_triggerNewIncognitoTabTip = triggerNewIncognitoTabTip;
} }
return self; return self;
} }
...@@ -308,6 +316,10 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID, ...@@ -308,6 +316,10 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID,
} }
[_popupMenu setPopupMenuItems:self.items]; [_popupMenu setPopupMenuItems:self.items];
if (self.triggerNewIncognitoTabTip) {
_popupMenu.itemToHighlight = self.openNewIncognitoTabItem;
self.triggerNewIncognitoTabTip = NO;
}
_popupMenu.commandHandler = self; _popupMenu.commandHandler = self;
if (self.webState) { if (self.webState) {
[self updatePopupMenu]; [self updatePopupMenu];
...@@ -591,11 +603,11 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID, ...@@ -591,11 +603,11 @@ PopupMenuToolsItem* CreateTableViewItem(int titleID,
@"popup_menu_new_tab", kToolsMenuNewTabId); @"popup_menu_new_tab", kToolsMenuNewTabId);
// Open New Incognito Tab. // Open New Incognito Tab.
TableViewItem* openNewIncognitoTabItem = CreateTableViewItem( self.openNewIncognitoTabItem = CreateTableViewItem(
IDS_IOS_TOOLS_MENU_NEW_INCOGNITO_TAB, PopupMenuActionOpenNewIncognitoTab, IDS_IOS_TOOLS_MENU_NEW_INCOGNITO_TAB, PopupMenuActionOpenNewIncognitoTab,
@"popup_menu_new_incognito_tab", kToolsMenuNewIncognitoTabId); @"popup_menu_new_incognito_tab", kToolsMenuNewIncognitoTabId);
return @[ openNewTabItem, openNewIncognitoTabItem ]; return @[ openNewTabItem, self.openNewIncognitoTabItem ];
} }
- (NSArray<TableViewItem*>*)actionItems { - (NSArray<TableViewItem*>*)actionItems {
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "ios/chrome/browser/web_state_list/web_state_list.h" #include "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h" #import "ios/chrome/browser/web_state_list/web_state_opener.h"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h"
#import "ios/web/public/test/fakes/fake_navigation_context.h" #import "ios/web/public/test/fakes/fake_navigation_context.h"
#import "ios/web/public/test/fakes/test_navigation_manager.h" #import "ios/web/public/test/fakes/test_navigation_manager.h"
#import "ios/web/public/test/fakes/test_web_state.h" #import "ios/web/public/test/fakes/test_web_state.h"
...@@ -43,14 +45,6 @@ class PopupMenuMediatorTest : public PlatformTest { ...@@ -43,14 +45,6 @@ class PopupMenuMediatorTest : public PlatformTest {
PopupMenuMediatorTest() { PopupMenuMediatorTest() {
reading_list_model_.reset(new ReadingListModelImpl( reading_list_model_.reset(new ReadingListModelImpl(
nullptr, nullptr, base::DefaultClock::GetInstance())); nullptr, nullptr, base::DefaultClock::GetInstance()));
mediator_incognito_ =
[[PopupMenuMediator alloc] initWithType:PopupMenuTypeToolsMenu
isIncognito:YES
readingListModel:reading_list_model_.get()];
mediator_ =
[[PopupMenuMediator alloc] initWithType:PopupMenuTypeToolsMenu
isIncognito:NO
readingListModel:reading_list_model_.get()];
popup_menu_ = OCMClassMock([PopupMenuTableViewController class]); popup_menu_ = OCMClassMock([PopupMenuTableViewController class]);
popup_menu_strict_ = popup_menu_strict_ =
OCMStrictClassMock([PopupMenuTableViewController class]); OCMStrictClassMock([PopupMenuTableViewController class]);
...@@ -62,11 +56,21 @@ class PopupMenuMediatorTest : public PlatformTest { ...@@ -62,11 +56,21 @@ class PopupMenuMediatorTest : public PlatformTest {
// Explicitly disconnect the mediator so there won't be any WebStateList // Explicitly disconnect the mediator so there won't be any WebStateList
// observers when web_state_list_ gets dealloc. // observers when web_state_list_ gets dealloc.
~PopupMenuMediatorTest() override { ~PopupMenuMediatorTest() override {
[mediator_incognito_ disconnect];
[mediator_ disconnect]; [mediator_ disconnect];
} }
protected: protected:
PopupMenuMediator* CreateMediator(PopupMenuType type,
BOOL is_incognito,
BOOL trigger_incognito_hint) {
mediator_ =
[[PopupMenuMediator alloc] initWithType:type
isIncognito:is_incognito
readingListModel:reading_list_model_.get()
triggerNewIncognitoTabTip:trigger_incognito_hint];
return mediator_;
}
void SetUpWebStateList() { void SetUpWebStateList() {
auto navigation_manager = std::make_unique<ToolbarTestNavigationManager>(); auto navigation_manager = std::make_unique<ToolbarTestNavigationManager>();
navigation_manager_ = navigation_manager.get(); navigation_manager_ = navigation_manager.get();
...@@ -97,7 +101,29 @@ class PopupMenuMediatorTest : public PlatformTest { ...@@ -97,7 +101,29 @@ class PopupMenuMediatorTest : public PlatformTest {
void SetUpActiveWebState() { web_state_list_->ActivateWebStateAt(0); } void SetUpActiveWebState() { web_state_list_->ActivateWebStateAt(0); }
PopupMenuMediator* mediator_incognito_; // Checks that the popup_menu_ is receiving a number of items corresponding to
// |number_items|.
void CheckMediatorSetItems(NSArray<NSNumber*>* number_items) {
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
auto same_number_items = ^BOOL(id items) {
if (![items isKindOfClass:[NSArray class]])
return NO;
if ([items count] != number_items.count)
return NO;
for (NSUInteger index = 0; index < number_items.count; index++) {
NSArray* section = [items objectAtIndex:index];
if (section.count != number_items[index].unsignedIntegerValue)
return NO;
}
return YES;
};
OCMExpect([popup_menu_
setPopupMenuItems:[OCMArg checkWithBlock:same_number_items]]);
mediator_.popupMenu = popup_menu_;
EXPECT_OCMOCK_VERIFY(popup_menu_);
}
PopupMenuMediator* mediator_; PopupMenuMediator* mediator_;
std::unique_ptr<ReadingListModelImpl> reading_list_model_; std::unique_ptr<ReadingListModelImpl> reading_list_model_;
ToolbarTestWebState* web_state_; ToolbarTestWebState* web_state_;
...@@ -112,6 +138,7 @@ class PopupMenuMediatorTest : public PlatformTest { ...@@ -112,6 +138,7 @@ class PopupMenuMediatorTest : public PlatformTest {
// Tests that the feature engagement tracker get notified when the mediator is // Tests that the feature engagement tracker get notified when the mediator is
// disconnected and the tracker wants the notification badge displayed. // disconnected and the tracker wants the notification badge displayed.
TEST_F(PopupMenuMediatorTest, TestFeatureEngagementDisconnect) { TEST_F(PopupMenuMediatorTest, TestFeatureEngagementDisconnect) {
CreateMediator(PopupMenuTypeToolsMenu, NO, NO);
feature_engagement::test::MockTracker tracker; feature_engagement::test::MockTracker tracker;
EXPECT_CALL(tracker, ShouldTriggerHelpUI(testing::_)) EXPECT_CALL(tracker, ShouldTriggerHelpUI(testing::_))
.WillRepeatedly(testing::Return(true)); .WillRepeatedly(testing::Return(true));
...@@ -121,3 +148,59 @@ TEST_F(PopupMenuMediatorTest, TestFeatureEngagementDisconnect) { ...@@ -121,3 +148,59 @@ TEST_F(PopupMenuMediatorTest, TestFeatureEngagementDisconnect) {
EXPECT_CALL(tracker, Dismissed(testing::_)); EXPECT_CALL(tracker, Dismissed(testing::_));
[mediator_ disconnect]; [mediator_ disconnect];
} }
// Tests that the mediator is returning the right number of items and sections
// for the Tools Menu type.
TEST_F(PopupMenuMediatorTest, TestElementsToolsMenu) {
CreateMediator(PopupMenuTypeToolsMenu, NO, NO);
NSUInteger number_of_action_items = 6;
if (ios::GetChromeBrowserProvider()
->GetUserFeedbackProvider()
->IsUserFeedbackEnabled()) {
number_of_action_items++;
}
CheckMediatorSetItems(@[ @(3), @(number_of_action_items), @(5) ]);
}
// Tests that the mediator is returning the right number of items and sections
// for the Tab Grid type, in non-incognito.
TEST_F(PopupMenuMediatorTest, TestElementsTabGridNonIncognito) {
CreateMediator(PopupMenuTypeTabGrid, NO, NO);
CheckMediatorSetItems(@[ @(2), @(1) ]);
}
// Tests that the mediator is returning the right number of items and sections
// for the Tab Grid type, in incognito.
TEST_F(PopupMenuMediatorTest, TestElementsTabGridIncognito) {
CreateMediator(PopupMenuTypeTabGrid, YES, NO);
CheckMediatorSetItems(@[ @(2), @(2) ]);
}
// Tests that the mediator is asking for an item to be highlighted when asked.
TEST_F(PopupMenuMediatorTest, TestNewIncognitoHint) {
CreateMediator(PopupMenuTypeToolsMenu, NO, YES);
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
OCMExpect([popup_menu_ setItemToHighlight:[OCMArg isNotNil]]);
mediator_.popupMenu = popup_menu_;
EXPECT_OCMOCK_VERIFY(popup_menu_);
}
// Test that the mediator isn't asking for an highlighted item.
TEST_F(PopupMenuMediatorTest, TestNewIncognitoNoHint) {
CreateMediator(PopupMenuTypeToolsMenu, NO, NO);
[[popup_menu_ reject] setItemToHighlight:[OCMArg any]];
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.popupMenu = popup_menu_;
}
// Tests that the mediator is asking for an item to be highlighted when asked.
TEST_F(PopupMenuMediatorTest, TestNewIncognitoHintTabGrid) {
CreateMediator(PopupMenuTypeTabGrid, NO, YES);
OCMExpect([popup_menu_ setItemToHighlight:[OCMArg isNotNil]]);
mediator_.webStateList = web_state_list_.get();
SetUpActiveWebState();
mediator_.popupMenu = popup_menu_;
EXPECT_OCMOCK_VERIFY(popup_menu_);
}
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
// Presenting ViewController for the ViewController needing to be presented as // Presenting ViewController for the ViewController needing to be presented as
// result of an interaction with the popup. // result of an interaction with the popup.
@property(nonatomic, weak) UIViewController* baseViewController; @property(nonatomic, weak) UIViewController* baseViewController;
// Item to be highlighted. Nil if no item should be highlighted. Must be set
// after the popup menu items.
@property(nonatomic, weak) TableViewItem<PopupMenuItem>* itemToHighlight;
// Initializers. // Initializers.
- (instancetype)init NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_DESIGNATED_INITIALIZER;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h" #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_footer_item.h" #import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_footer_item.h"
#import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_item.h" #import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_item.h"
#import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
#import "ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller_commands.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller_commands.h"
#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
...@@ -26,18 +27,35 @@ const CGFloat kPopupMenuVerticalInsets = 7; ...@@ -26,18 +27,35 @@ const CGFloat kPopupMenuVerticalInsets = 7;
const CGFloat kScrollIndicatorVerticalInsets = 11; const CGFloat kScrollIndicatorVerticalInsets = 11;
} // namespace } // namespace
@interface PopupMenuTableViewController ()
// Whether the -viewDidAppear: callback has been called.
@property(nonatomic, assign) BOOL viewDidAppear;
@end
@implementation PopupMenuTableViewController @implementation PopupMenuTableViewController
@dynamic tableViewModel; @dynamic tableViewModel;
@synthesize baseViewController = _baseViewController; @synthesize baseViewController = _baseViewController;
@synthesize commandHandler = _commandHandler; @synthesize commandHandler = _commandHandler;
@synthesize dispatcher = _dispatcher; @synthesize dispatcher = _dispatcher;
@synthesize itemToHighlight = _itemToHighlight;
@synthesize viewDidAppear = _viewDidAppear;
- (instancetype)init { - (instancetype)init {
return [super initWithTableViewStyle:UITableViewStyleGrouped return [super initWithTableViewStyle:UITableViewStyleGrouped
appBarStyle:ChromeTableViewControllerStyleNoAppBar]; appBarStyle:ChromeTableViewControllerStyleNoAppBar];
} }
#pragma mark - Properties
- (void)setItemToHighlight:(TableViewItem<PopupMenuItem>*)itemToHighlight {
DCHECK_GT(self.tableViewModel.numberOfSections, 0L);
_itemToHighlight = itemToHighlight;
if (itemToHighlight && self.viewDidAppear) {
[self highlightItem:itemToHighlight repeat:YES];
}
}
#pragma mark - UIViewController #pragma mark - UIViewController
- (void)viewDidLoad { - (void)viewDidLoad {
...@@ -57,6 +75,14 @@ const CGFloat kScrollIndicatorVerticalInsets = 11; ...@@ -57,6 +75,14 @@ const CGFloat kScrollIndicatorVerticalInsets = 11;
0.01f)]; 0.01f)];
} }
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.viewDidAppear = YES;
if (self.itemToHighlight) {
[self highlightItem:self.itemToHighlight repeat:YES];
}
}
- (void)setPopupMenuItems: - (void)setPopupMenuItems:
(NSArray<NSArray<TableViewItem<PopupMenuItem>*>*>*)items { (NSArray<NSArray<TableViewItem<PopupMenuItem>*>*>*)items {
[super loadModel]; [super loadModel];
...@@ -126,6 +152,36 @@ const CGFloat kScrollIndicatorVerticalInsets = 11; ...@@ -126,6 +152,36 @@ const CGFloat kScrollIndicatorVerticalInsets = 11;
#pragma mark - Private #pragma mark - Private
// Highlights the |item| and |repeat| the highlighting once.
- (void)highlightItem:(TableViewItem<PopupMenuItem>*)item repeat:(BOOL)repeat {
NSIndexPath* indexPath = [self.tableViewModel indexPathForItem:item];
[self.tableView selectRowAtIndexPath:indexPath
animated:YES
scrollPosition:UITableViewScrollPositionNone];
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(kHighlightAnimationDuration * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[self unhighlightItem:item repeat:repeat];
});
}
// Removes the highlight from |item| and |repeat| the highlighting once.
- (void)unhighlightItem:(TableViewItem<PopupMenuItem>*)item
repeat:(BOOL)repeat {
NSIndexPath* indexPath = [self.tableViewModel indexPathForItem:item];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
if (!repeat)
return;
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(kHighlightAnimationDuration * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[self highlightItem:item repeat:NO];
});
}
// Executes the action associated with |identifier|, using |origin| as the point // Executes the action associated with |identifier|, using |origin| as the point
// of origin of the action if one is needed. // of origin of the action if one is needed.
- (void)executeActionForItem:(TableViewItem<PopupMenuItem>*)item - (void)executeActionForItem:(TableViewItem<PopupMenuItem>*)item
......
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