diff options
Diffstat (limited to 'frontend/src/tabs-hook.ts')
| -rw-r--r-- | frontend/src/tabs-hook.ts | 85 |
1 files changed, 75 insertions, 10 deletions
diff --git a/frontend/src/tabs-hook.ts b/frontend/src/tabs-hook.ts index dd013844..de03310e 100644 --- a/frontend/src/tabs-hook.ts +++ b/frontend/src/tabs-hook.ts @@ -1,3 +1,6 @@ +import { afterPatch, sleep, unpatch } from 'decky-frontend-lib'; +import { memo } from 'react'; + import Logger from './logger'; declare global { @@ -11,7 +14,7 @@ declare global { const isTabsArray = (tabs: any) => { const length = tabs.length; - return length === 7 && tabs[length - 1]?.key === 6 && tabs[length - 1]?.tab; + return length >= 7 && tabs[length - 1]?.tab; }; interface Tab { @@ -24,24 +27,86 @@ interface Tab { class TabsHook extends Logger { // private keys = 7; tabs: Tab[] = []; + private quickAccess: any; + private tabRenderer: any; + private memoizedQuickAccess: any; + private cNode: any; + + private qAPTree: any; + private rendererTree: any; constructor() { super('TabsHook'); this.log('Initialized'); + window.__TABS_HOOK_INSTANCE?.deinit?.(); window.__TABS_HOOK_INSTANCE = this; const self = this; - - const filter = Array.prototype.__filter ?? Array.prototype.filter; - Array.prototype.__filter = filter; - Array.prototype.filter = function (...args: any[]) { - if (isTabsArray(this)) { - self.render(this); + const tree = (document.getElementById('root') as any)._reactRootContainer._internalRoot.current; + let scrollRoot: any; + let currentNode = tree; + (async () => { + let iters = 0; + while (!scrollRoot) { + iters++; + currentNode = currentNode?.child; + if (iters >= 30 || !currentNode) { + iters = 0; + currentNode = tree; + await sleep(5000); + } + if (currentNode?.type?.prototype?.RemoveSmartScrollContainer) scrollRoot = currentNode; } - // @ts-ignore - return filter.call(this, ...args); - }; + let newQA: any; + let newQATabRenderer: any; + afterPatch(scrollRoot.stateNode, 'render', (_: any, ret: any) => { + if (!this.quickAccess && ret.props.children.props.children[4]) { + this.quickAccess = ret?.props?.children?.props?.children[4].type; + newQA = (...args: any) => { + const ret = this.quickAccess.type(...args); + if (ret) { + if (!newQATabRenderer) { + this.tabRenderer = ret.props.children[1].children.type; + newQATabRenderer = (...args: any) => { + const oFilter = Array.prototype.filter; + Array.prototype.filter = function (...args: any[]) { + if (isTabsArray(this)) { + self.render(this); + } + // @ts-ignore + return oFilter.call(this, ...args); + }; + // TODO remove array hack entirely and use this instead const tabs = ret.props.children.props.children[0].props.children[1].props.children[0].props.children[0].props.tabs + const ret = this.tabRenderer(...args); + Array.prototype.filter = oFilter; + return ret; + }; + } + this.rendererTree = ret.props.children[1].children; + ret.props.children[1].children.type = newQATabRenderer; + } + return ret; + }; + this.memoizedQuickAccess = memo(newQA); + this.memoizedQuickAccess.isDeckyQuickAccess = true; + } + if (ret.props.children.props.children[4]) { + this.qAPTree = ret.props.children.props.children[4]; + ret.props.children.props.children[4].type = this.memoizedQuickAccess; + } + return ret; + }); + this.cNode = scrollRoot; + this.cNode.stateNode.forceUpdate(); + })(); + } + + deinit() { + unpatch(this.cNode.stateNode, 'render'); + if (this.qAPTree) this.qAPTree.type = this.quickAccess; + if (this.rendererTree) this.rendererTree.type = this.tabRenderer; + if (this.cNode) this.cNode.stateNode.forceUpdate(); } add(tab: Tab) { |
