Refactor TabsHook (#458)

This commit is contained in:
MIkhail Kozlov
2023-05-30 23:53:48 -07:00
committed by GitHub
parent c5229c6a62
commit b27b625921
3 changed files with 66 additions and 79 deletions
+1 -1
View File
@@ -43,7 +43,7 @@
}
},
"dependencies": {
"decky-frontend-lib": "3.20.7",
"decky-frontend-lib": "3.21.1",
"i18next": "^22.5.0",
"i18next-http-backend": "^2.2.1",
"react-file-icon": "^1.3.0",
+4 -4
View File
@@ -2,8 +2,8 @@ lockfileVersion: '6.0'
dependencies:
decky-frontend-lib:
specifier: 3.20.7
version: 3.20.7
specifier: 3.21.1
version: 3.21.1
i18next:
specifier: ^22.5.0
version: 22.5.0
@@ -1393,8 +1393,8 @@ packages:
dependencies:
ms: 2.1.2
/decky-frontend-lib@3.20.7:
resolution: {integrity: sha512-Zwwbo50cqpTbCfSCZaqITgTRvWs7pK9KO1A+Oo2sCC/DqOfyUtEH5niNPid4Qxu+yh4lsbEjTurJk1nCfd+nZw==}
/decky-frontend-lib@3.21.1:
resolution: {integrity: sha512-30605ET9qqZ6St6I9WmMmLGgSrTIdMwo7xy85+lRaF1miUd2icOGEJjwnbVcZDdkal+1fJ3tNEDXlchVfG4TrA==}
dev: false
/decode-named-character-reference@1.0.2:
+61 -74
View File
@@ -1,5 +1,14 @@
// TabsHook for versions after the Desktop merge
import { Patch, QuickAccessTab, afterPatch, findInReactTree, sleep } from 'decky-frontend-lib';
import {
Patch,
QuickAccessTab,
afterPatch,
findInReactTree,
findSP,
gamepadUIClasses,
getReactInstance,
sleep,
} from 'decky-frontend-lib';
import { QuickAccessVisibleStateProvider } from './components/QuickAccessVisibleState';
import Logger from './logger';
@@ -31,82 +40,60 @@ class TabsHook extends Logger {
window.__TABS_HOOK_INSTANCE = this;
}
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);
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;
}
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 inner', e);
}
return ret;
});
this.qAMRoot.child.type.decky = true;
this.qAMRoot.child.alternate.type = this.qAMRoot.child.type;
}
return ret;
});
if (qAMRoot.return.alternate) {
qAMRoot.return.alternate.type = qAMRoot.return.type;
} catch (e) {
this.error('Error patching QAM', e);
}
this.log('Finished initial injection');
})();
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'),
);
}
deinit() {