diff --git a/.vscode/settings.json b/.vscode/settings.json index 586e80f5f..ef71cc14f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -31,6 +31,7 @@ "cntr", "compositionend", "compositionstart", + "contenteditable", "csrf", "ctnr", "Danmaku", diff --git a/registry/lib/components/utils/keymap/actions.ts b/registry/lib/components/utils/keymap/actions.ts index 89c7add0c..2bb249c40 100644 --- a/registry/lib/components/utils/keymap/actions.ts +++ b/registry/lib/components/utils/keymap/actions.ts @@ -3,7 +3,7 @@ import { getComponentSettings } from '@/core/settings' import { registerAndGetData } from '@/plugins/data' import { Options } from '.' import { KeyBindingAction, KeyBindingActionContext } from './bindings' -import { simulateClick } from '@/core/utils' +import { getActiveElement, simulateClick } from '@/core/utils' export const keyboardEventToPointer = (event: KeyboardEvent): PointerEventInit => { return { @@ -239,15 +239,24 @@ export const builtInActions: Record = { sendComment: { displayName: '发送评论', ignoreTyping: false, + prevent: true, run: () => { - const { activeElement } = document - if (!activeElement || !(activeElement instanceof HTMLTextAreaElement)) { + const activeElement = getActiveElement() + if (!activeElement) { return null } + const isEditable = + activeElement instanceof HTMLTextAreaElement || + activeElement.hasAttribute('contenteditable') + if (!isEditable) { + return null + } + const getShadowRoot = (node: Node) => node.getRootNode() as ShadowRoot | null const sendButton = (() => { const candidates = [ () => activeElement.nextElementSibling, () => activeElement.parentElement.nextElementSibling, + () => getShadowRoot(getShadowRoot(activeElement)?.host)?.querySelector('#pub button'), () => dq('.reply-box:focus-within .reply-box-send'), ] const match = candidates.find(fn => fn() !== null) diff --git a/registry/lib/components/utils/keymap/bindings.ts b/registry/lib/components/utils/keymap/bindings.ts index f86b83508..bb30371a4 100644 --- a/registry/lib/components/utils/keymap/bindings.ts +++ b/registry/lib/components/utils/keymap/bindings.ts @@ -1,6 +1,7 @@ import { isTyping, matchUrlPattern } from '@/core/utils' import { mediaListUrls, watchlaterUrls } from '@/core/utils/urls' import { clickElement, changeVideoTime, showTip } from './actions' +import { shadowDomObserver } from '@/core/shadow-root' export interface KeyBindingActionContext { binding: KeyBinding @@ -29,7 +30,7 @@ export const loadKeyBindings = lodash.once((bindings: KeyBinding[]) => { enable: true, bindings, } - document.body.addEventListener('keydown', (e: KeyboardEvent & { [key: string]: boolean }) => { + const keyboardHandler = (e: KeyboardEvent & { [key: string]: boolean }) => { if (!config.enable) { return } @@ -87,10 +88,15 @@ export const loadKeyBindings = lodash.once((bindings: KeyBinding[]) => { const actionSuccess = !lodash.isNil(actionResult) if (binding.action.prevent ?? actionSuccess) { - e.stopPropagation() + e.stopImmediatePropagation() e.preventDefault() } }) + } + document.body.addEventListener('keydown', keyboardHandler, { capture: true }) + shadowDomObserver.watchShadowDom({ + added: shadowDom => + shadowDom.shadowRoot.addEventListener('keydown', keyboardHandler, { capture: true }), }) return config })