docs/references/data/preference-usage.md
Use usePreference for one key. The value has its generated default applied and
the setter returns a Promise.
import { usePreference } from '@data/hooks/usePreference'
const [theme, setTheme] = usePreference('ui.theme_mode')
await setTheme('dark')
Updates are optimistic by default. Request pessimistic behavior when the UI must wait for persistence confirmation:
const [developerMode, setDeveloperMode] = usePreference('app.developer_mode.enabled', {
optimistic: false
})
await setDeveloperMode(true)
Use useMultiplePreferences for a related set. It accepts an object that maps
local names to generated keys and returns [values, updateValues]:
import { useMultiplePreferences } from '@data/hooks/usePreference'
const [settings, updateSettings] = useMultiplePreferences({
theme: 'ui.theme_mode',
language: 'app.language',
fontSize: 'chat.message.font_size'
})
await updateSettings({ theme: 'system', language: 'en-US' })
Keep the key-map object referentially stable (module constant or useMemo) when
it is constructed from dynamic input; it is a hook dependency and subscription
definition.
Non-React renderer code can use the singleton directly:
import { preferenceService } from '@data/PreferenceService'
const theme = await preferenceService.get('ui.theme_mode')
const settings = await preferenceService.getMultiple({
language: 'app.language',
fontSize: 'chat.message.font_size'
})
await preferenceService.set('ui.theme_mode', 'dark')
await preferenceService.setMultiple({
'app.language': 'en-US',
'chat.message.font_size': 16
})
getMultiple() takes a local-name-to-key object. Use getMultipleRaw(keys) only
when the returned object must be keyed by the Preference keys themselves.
Renderer subscribeChange(key) is curried:
const unsubscribe = preferenceService.subscribeChange('ui.theme_mode')(() => {
const theme = preferenceService.getCachedValue('ui.theme_mode')
logger.info('Theme changed', { theme })
})
Always call the returned unsubscribe when the owner is disposed. React code should use the hooks, which manage this lifecycle automatically.
Main code accesses the lifecycle-managed service through application:
import { application } from '@application'
const preferences = application.get('PreferenceService')
const theme = preferences.get('ui.theme_mode')
const { language, fontSize } = preferences.getMultiple({
language: 'app.language',
fontSize: 'chat.message.font_size'
})
await preferences.set('ui.theme_mode', 'dark')
Main get()/getMultiple() are synchronous cached reads. Writes return a
Promise because the service publishes cross-window notifications after the
synchronous storage operation.
Main subscriptions use subscribeChange(key, callback). A lifecycle service
must register the returned disposable:
this.registerDisposable(
preferences.subscribeChange('ui.theme_mode', (theme) => {
logger.info('Theme changed', { theme })
})
)
Add generator input and regenerate; never edit preferenceSchemas.ts or
DefaultPreferences directly. See
Preference Schema Guide.