import React, { FunctionComponent, useEffect, useRef } from 'react'; import dis from '../../../../dispatcher/dispatcher'; import ICanvasEffect from './ICanvasEffect.js'; export type EffectsOverlayProps = { roomWidth: number; } const EffectsOverlay: FunctionComponent = ({ roomWidth }) => { const canvasRef = useRef(null); const effectsRef = useRef>(new Map()); const lazyLoadEffectModule = async (name: string): Promise => { if (!name) return null; let effect = effectsRef.current[name] ?? null; if (effect === null) { try { const { 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; }; useEffect(() => { const resize = () => { canvasRef.current.height = window.innerHeight; }; 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)); } } const dispatcherRef = dis.register(onAction); const canvas = canvasRef.current; canvas.height = window.innerHeight; window.addEventListener('resize', resize, true); return () => { dis.unregister(dispatcherRef); window.removeEventListener('resize', resize); // eslint-disable-next-line react-hooks/exhaustive-deps const currentEffects = effectsRef.current; // this is not a react node ref, warning can be safely ignored for (const effect in currentEffects) { const effectModule: ICanvasEffect = currentEffects[effect]; if (effectModule && effectModule.isRunning) { effectModule.stop(); } } }; }, []); return ( ) } export default EffectsOverlay;