feat: disable keybindings when a modal is open
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user