-
Notifications
You must be signed in to change notification settings - Fork 35
Settings Doc Part 1: The structure of user settings.json (feat basics of global state management)
To understand how settings work in the new react version of the app, we need to understand how state management is structured.
We use a state management library called easy-peasy
, it's an abstraction over redux that makes handling the global state easy.
The global state management lives in common/store/GlobalState.js
. If you open that file you will find two sections
- The state objects with their default values
adminPin: null,
code: null,
isConnected: false,
- Functions that change the above states
setAdminPin: action ((state, adminPin) => {
...
}
setCode: action ((state, code) => {
...
}
We make sure to always follow the pattern of stateName
and then its action as setStateName
. By the way, yeah those functions that change state are called actions.
Now to use this in some react component all we need to do is
const {adminPin, code} = useStoreState(state => state.baniController);
const {setAdminPin, setCode} = useStoreActions(actions => actions.baniController);
The above will work only if you have the root component wrapped in the state object. To get more info on how easy-peasy state management works, follow https://easy-peasy.now.sh/
We can think of settings as a state that persists AKA the state that remains saved in a file (user-data-path/user-data.json).
At the core of settings is the file user-settings.json
. It has two objects categories
and settings
. Categories provide the hierarchical relation to settings. A category can have subcategories, and then each subcategory can then have settings. Settings are listed in settings
object with key and its default value.
For example here's what main category looks like with its sub categories.
"slide-layout" : {
"title": "SLIDE_LAYOUT",
"type" : "title",
"subcategories": ["font-sizes", "display-options", "autoplay-options"
}
And then you can define a subcategory with it's list of settings as below
"autoplay-options" : {
"title": "AUTOPLAY_OPTIONS",
"type": "switch"
"settings": ["autoplay-toggle, "autoplay-delay"]
}
So each category subobject can have three things
- title (name that appears on the settings navigation)
- type (default type of all the settings inside that category, this can be overridden in the settings object)
- settings or subcategories (if the category has subcategories in which settings are grouped, we can add those or just direclty add setting keys in an array]
**The order of how settings are shown in UI is determined by their order in the settings array of the category object. **
Here's how settings object look like
[
"setting-name": {
"title": "LIVE_FEED",
"initialValue": false,
},
"larivaar-assist-type": {
"title": "ASSIST_TYPE",
"type": "dropdown",
"options": {
"single-color": "SINGLE_COLOR",
"multi-color": "MULTI_COLOR"
},
"initialValue": "single-color"
},
"autoplay-delay": {
"title": "DELAY",
"type": "range",
"max": 20,
"min": 1,
"step": 1,
"initialValue": 10
},
Only title
and initialValue
are required attributes, rest are optional.
-
title
describing what it would be labeled as -
initialValue
describing its default value, could be string or number. For objects and arrays , we have to apply thedontApplyClass:true
attribute as well. -
store
is if we want to store the setting not only in global easy peasy store, but also in the legacy store object. This is just for backwards compatibility and graceful degradation. -
notes
notes add description to the title, so for example in some places you might want to add some helper text in setting input along with its label. The string you give tonotes
will appear along side label in brackets. -
type
By default setting will choose the type given to its category, otherwise you can over ride the type by mentioning type here.
Setting type can be applied to both the category as well as the setting itself. If its apply to a category, all the settings in that category would default to the type given in category.
"autoplay-delay": {
"title": "DELAY",
"type": "range",
"max": 20,
"min": 1,
"step": 1,
"initialValue": 10
},
Range type renders as a slider. If type is range you need to give max
, min
and step
attributes as well. Max, min defines the numeric range, and step defines how much it changes as a unit.
"translation-language": {
"title": "TRANSLATION_LANGUAGE",
"type": "dropdown",
"options": {
"English": "ENGLISH_LANGUAGE",
"Spanish": "SPANISH_LANGUAGE",
"Hindi": "HINDI_LANGUAGE"
},
"initialValue": "English"
},
Dropdown renders a drop-down of options. You need to give the options
object along with it.
"app-layout": {
"title": "APP_SETTINGS",
"type": "switch",
"settings": ["quick-tools", "shortcut-tray", "live-feed"]
},
Switch renders an on/off toggle.
We show visibility icons along with translation, transliteration, teeka. You will see that the visibility
category is not in any parent category. So in code, we specially pick that object and render that setting as "eye" icon in front of translation, transliteration and teeka size.