Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@
}
},
"enableAnalytics": "Enable anonymous analytics",
"enableFullscreenInteraction": "Enable fullscreen interaction",
"help": {
"feedback": "Provide feedback",
"reportBug": "Report Bug"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@
}
},
"enableAnalytics": "匿名数据收集",
"enableFullscreenInteraction": "全屏时启用交互",
"help": {
"feedback": "提交意见或建议",
"reportBug": "报告Bug"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const defaultExtensionOptions: ExtensionOptions = {
playerOptions: {
showSkipButton: true,
showDanmakuTimeline: true,
enableFullscreenInteraction: true,
},
theme: {
colorMode: ColorMode.System,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const danmakuSourcesSchema = z.object({
export const playerOptionsSchema = z.object({
showSkipButton: z.boolean(),
showDanmakuTimeline: z.boolean(),
enableFullscreenInteraction: z.boolean(),
})

export const retentionPolicySchema = z.object({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ export class ExtensionOptionsService implements IStoreService {
draft.playerOptions = {
showSkipButton: true,
showDanmakuTimeline: true,
enableFullscreenInteraction: true,
}
}),
})
Expand Down Expand Up @@ -248,6 +249,12 @@ export class ExtensionOptionsService implements IStoreService {
})
},
})
.version(23, {
upgrade: (data) =>
produce<ExtensionOptions>(data, (draft) => {
draft.playerOptions.enableFullscreenInteraction = true
}),
})
}

async get() {
Expand Down
17 changes: 17 additions & 0 deletions packages/danmaku-anywhere/src/common/settings/settingConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@ export type ButtonSettingConfig = CommonSettingConfig & {
export type SettingConfig<S> = ToggleSettingConfig<S>

const advancedSettings: SettingConfig<ExtensionOptions>[] = [
{
id: 'toggle.player.enableFullscreenInteraction',
label: () =>
i18n.t(
'optionsPage.enableFullscreenInteraction',
'Enable fullscreen interaction'
),
category: 'advanced',
type: 'toggle',
getValue: (options) => options.playerOptions.enableFullscreenInteraction,
createUpdate: (options, newValue) => ({
playerOptions: {
...options.playerOptions,
enableFullscreenInteraction: newValue,
},
}),
},
{
id: 'toggle.analytics',
label: () =>
Expand Down
35 changes: 35 additions & 0 deletions packages/danmaku-anywhere/src/content/common/reparentPopover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// When video becomes full screen, the popover (content script) will be visible on top of the video,
// but will become "inert" and non-interactive.
// To maintain interactivity, we need to re-parent the popover into the fullscreen element.
// https://github.com/whatwg/html/issues/10811
export function reparentPopover(
popover: HTMLDivElement,
document: Document,
target: Element | null
) {
if (!target) {
// if no target, reparent to body and show the popover
if (popover.parentElement !== document.body) {
document.body.appendChild(popover)
}
popover.hidePopover()
popover.showPopover()
return
}

if (
target instanceof HTMLVideoElement ||
target instanceof HTMLIFrameElement
) {
// Cannot reparent to these elements, hide and show so the popover will be visible on top of the video
popover.hidePopover()
popover.showPopover()
} else {
// reparent to target and show the popover
if (popover.parentElement !== target) {
target.appendChild(popover)
}
popover.hidePopover()
popover.showPopover()
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useEventCallback } from '@mui/material'
import { useEffect } from 'react'
import { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useToast } from '@/common/components/Toast/toastStore'
import { IS_STANDALONE_RUNTIME } from '@/common/environment/isStandalone'
import { uiContainer } from '@/common/ioc/uiIoc'
import { Logger } from '@/common/Logger'
import { useExtensionOptions } from '@/common/options/extensionOptions/useExtensionOptions'
import { createRpcServer } from '@/common/rpc/server'
import { playerRpcClient } from '@/common/rpcClient/background/client'
import type { PlayerRelayEvents } from '@/common/rpcClient/background/types'
import { reparentPopover } from '@/content/common/reparentPopover'
import { CONTROLLER_ROOT_ID } from '@/content/controller/common/constants/rootId'
import { useActiveConfig } from '@/content/controller/common/context/useActiveConfig'
import { useUnmountDanmaku } from '@/content/controller/common/hooks/useUnmountDanmaku'
Expand All @@ -25,6 +27,14 @@ export const FrameManager = () => {
const { toast } = useToast()

const config = useActiveConfig()
const { data: extensionOptions } = useExtensionOptions()

const enableFullscreenInteraction =
extensionOptions.playerOptions.enableFullscreenInteraction

const enableFullscreenInteractionRef = useRef(enableFullscreenInteraction)

enableFullscreenInteractionRef.current = enableFullscreenInteraction

const setVideoId = useStore.use.setVideoId()
const { activeFrame, setActiveFrame, updateFrame } = useStore.use.frame()
Expand Down Expand Up @@ -106,9 +116,15 @@ export const FrameManager = () => {
const root: HTMLDivElement | null = document.querySelector(
`#${CONTROLLER_ROOT_ID}`
)
if (root) {
root.hidePopover()
root.showPopover()
if (!root) {
return
}

if (enableFullscreenInteractionRef.current) {
const fullscreenElement = document.fullscreenElement
reparentPopover(root, document, fullscreenElement)
} else {
reparentPopover(root, document, null)
}
},
},
Expand Down
24 changes: 15 additions & 9 deletions packages/danmaku-anywhere/src/content/player/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { createPipWindow, moveElement } from '@/content/player/pipUtils'
import { VideoEventService } from '@/content/player/videoEvent/VideoEvent.service'
import { VideoNodeObserverService } from '@/content/player/videoObserver/VideoNodeObserver.service'
import { VideoSkipService } from '@/content/player/videoSkip/VideoSkip.service'
import { reparentPopover } from '../common/reparentPopover'

const { data: frameId } = await chromeRpcClient.getFrameId()

Expand Down Expand Up @@ -155,6 +156,8 @@ danmakuOptionsService.get().then((options) => {

const extensionOptionsService = uiContainer.get(ExtensionOptionsService)

let enableFullscreenInteraction = true

extensionOptionsService.get().then((options) => {
if (options.playerOptions.showSkipButton) {
videoSkipService.enable()
Expand All @@ -166,6 +169,8 @@ extensionOptionsService.get().then((options) => {
} else {
danmakuDensityService.disable()
}
enableFullscreenInteraction =
options.playerOptions.enableFullscreenInteraction
})

extensionOptionsService.onChange((options) => {
Expand All @@ -179,21 +184,22 @@ extensionOptionsService.onChange((options) => {
} else {
danmakuDensityService.disable()
}
enableFullscreenInteraction =
options.playerOptions.enableFullscreenInteraction
})

/**
* Window events
*/
document.addEventListener('fullscreenchange', () => {
/**
* The last element in the top layer is shown on top.
* Hiding then showing the popover will make it the last element in the top layer.
*
* Do this every time something goes fullscreen, to ensure the popover is always on top.
*/
root.hidePopover()
root.showPopover()
// Then notify the controller so that the controller can also toggle popover to stay on top
if (enableFullscreenInteraction) {
const fullscreenElement = document.fullscreenElement
reparentPopover(root, document, fullscreenElement)
} else {
reparentPopover(root, document, null)
}

// Notify the controller so it can also handle its popover
void playerRpcClient.controller['relay:event:showPopover']({ frameId })
})

Expand Down
Loading