Commit 099f31e4 authored by Richard Knoll's avatar Richard Knoll Committed by Commit Bot

Remove overflow menu for single notification action on macOS

If a notification does not need the Settings button and only has one
action button we don't need the overflow menu as it would only have a
single entry. Instead just show the action as the second button in the
notification.

Before: https://imgur.com/SUvMXlW
After: https://imgur.com/QRijUhf

Bug: 1139892
Change-Id: Ia8b95aeffcea95345a9d483d065f818d03584939
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2485153
Commit-Queue: Richard Knoll <knollr@chromium.org>
Reviewed-by: default avatarRayan Kanso <rayankans@chromium.org>
Cr-Commit-Position: refs/heads/master@{#818563}
parent f4226913
...@@ -83,24 +83,39 @@ ...@@ -83,24 +83,39 @@
objectForKey:notification_constants:: objectForKey:notification_constants::
kNotificationCloseButtonTag]]; kNotificationCloseButtonTag]];
// Display the Settings button as the action button if there are either no NSMutableArray* buttons = [NSMutableArray arrayWithCapacity:3];
// developer-provided action buttons, or the alternate action menu is not if ([_notificationData
// available on this Mac version. This avoids needlessly showing the menu. objectForKey:notification_constants::kNotificationButtonOne]) {
if (![_notificationData [buttons addObject:[_notificationData
objectForKey:notification_constants::kNotificationButtonOne] || objectForKey:notification_constants::
![toast respondsToSelector:@selector(_alwaysShowAlternateActionMenu)]) { kNotificationButtonOne]];
if (settingsButton) { }
[toast setActionButtonTitle: if ([_notificationData
[_notificationData objectForKey:notification_constants::kNotificationButtonTwo]) {
objectForKey:notification_constants:: [buttons addObject:[_notificationData
kNotificationSettingsButtonTag]]; objectForKey:notification_constants::
} else { kNotificationButtonTwo]];
[toast setHasActionButton:NO]; }
if (settingsButton) {
// If we can't show an action menu but need a settings button, only show
// the settings button and don't show developer provided actions.
if (![toast
respondsToSelector:@selector(_alwaysShowAlternateActionMenu)]) {
[buttons removeAllObjects];
} }
[buttons addObject:[_notificationData
objectForKey:notification_constants::
kNotificationSettingsButtonTag]];
}
if ([buttons count] == 0) {
// Don't show action button if no actions needed.
[toast setHasActionButton:NO];
} else if ([buttons count] == 1) {
// Only one action so we don't need a menu. Just set the button title.
[toast setActionButtonTitle:[buttons firstObject]];
} else { } else {
// Otherwise show the alternate menu, then show the developer actions and // Show the alternate menu with developer actions and settings if needed.
// finally the settings one if needed.
DCHECK( DCHECK(
[toast respondsToSelector:@selector(_alwaysShowAlternateActionMenu)]); [toast respondsToSelector:@selector(_alwaysShowAlternateActionMenu)]);
DCHECK( DCHECK(
...@@ -110,24 +125,6 @@ ...@@ -110,24 +125,6 @@
objectForKey:notification_constants:: objectForKey:notification_constants::
kNotificationOptionsButtonTag]]; kNotificationOptionsButtonTag]];
[toast setValue:@YES forKey:@"_alwaysShowAlternateActionMenu"]; [toast setValue:@YES forKey:@"_alwaysShowAlternateActionMenu"];
NSMutableArray* buttons = [NSMutableArray arrayWithCapacity:3];
[buttons addObject:[_notificationData
objectForKey:notification_constants::
kNotificationButtonOne]];
if ([_notificationData
objectForKey:notification_constants::kNotificationButtonTwo]) {
[buttons addObject:[_notificationData
objectForKey:notification_constants::
kNotificationButtonTwo]];
}
if (settingsButton) {
[buttons
addObject:[_notificationData
objectForKey:notification_constants::
kNotificationSettingsButtonTag]];
}
[toast setValue:buttons forKey:@"_alternateActionButtonTitles"]; [toast setValue:buttons forKey:@"_alternateActionButtonTitles"];
} }
} }
......
...@@ -152,6 +152,34 @@ TEST(NotificationBuilderMacTest, TestNotificationExtensionNoButtons) { ...@@ -152,6 +152,34 @@ TEST(NotificationBuilderMacTest, TestNotificationExtensionNoButtons) {
EXPECT_EQ("Close", base::SysNSStringToUTF8([notification otherButtonTitle])); EXPECT_EQ("Close", base::SysNSStringToUTF8([notification otherButtonTitle]));
} }
TEST(NotificationBuilderMacTest, TestNotificationExtensionOneButton) {
base::scoped_nsobject<NotificationBuilder> builder(
[[NotificationBuilder alloc] initWithCloseLabel:@"Close"
optionsLabel:@"Options"
settingsLabel:@"Settings"]);
[builder setTitle:@"Title"];
[builder setSubTitle:@"https://www.miguel.com"];
[builder setContextMessage:@"SubTitle"];
[builder setButtons:@"Button1" secondaryButton:@""];
[builder setNotificationId:@"notificationId"];
[builder setProfileId:@"profileId"];
[builder setIncognito:false];
[builder setCreatorPid:@1];
[builder setNotificationType:[NSNumber
numberWithInteger:static_cast<int>(
NotificationHandler::
Type::EXTENSION)]];
[builder setShowSettingsButton:false];
NSUserNotification* notification = [builder buildUserNotification];
// No settings button but one action button without overflow menu.
EXPECT_TRUE([notification hasActionButton]);
EXPECT_EQ("Button1",
base::SysNSStringToUTF8([notification actionButtonTitle]));
EXPECT_EQ("Close", base::SysNSStringToUTF8([notification otherButtonTitle]));
}
TEST(NotificationBuilderMacTest, TestNotificationExtensionButtons) { TEST(NotificationBuilderMacTest, TestNotificationExtensionButtons) {
base::scoped_nsobject<NotificationBuilder> builder( base::scoped_nsobject<NotificationBuilder> builder(
[[NotificationBuilder alloc] initWithCloseLabel:@"Close" [[NotificationBuilder alloc] initWithCloseLabel:@"Close"
......
...@@ -53,37 +53,30 @@ ...@@ -53,37 +53,30 @@
// Determine whether the user clicked on a button, and if they did, whether it // Determine whether the user clicked on a button, and if they did, whether it
// was a developer-provided button or the Settings button. // was a developer-provided button or the Settings button.
if (activationType == NSUserNotificationActivationTypeActionButtonClicked) { if (activationType == NSUserNotificationActivationTypeActionButtonClicked) {
NSArray* alternateButtons = @[]; int buttonCount = 1;
if ([notification if ([notification
respondsToSelector:@selector(_alternateActionButtonTitles)]) { respondsToSelector:@selector(_alternateActionButtonTitles)]) {
alternateButtons = buttonCount =
[notification valueForKey:@"_alternateActionButtonTitles"]; [[notification valueForKey:@"_alternateActionButtonTitles"] count];
}
if (buttonCount > 1) {
// There are multiple buttons in the overflow menu. Get the clicked index.
buttonIndex =
[[notification valueForKey:@"_alternateActionIndex"] intValue];
} else {
// There was only one button so we know it was clicked.
buttonIndex = 0;
buttonCount = 1;
} }
BOOL settingsButtonRequired = [hasSettingsButton boolValue]; BOOL settingsButtonRequired = [hasSettingsButton boolValue];
BOOL multipleButtons = (alternateButtons.count > 0); BOOL clickedLastButton = buttonIndex == buttonCount - 1;
// No developer actions, just the settings button. // The settings button is always the last button if present.
if (!multipleButtons) { if (clickedLastButton && settingsButtonRequired) {
DCHECK(settingsButtonRequired);
operation = NotificationOperation::NOTIFICATION_SETTINGS; operation = NotificationOperation::NOTIFICATION_SETTINGS;
buttonIndex = notification_constants::kNotificationInvalidButtonIndex; buttonIndex = notification_constants::kNotificationInvalidButtonIndex;
} else {
// 0 based array containing.
// Button 1
// Button 2 (optional)
// Settings (if required)
NSNumber* actionIndex =
[notification valueForKey:@"_alternateActionIndex"];
operation = settingsButtonRequired && (actionIndex.unsignedLongValue ==
alternateButtons.count - 1)
? NotificationOperation::NOTIFICATION_SETTINGS
: NotificationOperation::NOTIFICATION_CLICK;
buttonIndex =
settingsButtonRequired &&
(actionIndex.unsignedLongValue == alternateButtons.count - 1)
? notification_constants::kNotificationInvalidButtonIndex
: actionIndex.intValue;
} }
} }
......
...@@ -142,6 +142,30 @@ TEST_F(NotificationResponseBuilderMacTest, TestNotificationOneActionClick) { ...@@ -142,6 +142,30 @@ TEST_F(NotificationResponseBuilderMacTest, TestNotificationOneActionClick) {
EXPECT_EQ(0, buttonIndex.intValue); EXPECT_EQ(0, buttonIndex.intValue);
} }
TEST_F(NotificationResponseBuilderMacTest,
TestNotificationOneActionNoSettingsClick) {
base::scoped_nsobject<NotificationBuilder> builder =
NewTestBuilder(NotificationHandler::Type::EXTENSION);
[builder setButtons:@"Button1" secondaryButton:@""];
NSUserNotification* notification = [builder buildUserNotification];
// This will be set by the notification center to indicate the only available
// button was clicked.
[notification setValue:@(NSUserNotificationActivationTypeActionButtonClicked)
forKey:@"_activationType"];
NSDictionary* response =
[NotificationResponseBuilder buildActivatedDictionary:notification];
NSNumber* operation =
[response objectForKey:notification_constants::kNotificationOperation];
NSNumber* buttonIndex =
[response objectForKey:notification_constants::kNotificationButtonIndex];
EXPECT_EQ(static_cast<int>(NotificationOperation::NOTIFICATION_CLICK),
operation.intValue);
EXPECT_EQ(0, buttonIndex.intValue);
}
TEST_F(NotificationResponseBuilderMacTest, TestNotificationTwoActionClick) { TEST_F(NotificationResponseBuilderMacTest, TestNotificationTwoActionClick) {
base::scoped_nsobject<NotificationBuilder> builder = base::scoped_nsobject<NotificationBuilder> builder =
NewTestBuilder(NotificationHandler::Type::WEB_PERSISTENT); NewTestBuilder(NotificationHandler::Type::WEB_PERSISTENT);
......
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