diff options
| author | AAGaming <aa@mail.catvibers.me> | 2022-10-24 19:14:56 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-24 16:14:56 -0700 |
| commit | 84c3b039c385ad872bb0f22eba7a3d2cd4a5ea10 (patch) | |
| tree | 20b13066c6256cc6ca1beac085094c7964226a37 /frontend/src/toaster.tsx | |
| parent | 2e6b3834da357c7e81821ce60bad36f54dd9fa6e (diff) | |
| download | decky-loader-84c3b039c385ad872bb0f22eba7a3d2cd4a5ea10.tar.gz decky-loader-84c3b039c385ad872bb0f22eba7a3d2cd4a5ea10.zip | |
preview 10/21/2022 fixes (#234)
* initial fixes: everything working except toasts and patch notes
* tabshook changes, disable toaster for now
* prettier
* oops
* implement custom toaster because I am tired of Valve's shit
also fix QAM not injecting sometimes
* remove extra logging
* add findSP, fix patch notes, fix vscode screwup
* fix patch notes
* show error when plugin frontends fail to load
* add get_tab_lambda
* add css and has_element helpers to Tab
* small modals fixup
* Don't forceUpdate QuickAccess on stable
* add routes prop used to get tabs component
* add more dev utils to DFL global
Diffstat (limited to 'frontend/src/toaster.tsx')
| -rw-r--r-- | frontend/src/toaster.tsx | 211 |
1 files changed, 132 insertions, 79 deletions
diff --git a/frontend/src/toaster.tsx b/frontend/src/toaster.tsx index d7c0584f..94b08d70 100644 --- a/frontend/src/toaster.tsx +++ b/frontend/src/toaster.tsx @@ -1,8 +1,10 @@ -import { Patch, ToastData, afterPatch, findInReactTree, findModuleChild, sleep } from 'decky-frontend-lib'; -import { ReactNode } from 'react'; +import { Patch, ToastData, sleep } from 'decky-frontend-lib'; +import DeckyToaster from './components/DeckyToaster'; +import { DeckyToasterState, DeckyToasterStateContextProvider } from './components/DeckyToasterState'; import Toast from './components/Toast'; import Logger from './logger'; +import RouterHook from './router-hook'; declare global { interface Window { @@ -13,12 +15,15 @@ declare global { class Toaster extends Logger { private instanceRetPatch?: Patch; + private routerHook: RouterHook; + private toasterState: DeckyToasterState = new DeckyToasterState(); private node: any; private settingsModule: any; private ready: boolean = false; - constructor() { + constructor(routerHook: RouterHook) { super('Toaster'); + this.routerHook = routerHook; window.__TOASTER_INSTANCE?.deinit?.(); window.__TOASTER_INSTANCE = this; @@ -26,87 +31,135 @@ class Toaster extends Logger { } async init() { - let instance: any; - - while (true) { - instance = findInReactTree( - (document.getElementById('root') as any)._reactRootContainer._internalRoot.current, - (x) => x?.memoizedProps?.className?.startsWith?.('toastmanager_ToastPlaceholder'), - ); - if (instance) break; - this.debug('finding instance'); - await sleep(2000); - } - - this.node = instance.return.return; - let toast: any; - let renderedToast: ReactNode = null; - this.node.stateNode.render = (...args: any[]) => { - const ret = this.node.stateNode.__proto__.render.call(this.node.stateNode, ...args); - if (ret) { - this.instanceRetPatch = afterPatch(ret, 'type', (_: any, ret: any) => { - if (ret?.props?.children[1]?.children?.props) { - const currentToast = ret.props.children[1].children.props.notification; - if (currentToast?.decky) { - if (currentToast == toast) { - ret.props.children[1].children = renderedToast; - } else { - toast = currentToast; - renderedToast = <Toast toast={toast} />; - ret.props.children[1].children = renderedToast; - } - } else { - toast = null; - renderedToast = null; - } - } - return ret; - }); - this.node.stateNode.shouldComponentUpdate = () => { - return false; - }; - delete this.node.stateNode.render; - } - return ret; - }; - this.settingsModule = findModuleChild((m) => { - if (typeof m !== 'object') return undefined; - for (let prop in m) { - if (typeof m[prop]?.settings && m[prop]?.communityPreferences) return m[prop]; - } - }); - this.log('Initialized'); - this.ready = true; + this.routerHook.addGlobalComponent('DeckyToaster', () => ( + <DeckyToasterStateContextProvider deckyToasterState={this.toasterState}> + <DeckyToaster /> + </DeckyToasterStateContextProvider> + )); + // let instance: any; + // while (true) { + // instance = findInReactTree( + // (document.getElementById('root') as any)._reactRootContainer._internalRoot.current, + // (x) => x?.memoizedProps?.className?.startsWith?.('toastmanager_ToastPlaceholder'), + // ); + // if (instance) break; + // this.debug('finding instance'); + // await sleep(2000); + // } + // // const windowManager = findModuleChild((m) => { + // // if (typeof m !== 'object') return false; + // // for (let prop in m) { + // // if (m[prop]?.prototype?.GetRenderElement) return m[prop]; + // // } + // // return false; + // // }); + // this.node = instance.return.return; + // let toast: any; + // let renderedToast: ReactNode = null; + // console.log(instance, this.node); + // // replacePatch(window.SteamClient.BrowserView, "Destroy", (args: any[]) => { + // // console.debug("destroy", args) + // // return callOriginal; + // // }) + // // let node = this.node.child.updateQueue.lastEffect; + // // while (node.next && !node.deckyPatched) { + // // node = node.next; + // // if (node.deps[1] == "notificationtoasts") { + // // console.log("Deleting destroy"); + // // node.deckyPatched = true; + // // node.create = () => {console.debug("VVVVVVVVVVV")}; + // // node.destroy = () => {console.debug("AAAAAAAAAAAAAAAAaaaaaaaaaaaaaaa")}; + // // } + // // } + // this.node.stateNode.render = (...args: any[]) => { + // const ret = this.node.stateNode.__proto__.render.call(this.node.stateNode, ...args); + // console.log('toast', ret); + // if (ret) { + // console.log(ret) + // // this.instanceRetPatch = replacePatch(ret, 'type', (innerArgs: any) => { + // // console.log("inner toast", innerArgs) + // // // @ts-ignore + // // const oldEffect = window.SP_REACT.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher.current.useEffect; + // // // @ts-ignore + // // window.SP_REACT.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher.current.useEffect = (effect, deps) => { + // // console.log(effect, deps) + // // if (deps?.[1] == "notificationtoasts") { + // // console.log("run") + // // effect(); + // // } + // // return oldEffect(effect, deps); + // // } + // // const ret = this.instanceRetPatch?.original(...args); + // // console.log("inner ret", ret) + // // // @ts-ignore + // // window.SP_REACT.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher.current.useEffect = oldEffect; + // // return ret + // // }); + // } + // // console.log("toast ret", ret) + // // if (ret?.props?.children[1]?.children?.props) { + // // const currentToast = ret.props.children[1].children.props.notification; + // // if (currentToast?.decky) { + // // if (currentToast == toast) { + // // ret.props.children[1].children = renderedToast; + // // } else { + // // toast = currentToast; + // // renderedToast = <Toast toast={toast} />; + // // ret.props.children[1].children = renderedToast; + // // } + // // } else { + // // toast = null; + // // renderedToast = null; + // // } + // // } + // // return ret; + // // }); + // // } + // return ret; + // }; + // this.settingsModule = findModuleChild((m) => { + // if (typeof m !== 'object') return undefined; + // for (let prop in m) { + // if (typeof m[prop]?.settings && m[prop]?.communityPreferences) return m[prop]; + // } + // }); + // // const idx = FocusNavController.m_ActiveContext.m_rgGamepadNavigationTrees.findIndex((x: any) => x.m_ID == "ToastContainer"); + // // if (idx > -1) { + // // FocusNavController.m_ActiveContext.m_rgGamepadNavigationTrees.splice(idx, 1) + // // } + // this.node.stateNode.forceUpdate(); + // this.node.stateNode.shouldComponentUpdate = () => { + // return false; + // }; + // this.log('Initialized'); + // this.ready = true; } - async toast(toast: ToastData) { - while (!this.ready) { - await sleep(100); - } - const settings = this.settingsModule?.settings; - let toastData = { - nNotificationID: window.NotificationStore.m_nNextTestNotificationID++, - rtCreated: Date.now(), - eType: 15, - nToastDurationMS: toast.duration || 5e3, - data: toast, - decky: true, - }; - // @ts-ignore - toastData.data.appid = () => 0; - if ( - (settings?.bDisableAllToasts && !toast.critical) || - (settings?.bDisableToastsInGame && !toast.critical && window.NotificationStore.BIsUserInGame()) - ) - return; - window.NotificationStore.m_rgNotificationToasts.push(toastData); - window.NotificationStore.DispatchNextToast(); + toast(toast: ToastData) { + toast.duration = toast.duration || 5e3; + this.toasterState.addToast(toast); + // const settings = this.settingsModule?.settings; + // let toastData = { + // nNotificationID: window.NotificationStore.m_nNextTestNotificationID++, + // rtCreated: Date.now(), + // eType: 15, + // nToastDurationMS: toast.duration || 5e3, + // data: toast, + // decky: true, + // }; + // // @ts-ignore + // toastData.data.appid = () => 0; + // if ( + // (settings?.bDisableAllToasts && !toast.critical) || + // (settings?.bDisableToastsInGame && !toast.critical && window.NotificationStore.BIsUserInGame()) + // ) + // return; + // window.NotificationStore.m_rgNotificationToasts.push(toastData); + // window.NotificationStore.DispatchNextToast(); } deinit() { - this.instanceRetPatch?.unpatch(); - this.node && delete this.node.stateNode.shouldComponentUpdate; - this.node && this.node.stateNode.forceUpdate(); + this.routerHook.removeGlobalComponent('DeckyToaster'); } } |
