Skip to content

Commit

Permalink
API for patching existing routes, lower power use
Browse files Browse the repository at this point in the history
  • Loading branch information
AAGaming00 committed Aug 2, 2022
1 parent f1e8097 commit ab6ec98
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 23 deletions.
4 changes: 2 additions & 2 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ async def load_plugins(self):

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()

Expand Down
40 changes: 35 additions & 5 deletions frontend/src/components/DeckyRouterState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,48 @@ 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'] = {}) {
this._routes.set(path, { props, component });
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();
Expand All @@ -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;
}

Expand All @@ -54,6 +80,7 @@ export const DeckyRouterStateContextProvider: FC<Props> = ({ children, deckyRout

useEffect(() => {
function onUpdate() {
console.log('test', deckyRouterState.publicState());
setPublicDeckyRouterState({ ...deckyRouterState.publicState() });
}

Expand All @@ -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>
);
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ declare global {
DeckyUpdater?: DeckyUpdater;
importDeckyPlugin: Function;
syncDeckyPlugins: Function;
deckyHasLoaded: boolean;
}
}

Expand All @@ -26,3 +27,5 @@ window.syncDeckyPlugins = async function () {
};

setTimeout(() => window.syncDeckyPlugins(), 5000);

window.deckyHasLoaded = true;
12 changes: 11 additions & 1 deletion frontend/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
Expand All @@ -28,7 +38,7 @@ class Logger {
}

debug(...args: any[]) {
log(this.name, ...args);
debug(this.name, ...args);
}
}

Expand Down
50 changes: 37 additions & 13 deletions frontend/src/router-hook.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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(
Expand All @@ -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;
};

Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/tabs-hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down

0 comments on commit ab6ec98

Please sign in to comment.