You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
55 lines
1.4 KiB
TypeScript
55 lines
1.4 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useRef } from "react"
|
|
import { themeSignal } from "../Appearance"
|
|
|
|
interface Module {
|
|
setup?: (wabt?: any) => Promise<undefined>
|
|
cleanup?: () => Promise<undefined>
|
|
onThemeChange?: () => void
|
|
}
|
|
|
|
export default function PageScript({ script, wasm }: { script?: string, wasm?: Uint8Array }) {
|
|
const moduleRef = useRef<Module | null>(null)
|
|
|
|
useEffect(() => {
|
|
if (!script) return undefined
|
|
|
|
import(/* webpackIgnore: true */ script)
|
|
.then(scriptModule => {
|
|
if (!wasm) return [scriptModule]
|
|
|
|
return WebAssembly.instantiate(Uint8Array.from(wasm)).then(({ instance }) => [scriptModule, instance])
|
|
})
|
|
.then(([scriptModule, wasmModule]) => {
|
|
moduleRef.current = scriptModule
|
|
|
|
if (scriptModule.setup && typeof scriptModule.setup === 'function')
|
|
scriptModule.setup(wasmModule)
|
|
})
|
|
|
|
return () => {
|
|
const mod = moduleRef.current
|
|
|
|
if (mod?.cleanup && typeof mod.cleanup === 'function') {
|
|
mod.cleanup()
|
|
}
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
function onThemeChange() {
|
|
const mod = moduleRef.current
|
|
|
|
if (mod?.onThemeChange && typeof mod?.onThemeChange === 'function') {
|
|
mod.onThemeChange()
|
|
}
|
|
}
|
|
|
|
themeSignal.addListener('change', onThemeChange)
|
|
return () => { themeSignal.removeListener('change', onThemeChange) }
|
|
}, [])
|
|
|
|
return null
|
|
}
|