feat(lib/discord): add initial impl of discord/ui/settings
This commit is contained in:
parent
c379d815a6
commit
ca94e6122b
7 changed files with 128 additions and 0 deletions
|
|
@ -15,8 +15,17 @@
|
|||
"./preinit": {
|
||||
"default": "./src/preinit.ts"
|
||||
},
|
||||
"./ui": {
|
||||
"default": "./src/ui/index.ts"
|
||||
},
|
||||
"./ui/settings": {
|
||||
"default": "./src/ui/settings/index.ts"
|
||||
},
|
||||
"./types": {
|
||||
"types": "./types/index.ts"
|
||||
},
|
||||
"./_/ui/settings": {
|
||||
"default": "./src/ui/settings/_internal.ts"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export * from './preinit'
|
|||
|
||||
export * as flux from './flux'
|
||||
export * as native from './native'
|
||||
export * as ui from './ui'
|
||||
|
||||
// ../discord_common/js/shared/Logger.tsx
|
||||
export const Logger = lookupModule(byName<DiscordModules.Logger>('Logger'))!
|
||||
|
|
|
|||
1
lib/discord/src/ui/index.ts
Normal file
1
lib/discord/src/ui/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * as settings from './settings'
|
||||
11
lib/discord/src/ui/settings/_internal.ts
Normal file
11
lib/discord/src/ui/settings/_internal.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import type { SettingsRowConfig, SettingsSection } from './api'
|
||||
|
||||
export const _suiData = {
|
||||
// Settings that are in the Overview screen
|
||||
sections: {},
|
||||
// Settings that are not in the Overview screen (submenus, hidden, etc.)
|
||||
settings: {},
|
||||
} as {
|
||||
sections: Record<string, SettingsSection>
|
||||
settings: Record<string, SettingsRowConfig>
|
||||
}
|
||||
53
lib/discord/src/ui/settings/api.ts
Normal file
53
lib/discord/src/ui/settings/api.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import { _suiData } from './_internal'
|
||||
|
||||
import type { ComponentType, ReactNode } from 'react'
|
||||
|
||||
export function addSettingsSection(key: string, section: SettingsSection) {
|
||||
_suiData.sections[key] = section
|
||||
return () => delete _suiData.sections[key]
|
||||
}
|
||||
|
||||
export function addSettingsRow(key: string, row: SettingsRowConfig) {
|
||||
_suiData.settings[key] = row
|
||||
return () => delete _suiData.settings[key]
|
||||
}
|
||||
|
||||
export function addSettingsRowToSection(sectionKey: string, rowKey: string, row: SettingsRowConfig) {
|
||||
if (!_suiData.sections[sectionKey]) throw new Error(`Section "${sectionKey}" does not exist`)
|
||||
_suiData.sections[sectionKey].settings[rowKey] = row
|
||||
return () => delete _suiData.sections[sectionKey].settings[rowKey]
|
||||
}
|
||||
|
||||
export interface SettingsSection {
|
||||
label: string
|
||||
settings: Record<string, SettingsRowConfig>
|
||||
}
|
||||
|
||||
interface BaseSettingsRowConfig {
|
||||
title: () => string
|
||||
parent: string | null
|
||||
unsearchable?: boolean
|
||||
IconComponent?: () => ReactNode
|
||||
usePredicate?: () => boolean
|
||||
useTrailing?: () => ReactNode
|
||||
useDescription?: () => string
|
||||
useIsDisabled?: () => boolean
|
||||
}
|
||||
|
||||
export interface PressableSettingsRowConfig extends BaseSettingsRowConfig {
|
||||
type: 'pressable'
|
||||
onPress?: () => void
|
||||
}
|
||||
|
||||
export interface ToggleSettingsRowConfig extends BaseSettingsRowConfig {
|
||||
type: 'toggle'
|
||||
useValue?: () => boolean
|
||||
onValueChange?: (value: boolean) => void
|
||||
}
|
||||
|
||||
export interface RouteSettingsRowConfig extends BaseSettingsRowConfig {
|
||||
type: 'route'
|
||||
screen: { route: string; getComponent(): ComponentType }
|
||||
}
|
||||
|
||||
export type SettingsRowConfig = PressableSettingsRowConfig | ToggleSettingsRowConfig | RouteSettingsRowConfig
|
||||
49
lib/discord/src/ui/settings/common.ts
Normal file
49
lib/discord/src/ui/settings/common.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import { lookupModule } from '@revenge-mod/modules/finders'
|
||||
import { byDependencies, byProps, looseDeps, moduleStateAware, relativeDep } from '@revenge-mod/modules/finders/filters'
|
||||
import { ReactJsxRuntimeModuleId, ReactModuleId, ReactNativeModuleId } from '@revenge-mod/react'
|
||||
import { proxify } from '@revenge-mod/utils/proxy'
|
||||
|
||||
import type { ComponentType, ReactNode } from 'react'
|
||||
|
||||
export let SettingListRenderer: SettingListRenderer = proxify(
|
||||
() => {
|
||||
const module = lookupModule(
|
||||
moduleStateAware(
|
||||
byProps('SettingsList'),
|
||||
byDependencies(
|
||||
// biome-ignore lint/suspicious/noSparseArray: don't care
|
||||
looseDeps([
|
||||
ReactModuleId,
|
||||
ReactNativeModuleId,
|
||||
relativeDep(1),
|
||||
relativeDep(2),
|
||||
,
|
||||
ReactJsxRuntimeModuleId,
|
||||
]),
|
||||
),
|
||||
),
|
||||
{
|
||||
includeUninitialized: true,
|
||||
},
|
||||
) as SettingListRenderer | undefined
|
||||
|
||||
if (module) {
|
||||
// This allows the Proxy instance to be garbage collected
|
||||
// after the module is initialized.
|
||||
SettingListRenderer = module
|
||||
gc()
|
||||
return module
|
||||
}
|
||||
},
|
||||
{
|
||||
cache: true,
|
||||
hint: 'object',
|
||||
},
|
||||
)!
|
||||
|
||||
export interface SettingListRenderer {
|
||||
SettingsList: ComponentType<{
|
||||
ListHeaderComponent: ComponentType
|
||||
sections: Array<{ label: string | ReactNode; settings: string[] }>
|
||||
}>
|
||||
}
|
||||
4
lib/discord/src/ui/settings/index.ts
Normal file
4
lib/discord/src/ui/settings/index.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import { _suiData } from './_internal'
|
||||
|
||||
export * from './api'
|
||||
export * from './common'
|
||||
Loading…
Add table
Reference in a new issue