blob: 72c99b7b024c6cb77ee312e1ad97661a1bbb6f00 [file] [log] [blame]
// Copyright 2016 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.
#import "ios/chrome/browser/ui/key_commands_provider.h"
#include "base/logging.h"
#include "components/strings/grit/components_strings.h"
#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/keyboard/UIKeyCommand+Chrome.h"
#include "ios/chrome/browser/ui/rtl_geometry.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ui/base/l10n/l10n_util_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@implementation KeyCommandsProvider
- (NSArray*)keyCommandsForConsumer:(id<KeyCommandsPlumbing>)consumer
editingText:(BOOL)editingText {
__weak id<KeyCommandsPlumbing> weakConsumer = consumer;
// Block to execute a command from the |tag|.
void (^execute)(NSInteger) = ^(NSInteger tag) {
[weakConsumer
chromeExecuteCommand:[GenericChromeCommand commandWithTag:tag]];
};
// Block to have the tab model open the tab at |index|, if there is one.
void (^focusTab)(NSUInteger) = ^(NSUInteger index) {
[weakConsumer focusTabAtIndex:index];
};
const BOOL hasTabs = [consumer tabsCount] > 0;
const BOOL useRTLLayout = UseRTLLayout();
const NSInteger browseLeft = useRTLLayout ? IDC_FORWARD : IDC_BACK;
const NSInteger browseRight = useRTLLayout ? IDC_BACK : IDC_FORWARD;
const int browseLeftDescriptionID = useRTLLayout
? IDS_IOS_KEYBOARD_HISTORY_FORWARD
: IDS_IOS_KEYBOARD_HISTORY_BACK;
const int browseRightDescriptionID = useRTLLayout
? IDS_IOS_KEYBOARD_HISTORY_BACK
: IDS_IOS_KEYBOARD_HISTORY_FORWARD;
BOOL (^canBrowseLeft)() = ^() {
return useRTLLayout ? [weakConsumer canGoForward]
: [weakConsumer canGoBack];
};
BOOL (^canBrowseRight)() = ^() {
return useRTLLayout ? [weakConsumer canGoBack]
: [weakConsumer canGoForward];
};
// Initialize the array of commands with an estimated capacity.
NSMutableArray* keyCommands = [NSMutableArray arrayWithCapacity:32];
// List the commands that always appear in the HUD. They appear in the HUD
// since they have titles.
[keyCommands addObjectsFromArray:@[
[UIKeyCommand cr_keyCommandWithInput:@"t"
modifierFlags:UIKeyModifierCommand
title:l10n_util::GetNSStringWithFixup(
IDS_IOS_TOOLS_MENU_NEW_TAB)
action:^{
if ([weakConsumer isOffTheRecord]) {
execute(IDC_NEW_INCOGNITO_TAB);
} else {
execute(IDC_NEW_TAB);
}
}],
[UIKeyCommand
cr_keyCommandWithInput:@"n"
modifierFlags:UIKeyModifierCommand | UIKeyModifierShift
title:l10n_util::GetNSStringWithFixup(
IDS_IOS_TOOLS_MENU_NEW_INCOGNITO_TAB)
action:^{
execute(IDC_NEW_INCOGNITO_TAB);
}],
[UIKeyCommand
cr_keyCommandWithInput:@"t"
modifierFlags:UIKeyModifierCommand | UIKeyModifierShift
title:l10n_util::GetNSStringWithFixup(
IDS_IOS_KEYBOARD_REOPEN_CLOSED_TAB)
action:^{
[weakConsumer reopenClosedTab];
}],
]];
// List the commands that only appear when there is at least a tab. When they
// appear, they are in the HUD since they have titles.
if (hasTabs) {
[keyCommands addObjectsFromArray:@[
[UIKeyCommand cr_keyCommandWithInput:@"l"
modifierFlags:UIKeyModifierCommand
title:l10n_util::GetNSStringWithFixup(
IDS_IOS_KEYBOARD_OPEN_LOCATION)
action:^{
[weakConsumer focusOmnibox];
}],
[UIKeyCommand cr_keyCommandWithInput:@"w"
modifierFlags:UIKeyModifierCommand
title:l10n_util::GetNSStringWithFixup(
IDS_IOS_TOOLS_MENU_CLOSE_TAB)
action:^{
execute(IDC_CLOSE_TAB);
}],
[UIKeyCommand
cr_keyCommandWithInput:@"d"
modifierFlags:UIKeyModifierCommand
title:l10n_util::GetNSStringWithFixup(
IDS_IOS_KEYBOARD_BOOKMARK_THIS_PAGE)
action:^{
execute(IDC_BOOKMARK_PAGE);
}],
[UIKeyCommand cr_keyCommandWithInput:@"f"
modifierFlags:UIKeyModifierCommand
title:l10n_util::GetNSStringWithFixup(
IDS_IOS_TOOLS_MENU_FIND_IN_PAGE)
action:^{
execute(IDC_FIND);
}],
[UIKeyCommand cr_keyCommandWithInput:@"g"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
execute(IDC_FIND_NEXT);
}],
[UIKeyCommand
cr_keyCommandWithInput:@"g"
modifierFlags:UIKeyModifierCommand | UIKeyModifierShift
title:nil
action:^{
execute(IDC_FIND_PREVIOUS);
}],
[UIKeyCommand cr_keyCommandWithInput:@"r"
modifierFlags:UIKeyModifierCommand
title:l10n_util::GetNSStringWithFixup(
IDS_IOS_ACCNAME_RELOAD)
action:^{
execute(IDC_RELOAD);
}],
]];
// Since cmd+left and cmd+right are valid system shortcuts when editing
// text, don't register those if text is being edited.
if (!editingText) {
[keyCommands addObjectsFromArray:@[
[UIKeyCommand cr_keyCommandWithInput:UIKeyInputLeftArrow
modifierFlags:UIKeyModifierCommand
title:l10n_util::GetNSStringWithFixup(
browseLeftDescriptionID)
action:^{
if (canBrowseLeft()) {
execute(browseLeft);
}
}],
[UIKeyCommand cr_keyCommandWithInput:UIKeyInputRightArrow
modifierFlags:UIKeyModifierCommand
title:l10n_util::GetNSStringWithFixup(
browseRightDescriptionID)
action:^{
if (canBrowseRight()) {
execute(browseRight);
}
}],
]];
}
NSString* voiceSearchTitle = l10n_util::GetNSStringWithFixup(
IDS_IOS_VOICE_SEARCH_KEYBOARD_DISCOVERY_TITLE);
[keyCommands addObjectsFromArray:@[
[UIKeyCommand cr_keyCommandWithInput:@"y"
modifierFlags:UIKeyModifierCommand
title:l10n_util::GetNSStringWithFixup(
IDS_HISTORY_SHOW_HISTORY)
action:^{
execute(IDC_SHOW_HISTORY);
}],
[UIKeyCommand
cr_keyCommandWithInput:@"."
modifierFlags:UIKeyModifierCommand | UIKeyModifierShift
title:voiceSearchTitle
action:^{
execute(IDC_VOICE_SEARCH);
}],
]];
}
// List the commands that don't appear in the HUD but are always present.
[keyCommands addObjectsFromArray:@[
[UIKeyCommand cr_keyCommandWithInput:UIKeyInputEscape
modifierFlags:Cr_UIKeyModifierNone
title:nil
action:^{
execute(IDC_CLOSE_MODALS);
}],
[UIKeyCommand cr_keyCommandWithInput:@"n"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
if ([weakConsumer isOffTheRecord]) {
execute(IDC_NEW_INCOGNITO_TAB);
} else {
execute(IDC_NEW_TAB);
}
}],
[UIKeyCommand cr_keyCommandWithInput:@","
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
execute(IDC_OPTIONS);
}],
]];
// List the commands that don't appear in the HUD and only appear when there
// is at least a tab.
if (hasTabs) {
[keyCommands addObjectsFromArray:@[
[UIKeyCommand cr_keyCommandWithInput:@"["
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
if (canBrowseLeft()) {
execute(browseLeft);
}
}],
[UIKeyCommand cr_keyCommandWithInput:@"]"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
if (canBrowseRight()) {
execute(browseRight);
}
}],
[UIKeyCommand cr_keyCommandWithInput:@"."
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
execute(IDC_STOP);
}],
[UIKeyCommand cr_keyCommandWithInput:@"?"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
execute(IDC_HELP_PAGE_VIA_MENU);
}],
[UIKeyCommand cr_keyCommandWithInput:@"1"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
focusTab(0);
}],
[UIKeyCommand cr_keyCommandWithInput:@"2"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
focusTab(1);
}],
[UIKeyCommand cr_keyCommandWithInput:@"3"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
focusTab(2);
}],
[UIKeyCommand cr_keyCommandWithInput:@"4"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
focusTab(3);
}],
[UIKeyCommand cr_keyCommandWithInput:@"5"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
focusTab(4);
}],
[UIKeyCommand cr_keyCommandWithInput:@"6"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
focusTab(5);
}],
[UIKeyCommand cr_keyCommandWithInput:@"7"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
focusTab(6);
}],
[UIKeyCommand cr_keyCommandWithInput:@"8"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
focusTab(7);
}],
[UIKeyCommand cr_keyCommandWithInput:@"9"
modifierFlags:UIKeyModifierCommand
title:nil
action:^{
focusTab([weakConsumer tabsCount] - 1);
}],
[UIKeyCommand
cr_keyCommandWithInput:UIKeyInputLeftArrow
modifierFlags:UIKeyModifierCommand | UIKeyModifierAlternate
title:nil
action:^{
[weakConsumer focusPreviousTab];
}],
[UIKeyCommand
cr_keyCommandWithInput:UIKeyInputRightArrow
modifierFlags:UIKeyModifierCommand | UIKeyModifierAlternate
title:nil
action:^{
[weakConsumer focusNextTab];
}],
]];
}
return keyCommands;
}
@end