Suppress keyboard shortcuts if user has disabled them

Change 292033 added a user preference to disable all keyboard
shortcuts.
Suppress all keyboard shortcuts if user has enabled this setting.

Bug: Issue 13571
Change-Id: I4750e270aa12c1c82db32fdf357dc91fe8496fc4
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js
index 092daa2..3f6148b 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.js
@@ -21,6 +21,7 @@
 import {__testOnly_ErrorType} from './gr-error-manager.js';
 import {stubRestApi} from '../../../test/test-utils.js';
 import {appContext} from '../../../services/app-context.js';
+import {createPreferences} from '../../../test/test-data-generators.js';
 
 const basicFixture = fixtureFromElement('gr-error-manager');
 
@@ -40,6 +41,8 @@
           .returns(Promise.resolve({ok: true, status: 204}));
       getLoggedInStub = stubRestApi('getLoggedIn')
           .callsFake(() => appContext.authService.authCheck());
+      stubRestApi('getPreferences').returns(Promise.resolve(
+          createPreferences()));
       element = basicFixture.instantiate();
       element._authService.clearCache();
       toastSpy = sinon.spy(element, '_createToastAlert');
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
index 809139d..3c00a47 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
@@ -76,6 +76,7 @@
   'email_strategy',
   'diff_view',
   'publish_comments_on_push',
+  'disable_keyboard_shortcuts',
   'work_in_progress_by_default',
   'default_base_for_merges',
   'signed_off_by',
@@ -114,6 +115,7 @@
     workInProgressByDefault: HTMLInputElement;
     showSizeBarsInFileList: HTMLInputElement;
     publishCommentsOnPush: HTMLInputElement;
+    disableKeyboardShortcuts: HTMLInputElement;
     relativeDateInChangeTable: HTMLInputElement;
   };
 }
@@ -384,6 +386,13 @@
     );
   }
 
+  _handleDisableKeyboardShortcutsChanged() {
+    this.set(
+      '_localPrefs.disable_keyboard_shortcuts',
+      this.$.disableKeyboardShortcuts.checked
+    );
+  }
+
   _handleWorkInProgressByDefault() {
     this.set(
       '_localPrefs.work_in_progress_by_default',
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
index 11372a1..b141a86 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
@@ -278,6 +278,19 @@
           </span>
         </section>
         <section>
+          <label for="disableKeyboardShortcuts" class="title"
+            >Disable all keyboard shortcuts</label
+          >
+          <span class="value">
+            <input
+              id="disableKeyboardShortcuts"
+              type="checkbox"
+              checked$="[[_localPrefs.disable_keyboard_shortcuts]]"
+              on-change="_handleDisableKeyboardShortcutsChanged"
+            />
+          </span>
+        </section>
+        <section>
           <label for="insertSignedOff" class="title">
             Insert Signed-off-by Footer For Inline Edit Changes
           </label>
diff --git a/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts b/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts
index 881e102..9bd2f5a 100644
--- a/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts
+++ b/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts
@@ -107,6 +107,7 @@
   CustomKeyboardEvent,
   ShortcutTriggeredEventDetail,
 } from '../../types/events';
+import {appContext} from '../../services/app-context';
 
 /** Enum for all special shortcuts */
 export enum SPECIAL_SHORTCUT {
@@ -805,6 +806,10 @@
 
       ShortcutSection = ShortcutSection;
 
+      private _disableKeyboardShortcuts = false;
+
+      private restApiService = appContext.restApiService;
+
       modifierPressed(event: CustomKeyboardEvent) {
         /* We are checking for g/v as modifiers pressed. There are cases such as
          * pressing v and then /, where we want the handler for / to be triggered.
@@ -826,6 +831,7 @@
       }
 
       shouldSuppressKeyboardShortcut(event: CustomKeyboardEvent) {
+        if (this._disableKeyboardShortcuts) return true;
         const e = getKeyboardEvent(event);
         // TODO(TS): maybe override the EventApi, narrow it down to Element always
         const target = (dom(e) as EventApi).rootTarget as Element;
@@ -926,6 +932,13 @@
       /** @override */
       connectedCallback() {
         super.connectedCallback();
+
+        this.restApiService.getPreferences().then(prefs => {
+          if (prefs?.disable_keyboard_shortcuts) {
+            this._disableKeyboardShortcuts = true;
+          }
+        });
+
         const shortcuts = shortcutManager.attachHost(this);
         if (!shortcuts) {
           return;
diff --git a/polygerrit-ui/app/types/common.ts b/polygerrit-ui/app/types/common.ts
index 5f196b1..2ef4df6 100644
--- a/polygerrit-ui/app/types/common.ts
+++ b/polygerrit-ui/app/types/common.ts
@@ -1756,6 +1756,7 @@
   email_strategy: EmailStrategy;
   default_base_for_merges: DefaultBase;
   publish_comments_on_push?: boolean;
+  disable_keyboard_shortcuts?: boolean;
   work_in_progress_by_default?: boolean;
   // The email_format doesn't mentioned in doc, but exists in Java class GeneralPreferencesInfo
   email_format?: EmailFormat;