Add Shadow DOM support for sendComment action (#4843)

This commit is contained in:
the1812 2024-09-12 23:02:31 +08:00
parent 98d8c57f27
commit 18017644dc
3 changed files with 21 additions and 5 deletions

View File

@ -31,6 +31,7 @@
"cntr", "cntr",
"compositionend", "compositionend",
"compositionstart", "compositionstart",
"contenteditable",
"csrf", "csrf",
"ctnr", "ctnr",
"Danmaku", "Danmaku",

View File

@ -3,7 +3,7 @@ import { getComponentSettings } from '@/core/settings'
import { registerAndGetData } from '@/plugins/data' import { registerAndGetData } from '@/plugins/data'
import { Options } from '.' import { Options } from '.'
import { KeyBindingAction, KeyBindingActionContext } from './bindings' import { KeyBindingAction, KeyBindingActionContext } from './bindings'
import { simulateClick } from '@/core/utils' import { getActiveElement, simulateClick } from '@/core/utils'
export const keyboardEventToPointer = (event: KeyboardEvent): PointerEventInit => { export const keyboardEventToPointer = (event: KeyboardEvent): PointerEventInit => {
return { return {
@ -239,15 +239,24 @@ export const builtInActions: Record<string, KeyBindingAction> = {
sendComment: { sendComment: {
displayName: '发送评论', displayName: '发送评论',
ignoreTyping: false, ignoreTyping: false,
prevent: true,
run: () => { run: () => {
const { activeElement } = document const activeElement = getActiveElement()
if (!activeElement || !(activeElement instanceof HTMLTextAreaElement)) { if (!activeElement) {
return null 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 sendButton = (() => {
const candidates = [ const candidates = [
() => activeElement.nextElementSibling, () => activeElement.nextElementSibling,
() => activeElement.parentElement.nextElementSibling, () => activeElement.parentElement.nextElementSibling,
() => getShadowRoot(getShadowRoot(activeElement)?.host)?.querySelector('#pub button'),
() => dq('.reply-box:focus-within .reply-box-send'), () => dq('.reply-box:focus-within .reply-box-send'),
] ]
const match = candidates.find(fn => fn() !== null) const match = candidates.find(fn => fn() !== null)

View File

@ -1,6 +1,7 @@
import { isTyping, matchUrlPattern } from '@/core/utils' import { isTyping, matchUrlPattern } from '@/core/utils'
import { mediaListUrls, watchlaterUrls } from '@/core/utils/urls' import { mediaListUrls, watchlaterUrls } from '@/core/utils/urls'
import { clickElement, changeVideoTime, showTip } from './actions' import { clickElement, changeVideoTime, showTip } from './actions'
import { shadowDomObserver } from '@/core/shadow-root'
export interface KeyBindingActionContext { export interface KeyBindingActionContext {
binding: KeyBinding binding: KeyBinding
@ -29,7 +30,7 @@ export const loadKeyBindings = lodash.once((bindings: KeyBinding[]) => {
enable: true, enable: true,
bindings, bindings,
} }
document.body.addEventListener('keydown', (e: KeyboardEvent & { [key: string]: boolean }) => { const keyboardHandler = (e: KeyboardEvent & { [key: string]: boolean }) => {
if (!config.enable) { if (!config.enable) {
return return
} }
@ -87,10 +88,15 @@ export const loadKeyBindings = lodash.once((bindings: KeyBinding[]) => {
const actionSuccess = !lodash.isNil(actionResult) const actionSuccess = !lodash.isNil(actionResult)
if (binding.action.prevent ?? actionSuccess) { if (binding.action.prevent ?? actionSuccess) {
e.stopPropagation() e.stopImmediatePropagation()
e.preventDefault() e.preventDefault()
} }
}) })
}
document.body.addEventListener('keydown', keyboardHandler, { capture: true })
shadowDomObserver.watchShadowDom({
added: shadowDom =>
shadowDom.shadowRoot.addEventListener('keydown', keyboardHandler, { capture: true }),
}) })
return config return config
}) })