feat: disable keybindings when a modal is open

This commit is contained in:
Andrew Bastin
2021-08-04 10:48:41 -04:00
parent a4caeac584
commit b524af174a
2 changed files with 53 additions and 8 deletions

View File

@@ -66,11 +66,15 @@
</transition> </transition>
</template> </template>
<script> <script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api"
import { useKeybindingDisabler } from "~/helpers/keybindings"
const PORTAL_DOM_ID = "hoppscotch-modal-portal" const PORTAL_DOM_ID = "hoppscotch-modal-portal"
// Why ?
const stack = (() => { const stack = (() => {
const stack = [] const stack: number[] = []
return { return {
push: stack.push.bind(stack), push: stack.push.bind(stack),
pop: stack.pop.bind(stack), pop: stack.pop.bind(stack),
@@ -78,13 +82,21 @@ const stack = (() => {
} }
})() })()
export default { export default defineComponent({
props: { props: {
dialog: { dialog: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
}, },
setup() {
const { disableKeybindings, enableKeybindings } = useKeybindingDisabler()
return {
disableKeybindings,
enableKeybindings,
}
},
data() { data() {
return { return {
stackId: Math.random(), stackId: Math.random(),
@@ -94,20 +106,21 @@ export default {
} }
}, },
computed: { computed: {
hasFooterSlot() { hasFooterSlot(): boolean {
return !!this.$slots.footer return !!this.$slots.footer
}, },
}, },
mounted() { mounted() {
const $portal = this.$getPortal() const $portal = this.$getPortal()
$portal.appendChild(this.$refs.modal) $portal.appendChild(this.$refs.modal as any)
stack.push(this.stackId) stack.push(this.stackId)
document.addEventListener("keydown", this.onKeyDown) document.addEventListener("keydown", this.onKeyDown)
this.disableKeybindings()
}, },
beforeDestroy() { beforeDestroy() {
const $modal = this.$refs.modal const $modal = this.$refs.modal
if (this.shouldCleanupDomOnUnmount && $modal) { if (this.shouldCleanupDomOnUnmount && $modal) {
this.$getPortal().removeChild($modal) this.$getPortal().removeChild($modal as any)
} }
stack.pop() stack.pop()
document.removeEventListener("keydown", this.onKeyDown) document.removeEventListener("keydown", this.onKeyDown)
@@ -115,8 +128,9 @@ export default {
methods: { methods: {
close() { close() {
this.$emit("close") this.$emit("close")
this.enableKeybindings()
}, },
onKeyDown(e) { onKeyDown(e: KeyboardEvent) {
if (e.key === "Escape" && this.stackId === stack.peek()) { if (e.key === "Escape" && this.stackId === stack.peek()) {
e.preventDefault() e.preventDefault()
this.close() this.close()
@@ -136,5 +150,5 @@ export default {
return $el return $el
}, },
}, },
} })
</script> </script>

View File

@@ -2,6 +2,13 @@ import { onBeforeUnmount, onMounted } from "@nuxtjs/composition-api"
import { HoppAction, invokeAction } from "./actions" import { HoppAction, invokeAction } from "./actions"
import { isAppleDevice } from "./platformutils" import { isAppleDevice } from "./platformutils"
/**
* This variable keeps track whether keybindings are being accepted
* true -> Keybindings are checked
* false -> Key presses are ignored (Keybindings are not checked)
*/
let keybindingsEnabled = true
/** /**
* Alt is also regarded as macOS OPTION (⌥) key * Alt is also regarded as macOS OPTION (⌥) key
* Ctrl is also regarded as macOS COMMAND (⌘) key (NOTE: this differs from HTML Keyboard spec where COMMAND is Meta key!) * Ctrl is also regarded as macOS COMMAND (⌘) key (NOTE: this differs from HTML Keyboard spec where COMMAND is Meta key!)
@@ -50,6 +57,9 @@ export function hookKeybindingsListener() {
} }
function handleKeyDown(ev: KeyboardEvent) { function handleKeyDown(ev: KeyboardEvent) {
// Do not check keybinds if the mode is disabled
if (!keybindingsEnabled) return
const binding = generateKeybindingString(ev) const binding = generateKeybindingString(ev)
if (!binding) return if (!binding) return
@@ -105,3 +115,24 @@ function getActiveModifier(ev: KeyboardEvent): ModifierKeys | null {
return null return null
} }
/**
* This composable allows for the UI component to be disabled if the component in question is mounted
*/
export function useKeybindingDisabler() {
// TODO: Move to a lock based system that keeps the bindings disabled until all locks are lifted
const disableKeybindings = () => {
keybindingsEnabled = false
console.log("Keybinds disabled by a component")
}
const enableKeybindings = () => {
keybindingsEnabled = true
console.log("Keybinds enabled by a component")
}
return {
disableKeybindings,
enableKeybindings,
}
}