// Copyright (C) 2017-2023 Smart code 203358507 const React = require('react'); const throttle = require('lodash.throttle'); const isEqual = require('lodash.isequal'); const intersection = require('lodash.intersection'); const { useCoreSuspender } = require('stremio/common/CoreSuspender'); const { useRouteFocused } = require('stremio-router'); const { useServices } = require('stremio/services'); const useModelState = ({ action, ...args }) => { const { core } = useServices(); const routeFocused = useRouteFocused(); const mountedRef = React.useRef(false); const [model, timeout, map, deps] = React.useMemo(() => { return [args.model, args.timeout, args.map, args.deps]; }, []); const { getState } = useCoreSuspender(); const [state, setState] = React.useReducer( (prevState, nextState) => { return Object.keys(prevState).reduce((result, key) => { result[key] = isEqual(prevState[key], nextState[key]) ? prevState[key] : nextState[key]; return result; }, {}); }, undefined, () => { if (typeof map === 'function') { return map(getState(model)); } else { return getState(model); } } ); React.useInsertionEffect(() => { if (action) { core.transport.dispatch(action, model); } }, [action]); React.useInsertionEffect(() => { return () => { core.transport.dispatch({ action: 'Unload' }, model); }; }, []); React.useInsertionEffect(() => { const onNewState = async (models) => { if (models.indexOf(model) === -1 && (!Array.isArray(deps) || intersection(deps, models).length === 0)) { return; } const state = await core.transport.getState(model); if (typeof map === 'function') { setState(map(state)); } else { setState(state); } }; const onNewStateThrottled = throttle(onNewState, timeout); if (routeFocused) { core.transport.on('NewState', onNewStateThrottled); if (mountedRef.current) { onNewState([model]); } } return () => { onNewStateThrottled.cancel(); core.transport.off('NewState', onNewStateThrottled); }; }, [routeFocused]); React.useInsertionEffect(() => { mountedRef.current = true; }, []); return state; }; module.exports = useModelState;