diff --git a/app/src/components/v-dialog/v-dialog.vue b/app/src/components/v-dialog/v-dialog.vue index 08b8529eaf..7a40ec3fb9 100644 --- a/app/src/components/v-dialog/v-dialog.vue +++ b/app/src/components/v-dialog/v-dialog.vue @@ -33,10 +33,10 @@ export default defineComponent({ }, setup(props, { emit }) { const dialog = ref(null); - useShortcut('escape', (event) => { + useShortcut('escape', (event, cancelNext) => { if (_active.value) { emitToggle(); - event.cancelNext(); + cancelNext(); } }); diff --git a/app/src/composables/use-shortcut/use-shortcut.ts b/app/src/composables/use-shortcut/use-shortcut.ts index f974fd3143..d471ecb3d0 100644 --- a/app/src/composables/use-shortcut/use-shortcut.ts +++ b/app/src/composables/use-shortcut/use-shortcut.ts @@ -1,11 +1,7 @@ import { onMounted, onUnmounted, Ref, ref } from '@vue/composition-api'; import Vue from 'vue'; -type ShortcutHandler = (event: CancelableKeyboardEvent) => void | any | boolean; - -interface CancelableKeyboardEvent extends KeyboardEvent { - cancelNext: () => void; -} +type ShortcutHandler = (event: KeyboardEvent, cancelNext: () => void) => void | any | boolean; const keysdown: Set = new Set([]); const handlers: Record = {}; @@ -23,11 +19,56 @@ document.body.addEventListener('keyup', (event: KeyboardEvent) => { keysdown.delete(key.toUpperCase()); }); +export default function useShortcut( + shortcuts: string | string[], + handler: ShortcutHandler, + reference: Ref | Ref = ref(document.body) +) { + const callback: ShortcutHandler = (event, cancelNext) => { + if (!reference.value) return; + const ref = reference.value instanceof HTMLElement ? reference.value : (reference.value.$el as HTMLElement); + + if ( + document.activeElement === ref || + ref.contains(document.activeElement) || + document.activeElement === document.body + ) { + event.preventDefault(); + return handler(event, cancelNext); + } + + return false; + }; + + onMounted(() => { + [shortcuts].flat().forEach((shortcut) => { + if (handlers.hasOwnProperty(shortcut)) { + handlers[shortcut].unshift(callback); + } else { + handlers[shortcut] = [callback]; + } + }); + }); + + onUnmounted(() => { + [shortcuts].flat().forEach((shortcut) => { + if (handlers.hasOwnProperty(shortcut)) { + handlers[shortcut] = handlers[shortcut].filter((f) => f !== callback); + + if (handlers[shortcut].length === 0) { + delete handlers[shortcut]; + } + } + }); + }); +} + function mapKeys(key: string) { const map: Record = { Control: 'meta', Command: 'meta', }; + key = map.hasOwnProperty(key) ? map[key] : key; if (key.match(/^[a-z]$/) !== null) { @@ -44,56 +85,20 @@ function mapKeys(key: string) { function callHandlers(event: KeyboardEvent) { Object.entries(handlers).forEach(([key, value]) => { const rest = key.split('+').filter((keySegment) => keysdown.has(keySegment) === false); + if (rest.length > 0) return; + for (let i = 0; i < value.length; i++) { let cancel = false; - (event as CancelableKeyboardEvent).cancelNext = () => { - cancel = true; - }; - value[i](event as CancelableKeyboardEvent); + + value[i](event, cancelNext); // if cancelNext is called, discontinue going through the queue. if (typeof cancel === 'boolean' && cancel) break; + + function cancelNext() { + cancel = true; + } } }); } - -export default function useShortcut( - shortcuts: string | string[], - handler: ShortcutHandler, - reference: Ref | Ref = ref(document.body) -) { - const callback: ShortcutHandler = (event) => { - if (!reference.value) return; - const ref = reference.value instanceof HTMLElement ? reference.value : (reference.value.$el as HTMLElement); - - if ( - document.activeElement === ref || - ref.contains(document.activeElement) || - document.activeElement === document.body - ) { - event.preventDefault(); - return handler(event); - } - return false; - }; - onMounted(() => { - [shortcuts].flat().forEach((shortcut) => { - if (handlers.hasOwnProperty(shortcut)) { - handlers[shortcut].unshift(callback); - } else { - handlers[shortcut] = [callback]; - } - }); - }); - onUnmounted(() => { - [shortcuts].flat().forEach((shortcut) => { - if (handlers.hasOwnProperty(shortcut)) { - handlers[shortcut] = handlers[shortcut].filter((f) => f !== callback); - if (handlers[shortcut].length === 0) { - delete handlers[shortcut]; - } - } - }); - }); -}