mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-07 08:30:06 +00:00
[Refactor] Move keybinds extension to keybindingService (#2063)
This commit is contained in:
@@ -6,7 +6,6 @@ import './groupNode'
|
||||
import './groupNodeManage'
|
||||
import './groupOptions'
|
||||
import './invertMenuScrolling'
|
||||
import './keybinds'
|
||||
import './maskeditor'
|
||||
import './nodeTemplates'
|
||||
import './noteNode'
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import { app } from '../../scripts/app'
|
||||
import { KeyComboImpl, useKeybindingStore } from '@/stores/keybindingStore'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
|
||||
app.registerExtension({
|
||||
name: 'Comfy.Keybinds',
|
||||
init() {
|
||||
const keybindListener = async function (event: KeyboardEvent) {
|
||||
// Ignore keybindings for legacy jest tests as jest tests don't have
|
||||
// a Vue app instance or pinia stores.
|
||||
if (!app.vueAppReady) return
|
||||
|
||||
const keyCombo = KeyComboImpl.fromEvent(event)
|
||||
if (keyCombo.isModifier) {
|
||||
return
|
||||
}
|
||||
|
||||
// Ignore non-modifier keybindings if typing in input fields
|
||||
const target = event.composedPath()[0] as HTMLElement
|
||||
if (
|
||||
!keyCombo.hasModifier &&
|
||||
(target.tagName === 'TEXTAREA' ||
|
||||
target.tagName === 'INPUT' ||
|
||||
(target.tagName === 'SPAN' &&
|
||||
target.classList.contains('property_value')))
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const keybindingStore = useKeybindingStore()
|
||||
const commandStore = useCommandStore()
|
||||
const keybinding = keybindingStore.getKeybinding(keyCombo)
|
||||
if (keybinding && keybinding.targetSelector !== '#graph-canvas') {
|
||||
// Prevent default browser behavior first, then execute the command
|
||||
event.preventDefault()
|
||||
await commandStore.execute(keybinding.commandId)
|
||||
return
|
||||
}
|
||||
|
||||
// Only clear dialogs if not using modifiers
|
||||
if (event.ctrlKey || event.altKey || event.metaKey) {
|
||||
return
|
||||
}
|
||||
|
||||
// Escape key: close the first open modal found, and all dialogs
|
||||
if (event.key === 'Escape') {
|
||||
const modals = document.querySelectorAll<HTMLElement>('.comfy-modal')
|
||||
for (const modal of modals) {
|
||||
const modalDisplay = window
|
||||
.getComputedStyle(modal)
|
||||
.getPropertyValue('display')
|
||||
|
||||
if (modalDisplay !== 'none') {
|
||||
modal.style.display = 'none'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (const d of document.querySelectorAll('dialog')) d.close()
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', keybindListener)
|
||||
}
|
||||
})
|
||||
60
src/services/keybindingService.ts
Normal file
60
src/services/keybindingService.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
import { KeyComboImpl, useKeybindingStore } from '@/stores/keybindingStore'
|
||||
|
||||
export const useKeybindingService = () => {
|
||||
const keybindingStore = useKeybindingStore()
|
||||
const commandStore = useCommandStore()
|
||||
|
||||
const keybindHandler = async function (event: KeyboardEvent) {
|
||||
const keyCombo = KeyComboImpl.fromEvent(event)
|
||||
if (keyCombo.isModifier) {
|
||||
return
|
||||
}
|
||||
|
||||
// Ignore non-modifier keybindings if typing in input fields
|
||||
const target = event.composedPath()[0] as HTMLElement
|
||||
if (
|
||||
!keyCombo.hasModifier &&
|
||||
(target.tagName === 'TEXTAREA' ||
|
||||
target.tagName === 'INPUT' ||
|
||||
(target.tagName === 'SPAN' &&
|
||||
target.classList.contains('property_value')))
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const keybinding = keybindingStore.getKeybinding(keyCombo)
|
||||
if (keybinding && keybinding.targetSelector !== '#graph-canvas') {
|
||||
// Prevent default browser behavior first, then execute the command
|
||||
event.preventDefault()
|
||||
await commandStore.execute(keybinding.commandId)
|
||||
return
|
||||
}
|
||||
|
||||
// Only clear dialogs if not using modifiers
|
||||
if (event.ctrlKey || event.altKey || event.metaKey) {
|
||||
return
|
||||
}
|
||||
|
||||
// Escape key: close the first open modal found, and all dialogs
|
||||
if (event.key === 'Escape') {
|
||||
const modals = document.querySelectorAll<HTMLElement>('.comfy-modal')
|
||||
for (const modal of modals) {
|
||||
const modalDisplay = window
|
||||
.getComputedStyle(modal)
|
||||
.getPropertyValue('display')
|
||||
|
||||
if (modalDisplay !== 'none') {
|
||||
modal.style.display = 'none'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (const d of document.querySelectorAll('dialog')) d.close()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
keybindHandler
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,8 @@ import { SERVER_CONFIG_ITEMS } from '@/constants/serverConfig'
|
||||
import { useMenuItemStore } from '@/stores/menuItemStore'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
import { useCoreCommands } from '@/hooks/coreCommandHooks'
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { useKeybindingService } from '@/services/keybindingService'
|
||||
|
||||
setupAutoQueueHandler()
|
||||
|
||||
@@ -160,6 +162,8 @@ onBeforeUnmount(() => {
|
||||
executionStore.unbindExecutionEvents()
|
||||
})
|
||||
|
||||
useEventListener(window, 'keydown', useKeybindingService().keybindHandler)
|
||||
|
||||
const onGraphReady = () => {
|
||||
requestIdleCallback(
|
||||
() => {
|
||||
|
||||
Reference in New Issue
Block a user