interface IPluginApi { React: typeof React; GQL: any; Event: { addEventListener: (event: string, callback: (e: CustomEvent) => void) => void; }; libraries: { ReactRouterDOM: { Link: React.FC; Route: React.FC; NavLink: React.FC; }, Bootstrap: { Button: React.FC; Nav: React.FC & { Link: React.FC; }; }, FontAwesomeSolid: { faEthernet: any; }, Intl: { FormattedMessage: React.FC; } }, loadableComponents: any; components: Record>; utils: { NavUtils: any; loadComponents: any; }, hooks: any; patch: { before: (target: string, fn: Function) => void; instead: (target: string, fn: Function) => void; after: (target: string, fn: Function) => void; }, register: { route: (path: string, component: React.FC) => void; } } (function () { const PluginApi = (window as any).PluginApi as IPluginApi; const React = PluginApi.React; const GQL = PluginApi.GQL; const { Button } = PluginApi.libraries.Bootstrap; const { faEthernet } = PluginApi.libraries.FontAwesomeSolid; const { Link, NavLink, } = PluginApi.libraries.ReactRouterDOM; const { NavUtils } = PluginApi.utils; PluginApi.Event.addEventListener("stash:location", (e) => console.log("Page Changed", e.detail.data.location.pathname, e.detail.data.location.search)) const ScenePerformer: React.FC<{ performer: any; }> = ({ performer }) => { // PluginApi.components may not be registered when the outside function is run // need to initialise these inside the function component const { HoverPopover, } = PluginApi.components; const popoverContent = React.useMemo( () => (
{performer.name
), [performer] ); return ( {performer.name} ); }; function SceneDetails(props: any) { const { TagLink, } = PluginApi.components; function maybeRenderPerformers() { if (props.scene.performers.length <= 0) return; return (
{props.scene.performers.map((performer: any) => ( ))}
); } function maybeRenderTags() { if (props.scene.tags.length <= 0) return; return (
{props.scene.tags.map((tag: any) => ( ))}
); } return (
{props.scene.date} {maybeRenderPerformers()} {maybeRenderTags()}
); } PluginApi.patch.instead("SceneCard.Details", function (props: any, _: any, original: any) { return ; }); const TestPage: React.FC = () => { const componentsLoading = PluginApi.hooks.useLoadComponents([PluginApi.loadableComponents.SceneCard]); const { SceneCard, LoadingIndicator, } = PluginApi.components; // read a random scene and show a scene card for it const { data } = GQL.useFindScenesQuery({ variables: { filter: { per_page: 1, sort: "random", }, }, }); const scene = data?.findScenes.scenes[0]; if (componentsLoading) return ( ); return (
This is a test page.
{!!scene && }
); }; PluginApi.register.route("/plugin/test-react", TestPage); PluginApi.patch.before("SettingsToolsSection", function (props: any) { const { Setting, } = PluginApi.components; return [ { children: ( <> {props.children} } /> ), }, ]; }); PluginApi.patch.before("MainNavBar.UtilityItems", function (props: any) { const { Icon, } = PluginApi.components; return [ { children: ( <> {props.children} ) } ] }) })();