react: Add Router hook & fix typescript issues (#68)

* add rollup watch command, add pnpm lockfile

* wait for react

* add WIP patcher, window hook, and webpack

* fix typescript, fix React, lint, add pnpm to gitignore

* actually fix react

* show frontend JS errors in console

* cleanup

* Add Router hook

* Remove console.log

* Expose routerHook in createPluginAPI

Co-authored-by: Jonas Dellinger <jonas@dellinger.dev>
This commit is contained in:
AAGaming
2022-05-30 14:26:54 -04:00
committed by GitHub
parent 44776b393e
commit 007860f8f7
9 changed files with 185 additions and 13 deletions
@@ -0,0 +1,67 @@
import { ComponentType, FC, createContext, useContext, useEffect, useState } from 'react';
interface PublicDeckyRouterState {
routes: Map<string, ComponentType>;
}
export class DeckyRouterState {
private _routes: Map<string, ComponentType> = new Map<string, ComponentType>();
public eventBus = new EventTarget();
publicState(): PublicDeckyRouterState {
return { routes: this._routes };
}
addRoute(path: string, render: ComponentType) {
this._routes.set(path, render);
this.notifyUpdate();
}
removeRoute(path: string) {
this._routes.delete(path);
this.notifyUpdate();
}
private notifyUpdate() {
this.eventBus.dispatchEvent(new Event('update'));
}
}
interface DeckyRouterStateContext extends PublicDeckyRouterState {
addRoute(path: string, render: ComponentType): void;
removeRoute(path: string): void;
}
const DeckyRouterStateContext = createContext<DeckyRouterStateContext>(null as any);
export const useDeckyRouterState = () => useContext(DeckyRouterStateContext);
interface Props {
deckyRouterState: DeckyRouterState;
}
export const DeckyRouterStateContextProvider: FC<Props> = ({ children, deckyRouterState }) => {
const [publicDeckyRouterState, setPublicDeckyRouterState] = useState<PublicDeckyRouterState>({
...deckyRouterState.publicState(),
});
useEffect(() => {
function onUpdate() {
setPublicDeckyRouterState({ ...deckyRouterState.publicState() });
}
deckyRouterState.eventBus.addEventListener('update', onUpdate);
return () => deckyRouterState.eventBus.removeEventListener('update', onUpdate);
}, []);
const addRoute = (path: string, render: ComponentType) => deckyRouterState.addRoute(path, render);
const removeRoute = (path: string) => deckyRouterState.removeRoute(path);
return (
<DeckyRouterStateContext.Provider value={{ ...publicDeckyRouterState, addRoute, removeRoute }}>
{children}
</DeckyRouterStateContext.Provider>
);
};
+1 -1
View File
@@ -9,7 +9,7 @@ const PluginView: VFC = () => {
if (activePlugin) {
return (
<div style={{height: '100%'}}>
<div style={{ height: '100%' }}>
<div style={{ position: 'absolute', top: '3px', left: '16px', zIndex: 20 }}>
<DialogButton style={{ minWidth: 0, padding: '10px 12px' }} onClick={closeActivePlugin}>
<FaArrowLeft style={{ display: 'block' }} />
+11 -9
View File
@@ -1,23 +1,25 @@
import { staticClasses, DialogButton } from 'decky-frontend-lib';
import { DialogButton, staticClasses } from 'decky-frontend-lib';
import { VFC } from 'react';
import { FaShoppingBag } from "react-icons/fa";
import { FaShoppingBag } from 'react-icons/fa';
import { useDeckyState } from './DeckyState';
const TitleView: VFC = () => {
const { activePlugin } = useDeckyState();
const openPluginStore = () => fetch("http://127.0.0.1:1337/methods/open_plugin_store", {method: "POST"});
const openPluginStore = () => fetch('http://127.0.0.1:1337/methods/open_plugin_store', { method: 'POST' });
if (activePlugin === null) {
return <div className={staticClasses.Title}>
Decky
<div style={{ position: 'absolute', top: '3px', right: '16px', zIndex: 20 }}>
<DialogButton style={{ minWidth: 0, padding: '10px 12px' }} onClick={openPluginStore}>
return (
<div className={staticClasses.Title}>
Decky
<div style={{ position: 'absolute', top: '3px', right: '16px', zIndex: 20 }}>
<DialogButton style={{ minWidth: 0, padding: '10px 12px' }} onClick={openPluginStore}>
<FaShoppingBag style={{ display: 'block' }} />
</DialogButton>
</DialogButton>
</div>
</div>;
</div>
);
}
return (