Replace KeyboardShortcutMixin by addShortcut() util in 3 dialogs
Google-Bug-Id: b/199305453
Change-Id: Id5e1ece4e5eb8cbaa6bc627c05d2bd61c39b6d6d
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts
index 07da53f..df537e0 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts
@@ -19,9 +19,9 @@
import '../../../styles/shared-styles';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-confirm-abandon-dialog_html';
-import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {customElement, property} from '@polymer/decorators';
import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import {addShortcut, Key, Modifier} from '../../../utils/dom-util';
export interface GrConfirmAbandonDialog {
$: {
@@ -35,11 +35,8 @@
}
}
-// This avoids JSC_DYNAMIC_EXTENDS_WITHOUT_JSDOC closure compiler error.
-const base = KeyboardShortcutMixin(PolymerElement);
-
@customElement('gr-confirm-abandon-dialog')
-export class GrConfirmAbandonDialog extends base {
+export class GrConfirmAbandonDialog extends PolymerElement {
static get template() {
return htmlTemplate;
}
@@ -59,20 +56,33 @@
@property({type: String})
message = '';
- get keyBindings() {
- return {
- 'ctrl+enter meta+enter': '_handleEnterKey',
- };
+ /** Called in disconnectedCallback. */
+ private cleanups: (() => void)[] = [];
+
+ override disconnectedCallback() {
+ super.disconnectedCallback();
+ for (const cleanup of this.cleanups) cleanup();
+ this.cleanups = [];
+ }
+
+ override connectedCallback() {
+ super.connectedCallback();
+ this.cleanups.push(
+ addShortcut(this, {key: Key.ENTER, modifiers: [Modifier.CTRL_KEY]}, _ =>
+ this._confirm()
+ )
+ );
+ this.cleanups.push(
+ addShortcut(this, {key: Key.ENTER, modifiers: [Modifier.META_KEY]}, _ =>
+ this._confirm()
+ )
+ );
}
resetFocus() {
this.$.messageInput.textarea.focus();
}
- _handleEnterKey() {
- this._confirm();
- }
-
_handleConfirmTap(e: Event) {
e.preventDefault();
e.stopPropagation();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
index 8e6521d..b3bbc8a 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
@@ -19,17 +19,14 @@
import '../../shared/gr-dialog/gr-dialog';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-confirm-move-dialog_html';
-import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {customElement, property} from '@polymer/decorators';
import {BranchName, RepoName} from '../../../types/common';
import {appContext} from '../../../services/app-context';
import {GrTypedAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
+import {addShortcut, Key, Modifier} from '../../../utils/dom-util';
const SUGGESTIONS_LIMIT = 15;
-// This avoids JSC_DYNAMIC_EXTENDS_WITHOUT_JSDOC closure compiler error.
-const base = KeyboardShortcutMixin(PolymerElement);
-
// This is used to make sure 'branch'
// can be typed as BranchName.
export interface GrConfirmMoveDialog {
@@ -39,7 +36,7 @@
}
@customElement('gr-confirm-move-dialog')
-export class GrConfirmMoveDialog extends base {
+export class GrConfirmMoveDialog extends PolymerElement {
static get template() {
return htmlTemplate;
}
@@ -68,10 +65,27 @@
@property({type: Object})
_query?: (input: string) => Promise<{name: BranchName}[]>;
- get keyBindings() {
- return {
- 'ctrl+enter meta+enter': '_handleConfirmTap',
- };
+ /** Called in disconnectedCallback. */
+ private cleanups: (() => void)[] = [];
+
+ override disconnectedCallback() {
+ super.disconnectedCallback();
+ for (const cleanup of this.cleanups) cleanup();
+ this.cleanups = [];
+ }
+
+ override connectedCallback() {
+ super.connectedCallback();
+ this.cleanups.push(
+ addShortcut(this, {key: Key.ENTER, modifiers: [Modifier.CTRL_KEY]}, e =>
+ this._handleConfirmTap(e)
+ )
+ );
+ this.cleanups.push(
+ addShortcut(this, {key: Key.ENTER, modifiers: [Modifier.META_KEY]}, e =>
+ this._handleConfirmTap(e)
+ )
+ );
}
private readonly restApiService = appContext.restApiService;
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
index 17036e6..be57ef6 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
@@ -38,7 +38,6 @@
ReviewerState,
SpecialFilePath,
} from '../../../constants/constants';
-import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {
accountOrGroupKey,
isReviewerOrCC,
@@ -116,6 +115,7 @@
import {StorageLocation} from '../../../services/storage/gr-storage';
import {Interaction, Timing} from '../../../constants/reporting';
import {getReplyByReason} from '../../../utils/attention-set-util';
+import {addShortcut, Key, Modifier} from '../../../utils/dom-util';
const STORAGE_DEBOUNCE_INTERVAL_MS = 400;
@@ -163,11 +163,8 @@
};
}
-// This avoids JSC_DYNAMIC_EXTENDS_WITHOUT_JSDOC closure compiler error.
-const base = KeyboardShortcutMixin(PolymerElement);
-
@customElement('gr-reply-dialog')
-export class GrReplyDialog extends base {
+export class GrReplyDialog extends PolymerElement {
static get template() {
return htmlTemplate;
}
@@ -368,12 +365,8 @@
private storeTask?: DelayedTask;
- get keyBindings() {
- return {
- esc: '_handleEscKey',
- 'ctrl+enter meta+enter': '_handleEnterKey',
- };
- }
+ /** Called in disconnectedCallback. */
+ private cleanups: (() => void)[] = [];
constructor() {
super();
@@ -391,6 +384,17 @@
if (account) this._account = account;
});
+ this.cleanups.push(
+ addShortcut(this, {key: Key.ENTER, modifiers: [Modifier.CTRL_KEY]}, _ =>
+ this._submit()
+ )
+ );
+ this.cleanups.push(
+ addShortcut(this, {key: Key.ENTER, modifiers: [Modifier.META_KEY]}, _ =>
+ this._submit()
+ )
+ );
+ this.cleanups.push(addShortcut(this, {key: Key.ESC}, _ => this.cancel()));
this.addEventListener('comment-editing-changed', e => {
this._commentEditing = (e as CustomEvent).detail;
});
@@ -418,6 +422,8 @@
override disconnectedCallback() {
this.storeTask?.cancel();
+ for (const cleanup of this.cleanups) cleanup();
+ this.cleanups = [];
super.disconnectedCallback();
}
@@ -492,14 +498,6 @@
return (selectorEl as GrLabelScoreRow).selectedValue;
}
- _handleEscKey() {
- this.cancel();
- }
-
- _handleEnterKey() {
- this._submit();
- }
-
@observe('_ccs.splices')
_ccsChanged(splices: PolymerSpliceChange<AccountInfo[] | GroupInfo[]>) {
this._reviewerTypeChanged(splices, ReviewerType.CC);
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
index e57ffc7..91b8603 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
@@ -1799,7 +1799,7 @@
test('emits cancel on esc key', () => {
const cancelHandler = sinon.spy();
element.addEventListener('cancel', cancelHandler);
- pressAndReleaseKeyOn(element, 27, null, 'esc');
+ pressAndReleaseKeyOn(element, 27, null, 'Escape');
flush();
assert.isTrue(cancelHandler.called);
@@ -1808,14 +1808,14 @@
test('should not send on enter key', () => {
stubSaveReview(() => undefined);
element.addEventListener('send', () => assert.fail('wrongly called'));
- pressAndReleaseKeyOn(element, 13, null, 'enter');
+ pressAndReleaseKeyOn(element, 13, null, 'Enter');
});
test('emit send on ctrl+enter key', async () => {
stubSaveReview(() => undefined);
const promise = mockPromise();
element.addEventListener('send', () => promise.resolve());
- pressAndReleaseKeyOn(element, 13, 'ctrl', 'enter');
+ pressAndReleaseKeyOn(element, 13, 'ctrl', 'Enter');
await promise;
});
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
index e7417f4..deb45d3 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
@@ -70,7 +70,7 @@
import {anyLineTooLong} from '../../diff/gr-diff/gr-diff-utils';
import {getUserName} from '../../../utils/display-name-util';
import {generateAbsoluteUrl} from '../../../utils/url-util';
-import {addShortcut} from '../../../utils/dom-util';
+import {addGlobalShortcut} from '../../../utils/dom-util';
const UNRESOLVED_EXPAND_COUNT = 5;
const NEWLINE_PATTERN = /\n/g;
@@ -239,10 +239,10 @@
override connectedCallback() {
super.connectedCallback();
this.cleanups.push(
- addShortcut({key: 'e'}, e => this.handleExpandShortcut(e))
+ addGlobalShortcut({key: 'e'}, e => this.handleExpandShortcut(e))
);
this.cleanups.push(
- addShortcut({key: 'E'}, e => this.handleCollapseShortcut(e))
+ addGlobalShortcut({key: 'E'}, e => this.handleCollapseShortcut(e))
);
this._getLoggedIn().then(loggedIn => {
this._showActions = loggedIn;
diff --git a/polygerrit-ui/app/utils/dom-util.ts b/polygerrit-ui/app/utils/dom-util.ts
index cdcadb0..a7ad6e1 100644
--- a/polygerrit-ui/app/utils/dom-util.ts
+++ b/polygerrit-ui/app/utils/dom-util.ts
@@ -379,7 +379,15 @@
return true;
}
+export function addGlobalShortcut(
+ shortcut: Shortcut,
+ listener: (e: KeyboardEvent) => void
+) {
+ return addShortcut(document.body, shortcut, listener);
+}
+
export function addShortcut(
+ element: HTMLElement,
shortcut: Shortcut,
listener: (e: KeyboardEvent) => void
) {
@@ -387,8 +395,8 @@
if (e.repeat) return;
if (eventMatchesShortcut(e, shortcut)) listener(e);
};
- document.addEventListener('keydown', wrappedListener);
- return () => document.removeEventListener('keydown', wrappedListener);
+ element.addEventListener('keydown', wrappedListener);
+ return () => element.removeEventListener('keydown', wrappedListener);
}
export function modifierPressed(e: KeyboardEvent) {