diff options
| author | Jonas Dellinger <jonas@dellinger.dev> | 2022-05-30 20:55:51 +0200 |
|---|---|---|
| committer | Jonas Dellinger <jonas@dellinger.dev> | 2022-05-30 20:55:51 +0200 |
| commit | 8fcaadd8f30182c61809748a324808add56ec1c0 (patch) | |
| tree | 1e8590a794c7e5b0461a79785e7c059b1a29d91b | |
| parent | 007860f8f771a7ee62b1c384fbe4f741528a75d5 (diff) | |
| download | decky-loader-8fcaadd8f30182c61809748a324808add56ec1c0.tar.gz decky-loader-8fcaadd8f30182c61809748a324808add56ec1c0.zip | |
All props of route, expose routerHook
| -rw-r--r-- | frontend/package-lock.json | 73 | ||||
| -rw-r--r-- | frontend/package.json | 3 | ||||
| -rw-r--r-- | frontend/src/components/DeckyRouterState.tsx | 19 | ||||
| -rw-r--r-- | frontend/src/plugin-loader.tsx | 4 | ||||
| -rw-r--r-- | frontend/src/router-hook.tsx | 33 |
5 files changed, 90 insertions, 42 deletions
diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 1605b373..0fe1d18f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "license": "GPLV2", "dependencies": { - "decky-frontend-lib": "^0.0.3", + "decky-frontend-lib": "^0.0.4", "react-icons": "^4.3.1" }, "devDependencies": { @@ -19,6 +19,7 @@ "@rollup/plugin-replace": "^4.0.0", "@rollup/plugin-typescript": "^8.3.2", "@types/react": "16.14.0", + "@types/react-router": "5.1.18", "@types/webpack": "^5.28.0", "husky": "^8.0.1", "import-sort-style-module": "^6.0.0", @@ -26,7 +27,9 @@ "prettier-plugin-import-sort": "^0.0.7", "react": "16.14.0", "react-dom": "16.14.0", - "rollup": "^2.70.2" + "rollup": "^2.70.2", + "tslib": "^2.4.0", + "typescript": "^4.7.2" } }, "node_modules/@ampproject/remapping": { @@ -509,6 +512,12 @@ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -537,6 +546,16 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-router": { + "version": "5.1.18", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz", + "integrity": "sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==", + "dev": true, + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -998,9 +1017,9 @@ } }, "node_modules/decky-frontend-lib": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/decky-frontend-lib/-/decky-frontend-lib-0.0.3.tgz", - "integrity": "sha512-kOiXyUcxN4wtCsYZ/aMnNdvGL8lqM04Q9JmbzE9ykdbKq1AStn3HxE6dzOL4DukHahM/dyifLt7tTN93bDE0SA==" + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/decky-frontend-lib/-/decky-frontend-lib-0.0.4.tgz", + "integrity": "sha512-FSOsvhd1TR/hgLpO98IjAm9id4SZrTwUtQcUIeoyDlJCOMH7qg18bTB+yvGBkP05nykEGuxKS5I/o4GC++F1kg==" }, "node_modules/deepmerge": { "version": "4.2.2", @@ -2044,15 +2063,13 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/typescript": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", - "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz", + "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==", "dev": true, - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2532,6 +2549,12 @@ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, + "@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "dev": true + }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -2560,6 +2583,16 @@ "csstype": "^3.0.2" } }, + "@types/react-router": { + "version": "5.1.18", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz", + "integrity": "sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==", + "dev": true, + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -2946,9 +2979,9 @@ } }, "decky-frontend-lib": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/decky-frontend-lib/-/decky-frontend-lib-0.0.3.tgz", - "integrity": "sha512-kOiXyUcxN4wtCsYZ/aMnNdvGL8lqM04Q9JmbzE9ykdbKq1AStn3HxE6dzOL4DukHahM/dyifLt7tTN93bDE0SA==" + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/decky-frontend-lib/-/decky-frontend-lib-0.0.4.tgz", + "integrity": "sha512-FSOsvhd1TR/hgLpO98IjAm9id4SZrTwUtQcUIeoyDlJCOMH7qg18bTB+yvGBkP05nykEGuxKS5I/o4GC++F1kg==" }, "deepmerge": { "version": "4.2.2", @@ -3756,15 +3789,13 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true, - "peer": true + "dev": true }, "typescript": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", - "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", - "dev": true, - "peer": true + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz", + "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==", + "dev": true }, "uri-js": { "version": "4.4.1", diff --git a/frontend/package.json b/frontend/package.json index 73c033b1..790c59fd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,6 +17,7 @@ "@rollup/plugin-replace": "^4.0.0", "@rollup/plugin-typescript": "^8.3.2", "@types/react": "16.14.0", + "@types/react-router": "5.1.18", "@types/webpack": "^5.28.0", "husky": "^8.0.1", "import-sort-style-module": "^6.0.0", @@ -34,7 +35,7 @@ } }, "dependencies": { - "decky-frontend-lib": "^0.0.3", + "decky-frontend-lib": "^0.0.4", "react-icons": "^4.3.1" } } 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'); |
