166 lines
5.1 KiB
TypeScript
166 lines
5.1 KiB
TypeScript
import { sRefresher, sSections } from '@revenge-mod/discord/_/modules/settings'
|
|
import { onSettingsModulesLoaded } from '@revenge-mod/discord/modules/settings'
|
|
import {
|
|
waitForModules,
|
|
waitForModuleWithImportedPath,
|
|
} from '@revenge-mod/modules/finders'
|
|
import { withName } from '@revenge-mod/modules/finders/filters'
|
|
import { instead } from '@revenge-mod/patcher'
|
|
import { InternalPluginFlags, registerPlugin } from '@revenge-mod/plugins/_'
|
|
import { PluginFlags } from '@revenge-mod/plugins/constants'
|
|
import { React } from '@revenge-mod/react'
|
|
import { asap, noop } from '@revenge-mod/utils/callback'
|
|
import { getCurrentStack } from '@revenge-mod/utils/error'
|
|
import { useReRender } from '@revenge-mod/utils/react'
|
|
import { useEffect } from 'react'
|
|
import type { FC } from 'react'
|
|
|
|
let DEBUG_patchedNavigator = false
|
|
|
|
const pluginSettings = registerPlugin(
|
|
{
|
|
id: 'revenge.settings',
|
|
name: 'Settings',
|
|
description: 'Settings UI for Revenge.',
|
|
author: 'Revenge',
|
|
icon: 'SettingsIcon',
|
|
},
|
|
{
|
|
start() {
|
|
// @as-require
|
|
import('./plugins')
|
|
|
|
onSettingsModulesLoaded(() => {
|
|
// @as-require
|
|
import('./register')
|
|
|
|
// Debug warnings
|
|
asap(() => {
|
|
if (__DEV__ && !DEBUG_patchedNavigator)
|
|
DEBUG_warnUnpatchedNavigator()
|
|
})
|
|
})
|
|
|
|
waitForModuleWithImportedPath(
|
|
'modules/user_settings/native/core/SettingsNavigator.tsx',
|
|
exports => {
|
|
patchSettingsNavigator(exports)
|
|
},
|
|
)
|
|
|
|
const unsubSOS = waitForModules(
|
|
withName('SettingsOverviewScreen'),
|
|
exports => {
|
|
unsubSOS()
|
|
patchSettingsOverviewScreen(exports)
|
|
},
|
|
{
|
|
cached: true,
|
|
returnNamespace: true,
|
|
},
|
|
)
|
|
},
|
|
},
|
|
PluginFlags.Enabled,
|
|
InternalPluginFlags.Internal | InternalPluginFlags.Essential,
|
|
)
|
|
|
|
function patchSettingsNavigator(exports: any) {
|
|
instead(exports.default, 'type', (args, orig) => {
|
|
const reRender = useReRender()
|
|
useEffect(() => {
|
|
sRefresher.callNavigator = reRender
|
|
|
|
return () => {
|
|
sRefresher.navigator = false
|
|
sRefresher.callNavigator = noop
|
|
}
|
|
}, [reRender])
|
|
|
|
// useMemo(() => getSettingScreens(), [])
|
|
const unpatchMemo = instead(React, 'useMemo', (args, orig) => {
|
|
if (!args[1]?.length && sRefresher.navigator) {
|
|
args[1] = undefined
|
|
sRefresher.navigator = false
|
|
}
|
|
|
|
return Reflect.apply(orig, React, args)
|
|
})
|
|
|
|
const el = Reflect.apply(orig, undefined, args)
|
|
unpatchMemo()
|
|
return el
|
|
})
|
|
|
|
DEBUG_patchedNavigator = true
|
|
}
|
|
|
|
let sectionsInst: object | undefined
|
|
|
|
function patchSettingsOverviewScreen(exports: any) {
|
|
instead(
|
|
exports as {
|
|
default: FC
|
|
},
|
|
'default',
|
|
(args, orig) => {
|
|
const reRender = useReRender()
|
|
useEffect(() => {
|
|
sRefresher.callOverviewScreen = reRender
|
|
|
|
return () => {
|
|
sRefresher.overviewScreen = false
|
|
sRefresher.callOverviewScreen = noop
|
|
}
|
|
}, [reRender])
|
|
|
|
/**
|
|
* In useOverviewSettings (called by SettingsOverviewScreen):
|
|
*
|
|
* const hasPremiumSubscriptionToDisplay = useHasPremiumSubscriptionToDisplay()
|
|
* const sections = useMemo(() =>
|
|
* (...constructed sections array...),
|
|
* [hasPremiumSubscriptionToDisplay])
|
|
*/
|
|
const unpatchMemo = instead(React, 'useMemo', (args, orig) => {
|
|
if (sRefresher.overviewScreen) args[1] = undefined
|
|
|
|
const node = Reflect.apply(orig, React, args)
|
|
const sections = node.sections
|
|
|
|
// Add our custom sections here, and only do this per instance!
|
|
if (sectionsInst !== sections) {
|
|
for (const section of Object.values(sSections))
|
|
if (section.index)
|
|
sections.splice(section.index, 0, section)
|
|
else sections.unshift(section)
|
|
|
|
sectionsInst = sections
|
|
}
|
|
|
|
if (sRefresher.overviewScreen) {
|
|
node.sections = sectionsInst = [...sections]
|
|
sRefresher.overviewScreen = false
|
|
}
|
|
|
|
return node
|
|
})
|
|
|
|
const el = Reflect.apply(orig, undefined, args)
|
|
unpatchMemo()
|
|
return el
|
|
},
|
|
)
|
|
}
|
|
|
|
export default pluginSettings
|
|
|
|
/**
|
|
* Warns the developer that SettingsNavigator was not patched.
|
|
*/
|
|
function DEBUG_warnUnpatchedNavigator() {
|
|
nativeLoggingHook(
|
|
`\u001b[31mSettingsNavigator was not patched\n${getCurrentStack()}\u001b[0m`,
|
|
2,
|
|
)
|
|
}
|