-
-
Notifications
You must be signed in to change notification settings - Fork 346
Expand file tree
/
Copy pathmount-subtitles-ui.tsx
More file actions
112 lines (98 loc) · 3.48 KB
/
mount-subtitles-ui.tsx
File metadata and controls
112 lines (98 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import type { UniversalVideoAdapter } from "../universal-adapter"
import type { PlatformConfig } from "@/entrypoints/subtitles.content/platforms"
import { Provider as JotaiProvider } from "jotai"
import ReactDOM from "react-dom/client"
import { Toaster } from "sonner"
import themeCSS from "@/assets/styles/theme.css?inline"
import { ThemeProvider } from "@/components/providers/theme-provider"
import { REACT_SHADOW_HOST_CLASS } from "@/utils/constants/dom-labels"
import { waitForElement } from "@/utils/dom/wait-for-element"
import { ShadowWrapperContext } from "@/utils/react-shadow-host/create-shadow-host"
import { ShadowHostBuilder } from "@/utils/react-shadow-host/shadow-host-builder"
import { subtitlesStore } from "../atoms"
import { SubtitlesContainer } from "../ui/subtitles-container"
import { SubtitlesUIContext } from "../ui/subtitles-ui-context"
const SUBTITLES_UI_HOST_ID = "read-frog-subtitles-ui-host"
type MountSubtitlesUIAdapter = Pick<
UniversalVideoAdapter,
"downloadSourceSubtitles" | "getControlsConfig" | "toggleSubtitlesManually"
>
interface MountSubtitlesUIOptions {
adapter: MountSubtitlesUIAdapter
config: Pick<PlatformConfig, "selectors">
}
export async function mountSubtitlesUI(
{ adapter, config }: MountSubtitlesUIOptions,
): Promise<void> {
const videoContainer = await waitForElement(config.selectors.playerContainer)
if (!videoContainer)
return
const parentEl = videoContainer as HTMLElement
const computedStyle = window.getComputedStyle(parentEl)
if (computedStyle.position === "static") {
parentEl.style.position = "relative"
}
const existingHost = document.getElementById(SUBTITLES_UI_HOST_ID) as HTMLDivElement | null
if (existingHost) {
if (existingHost.parentElement === parentEl) {
return
}
;(existingHost as any).__reactShadowContainerCleanup?.()
existingHost.remove()
}
const shadowHost = document.createElement("div")
shadowHost.id = SUBTITLES_UI_HOST_ID
shadowHost.classList.add(REACT_SHADOW_HOST_CLASS)
shadowHost.style.cssText = `
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
z-index: 9999;
transition: bottom 0.2s ease-out;
overflow: visible;
`
const shadowRoot = shadowHost.attachShadow({ mode: "open" })
const hostBuilder = new ShadowHostBuilder(shadowRoot, {
position: "block",
cssContent: [themeCSS],
inheritStyles: false,
style: {
position: "absolute",
top: "0",
left: "0",
right: "0",
bottom: "0",
pointerEvents: "none",
overflow: "visible",
},
})
const reactContainer = hostBuilder.build()
const reactRoot = ReactDOM.createRoot(reactContainer)
;(shadowHost as any).__reactShadowContainerCleanup = () => {
reactRoot?.unmount()
hostBuilder.cleanup()
}
parentEl.appendChild(shadowHost)
const app = (
<JotaiProvider store={subtitlesStore}>
<ShadowWrapperContext value={reactContainer}>
<ThemeProvider container={reactContainer}>
<SubtitlesUIContext
value={{
toggleSubtitles: adapter.toggleSubtitlesManually,
downloadSourceSubtitles: adapter.downloadSourceSubtitles,
controlsConfig: adapter.getControlsConfig(),
}}
>
<SubtitlesContainer />
<Toaster richColors className="z-2147483647 notranslate" />
</SubtitlesUIContext>
</ThemeProvider>
</ShadowWrapperContext>
</JotaiProvider>
)
reactRoot.render(app)
}