summaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'frontend')
-rw-r--r--frontend/src/tabs-hook.tsx133
1 files changed, 73 insertions, 60 deletions
diff --git a/frontend/src/tabs-hook.tsx b/frontend/src/tabs-hook.tsx
index 5d708fcb..08206c14 100644
--- a/frontend/src/tabs-hook.tsx
+++ b/frontend/src/tabs-hook.tsx
@@ -1,14 +1,5 @@
// TabsHook for versions after the Desktop merge
-import {
- Patch,
- QuickAccessTab,
- afterPatch,
- findInReactTree,
- findSP,
- gamepadUIClasses,
- getReactInstance,
- sleep,
-} from 'decky-frontend-lib';
+import { Patch, QuickAccessTab, afterPatch, findInReactTree, sleep } from 'decky-frontend-lib';
import { QuickAccessVisibleStateProvider } from './components/QuickAccessVisibleState';
import Logger from './logger';
@@ -40,60 +31,82 @@ class TabsHook extends Logger {
window.__TABS_HOOK_INSTANCE = this;
}
- async init() {
- this.qAMRoot = await this.getQAMRoot();
-
- let patchedInnerQAM: any;
- this.qamPatch = afterPatch(this.qAMRoot.return, 'type', (_: any, ret: any) => {
- try {
- if (this.qAMRoot?.child && !this.qAMRoot?.child?.type?.decky) {
- afterPatch(this.qAMRoot.child, 'type', (_: any, ret: any) => {
- try {
- const qamTabsRenderer = findInReactTree(ret, (x) => x?.props?.onFocusNavDeactivated);
- if (patchedInnerQAM) {
- qamTabsRenderer.type = patchedInnerQAM;
- } else {
- afterPatch(qamTabsRenderer, 'type', (innerArgs: any, ret: any) => {
- const tabs = findInReactTree(ret, (x) => x?.props?.tabs);
- this.render(tabs.props.tabs, innerArgs[0].visible);
- return ret;
- });
- patchedInnerQAM = qamTabsRenderer.type;
+ init() {
+ const tree = (document.getElementById('root') as any)._reactRootContainer._internalRoot.current;
+ let qAMRoot: any;
+ const findQAMRoot = (currentNode: any, iters: number): any => {
+ if (iters >= 65) {
+ // currently 45
+ return null;
+ }
+ if (
+ typeof currentNode?.memoizedProps?.visible == 'boolean' &&
+ currentNode?.type?.toString()?.includes('QuickAccessMenuBrowserView')
+ ) {
+ this.log(`QAM root was found in ${iters} recursion cycles`);
+ return currentNode;
+ }
+ if (currentNode.child) {
+ let node = findQAMRoot(currentNode.child, iters + 1);
+ if (node !== null) return node;
+ }
+ if (currentNode.sibling) {
+ let node = findQAMRoot(currentNode.sibling, iters + 1);
+ if (node !== null) return node;
+ }
+ return null;
+ };
+ (async () => {
+ qAMRoot = findQAMRoot(tree, 0);
+ while (!qAMRoot) {
+ this.error(
+ 'Failed to find QAM root node, reattempting in 5 seconds. A developer may need to increase the recursion limit.',
+ );
+ await sleep(5000);
+ qAMRoot = findQAMRoot(tree, 0);
+ }
+ this.qAMRoot = qAMRoot;
+ let patchedInnerQAM: any;
+ this.qamPatch = afterPatch(qAMRoot.return, 'type', (_: any, ret: any) => {
+ try {
+ if (!qAMRoot?.child) {
+ qAMRoot = findQAMRoot(tree, 0);
+ this.qAMRoot = qAMRoot;
+ }
+ if (qAMRoot?.child && !qAMRoot?.child?.type?.decky) {
+ afterPatch(qAMRoot.child, 'type', (_: any, ret: any) => {
+ try {
+ const qamTabsRenderer = findInReactTree(ret, (x) => x?.props?.onFocusNavDeactivated);
+ if (patchedInnerQAM) {
+ qamTabsRenderer.type = patchedInnerQAM;
+ } else {
+ afterPatch(qamTabsRenderer, 'type', (innerArgs: any, ret: any) => {
+ const tabs = findInReactTree(ret, (x) => x?.props?.tabs);
+ this.render(tabs.props.tabs, innerArgs[0].visible);
+ return ret;
+ });
+ patchedInnerQAM = qamTabsRenderer.type;
+ }
+ } catch (e) {
+ this.error('Error patching QAM inner', e);
}
- } catch (e) {
- this.error('Error patching QAM inner', e);
- }
- return ret;
- });
- this.qAMRoot.child.type.decky = true;
- this.qAMRoot.child.alternate.type = this.qAMRoot.child.type;
+ return ret;
+ });
+ qAMRoot.child.type.decky = true;
+ qAMRoot.child.alternate.type = qAMRoot.child.type;
+ }
+ } catch (e) {
+ this.error('Error patching QAM', e);
}
- } catch (e) {
- this.error('Error patching QAM', e);
- }
- return ret;
- });
+ return ret;
+ });
- if (this.qAMRoot.return.alternate) {
- this.qAMRoot.return.alternate.type = this.qAMRoot.return.type;
- }
- this.log('Finished initial injection');
- }
-
- async getQAMRoot() {
- while (!findSP()) {
- await sleep(50);
- }
-
- const parentNode = findSP().document.querySelector(`.${gamepadUIClasses.BasicUiRoot}`);
- if (!parentNode) return null;
-
- return findInReactTree(
- getReactInstance(parentNode),
- (n) =>
- typeof n.memoizedProps?.visible !== 'undefined' && n.type?.toString()?.includes('QuickAccessMenuBrowserView'),
- );
+ if (qAMRoot.return.alternate) {
+ qAMRoot.return.alternate.type = qAMRoot.return.type;
+ }
+ this.log('Finished initial injection');
+ })();
}
deinit() {