summaryrefslogtreecommitdiff
path: root/frontend/src
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src')
-rw-r--r--frontend/src/components/DeckyRouterState.tsx19
-rw-r--r--frontend/src/plugin-loader.tsx4
-rw-r--r--frontend/src/router-hook.tsx33
3 files changed, 36 insertions, 20 deletions
diff --git a/frontend/src/components/DeckyRouterState.tsx b/frontend/src/components/DeckyRouterState.tsx
index 3c9a5f9b..72fc5816 100644
--- a/frontend/src/components/DeckyRouterState.tsx
+++ b/frontend/src/components/DeckyRouterState.tsx
@@ -1,11 +1,17 @@
import { ComponentType, FC, createContext, useContext, useEffect, useState } from 'react';
+import { RouteProps } from 'react-router';
+
+export interface RouterEntry {
+ props: Omit<RouteProps, 'path' | 'children'>;
+ component: ComponentType;
+}
interface PublicDeckyRouterState {
- routes: Map<string, ComponentType>;
+ routes: Map<string, RouterEntry>;
}
export class DeckyRouterState {
- private _routes: Map<string, ComponentType> = new Map<string, ComponentType>();
+ private _routes = new Map<string, RouterEntry>();
public eventBus = new EventTarget();
@@ -13,8 +19,8 @@ export class DeckyRouterState {
return { routes: this._routes };
}
- addRoute(path: string, render: ComponentType) {
- this._routes.set(path, render);
+ addRoute(path: string, component: RouterEntry['component'], props: RouterEntry['props'] = {}) {
+ this._routes.set(path, { props, component });
this.notifyUpdate();
}
@@ -29,7 +35,7 @@ export class DeckyRouterState {
}
interface DeckyRouterStateContext extends PublicDeckyRouterState {
- addRoute(path: string, render: ComponentType): void;
+ addRoute(path: string, component: RouterEntry['component'], props: RouterEntry['props']): void;
removeRoute(path: string): void;
}
@@ -56,7 +62,8 @@ export const DeckyRouterStateContextProvider: FC<Props> = ({ children, deckyRout
return () => deckyRouterState.eventBus.removeEventListener('update', onUpdate);
}, []);
- const addRoute = (path: string, render: ComponentType) => deckyRouterState.addRoute(path, render);
+ const addRoute = (path: string, component: RouterEntry['component'], props: RouterEntry['props'] = {}) =>
+ deckyRouterState.addRoute(path, component, props);
const removeRoute = (path: string) => deckyRouterState.removeRoute(path);
return (
diff --git a/frontend/src/plugin-loader.tsx b/frontend/src/plugin-loader.tsx
index fc1f57e9..200fffdc 100644
--- a/frontend/src/plugin-loader.tsx
+++ b/frontend/src/plugin-loader.tsx
@@ -64,7 +64,7 @@ class PluginLoader extends Logger {
private async importReactPlugin(name: string) {
let res = await fetch(`http://127.0.0.1:1337/plugins/${name}/frontend_bundle`);
if (res.ok) {
- let content = await eval(await res.text())(PluginLoader.createPluginAPI(name));
+ let content = await eval(await res.text())(this.createPluginAPI(name));
this.plugins.push({
name: name,
icon: content.icon,
@@ -82,7 +82,7 @@ class PluginLoader extends Logger {
});
}
- static createPluginAPI(pluginName: string) {
+ createPluginAPI(pluginName: string) {
return {
routerHook: this.routerHook,
async callServerMethod(methodName: string, args = {}) {
diff --git a/frontend/src/router-hook.tsx b/frontend/src/router-hook.tsx
index ef2844b6..83d23bf1 100644
--- a/frontend/src/router-hook.tsx
+++ b/frontend/src/router-hook.tsx
@@ -1,7 +1,13 @@
import { afterPatch, findModuleChild, unpatch } from 'decky-frontend-lib';
-import { FC, ReactElement, createElement } from 'react';
+import { ReactElement, createElement, memo } from 'react';
+import type { Route } from 'react-router';
-import { DeckyRouterState, DeckyRouterStateContextProvider, useDeckyRouterState } from './components/DeckyRouterState';
+import {
+ DeckyRouterState,
+ DeckyRouterStateContextProvider,
+ RouterEntry,
+ useDeckyRouterState,
+} from './components/DeckyRouterState';
import Logger from './logger';
declare global {
@@ -10,11 +16,6 @@ declare global {
}
}
-interface RouteProps {
- path: string;
- children: ReactElement;
-}
-
class RouterHook extends Logger {
private router: any;
private memoizedRouter: any;
@@ -36,18 +37,22 @@ class RouterHook extends Logger {
}
});
- let Route: FC<RouteProps>;
+ let Route: new () => Route;
const DeckyWrapper = ({ children }: { children: ReactElement }) => {
const { routes } = useDeckyRouterState();
-
+
const routerIndex = children.props.children[0].props.children.length - 1;
if (
!children.props.children[0].props.children[routerIndex].length ||
children.props.children[0].props.children !== routes.size
) {
const newRouterArray: ReactElement[] = [];
- routes.forEach((Render, path) => {
- newRouterArray.push(<Route path={path}>{createElement(Render)}</Route>);
+ routes.forEach(({ component, props }, path) => {
+ newRouterArray.push(
+ <Route path={path} {...props}>
+ {createElement(component)}
+ </Route>,
+ );
});
children.props.children[0].props.children[routerIndex] = newRouterArray;
}
@@ -73,7 +78,7 @@ class RouterHook extends Logger {
);
return returnVal;
});
- this.memoizedRouter = window.SP_REACT.memo(this.router.type);
+ this.memoizedRouter = memo(this.router.type);
this.memoizedRouter.isDeckyRouter = true;
}
ret.props.children.props.children[2].props.children[0].type = this.memoizedRouter;
@@ -83,6 +88,10 @@ class RouterHook extends Logger {
});
}
+ addRoute(path: string, component: RouterEntry['component'], props: RouterEntry['props'] = {}) {
+ this.routerState.addRoute(path, component, props);
+ }
+
deinit() {
unpatch(this.gamepadWrapper, 'render');
this.router && unpatch(this.router, 'type');