Files
react-native-devtools-frontend/front_end/settings/KeybindsSettingsTab.js
T
Jack Lynch f1f00fa32a Add VS Code shortcuts as an option
This CL adds the ability (hidden behind an experiment) for users to
select a set of shortcuts to use, the two options initially being the
default shortcuts and shortcuts that match those from VS Code. A new
`keybindSets` array is added to binding objects in module.jsons,
allowing shortcuts to be filtered on launch much like the existing
platform option. Also like platform, if the keybindSets array is
undefined for a shortcut then that shortcut will be considered common to
all keybindSets.

In general, I left keybindSets undefined for default DevTools shortcuts
that do not conflict with VS Code shortcuts so that they remain common
shortcuts. When both the DevTools and VS Code define the same shortcut,
I add both sets to keybindSets.

This should only affect users who have opted into the custom keyboard
shortcuts experiment. If a user with the experiment enabled selects VS
Code shortcuts and then turns the experiment off, ShortcutRegistry will
reset the shortcuts to the DevTools default on next launch.

Enumerating the differences between VS Code and the DevTools default
shortcuts uncovered some workflows that we'd like to add shortcuts for
that do not currently have actions in the DevTools, such as save as and
find/replace. I plan to add those in future CLs.

Due to problems with ListWidget's accessibility, I have to manually add
aria roles to the list and list items. This is a temporary state of
affairs until this tab is changed to use ListControl rather than
ListWidget for better accessibility. Since the ListWidget here contains
no editable items and is only marked as a list, there are no keyboard
navigation or focus management requirements to worry about yet.

I have put up a telemetry CL here so that we can evaluate the success of
the feature:
https://chromium-review.googlesource.com/c/chromium/src/+/2172132

Screenshots:
  https://i.imgur.com/ka0VEyM.png
  https://i.imgur.com/CG8hAro.png

Custom shortcuts design doc: https://docs.google.com/document/d/1oOPSWPxCHvMoBZ0Fw9jwFZt6gP4lrsrsl8DEAp-Hy7o/edit#

Bug: 174309
Change-Id: I0e3484eb2712c945121cc7b68e14a1a98f858bab
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2095859
Reviewed-by: John Emau <John.Emau@microsoft.com>
Reviewed-by: Songtao Xia <soxia@microsoft.com>
Commit-Queue: Jack Lynch <jalyn@microsoft.com>
2020-05-01 23:48:06 +00:00

114 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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.
import * as UI from '../ui/ui.js';
/**
* @implements {UI.ListWidget.Delegate}
*/
export class KeybindsSettingsTab extends UI.Widget.VBox {
constructor() {
super(true);
this.registerRequiredCSS('settings/keybindsSettingsTab.css');
this._actions = self.UI.actionRegistry.actions().sort((actionA, actionB) => {
if (actionA.category() < actionB.category()) {
return -1;
}
if (actionA.category() > actionB.category()) {
return 1;
}
if (actionA.id() < actionB.id()) {
return -1;
}
if (actionA.id() > actionB.id()) {
return 1;
}
return 0;
});
const header = this.contentElement.createChild('header');
header.createChild('h1').textContent = ls`Shortcuts`;
const keybindsSetSetting = self.Common.settings.moduleSetting('activeKeybindSet');
keybindsSetSetting.addChangeListener(this.update, this);
const keybindsSetSelect =
UI.SettingsUI.createControlForSetting(keybindsSetSetting, ls`Match shortcuts from preset`);
keybindsSetSelect.classList.add('keybinds-set-select');
this.contentElement.appendChild(keybindsSetSelect);
this._list = new UI.ListWidget.ListWidget(this);
UI.ARIAUtils.markAsList(this._list.element);
this._list.registerRequiredCSS('settings/keybindsSettingsTab.css');
this._list.show(this.contentElement);
this.update();
}
/**
* @override
* @param {!KeybindsItem} item
* @return {!Element}
*/
renderItem(item) {
const itemElement = document.createElement('div');
itemElement.classList.add('keybinds-list-item');
UI.ARIAUtils.markAsListitem(itemElement);
if (typeof item === 'string') {
itemElement.classList.add('keybinds-category-header');
itemElement.textContent = item;
} else {
itemElement.createChild('div', 'keybinds-action-name keybinds-list-text').textContent = item.title();
const shortcuts = self.UI.shortcutRegistry.shortcutsForAction(item.id());
shortcuts.forEach((shortcut, index) => {
const shortcutElement = itemElement.createChild('div', 'keybinds-shortcut keybinds-list-text');
const keys = shortcut.descriptors.flatMap(descriptor => descriptor.name.split(' + '));
keys.forEach(key => shortcutElement.createChild('span', 'keybinds-key').textContent = key);
});
}
return itemElement;
}
/**
* @override
* @param {!KeybindsItem} item
* @param {number} index
*/
removeItemRequested(item, index) {
}
/**
* None of the items are editable, so this method will never be called
* @override
* @param {!KeybindsItem} item
* @return {!UI.ListWidget.Editor<!KeybindsItem>}
*/
beginEdit(item) {
return new UI.ListWidget.Editor();
}
/**
* @override
* @param {!KeybindsItem} item
* @param {!UI.ListWidget.Editor<!KeybindsItem>} editor
* @param {boolean} isNew
*/
commitEdit(item, editor, isNew) {
}
update() {
this._list.clear();
let currentCategory;
this._actions.forEach(action => {
if (currentCategory !== action.category()) {
this._list.appendItem(action.category(), false);
}
this._list.appendItem(action, false);
currentCategory = action.category();
});
}
}
/** @typedef {string|!UI.Action.Action} */
export let KeybindsItem;