Skip to content
Snippets Groups Projects
useLoadPluginFromUrl.ts 2.06 KiB
Newer Older
import { PluginsManager } from '@/services/pluginsManager';
import axios from 'axios';
import { ChangeEvent, useMemo, useState, KeyboardEvent } from 'react';
import { ENTER_KEY_CODE } from '@/constants/common';
import { getError } from '@/utils/error-report/getError';
import { handleError } from '@/utils/error-report/errorReporting';
import { store } from '@/redux/store';
import { PLUGIN_LOADING_ERROR_PREFIX } from '../../AvailablePluginsDrawer.constants';

type UseLoadPluginReturnType = {
  handleChangePluginUrl: (event: ChangeEvent<HTMLInputElement>) => void;
  handleLoadPlugin: () => Promise<void>;
  isPending: boolean;
  pluginUrl: string;
  handleKeyPress: (event: KeyboardEvent<HTMLInputElement>) => Promise<void>;
};

export const useLoadPluginFromUrl = (): UseLoadPluginReturnType => {
  const [pluginUrl, setPluginUrl] = useState('');
  const [isLoading, setIsLoading] = useState(false);

  const isPending = useMemo(
    () => !pluginUrl || isLoading || !URL.canParse(pluginUrl),
    [pluginUrl, isLoading],
  );

  const handleLoadPlugin = async (): Promise<void> => {
    try {
      setIsLoading(true);
      const response = await axios(pluginUrl);
      let pluginScript = response.data;
      PluginsManager.setHashedPlugin({
      pluginScript += `//# sourceURL=${pluginUrl}`;

      /* eslint-disable no-new-func */
      const loadPlugin = new Function(pluginScript);

      await handleError(getError({ error, prefix: PLUGIN_LOADING_ERROR_PREFIX }), store.getState());
    } finally {
      setIsLoading(false);
    }
  };

  const handleKeyPress = async (event: KeyboardEvent<HTMLInputElement>): Promise<void> => {
    if (event.code === ENTER_KEY_CODE && !isPending) {
      await handleLoadPlugin();
    }
  };

  const handleChangePluginUrl = (event: ChangeEvent<HTMLInputElement>): void => {
    setPluginUrl(event.target.value);
  };

  return {
    handleChangePluginUrl,
    handleLoadPlugin,