From 906790226701c99aede853b0ff46bd1998b40aa0 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 9 Nov 2022 14:40:44 +0000 Subject: [PATCH] Added shortcut input controls to make custom shortcuts work --- .../Controllers/UserPreferencesController.php | 2 +- resources/js/components/index.js | 2 + resources/js/components/shortcut-input.js | 57 +++++++++++++++++++ resources/js/components/shortcuts.js | 30 +++++++--- .../parts/shortcut-control.blade.php | 3 +- .../users/preferences/shortcuts.blade.php | 7 ++- 6 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 resources/js/components/shortcut-input.js diff --git a/app/Http/Controllers/UserPreferencesController.php b/app/Http/Controllers/UserPreferencesController.php index b8bb31468..c4718681a 100644 --- a/app/Http/Controllers/UserPreferencesController.php +++ b/app/Http/Controllers/UserPreferencesController.php @@ -35,7 +35,7 @@ class UserPreferencesController extends Controller public function updateShortcuts(Request $request) { $enabled = $request->get('enabled') === 'true'; - $providedShortcuts = $request->get('shortcuts', []); + $providedShortcuts = $request->get('shortcut', []); $shortcuts = new UserShortcutMap($providedShortcuts); setting()->putUser(user(), 'ui-shortcuts', $shortcuts->toJson()); diff --git a/resources/js/components/index.js b/resources/js/components/index.js index 6203d0b74..ee282b1fd 100644 --- a/resources/js/components/index.js +++ b/resources/js/components/index.js @@ -44,6 +44,7 @@ import settingAppColorPicker from "./setting-app-color-picker.js" import settingColorPicker from "./setting-color-picker.js" import shelfSort from "./shelf-sort.js" import shortcuts from "./shortcuts"; +import shortcutInput from "./shortcut-input"; import sidebar from "./sidebar.js" import sortableList from "./sortable-list.js" import submitOnChange from "./submit-on-change.js" @@ -103,6 +104,7 @@ const componentMapping = { "setting-color-picker": settingColorPicker, "shelf-sort": shelfSort, "shortcuts": shortcuts, + "shortcut-input": shortcutInput, "sidebar": sidebar, "sortable-list": sortableList, "submit-on-change": submitOnChange, diff --git a/resources/js/components/shortcut-input.js b/resources/js/components/shortcut-input.js new file mode 100644 index 000000000..fa1378988 --- /dev/null +++ b/resources/js/components/shortcut-input.js @@ -0,0 +1,57 @@ +/** + * Keys to ignore when recording shortcuts. + * @type {string[]} + */ +const ignoreKeys = ['Control', 'Alt', 'Shift', 'Meta', 'Super', ' ', '+', 'Tab', 'Escape']; + +/** + * @extends {Component} + */ +class ShortcutInput { + + setup() { + this.input = this.$el; + + this.setupListeners(); + } + + setupListeners() { + this.listenerRecordKey = this.listenerRecordKey.bind(this); + + this.input.addEventListener('focus', () => { + this.startListeningForInput(); + }); + + this.input.addEventListener('blur', () => { + this.stopListeningForInput(); + }) + } + + startListeningForInput() { + this.input.addEventListener('keydown', this.listenerRecordKey) + } + + /** + * @param {KeyboardEvent} event + */ + listenerRecordKey(event) { + if (ignoreKeys.includes(event.key)) { + return; + } + + const keys = [ + event.ctrlKey ? 'Ctrl' : '', + event.metaKey ? 'Cmd' : '', + event.key, + ]; + + this.input.value = keys.filter(s => Boolean(s)).join(' + '); + } + + stopListeningForInput() { + this.input.removeEventListener('keydown', this.listenerRecordKey); + } + +} + +export default ShortcutInput; \ No newline at end of file diff --git a/resources/js/components/shortcuts.js b/resources/js/components/shortcuts.js index ccad00f5d..cec8684c8 100644 --- a/resources/js/components/shortcuts.js +++ b/resources/js/components/shortcuts.js @@ -30,13 +30,7 @@ class Shortcuts { return; } - const shortcutId = this.mapByShortcut[event.key]; - if (shortcutId) { - const wasHandled = this.runShortcut(shortcutId); - if (wasHandled) { - event.preventDefault(); - } - } + this.handleShortcutPress(event); }); window.addEventListener('keydown', event => { @@ -46,6 +40,28 @@ class Shortcuts { }); } + /** + * @param {KeyboardEvent} event + */ + handleShortcutPress(event) { + + const keys = [ + event.ctrlKey ? 'Ctrl' : '', + event.metaKey ? 'Cmd' : '', + event.key, + ]; + + const combo = keys.filter(s => Boolean(s)).join(' + '); + + const shortcutId = this.mapByShortcut[combo]; + if (shortcutId) { + const wasHandled = this.runShortcut(shortcutId); + if (wasHandled) { + event.preventDefault(); + } + } + } + /** * Run the given shortcut, and return a boolean to indicate if the event * was successfully handled by a shortcut action. diff --git a/resources/views/users/preferences/parts/shortcut-control.blade.php b/resources/views/users/preferences/parts/shortcut-control.blade.php index 47fec3a5e..b85813ce0 100644 --- a/resources/views/users/preferences/parts/shortcut-control.blade.php +++ b/resources/views/users/preferences/parts/shortcut-control.blade.php @@ -1,7 +1,8 @@
- +

Here you can enable or disable keyboard system interface shortcuts, used for navigation - and actions. You can customize each of the shortcuts below. + and actions. + + You can customize each of the shortcuts below. Just press your desired key combination + after selecting the input for a shortcut.

-
+
@include('form.toggle-switch', [ 'name' => 'enabled', 'value' => $enabled,