Update GrReplyDialog to use ShortcutController

Release-Notes: skip
Google-bug-id: b/242982372
Change-Id: I9c750da9226fef6d6e83b2e7f07470d71b503014
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index 04a9fea..c48793d 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -625,7 +625,6 @@
 
   private setupShortcuts() {
     // TODO: Do we still need docOnly bindings?
-    this.shortcutsController.addAbstract(Shortcut.SEND_REPLY, () => {}); // docOnly
     this.shortcutsController.addAbstract(Shortcut.EMOJI_DROPDOWN, () => {}); // docOnly
     this.shortcutsController.addAbstract(Shortcut.MENTIONS_DROPDOWN, () => {}); // docOnly
     this.shortcutsController.addAbstract(Shortcut.REFRESH_CHANGE, () =>
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 2773675..47d7ed4 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
@@ -103,7 +103,6 @@
 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';
 import {RestApiService} from '../../../services/gr-rest-api/gr-rest-api';
 import {resolve} from '../../../models/dependency';
 import {changeModelToken} from '../../../models/change/change-model';
@@ -127,6 +126,8 @@
   CommentEditingChangedDetail,
   GrComment,
 } from '../../shared/gr-comment/gr-comment';
+import {Shortcut, ShortcutController} from '../../lit/shortcut-controller';
+import {Key} from '../../../utils/dom-util';
 
 const STORAGE_DEBOUNCE_INTERVAL_MS = 400;
 
@@ -403,8 +404,7 @@
 
   private isLoggedIn = false;
 
-  /** Called in disconnectedCallback. */
-  private cleanups: (() => void)[] = [];
+  private readonly shortcuts = new ShortcutController(this);
 
   static override styles = [
     sharedStyles,
@@ -650,6 +650,10 @@
       this.filterReviewerSuggestionGenerator(false);
     this.filterCCSuggestion = this.filterReviewerSuggestionGenerator(true);
     this.jsAPI.addElement(TargetElement.REPLY_DIALOG, this);
+
+    this.shortcuts.addLocal({key: Key.ESC}, () => this.cancel());
+    this.shortcuts.addAbstract(Shortcut.SEND_REPLY, () => this.submit());
+
     subscribe(
       this,
       () => getAppContext().userModel.loggedIn$,
@@ -717,17 +721,6 @@
       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: CustomEvent<CommentEditingChangedDetail>) => {
@@ -805,8 +798,6 @@
 
   override disconnectedCallback() {
     this.storeTask?.flush();
-    for (const cleanup of this.cleanups) cleanup();
-    this.cleanups = [];
     super.disconnectedCallback();
   }
 
diff --git a/polygerrit-ui/app/elements/lit/shortcut-controller.ts b/polygerrit-ui/app/elements/lit/shortcut-controller.ts
index b77874d..b5660a2 100644
--- a/polygerrit-ui/app/elements/lit/shortcut-controller.ts
+++ b/polygerrit-ui/app/elements/lit/shortcut-controller.ts
@@ -45,10 +45,12 @@
   // disabled or when the event comes from elements like <input>. So this method
   // is intended for shortcuts like ESC and Ctrl-ENTER.
   // If you need suppressed local shortcuts, then just add an options parameter.
+  // Call method in constructor of the component
   addLocal(binding: Binding, listener: (e: KeyboardEvent) => void) {
     this.listenersLocal.push({binding, listener});
   }
 
+  // Call method in constructor of the component
   addGlobal(binding: Binding, listener: (e: KeyboardEvent) => void) {
     this.listenersGlobal.push({binding, listener});
   }
@@ -60,6 +62,8 @@
    *
    * Use this method when you are migrating from Polymer to Lit. Call it for
    * each entry of keyboardShortcuts().
+   *
+   * Call method in constructor of the component
    */
   addAbstract(
     shortcut: Shortcut,
diff --git a/polygerrit-ui/app/services/shortcuts/shortcuts-config.ts b/polygerrit-ui/app/services/shortcuts/shortcuts-config.ts
index a7f4d19..7d1535c 100644
--- a/polygerrit-ui/app/services/shortcuts/shortcuts-config.ts
+++ b/polygerrit-ui/app/services/shortcuts/shortcuts-config.ts
@@ -522,8 +522,8 @@
     Shortcut.SEND_REPLY,
     ShortcutSection.REPLY_DIALOG,
     'Send reply',
-    {key: Key.ENTER, modifiers: [Modifier.CTRL_KEY], docOnly: true},
-    {key: Key.ENTER, modifiers: [Modifier.META_KEY], docOnly: true}
+    {key: Key.ENTER, modifiers: [Modifier.CTRL_KEY]},
+    {key: Key.ENTER, modifiers: [Modifier.META_KEY]}
   );
   describe(
     Shortcut.EMOJI_DROPDOWN,