chore: move SettingRendererConfig patches to lib, refactor how lifecycles are run

This commit is contained in:
PalmDevs 2025-07-19 23:23:32 +07:00
parent 832a3fc7da
commit 78614c1cc9
No known key found for this signature in database
GPG key ID: 6FAE8F8677ACA8BA
12 changed files with 105 additions and 85 deletions

View file

@ -30,6 +30,9 @@
"./preinit": {
"default": "./src/preinit.ts"
},
"./start": {
"default": "./src/start.ts"
},
"./modules/main_tabs_v2": {
"default": "./src/modules/main_tabs_v2.ts"
},
@ -46,4 +49,4 @@
"default": "./src/modules/settings/_internal.ts"
}
}
}
}

View file

@ -9,10 +9,4 @@ export const sSections: Record<string, SettingsSection> = {}
// SETTING_RENDERER_CONFIG settings
export const sConfig: Record<string, SettingsItem> = {}
export const sData = {
loaded: false,
} as {
loaded: boolean
}
export const sSubscriptions = new Set<SettingsModulesLoadedSubscription>()

View file

@ -2,8 +2,9 @@ import { ReactNavigationNative } from '@revenge-mod/externals/react-navigation'
import { noop } from '@revenge-mod/utils/callback'
import { findInTree } from '@revenge-mod/utils/tree'
import { Constants } from '../../common'
import { sLoaded } from '../../start'
import { RootNavigationRef } from '../main_tabs_v2'
import { sConfig, sData, sSections, sSubscriptions } from './_internal'
import { sConfig, sSections, sSubscriptions } from './_internal'
import type { NavigationState, PartialState } from '@react-navigation/core'
import type { DiscordModules } from '../../types'
@ -16,7 +17,7 @@ export type SettingsModulesLoadedSubscription = () => void
* Checks if the settings modules are loaded.
*/
export function isSettingsModulesLoaded() {
return sData.loaded
return sLoaded
}
/**

40
lib/discord/src/start.ts Normal file
View file

@ -0,0 +1,40 @@
import { byProps } from '@revenge-mod/modules/finders/filters'
import { waitForModules } from '@revenge-mod/modules/finders/wait'
import { sConfig, sSubscriptions } from './modules/settings/_internal'
import type { SettingsItem } from './modules/settings'
export let sLoaded = false
const unsubSRC = waitForModules(
byProps<{ SETTING_RENDERER_CONFIG: Record<string, SettingsItem> }>(
'SETTING_RENDERER_CONFIG',
),
SettingRendererConfig => {
unsubSRC()
sLoaded = true
for (const sub of sSubscriptions)
try {
sub()
} catch {}
// We don't ever need to call this again
sSubscriptions.clear()
let { SETTING_RENDERER_CONFIG: ORIGINAL } = SettingRendererConfig
Object.defineProperty(
SettingRendererConfig,
'SETTING_RENDERER_CONFIG',
{
get: () =>
({
...ORIGINAL,
...sConfig,
}) as Record<string, SettingsItem>,
set: v => (ORIGINAL = v),
},
)
},
)

View file

@ -6,11 +6,14 @@
"./constants": {
"default": "./src/constants.ts"
},
"./preinit": {
"default": "./src/preinit.ts"
},
"./init": {
"default": "./src/init.ts"
},
"./preinit": {
"default": "./src/preinit.ts"
"./start": {
"default": "./src/start.ts"
},
"./types": {
"types": "./src/types.ts"
@ -19,4 +22,4 @@
"default": "./src/_internal.ts"
}
}
}
}

View file

@ -1,6 +1,5 @@
import * as AssetsLibrary from '@revenge-mod/assets'
import { onRunApplication } from '@revenge-mod/react/native'
import { initPlugin, pList, startPlugin } from './_internal'
import { initPlugin, pList } from './_internal'
import { pUnscopedApi } from './apis'
import { PluginFlags } from './constants'
import type { UnscopedInitPluginApi } from './types'
@ -11,12 +10,3 @@ uapi.assets = AssetsLibrary
for (const plugin of pList.values())
if (plugin.flags & PluginFlags.Enabled) initPlugin(plugin)
const unsub = onRunApplication(() => {
unsub()
require('~/plugins/start')
for (const plugin of pList.values())
if (plugin.flags & PluginFlags.Enabled) startPlugin(plugin)
})

5
lib/plugins/src/start.ts Normal file
View file

@ -0,0 +1,5 @@
import { pList, startPlugin } from '@revenge-mod/plugins/_'
import { PluginFlags } from './constants'
for (const plugin of pList.values())
if (plugin.flags & PluginFlags.Enabled) startPlugin(plugin)

View file

@ -11,12 +11,18 @@ const unsub = waitForModules(byProps('AppRegistry'), () => {
unsub()
before(ReactNative.AppRegistry, 'runApplication', args => {
for (const cb of sBeforeRunApplication) cb()
for (const cb of sBeforeRunApplication)
try {
cb()
} catch {}
return args
})
after(ReactNative.AppRegistry, 'runApplication', res => {
for (const cb of sAfterRunApplication) cb()
for (const cb of sAfterRunApplication)
try {
cb()
} catch {}
return res
})
})

24
src/init.ts Normal file
View file

@ -0,0 +1,24 @@
// Initialize init libraries
import '@revenge-mod/utils/init'
import '@revenge-mod/react/init'
import '@revenge-mod/storage/init'
import '@revenge-mod/externals/init'
import '@revenge-mod/discord/init'
import '@revenge-mod/components/init'
// Run all init plugins
import '~/plugins/init'
import '@revenge-mod/plugins/init'
import { onRunApplication } from '@revenge-mod/react/native'
import { onError } from './preinit'
const unsub = onRunApplication(() => {
unsub()
try {
require('./start')
} catch (e) {
onError(e)
}
})

View file

@ -1,20 +1,15 @@
import {
sConfig,
sData,
sSections,
sSubscriptions,
} from '@revenge-mod/discord/_/modules/settings'
import { sSections } from '@revenge-mod/discord/_/modules/settings'
import { onSettingsModulesLoaded } from '@revenge-mod/discord/modules/settings'
import { byName, byProps } from '@revenge-mod/modules/finders/filters'
import { byName } from '@revenge-mod/modules/finders/filters'
import { waitForModules } from '@revenge-mod/modules/finders/wait'
import { after } from '@revenge-mod/patcher'
import { InternalPluginFlags, registerPlugin } from '@revenge-mod/plugins/_'
import { PluginFlags } from '@revenge-mod/plugins/constants'
import type { SettingsItem } from '@revenge-mod/discord/modules/settings'
import type { FC } from 'react'
import './register-routes'
// Always register before so setting modules that depend on the Revenge section can be registered properly
onSettingsModulesLoaded(() => {
require('./register')
})
@ -29,40 +24,6 @@ registerPlugin(
},
{
start() {
const unsubRC = waitForModules(
byProps<{
SETTING_RENDERER_CONFIG: Record<string, SettingsItem>
}>('SETTING_RENDERER_CONFIG'),
SettingRendererConfig => {
unsubRC()
for (const sub of sSubscriptions)
try {
sub()
} catch {}
// We don't ever need to call this again
sSubscriptions.clear()
sData.loaded = true
let ORIGINAL_RENDERER_CONFIG =
SettingRendererConfig.SETTING_RENDERER_CONFIG
Object.defineProperty(
SettingRendererConfig,
'SETTING_RENDERER_CONFIG',
{
get: () =>
({
...ORIGINAL_RENDERER_CONFIG,
...sConfig,
}) as Record<string, SettingsItem>,
set: v => (ORIGINAL_RENDERER_CONFIG = v),
},
)
},
)
const unsubSOS = waitForModules(
byName('SettingsOverviewScreen'),
exports => {

View file

@ -30,24 +30,11 @@ onModuleFirstRequired(IndexModuleId, function onIndexRequired() {
require('@revenge-mod/plugins/preinit')
onModuleInitialized(IndexModuleId, function onIndexInitialized() {
if (__DEV__)
nativeLoggingHook(`\u001b[31m--- INIT STAGE ---\u001b[0m`, 1)
try {
if (__DEV__)
nativeLoggingHook(
`\u001b[31m--- INIT STAGE ---\u001b[0m`,
1,
)
// Initialize init libraries
require('@revenge-mod/utils/init')
require('@revenge-mod/react/init')
require('@revenge-mod/storage/init')
require('@revenge-mod/externals/init')
require('@revenge-mod/discord/init')
require('@revenge-mod/components/init')
// Run all init plugins
require('~/plugins/init')
require('@revenge-mod/plugins/init')
require('./init')
} catch (e) {
onError(e)
}
@ -57,7 +44,7 @@ onModuleFirstRequired(IndexModuleId, function onIndexRequired() {
}
})
function onError(e: unknown) {
export function onError(e: unknown) {
// TODO(init): Move to use native provided alert function, which will accept a string stack trace
// Above will reduce the need for runCatching() to exist, as the code won't be able to be deduped any further
const { ClientInfoModule, DeviceModule } =

6
src/start.ts Normal file
View file

@ -0,0 +1,6 @@
// Initialize start libraries
require('@revenge-mod/discord/start')
// Run all start plugins
require('~/plugins/start')
require('@revenge-mod/plugins/start')