import React, { FunctionComponent, useEffect, useRef } from 'react'; import dis from '../../../../dispatcher/dispatcher'; import ICanvasEffect from './ICanvasEffect.js'; type EffectsOverlayProps = { roomWidth: number; } const EffectsOverlay: FunctionComponent = ({ roomWidth }) => { const canvasRef = useRef(null); const effectsRef = useRef>(new Map()); const resize = () => { canvasRef.current.height = window.innerHeight; }; const lazyLoadEffectModule = async (name: string): Promise => { if (!name) return null; let effect = effectsRef.current[name] ?? null; if (effect === null) { try { var { default: Effect } = await import(`./${name}`); effect = new Effect(); effectsRef.current[name] = effect; } catch (err) { console.warn('Unable to load effect module at \'./${name}\'.', err) } } return effect; } const onAction = (payload: { action: string }) => { const actionPrefix = 'effects.'; if (payload.action.indexOf(actionPrefix) === 0) { const effect = payload.action.substr(actionPrefix.length); lazyLoadEffectModule(effect).then((module) => module?.start(canvasRef.current)); } }; // on mount useEffect(() => { const dispatcherRef = dis.register(onAction); const canvas = canvasRef.current; canvas.width = roomWidth; canvas.height = window.innerHeight; window.addEventListener('resize', resize, true); return () => { dis.unregister(dispatcherRef); window.removeEventListener('resize', resize); for (const effect in effectsRef.current) { effectsRef.current[effect]?.stop(); } }; }, []); // on roomWidth change useEffect(() => { canvasRef.current.width = roomWidth; }, [roomWidth]); return ( ) } export default EffectsOverlay;