import React, { useMemo } from "react"; import { Button } from "react-bootstrap"; import { FormattedMessage, useIntl } from "react-intl"; import * as GQL from "src/core/generated-graphql"; import { mutateReloadPlugins, mutateSetPluginsEnabled, usePlugins, } from "src/core/StashService"; import { useToast } from "src/hooks/Toast"; import TextUtils from "src/utils/text"; import { CollapseButton } from "../Shared/CollapseButton"; import { Icon } from "../Shared/Icon"; import { LoadingIndicator } from "../Shared/LoadingIndicator"; import { SettingSection } from "./SettingSection"; import { BooleanSetting, NumberSetting, Setting, SettingGroup, StringSetting, } from "./Inputs"; import { faLink, faSyncAlt } from "@fortawesome/free-solid-svg-icons"; import { useSettings } from "./context"; import { AvailablePluginPackages, InstalledPluginPackages, } from "./PluginPackageManager"; import { ExternalLink } from "../Shared/ExternalLink"; import { PatchComponent } from "src/patch"; interface IPluginSettingProps { pluginID: string; setting: GQL.PluginSetting; value: unknown; onChange: (value: unknown) => void; } const PluginSetting: React.FC = ({ pluginID, setting, value, onChange, }) => { const commonProps = { heading: setting.display_name ? setting.display_name : setting.name, id: `plugin-${pluginID}-${setting.name}`, subHeading: setting.description ?? undefined, }; switch (setting.type) { case GQL.PluginSettingTypeEnum.Boolean: return ( onChange(!value)} /> ); case GQL.PluginSettingTypeEnum.String: return ( onChange(v)} /> ); case GQL.PluginSettingTypeEnum.Number: return ( onChange(v)} /> ); } }; const PluginSettings: React.FC<{ pluginID: string; settings: GQL.PluginSetting[]; }> = PatchComponent("PluginSettings", ({ pluginID, settings }) => { const { plugins, savePluginSettings } = useSettings(); const pluginSettings = plugins[pluginID] ?? {}; return (
{settings.map((setting) => ( savePluginSettings(pluginID, { ...pluginSettings, [setting.name]: v, }) } /> ))}
); }); export const SettingsPluginsPanel: React.FC = () => { const Toast = useToast(); const intl = useIntl(); const { loading: configLoading } = useSettings(); const { data, loading } = usePlugins(); const [changedPluginID, setChangedPluginID] = React.useState< string | undefined >(); async function onReloadPlugins() { try { await mutateReloadPlugins(); } catch (e) { Toast.error(e); } } const pluginElements = useMemo(() => { function renderLink(url?: string) { if (url) { return ( ); } } function renderEnableButton(pluginID: string, enabled: boolean) { async function onClick() { try { await mutateSetPluginsEnabled({ [pluginID]: !enabled }); } catch (e) { Toast.error(e); } setChangedPluginID(pluginID); } return ( ); } function onReloadUI() { window.location.reload(); } function maybeRenderReloadUI(pluginID: string) { if (pluginID === changedPluginID) { return ( ); } } function renderPlugins() { const elements = (data?.plugins ?? []).map((plugin) => ( {renderLink(plugin.url ?? undefined)} {maybeRenderReloadUI(plugin.id)} {renderEnableButton(plugin.id, plugin.enabled)} } > {renderPluginHooks(plugin.hooks ?? undefined)} )); return
{elements}
; } function renderPluginHooks( hooks?: Pick[] ) { if (!hooks || hooks.length === 0) { return; } return (
{hooks.map((h) => (
{h.name}
    {h.hooks?.map((hh) => (
  • {hh}
  • ))}
{h.description}
))}
); } return renderPlugins(); }, [data?.plugins, intl, Toast, changedPluginID]); if (loading || configLoading) return ; return ( <> {pluginElements} ); };