import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { isActiveLegendSelector } from '@/redux/legend/legend.selectors'; import { removePluginLegend, setDefaultLegendId } from '@/redux/legend/legend.slice'; import { allActivePluginsSelector, isPluginActiveSelector, isPluginLoadingSelector, isPluginSelectedSelector, } from '@/redux/plugins/plugins.selectors'; import { removePlugin, setCurrentDrawerPluginHash } from '@/redux/plugins/plugins.slice'; import { PluginsManager } from '@/services/pluginsManager'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { getErrorMessage } from '@/utils/getErrorMessage'; import { showToast } from '@/utils/showToast'; import axios from 'axios'; import { PLUGIN_LOADING_ERROR_PREFIX } from '../../AvailablePluginsDrawer.constants'; type UseLoadPluginReturnType = { togglePlugin: () => void; loadPlugin: () => Promise<void>; unloadPlugin: () => void; reloadPlugin: () => void; isPluginSelected: boolean; isPluginActive: boolean; isPluginLoading: boolean; }; type UseLoadPluginProps = { hash: string; pluginUrl: string; onPluginLoaded?(): void; }; export const useLoadPlugin = ({ hash, pluginUrl, onPluginLoaded, }: UseLoadPluginProps): UseLoadPluginReturnType => { const isPluginActive = useAppSelector(state => isPluginActiveSelector(state, hash)); const isPluginLoading = useAppSelector(state => isPluginLoadingSelector(state, hash)); const isPluginSelected = useAppSelector(state => isPluginSelectedSelector(state, hash)); const isActivePluginLegend = useAppSelector(state => isActiveLegendSelector(state, hash)); const allActivePlugins = useAppSelector(allActivePluginsSelector); const dispatch = useAppDispatch(); const setLastPluginAsCurrentActivePlugin = (): void => { const newAllActivePlugins = allActivePlugins.filter(p => p.hash !== hash); const lastActivePlugin = newAllActivePlugins.pop(); if (lastActivePlugin) { dispatch(setCurrentDrawerPluginHash(lastActivePlugin.hash)); } }; const handleLoadPlugin = async (): Promise<void> => { try { const response = await axios(pluginUrl); let pluginScript = response.data; PluginsManager.setHashedPlugin({ pluginUrl, pluginScript, }); pluginScript += `//# sourceURL=${pluginUrl}`; /* eslint-disable no-new-func */ const loadPlugin = new Function(pluginScript); loadPlugin(); if (onPluginLoaded) { onPluginLoaded(); } } catch (error) { const errorMessage = getErrorMessage({ error, prefix: PLUGIN_LOADING_ERROR_PREFIX, }); showToast({ type: 'error', message: errorMessage }); } }; const handleRemoveLegend = (): void => { if (isActivePluginLegend) { dispatch(setDefaultLegendId()); } dispatch(removePluginLegend(hash)); }; const handleUnloadPlugin = (): void => { dispatch(removePlugin({ pluginId: hash })); setLastPluginAsCurrentActivePlugin(); handleRemoveLegend(); PluginsManager.removePluginContent({ hash }); PluginsManager.unloadActivePlugin(hash); PluginsEventBus.dispatchEvent('onPluginUnload', { hash }); }; const handleReloadPlugin = async (): Promise<void> => { handleUnloadPlugin(); await handleLoadPlugin(); }; const togglePlugin = async (): Promise<void> => { if (isPluginActive) { handleUnloadPlugin(); } else { await handleLoadPlugin(); } }; return { isPluginSelected, togglePlugin, loadPlugin: handleLoadPlugin, unloadPlugin: handleUnloadPlugin, reloadPlugin: handleReloadPlugin, isPluginActive, isPluginLoading, }; };