summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAAGaming <aa@mail.catvibers.me>2022-08-02 18:54:55 -0400
committerAAGaming <aa@mail.catvibers.me>2022-08-02 18:54:55 -0400
commitab6ec981604a32611d972ede634abe7ccd19b0d2 (patch)
tree49f04b47f959cf48703a9b36fecc1d183d98cf7a
parentf1e809781ad60cf3f6cddf0a0b94273b61bf1999 (diff)
downloaddecky-loader-2.0.4-ab6ec98-pre.tar.gz
decky-loader-2.0.4-ab6ec98-pre.zip
API for patching existing routes, lower power usev2.0.4-ab6ec98-pre
-rw-r--r--backend/main.py4
-rw-r--r--frontend/src/components/DeckyRouterState.tsx40
-rw-r--r--frontend/src/index.tsx3
-rw-r--r--frontend/src/logger.ts12
-rw-r--r--frontend/src/router-hook.tsx50
-rw-r--r--frontend/src/tabs-hook.ts4
6 files changed, 90 insertions, 23 deletions
diff --git a/backend/main.py b/backend/main.py
index ce503e8e..b52180ab 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -83,8 +83,8 @@ class PluginManager:
async def loader_reinjector(self):
while True:
- await sleep(1)
- if not await tab_has_global_var("SP", "DeckyPluginLoader"):
+ await sleep(5)
+ if not await tab_has_global_var("SP", "deckyHasLoaded"):
logger.info("Plugin loader isn't present in Steam anymore, reinjecting...")
await self.inject_javascript()
diff --git a/frontend/src/components/DeckyRouterState.tsx b/frontend/src/components/DeckyRouterState.tsx
index 4aab7abd..c7da4034 100644
--- a/frontend/src/components/DeckyRouterState.tsx
+++ b/frontend/src/components/DeckyRouterState.tsx
@@ -6,17 +6,21 @@ export interface RouterEntry {
component: ComponentType;
}
+export type RoutePatch = (route: RouteProps) => RouteProps;
+
interface PublicDeckyRouterState {
routes: Map<string, RouterEntry>;
+ routePatches: Map<string, Set<RoutePatch>>;
}
export class DeckyRouterState {
private _routes = new Map<string, RouterEntry>();
+ private _routePatches = new Map<string, Set<RoutePatch>>();
public eventBus = new EventTarget();
publicState(): PublicDeckyRouterState {
- return { routes: this._routes };
+ return { routes: this._routes, routePatches: this._routePatches };
}
addRoute(path: string, component: RouterEntry['component'], props: RouterEntry['props'] = {}) {
@@ -24,6 +28,26 @@ export class DeckyRouterState {
this.notifyUpdate();
}
+ addPatch(path: string, patch: RoutePatch) {
+ let patchList = this._routePatches.get(path);
+ if (!patchList) {
+ patchList = new Set();
+ this._routePatches.set(path, patchList);
+ }
+ patchList.add(patch);
+ this.notifyUpdate();
+ return patch;
+ }
+
+ removePatch(path: string, patch: RoutePatch) {
+ const patchList = this._routePatches.get(path);
+ patchList?.delete(patch);
+ if (patchList?.size == 0) {
+ this._routePatches.delete(path);
+ }
+ this.notifyUpdate();
+ }
+
removeRoute(path: string) {
this._routes.delete(path);
this.notifyUpdate();
@@ -36,6 +60,8 @@ export class DeckyRouterState {
interface DeckyRouterStateContext extends PublicDeckyRouterState {
addRoute(path: string, component: RouterEntry['component'], props: RouterEntry['props']): void;
+ addPatch(path: string, patch: RoutePatch): RoutePatch;
+ removePatch(path: string, patch: RoutePatch): void;
removeRoute(path: string): void;
}
@@ -54,6 +80,7 @@ export const DeckyRouterStateContextProvider: FC<Props> = ({ children, deckyRout
useEffect(() => {
function onUpdate() {
+ console.log('test', deckyRouterState.publicState());
setPublicDeckyRouterState({ ...deckyRouterState.publicState() });
}
@@ -62,12 +89,15 @@ export const DeckyRouterStateContextProvider: FC<Props> = ({ children, deckyRout
return () => deckyRouterState.eventBus.removeEventListener('update', onUpdate);
}, []);
- const addRoute = (path: string, component: RouterEntry['component'], props: RouterEntry['props'] = {}) =>
- deckyRouterState.addRoute(path, component, props);
- const removeRoute = (path: string) => deckyRouterState.removeRoute(path);
+ const addRoute = deckyRouterState.addRoute.bind(deckyRouterState);
+ const addPatch = deckyRouterState.addPatch.bind(deckyRouterState);
+ const removePatch = deckyRouterState.removePatch.bind(deckyRouterState);
+ const removeRoute = deckyRouterState.removeRoute.bind(deckyRouterState);
return (
- <DeckyRouterStateContext.Provider value={{ ...publicDeckyRouterState, addRoute, removeRoute }}>
+ <DeckyRouterStateContext.Provider
+ value={{ ...publicDeckyRouterState, addRoute, addPatch, removePatch, removeRoute }}
+ >
{children}
</DeckyRouterStateContext.Provider>
);
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index 188c1330..4045751f 100644
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -7,6 +7,7 @@ declare global {
DeckyUpdater?: DeckyUpdater;
importDeckyPlugin: Function;
syncDeckyPlugins: Function;
+ deckyHasLoaded: boolean;
}
}
@@ -26,3 +27,5 @@ window.syncDeckyPlugins = async function () {
};
setTimeout(() => window.syncDeckyPlugins(), 5000);
+
+window.deckyHasLoaded = true;
diff --git a/frontend/src/logger.ts b/frontend/src/logger.ts
index 9eb515a3..22036362 100644
--- a/frontend/src/logger.ts
+++ b/frontend/src/logger.ts
@@ -8,6 +8,16 @@ export const log = (name: string, ...args: any[]) => {
);
};
+export const debug = (name: string, ...args: any[]) => {
+ console.debug(
+ `%c Decky %c ${name} %c`,
+ 'background: #16a085; color: black;',
+ 'background: #1abc9c; color: black;',
+ 'color: blue;',
+ ...args,
+ );
+};
+
export const error = (name: string, ...args: any[]) => {
console.log(
`%c Decky %c ${name} %c`,
@@ -28,7 +38,7 @@ class Logger {
}
debug(...args: any[]) {
- log(this.name, ...args);
+ debug(this.name, ...args);
}
}
diff --git a/frontend/src/router-hook.tsx b/frontend/src/router-hook.tsx
index 4e23658e..ca2a7039 100644
--- a/frontend/src/router-hook.tsx
+++ b/frontend/src/router-hook.tsx
@@ -1,10 +1,11 @@
import { afterPatch, findModuleChild, unpatch } from 'decky-frontend-lib';
import { ReactElement, createElement, memo } from 'react';
-import type { Route } from 'react-router';
+import type { Route, RouteProps } from 'react-router';
import {
DeckyRouterState,
DeckyRouterStateContextProvider,
+ RoutePatch,
RouterEntry,
useDeckyRouterState,
} from './components/DeckyRouterState';
@@ -38,19 +39,16 @@ class RouterHook extends Logger {
});
let Route: new () => Route;
+ // Used to store the new replicated routes we create to allow routes to be unpatched.
+ let toReplace = new Map<string, Route>();
const DeckyWrapper = ({ children }: { children: ReactElement }) => {
- const { routes } = useDeckyRouterState();
+ const { routes, routePatches } = useDeckyRouterState();
- let routerIndex = children.props.children[0].props.children.length;
- if (
- !children.props.children[0].props.children[routerIndex - 1]?.length ||
- children.props.children[0].props.children[routerIndex - 1]?.length !== routes.size
- ) {
- if (
- children.props.children[0].props.children[routerIndex - 1]?.length &&
- children.props.children[0].props.children[routerIndex - 1].length !== routes.size
- )
- routerIndex--;
+ const routeList = children.props.children[0].props.children;
+
+ let routerIndex = routeList.length;
+ if (!routeList[routerIndex - 1]?.length || routeList[routerIndex - 1]?.length !== routes.size) {
+ if (routeList[routerIndex - 1]?.length && routeList[routerIndex - 1].length !== routes.size) routerIndex--;
const newRouterArray: ReactElement[] = [];
routes.forEach(({ component, props }, path) => {
newRouterArray.push(
@@ -59,8 +57,26 @@ class RouterHook extends Logger {
</Route>,
);
});
- children.props.children[0].props.children[routerIndex] = newRouterArray;
+ routeList[routerIndex] = newRouterArray;
}
+ routeList.forEach((route: Route, index: number) => {
+ const replaced = toReplace.get(route?.props?.path as string);
+ if (replaced) {
+ routeList[index] = replaced;
+ toReplace.delete(route?.props?.path as string);
+ }
+ if (route?.props?.path && routePatches.has(route.props.path as string)) {
+ toReplace.set(
+ route?.props?.path as string,
+ // @ts-ignore
+ createElement(routeList[index].type, routeList[index].props, routeList[index].props.children),
+ );
+ routePatches.get(route.props.path as string)?.forEach((patch) => {
+ routeList[index].props = patch(routeList[index].props);
+ });
+ }
+ });
+ this.debug('Rerendered routes list');
return children;
};
@@ -97,6 +113,14 @@ class RouterHook extends Logger {
this.routerState.addRoute(path, component, props);
}
+ addPatch(path: string, patch: RoutePatch) {
+ return this.routerState.addPatch(path, patch);
+ }
+
+ removePatch(path: string, patch: RoutePatch) {
+ this.routerState.removePatch(path, patch);
+ }
+
removeRoute(path: string) {
this.routerState.removeRoute(path);
}
diff --git a/frontend/src/tabs-hook.ts b/frontend/src/tabs-hook.ts
index 667fc973..b83a1e97 100644
--- a/frontend/src/tabs-hook.ts
+++ b/frontend/src/tabs-hook.ts
@@ -110,12 +110,12 @@ class TabsHook extends Logger {
}
add(tab: Tab) {
- this.log('Adding tab', tab.id, 'to render array');
+ this.debug('Adding tab', tab.id, 'to render array');
this.tabs.push(tab);
}
removeById(id: number) {
- this.log('Removing tab', id);
+ this.debug('Removing tab', id);
this.tabs = this.tabs.filter((tab) => tab.id !== id);
}