mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-04-19 05:29:44 +00:00
feat: implement global context-aware keyboard shortcuts and modal keyboard support (Enter/Esc)
This commit is contained in:
parent
696961ea4c
commit
791d78884d
7 changed files with 36 additions and 5 deletions
|
|
@ -816,7 +816,7 @@ export default {
|
||||||
windowResize() {
|
windowResize() {
|
||||||
this.executeRebuild()
|
this.executeRebuild()
|
||||||
},
|
},
|
||||||
|
initListeners() {
|
||||||
window.addEventListener('resize', this.windowResize)
|
window.addEventListener('resize', this.windowResize)
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<modals-modal v-model="show" name="batchQuickMatch" :processing="processing" :width="500" :height="'unset'">
|
<modals-modal v-model="show" name="batchQuickMatch" :processing="processing" :width="500" :height="'unset'" @submit="doBatchQuickMatch">
|
||||||
<template #outer>
|
<template #outer>
|
||||||
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
|
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
|
||||||
<p class="text-3xl text-white truncate">{{ title }}</p>
|
<p class="text-3xl text-white truncate">{{ title }}</p>
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,13 @@ export default {
|
||||||
if (this.$store.state.innerModalOpen) return
|
if (this.$store.state.innerModalOpen) return
|
||||||
if (action === this.$hotkeys.Modal.CLOSE) {
|
if (action === this.$hotkeys.Modal.CLOSE) {
|
||||||
this.show = false
|
this.show = false
|
||||||
|
} else if (action === this.$hotkeys.Modal.SUBMIT) {
|
||||||
|
const activeElement = document.activeElement
|
||||||
|
// Don't submit if we are in a textarea or certain inputs
|
||||||
|
if (activeElement && ['TEXTAREA'].includes(activeElement.tagName)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$emit('submit')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setShow() {
|
setShow() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<modals-modal ref="modal" v-model="show" name="move-to-library" :width="400" :height="'unset'" :processing="processing">
|
<modals-modal ref="modal" v-model="show" name="move-to-library" :width="400" :height="'unset'" :processing="processing" @submit="moveItems">
|
||||||
<template #outer>
|
<template #outer>
|
||||||
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
|
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
|
||||||
<p class="text-3xl text-white truncate">{{ $strings.LabelMoveToLibrary }}</p>
|
<p class="text-3xl text-white truncate">{{ $strings.LabelMoveToLibrary }}</p>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<modals-modal ref="modal" v-model="show" name="split-book" :width="600" :height="'unset'" :processing="processing">
|
<modals-modal ref="modal" v-model="show" name="split-book" :width="600" :height="'unset'" :processing="processing" @submit="submit">
|
||||||
<template #outer>
|
<template #outer>
|
||||||
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
|
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
|
||||||
<p class="text-3xl text-white truncate">{{ $strings.HeaderSplitBook || 'Split Book' }}</p>
|
<p class="text-3xl text-white truncate">{{ $strings.HeaderSplitBook || 'Split Book' }}</p>
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,25 @@ export default {
|
||||||
this.$eventBus.$emit('showing-prompt', false)
|
this.$eventBus.$emit('showing-prompt', false)
|
||||||
this.content.style.transform = 'scale(0)'
|
this.content.style.transform = 'scale(0)'
|
||||||
this.el.remove()
|
this.el.remove()
|
||||||
|
},
|
||||||
|
handleKeyDown(e) {
|
||||||
|
if (!this.show) return
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
const activeElement = document.activeElement
|
||||||
|
// If an input is focused, let it handle the enter key if it wants,
|
||||||
|
// but ui-checkbox is okay to override if needed.
|
||||||
|
// Actually for a simple confirm prompt, Enter should usually confirm.
|
||||||
|
if (activeElement && ['INPUT', 'TEXTAREA'].includes(activeElement.tagName) && activeElement.type !== 'checkbox') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
this.confirm()
|
||||||
|
} else if (e.key === 'Escape') {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
this.nevermind()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -124,11 +143,14 @@ export default {
|
||||||
this.content.style.transition = 'transform 0.25s cubic-bezier(0.16, 1, 0.3, 1)'
|
this.content.style.transition = 'transform 0.25s cubic-bezier(0.16, 1, 0.3, 1)'
|
||||||
this.el.style.opacity = 1
|
this.el.style.opacity = 1
|
||||||
this.el.remove()
|
this.el.remove()
|
||||||
|
|
||||||
|
window.addEventListener('keydown', this.handleKeyDown)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (this.show) {
|
if (this.show) {
|
||||||
this.$eventBus.$emit('showing-prompt', false)
|
this.$eventBus.$emit('showing-prompt', false)
|
||||||
}
|
}
|
||||||
|
window.removeEventListener('keydown', this.handleKeyDown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ const Constants = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const KeyNames = {
|
const KeyNames = {
|
||||||
|
13: 'Enter',
|
||||||
27: 'Escape',
|
27: 'Escape',
|
||||||
32: 'Space',
|
32: 'Space',
|
||||||
37: 'ArrowLeft',
|
37: 'ArrowLeft',
|
||||||
|
|
@ -77,7 +78,8 @@ const Hotkeys = {
|
||||||
Modal: {
|
Modal: {
|
||||||
NEXT_PAGE: 'ArrowRight',
|
NEXT_PAGE: 'ArrowRight',
|
||||||
PREV_PAGE: 'ArrowLeft',
|
PREV_PAGE: 'ArrowLeft',
|
||||||
CLOSE: 'Escape'
|
CLOSE: 'Escape',
|
||||||
|
SUBMIT: 'Enter'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue