Settings Doc Part 1: The structure of user settings.json (feat basics of global state management) - KhalisFoundation/sttm-desktop GitHub Wiki

Basics of Global State Management in sttm-desktop

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/

Structure of user-settings.json

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.

Categories

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"
}

Subcategories

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. **

Settings 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
    },

Setting Attributes

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 the dontApplyClass: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 to notes 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.

Types of settings

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.

Range

"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.

Dropdown

    "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.

Switch

"app-layout": {
      "title": "APP_SETTINGS",
      "type": "switch",
      "settings": ["quick-tools", "shortcut-tray", "live-feed"]
    },

Switch renders an on/off toggle.

Special case of visibility category.

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.