mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-06-17 08:47:49 +00:00
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:
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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' }} />
|
||||
|
||||
@@ -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 (
|
||||
|
||||
Reference in New Issue
Block a user