-
Piotr Gawron authoredPiotr Gawron authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
useLoadPlugin.ts 3.70 KiB
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,
};
};