diff --git a/src/deck-components/static-classes.ts b/src/deck-components/static-classes.ts index 3687cb3..1972413 100644 --- a/src/deck-components/static-classes.ts +++ b/src/deck-components/static-classes.ts @@ -208,53 +208,108 @@ type UpdaterFieldClasses = Record< string >; +type PlaySectionClasses = Record< + | "AchievementCountLabel" + | "AchievementProgressRow" + | "ActionSection" + | "AppButtonsContainer" + | "Arrow" + | "AvatarAndPersona" + | "BreakNarrow" + | "BreakShort" + | "BreakTall" + | "BreakUltraWide" + | "BreakWide" + | "ClickablePlayBarItem" + | "CloudStatusIcon" + | "CloudStatusLabel" + | "CloudStatusRow" + | "CloudSyncProblem" + | "CloudSynching" + | "ComingSoon" + | "Container" + | "DetailsProgressBar" + | "DetailsProgressContainer" + | "DetailsSection" + | "DetailsSectionExtra" + | "DetailsSectionStatus" + | "DotDotDot" + | "DownloadPaused" + | "DownloadProgressBar" + | "Downloading" + | "FavoriteButton" + | "Favorited" + | "GameInfoButton" + | "GameStat" + | "GameStatIcon" + | "GameStatIconForced" + | "GameStatRight" + | "GameStatsSection" + | "GamepadUIBreakNarrow" + | "GamepadUIBreakShort" + | "GamepadUIBreakWide" + | "Glassy" + | "HideWhenNarrow" + | "Icon" + | "Icons" + | "InPage" + | "InnerContainer" + | "InvalidPlatform" + | "ItemFocusAnim-darkGrey" + | "ItemFocusAnim-darkerGrey" + | "ItemFocusAnim-darkerGrey-nocolor" + | "ItemFocusAnim-green" + | "ItemFocusAnim-grey" + | "ItemFocusAnimBorder-darkGrey" + | "Label" + | "LastPlayed" + | "LastPlayedInfo" + | "MenuActive" + | "MenuButton" + | "MiniAchievements" + | "OfflineMode" + | "OnlyDownloadBar" + | "PermanentlyUnavailable" + | "PlayBar" + | "PlayBarCloudStatusContainer" + | "PlayBarDetailLabel" + | "PlayBarGameIcon" + | "PlayBarGameName" + | "PlayBarIconAndGame" + | "PlayBarLabel" + | "Playtime" + | "PlaytimeIcon" + | "PlaytimeIconForced" + | "PortraitBar" + | "Presale" + | "RecentlyUpdated" + | "RecentlyUpdatedIcon" + | "RecentlyUpdatedLink" + | "RecentlyUpdatedText" + | "RightBreakNarrow" + | "RightBreakUltraNarrow" + | "RightBreakUltraWide" + | "RightBreakWide" + | "RightControls" + | "Row" + | "SharedLibrary" + | "StatusAndStats" + | "StatusNameContainer" + | "StickyHeader" + | "StickyHeaderShadow" + | "SuperimposedGridItems" + | "SyncAnim" + | "Visible" + | "duration-app-launch" + | "favorited" + | "focusAnimation" + | "hoverAnimation", + string +>; -export const staticClasses: StaticClasses = findModule((mod) => { - if (typeof mod !== 'object') return false; - - if (mod.TransitionMenuDelay) { - return true; - } - - return false; -}); - -export const scrollClasses: ScrollClasses = findModule((mod) => { - if (typeof mod !== 'object') return false; - - if (mod.ScrollPanel && mod.ScrollY) { - return true; - } - - return false; -}); - -export const gamepadDialogClasses: GamepadDialogClasses = findModule((mod) => { - if (typeof mod !== 'object') return false; - - if (mod.WithFirstRow) { - return true; - } - - return false; -}); - -export const quickAccessControlsClasses: QuickAccessControlsClasses = findModule((mod) => { - if (typeof mod !== 'object') return false; - - if (mod.PanelSectionRow) { - return true; - } - - return false; -}); - -export const updaterFieldClasses: UpdaterFieldClasses = findModule((mod) => { - if (typeof mod !== 'object') return false; - - if (mod.PatchNotes && mod.PostedTime) { - return true; - } - - return false; -}); +export const staticClasses: StaticClasses = findModule((mod) => typeof mod === 'object' && mod.TransitionMenuDelay); +export const scrollClasses: ScrollClasses = findModule((mod) => typeof mod === 'object' && mod.ScrollPanel && mod.ScrollY); +export const gamepadDialogClasses: GamepadDialogClasses = findModule((mod) => typeof mod === 'object' && mod.WithFirstRow); +export const quickAccessControlsClasses: QuickAccessControlsClasses = findModule((mod) => typeof mod === 'object' && mod.PanelSectionRow); +export const updaterFieldClasses: UpdaterFieldClasses = findModule((mod) => typeof mod === 'object' && mod.PatchNotes && mod.PostedTime); +export const playSectionClasses: PlaySectionClasses = findModule((mod) => typeof mod === 'object' && mod.MenuButton && mod.MenuActive); diff --git a/src/utils.ts b/src/utils.ts index 0f6b5b7..f2415c2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -42,22 +42,18 @@ export function fakeRenderComponent(fun: Function): any { return res; } -export function beforePatch(obj: any, name: string, fnc: (args: any[]) => any): void { +export interface PatchOptions { + singleShot?: boolean +} + +export function beforePatch(obj: any, name: string, fnc: (args: any[]) => any, options: PatchOptions = {}): void { const orig = obj[name]; obj[name] = function (...args: any[]) { fnc.call(this, args); - return orig.call(this, ...args); - } - Object.assign(obj[name], orig); - obj[name].toString = () => orig.toString(); - obj[name].__deckyOrig = orig; -} - -export function afterPatch(obj: any, name: string, fnc: (args: any[], ret: any) => any): void { - const orig = obj[name]; - obj[name] = function (...args: any[]) { - let ret = orig.call(this, ...args); - ret = fnc.call(this, args, ret); + const ret = orig.call(this, ...args); + if (options.singleShot) { + unpatch(obj, name); + } return ret; } Object.assign(obj[name], orig); @@ -65,11 +61,29 @@ export function afterPatch(obj: any, name: string, fnc: (args: any[], ret: any) obj[name].__deckyOrig = orig; } -export function replacePatch(obj: any, name: string, fnc: (args: any[]) => any): void { +export function afterPatch(obj: any, name: string, fnc: (args: any[], ret: any) => any, options: PatchOptions = {}): void { + const orig = obj[name]; + obj[name] = function (...args: any[]) { + let ret = orig.call(this, ...args); + ret = fnc.call(this, args, ret); + if (options.singleShot) { + unpatch(obj, name); + } + return ret; + } + Object.assign(obj[name], orig); + obj[name].toString = () => orig.toString(); + obj[name].__deckyOrig = orig; +} + +export function replacePatch(obj: any, name: string, fnc: (args: any[]) => any, options: PatchOptions = {}): void { const orig = obj[name]; obj[name] = function (...args: any[]) { const ret = fnc.call(this, args); - if (ret == 'CALL_ORIGINAL') return orig.call(this, ...args); + if (ret == 'CALL_ORIGINAL') ret = orig.call(this, ...args); + if (options.singleShot) { + unpatch(obj, name); + } return ret; }; Object.assign(obj[name], orig); @@ -79,7 +93,9 @@ export function replacePatch(obj: any, name: string, fnc: (args: any[]) => any): // TODO allow one method to be patched and unpatched multiple times independently using IDs in a Map or something export function unpatch(obj: any, name: any): void { - obj[name] = obj[name].__deckyOrig; + if (obj[name].__deckyOrig !== undefined) { + obj[name] = obj[name].__deckyOrig; + } } export function wrapReactType(node: any, prop: any = 'type') {