mirror of
https://github.com/SteamDeckHomebrew/decky-loader.git
synced 2026-07-11 03:11:55 +00:00
Main menu and overlay patching API
This commit is contained in:
@@ -14,13 +14,13 @@ export class DeckyGlobalComponentsState {
|
|||||||
return { components: this._components };
|
return { components: this._components };
|
||||||
}
|
}
|
||||||
|
|
||||||
addComponent(path: string, component: FC) {
|
addComponent(name: string, component: FC) {
|
||||||
this._components.set(path, component);
|
this._components.set(name, component);
|
||||||
this.notifyUpdate();
|
this.notifyUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
removeComponent(path: string) {
|
removeComponent(name: string) {
|
||||||
this._components.delete(path);
|
this._components.delete(name);
|
||||||
this.notifyUpdate();
|
this.notifyUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,8 +30,8 @@ export class DeckyGlobalComponentsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface DeckyGlobalComponentsContext extends PublicDeckyGlobalComponentsState {
|
interface DeckyGlobalComponentsContext extends PublicDeckyGlobalComponentsState {
|
||||||
addComponent(path: string, component: FC): void;
|
addComponent(name: string, component: FC): void;
|
||||||
removeComponent(path: string): void;
|
removeComponent(name: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeckyGlobalComponentsContext = createContext<DeckyGlobalComponentsContext>(null as any);
|
const DeckyGlobalComponentsContext = createContext<DeckyGlobalComponentsContext>(null as any);
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import { CustomMainMenuItem, ItemPatch, OverlayPatch } from 'decky-frontend-lib';
|
||||||
|
import { FC, ReactNode, createContext, useContext, useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
interface PublicDeckyMenuState {
|
||||||
|
items: Set<CustomMainMenuItem>;
|
||||||
|
itemPatches: Map<string, Set<ItemPatch>>;
|
||||||
|
overlayPatches: Set<OverlayPatch>;
|
||||||
|
overlayComponents: Set<ReactNode>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DeckyMenuState {
|
||||||
|
private _items = new Set<CustomMainMenuItem>();
|
||||||
|
private _itemPatches = new Map<string, Set<ItemPatch>>();
|
||||||
|
private _overlayPatches = new Set<OverlayPatch>();
|
||||||
|
private _overlayComponents = new Set<ReactNode>();
|
||||||
|
|
||||||
|
public eventBus = new EventTarget();
|
||||||
|
|
||||||
|
publicState(): PublicDeckyMenuState {
|
||||||
|
return {
|
||||||
|
items: this._items,
|
||||||
|
itemPatches: this._itemPatches,
|
||||||
|
overlayPatches: this._overlayPatches,
|
||||||
|
overlayComponents: this._overlayComponents,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
addItem(item: CustomMainMenuItem) {
|
||||||
|
this._items.add(item);
|
||||||
|
this.notifyUpdate();
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
addPatch(path: string, patch: ItemPatch) {
|
||||||
|
let patchList = this._itemPatches.get(path);
|
||||||
|
if (!patchList) {
|
||||||
|
patchList = new Set();
|
||||||
|
this._itemPatches.set(path, patchList);
|
||||||
|
}
|
||||||
|
patchList.add(patch);
|
||||||
|
this.notifyUpdate();
|
||||||
|
return patch;
|
||||||
|
}
|
||||||
|
|
||||||
|
addOverlayPatch(patch: OverlayPatch) {
|
||||||
|
this._overlayPatches.add(patch);
|
||||||
|
this.notifyUpdate();
|
||||||
|
return patch;
|
||||||
|
}
|
||||||
|
|
||||||
|
addOverlayComponent(component: ReactNode) {
|
||||||
|
this._overlayComponents.add(component);
|
||||||
|
this.notifyUpdate();
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
removePatch(path: string, patch: ItemPatch) {
|
||||||
|
const patchList = this._itemPatches.get(path);
|
||||||
|
patchList?.delete(patch);
|
||||||
|
if (patchList?.size == 0) {
|
||||||
|
this._itemPatches.delete(path);
|
||||||
|
}
|
||||||
|
this.notifyUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeItem(item: CustomMainMenuItem) {
|
||||||
|
this._items.delete(item);
|
||||||
|
this.notifyUpdate();
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeOverlayPatch(patch: OverlayPatch) {
|
||||||
|
this._overlayPatches.delete(patch);
|
||||||
|
this.notifyUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeOverlayComponent(component: ReactNode) {
|
||||||
|
this._overlayComponents.delete(component);
|
||||||
|
this.notifyUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private notifyUpdate() {
|
||||||
|
this.eventBus.dispatchEvent(new Event('update'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DeckyMenuStateContext extends PublicDeckyMenuState {
|
||||||
|
addItem: DeckyMenuState['addItem'];
|
||||||
|
addPatch: DeckyMenuState['addPatch'];
|
||||||
|
addOverlayPatch: DeckyMenuState['addOverlayPatch'];
|
||||||
|
addOverlayComponent: DeckyMenuState['addOverlayComponent'];
|
||||||
|
removePatch: DeckyMenuState['removePatch'];
|
||||||
|
removeOverlayPatch: DeckyMenuState['removeOverlayPatch'];
|
||||||
|
removeOverlayComponent: DeckyMenuState['removeOverlayComponent'];
|
||||||
|
removeItem: DeckyMenuState['removeItem'];
|
||||||
|
}
|
||||||
|
|
||||||
|
const DeckyMenuStateContext = createContext<DeckyMenuStateContext>(null as any);
|
||||||
|
|
||||||
|
export const useDeckyMenuState = () => useContext(DeckyMenuStateContext);
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
deckyMenuState: DeckyMenuState;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DeckyMenuStateContextProvider: FC<Props> = ({ children, deckyMenuState }) => {
|
||||||
|
const [publicDeckyMenuState, setPublicDeckyMenuState] = useState<PublicDeckyMenuState>({
|
||||||
|
...deckyMenuState.publicState(),
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function onUpdate() {
|
||||||
|
setPublicDeckyMenuState({ ...deckyMenuState.publicState() });
|
||||||
|
}
|
||||||
|
|
||||||
|
deckyMenuState.eventBus.addEventListener('update', onUpdate);
|
||||||
|
|
||||||
|
return () => deckyMenuState.eventBus.removeEventListener('update', onUpdate);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const addItem = deckyMenuState.addItem.bind(deckyMenuState);
|
||||||
|
const addPatch = deckyMenuState.addPatch.bind(deckyMenuState);
|
||||||
|
const addOverlayPatch = deckyMenuState.addOverlayPatch.bind(deckyMenuState);
|
||||||
|
const addOverlayComponent = deckyMenuState.addOverlayComponent.bind(deckyMenuState);
|
||||||
|
const removePatch = deckyMenuState.removePatch.bind(deckyMenuState);
|
||||||
|
const removeOverlayPatch = deckyMenuState.removeOverlayPatch.bind(deckyMenuState);
|
||||||
|
const removeOverlayComponent = deckyMenuState.removeOverlayComponent.bind(deckyMenuState);
|
||||||
|
const removeItem = deckyMenuState.removeItem.bind(deckyMenuState);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DeckyMenuStateContext.Provider
|
||||||
|
value={{
|
||||||
|
...publicDeckyMenuState,
|
||||||
|
addItem,
|
||||||
|
addPatch,
|
||||||
|
addOverlayPatch,
|
||||||
|
addOverlayComponent,
|
||||||
|
removePatch,
|
||||||
|
removeOverlayPatch,
|
||||||
|
removeOverlayComponent,
|
||||||
|
removeItem,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</DeckyMenuStateContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
import {
|
||||||
|
CustomMainMenuItem,
|
||||||
|
ItemPatch,
|
||||||
|
MainMenuItem,
|
||||||
|
OverlayPatch,
|
||||||
|
afterPatch,
|
||||||
|
findInReactTree,
|
||||||
|
sleep,
|
||||||
|
} from 'decky-frontend-lib';
|
||||||
|
import { FC } from 'react';
|
||||||
|
import { ReactNode, cloneElement, createElement } from 'react';
|
||||||
|
|
||||||
|
import { DeckyMenuState, DeckyMenuStateContextProvider, useDeckyMenuState } from './components/DeckyMenuState';
|
||||||
|
import Logger from './logger';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__MENU_HOOK_INSTANCE: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuHook extends Logger {
|
||||||
|
private menuRenderer?: any;
|
||||||
|
private originalRenderer?: any;
|
||||||
|
private menuState: DeckyMenuState = new DeckyMenuState();
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super('MenuHook');
|
||||||
|
|
||||||
|
this.log('Initialized');
|
||||||
|
window.__MENU_HOOK_INSTANCE?.deinit?.();
|
||||||
|
window.__MENU_HOOK_INSTANCE = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
const tree = (document.getElementById('root') as any)._reactRootContainer._internalRoot.current;
|
||||||
|
let outerMenuRoot: any;
|
||||||
|
const findMenuRoot = (currentNode: any, iters: number): any => {
|
||||||
|
if (iters >= 60) {
|
||||||
|
// currently 54
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (currentNode?.memoizedProps?.navID == 'MainNavMenuContainer') {
|
||||||
|
this.log(`Menu root was found in ${iters} recursion cycles`);
|
||||||
|
return currentNode;
|
||||||
|
}
|
||||||
|
if (currentNode.child) {
|
||||||
|
let node = findMenuRoot(currentNode.child, iters + 1);
|
||||||
|
if (node !== null) return node;
|
||||||
|
}
|
||||||
|
if (currentNode.sibling) {
|
||||||
|
let node = findMenuRoot(currentNode.sibling, iters + 1);
|
||||||
|
if (node !== null) return node;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
outerMenuRoot = findMenuRoot(tree, 0);
|
||||||
|
while (!outerMenuRoot) {
|
||||||
|
this.error(
|
||||||
|
'Failed to find Menu root node, reattempting in 5 seconds. A developer may need to increase the recursion limit.',
|
||||||
|
);
|
||||||
|
await sleep(5000);
|
||||||
|
outerMenuRoot = findMenuRoot(tree, 0);
|
||||||
|
}
|
||||||
|
this.log('found outermenuroot', outerMenuRoot);
|
||||||
|
const menuRenderer = outerMenuRoot.return;
|
||||||
|
this.menuRenderer = menuRenderer;
|
||||||
|
this.originalRenderer = menuRenderer.type;
|
||||||
|
let toReplace = new Map<string, ReactNode>();
|
||||||
|
|
||||||
|
let patchedInnerMenu: any;
|
||||||
|
let overlayComponentManager: any;
|
||||||
|
|
||||||
|
const DeckyOverlayComponentManager = () => {
|
||||||
|
const { overlayComponents } = useDeckyMenuState();
|
||||||
|
|
||||||
|
return <>{overlayComponents.values()}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeckyInnerMenuWrapper = (props: { innerProps: any }) => {
|
||||||
|
const { overlayPatches } = useDeckyMenuState();
|
||||||
|
|
||||||
|
const rendererRet = this.originalRenderer(props.innerProps);
|
||||||
|
|
||||||
|
// Find the first array of children, this contains [mainmenu, overlay]
|
||||||
|
const childArray = findInReactTree(rendererRet, (x) => x?.[0]?.type);
|
||||||
|
|
||||||
|
// Insert the overlay components manager
|
||||||
|
if (!overlayComponentManager) {
|
||||||
|
overlayComponentManager = <DeckyOverlayComponentManager />;
|
||||||
|
}
|
||||||
|
|
||||||
|
childArray.push(overlayComponentManager);
|
||||||
|
|
||||||
|
// This must be cached in patchedInnerMenu to prevent re-renders
|
||||||
|
if (patchedInnerMenu) {
|
||||||
|
childArray[0].type = patchedInnerMenu;
|
||||||
|
} else {
|
||||||
|
afterPatch(childArray[0], 'type', (menuArgs, ret) => {
|
||||||
|
const { itemPatches, items } = useDeckyMenuState();
|
||||||
|
|
||||||
|
const itemList = ret.props.children;
|
||||||
|
|
||||||
|
// Add custom menu items
|
||||||
|
if (items.size > 0) {
|
||||||
|
const button = findInReactTree(ret.props.children, (x) =>
|
||||||
|
x?.type?.toString()?.includes('exactRouteMatch:'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const MenuItemComponent: FC<MainMenuItem> = button.type;
|
||||||
|
|
||||||
|
items.forEach((item) => {
|
||||||
|
let realIndex = 0; // there are some non-item things in the array
|
||||||
|
let count = 0;
|
||||||
|
itemList.forEach((i: any) => {
|
||||||
|
if (count == item.index) return;
|
||||||
|
if (i?.type == MenuItemComponent) count++;
|
||||||
|
realIndex++;
|
||||||
|
});
|
||||||
|
itemList.splice(realIndex, 0, createElement(MenuItemComponent, item));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply and revert patches
|
||||||
|
itemList.forEach((item: { props: MainMenuItem }, index: number) => {
|
||||||
|
if (!item?.props?.route) return;
|
||||||
|
const replaced = toReplace.get(item?.props?.route as string);
|
||||||
|
if (replaced) {
|
||||||
|
itemList[index] = replaced;
|
||||||
|
toReplace.delete(item?.props.route as string);
|
||||||
|
}
|
||||||
|
if (item?.props?.route && itemPatches.has(item.props.route as string)) {
|
||||||
|
toReplace.set(item?.props?.route as string, itemList[index]);
|
||||||
|
itemPatches.get(item.props.route as string)?.forEach((patch) => {
|
||||||
|
const oType = itemList[index].type;
|
||||||
|
itemList[index] = patch({
|
||||||
|
...cloneElement(itemList[index]),
|
||||||
|
type: (props) => createElement(oType, props),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
patchedInnerMenu = childArray[0].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply patches to the overlay
|
||||||
|
if (childArray[1]) {
|
||||||
|
overlayPatches.forEach((patch) => (childArray[1] = patch(childArray[1])));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rendererRet;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeckyOuterMenuWrapper = (props: any) => {
|
||||||
|
return (
|
||||||
|
<DeckyMenuStateContextProvider deckyMenuState={this.menuState}>
|
||||||
|
<DeckyInnerMenuWrapper innerProps={props} />
|
||||||
|
</DeckyMenuStateContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
menuRenderer.type = DeckyOuterMenuWrapper;
|
||||||
|
if (menuRenderer.alternate) {
|
||||||
|
menuRenderer.alternate.type = menuRenderer.type;
|
||||||
|
}
|
||||||
|
this.log('Finished initial injection');
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit() {
|
||||||
|
this.menuRenderer.type = this.originalRenderer;
|
||||||
|
this.menuRenderer.alternate.type = this.menuRenderer.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
addItem(item: CustomMainMenuItem) {
|
||||||
|
return this.menuState.addItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
addPatch(path: string, patch: ItemPatch) {
|
||||||
|
return this.menuState.addPatch(path, patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
addOverlayPatch(patch: OverlayPatch) {
|
||||||
|
return this.menuState.addOverlayPatch(patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
addOverlayComponent(component: ReactNode) {
|
||||||
|
return this.menuState.addOverlayComponent(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
removePatch(path: string, patch: ItemPatch) {
|
||||||
|
return this.menuState.removePatch(path, patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeItem(item: CustomMainMenuItem) {
|
||||||
|
return this.menuState.removeItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeOverlayPatch(patch: OverlayPatch) {
|
||||||
|
return this.menuState.removeOverlayPatch(patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeOverlayComponent(component: ReactNode) {
|
||||||
|
return this.menuState.removeOverlayComponent(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MenuHook;
|
||||||
@@ -1,13 +1,4 @@
|
|||||||
import {
|
import { ConfirmModal, ModalRoot, QuickAccessTab, Router, showModal, sleep, staticClasses } from 'decky-frontend-lib';
|
||||||
ConfirmModal,
|
|
||||||
ModalRoot,
|
|
||||||
Patch,
|
|
||||||
QuickAccessTab,
|
|
||||||
Router,
|
|
||||||
showModal,
|
|
||||||
sleep,
|
|
||||||
staticClasses,
|
|
||||||
} from 'decky-frontend-lib';
|
|
||||||
import { FC, lazy } from 'react';
|
import { FC, lazy } from 'react';
|
||||||
import { FaCog, FaExclamationCircle, FaPlug } from 'react-icons/fa';
|
import { FaCog, FaExclamationCircle, FaPlug } from 'react-icons/fa';
|
||||||
|
|
||||||
@@ -19,6 +10,7 @@ import NotificationBadge from './components/NotificationBadge';
|
|||||||
import PluginView from './components/PluginView';
|
import PluginView from './components/PluginView';
|
||||||
import WithSuspense from './components/WithSuspense';
|
import WithSuspense from './components/WithSuspense';
|
||||||
import Logger from './logger';
|
import Logger from './logger';
|
||||||
|
import MenuHook from './menu-hook';
|
||||||
import { Plugin } from './plugin';
|
import { Plugin } from './plugin';
|
||||||
import RouterHook from './router-hook';
|
import RouterHook from './router-hook';
|
||||||
import { deinitSteamFixes, initSteamFixes } from './steamfixes';
|
import { deinitSteamFixes, initSteamFixes } from './steamfixes';
|
||||||
@@ -37,6 +29,7 @@ const FilePicker = lazy(() => import('./components/modals/filepicker'));
|
|||||||
class PluginLoader extends Logger {
|
class PluginLoader extends Logger {
|
||||||
private plugins: Plugin[] = [];
|
private plugins: Plugin[] = [];
|
||||||
private tabsHook: TabsHook | OldTabsHook = document.title == 'SP' ? new OldTabsHook() : new TabsHook();
|
private tabsHook: TabsHook | OldTabsHook = document.title == 'SP' ? new OldTabsHook() : new TabsHook();
|
||||||
|
private menuHook: MenuHook = new MenuHook();
|
||||||
// private windowHook: WindowHook = new WindowHook();
|
// private windowHook: WindowHook = new WindowHook();
|
||||||
private routerHook: RouterHook = new RouterHook();
|
private routerHook: RouterHook = new RouterHook();
|
||||||
public toaster: Toaster = new Toaster();
|
public toaster: Toaster = new Toaster();
|
||||||
@@ -46,11 +39,10 @@ class PluginLoader extends Logger {
|
|||||||
// stores a list of plugin names which requested to be reloaded
|
// stores a list of plugin names which requested to be reloaded
|
||||||
private pluginReloadQueue: { name: string; version?: string }[] = [];
|
private pluginReloadQueue: { name: string; version?: string }[] = [];
|
||||||
|
|
||||||
private focusWorkaroundPatch?: Patch;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(PluginLoader.name);
|
super(PluginLoader.name);
|
||||||
this.tabsHook.init();
|
this.tabsHook.init();
|
||||||
|
this.menuHook.init();
|
||||||
this.log('Initialized');
|
this.log('Initialized');
|
||||||
|
|
||||||
const TabBadge = () => {
|
const TabBadge = () => {
|
||||||
@@ -185,7 +177,6 @@ class PluginLoader extends Logger {
|
|||||||
this.routerHook.removeRoute('/decky/settings');
|
this.routerHook.removeRoute('/decky/settings');
|
||||||
deinitSteamFixes();
|
deinitSteamFixes();
|
||||||
deinitFilepickerPatches();
|
deinitFilepickerPatches();
|
||||||
this.focusWorkaroundPatch?.unpatch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public unloadPlugin(name: string) {
|
public unloadPlugin(name: string) {
|
||||||
@@ -322,6 +313,7 @@ class PluginLoader extends Logger {
|
|||||||
|
|
||||||
createPluginAPI(pluginName: string) {
|
createPluginAPI(pluginName: string) {
|
||||||
return {
|
return {
|
||||||
|
menuHook: this.menuHook,
|
||||||
routerHook: this.routerHook,
|
routerHook: this.routerHook,
|
||||||
toaster: this.toaster,
|
toaster: this.toaster,
|
||||||
callServerMethod: this.callServerMethod,
|
callServerMethod: this.callServerMethod,
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ class RouterHook extends Logger {
|
|||||||
return <>{renderedComponents}</>;
|
return <>{renderedComponents}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let globalComponents: any;
|
||||||
|
|
||||||
this.wrapperPatch = afterPatch(this.gamepadWrapper, 'render', (_: any, ret: any) => {
|
this.wrapperPatch = afterPatch(this.gamepadWrapper, 'render', (_: any, ret: any) => {
|
||||||
if (ret?.props?.children?.props?.children?.length == 5 || ret?.props?.children?.props?.children?.length == 4) {
|
if (ret?.props?.children?.props?.children?.length == 5 || ret?.props?.children?.props?.children?.length == 4) {
|
||||||
const idx = ret?.props?.children?.props?.children?.length == 4 ? 1 : 2;
|
const idx = ret?.props?.children?.props?.children?.length == 4 ? 1 : 2;
|
||||||
@@ -143,11 +145,17 @@ class RouterHook extends Logger {
|
|||||||
this.memoizedRouter = memo(this.router.type);
|
this.memoizedRouter = memo(this.router.type);
|
||||||
this.memoizedRouter.isDeckyRouter = true;
|
this.memoizedRouter.isDeckyRouter = true;
|
||||||
}
|
}
|
||||||
ret.props.children.props.children.push(
|
|
||||||
<DeckyGlobalComponentsStateContextProvider deckyGlobalComponentsState={this.globalComponentsState}>
|
if (!globalComponents) {
|
||||||
<DeckyGlobalComponentsWrapper />
|
globalComponents = (
|
||||||
</DeckyGlobalComponentsStateContextProvider>,
|
<DeckyGlobalComponentsStateContextProvider deckyGlobalComponentsState={this.globalComponentsState}>
|
||||||
);
|
<DeckyGlobalComponentsWrapper />
|
||||||
|
</DeckyGlobalComponentsStateContextProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.props.children.props.children.push(globalComponents);
|
||||||
|
|
||||||
ret.props.children.props.children[idx].props.children[0].type = this.memoizedRouter;
|
ret.props.children.props.children[idx].props.children[0].type = this.memoizedRouter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user