Using Browser Storage In SUSI Firefox Add-On

Browser storage API enables extensions to store and retrieve data, and listen for changes to the stored item. In SUSI Firefox add-on the browser storage is implemented to store the chat history in the browser memory. This allows the extension to maintain persistence when the popup is closed or opened. This article gives a brief idea about how to implement browser storage using SUSI Firefox add-on as a use case.

Adding Permission

To use this API you need to include the “storage” permission in your manifest.json file.

“permissions”: [
 “storage”
]

Adding this in the manifest.json file will grant your extension the permission to use the storage API

Properties of Storage

There are three properties of storage which allows the developer to use different types of storage areas. One can choose a suitable property to meet the requirements.

  1. Storage.sync – Represents the sync storage area. Data stored in sync storage are synced by the browser and are available across all instances of that browser (even on different devices) that the user is logged in. Note – Currently storage.sync is supported by modern browsers and recent versions of Firefox. Please refer the documentation for more details.
  2. Storage.local – Represents the local storage area. Items in local storage are local to the machine the extension was installed on.
  3. Storage.managed – Represents the managed storage area. Items in managed storage are set by the domain administrator and are read-only for the extension. Trying to modify this namespace results in an error.

In SUSI Firefox add-on Storage.sync is being used to leverage the benefit of storage sync across all instances of the browser. So the chat history and settings are synced across the browsers logged in by the user.

Storing Data

browser.storage.<storageType>.set(keys)  – This function allows one or more item to be stored in the browser storage. If there in key-value already existing then the value will be updated to the new value supplied in the function. The function returns a promise.

Note – <storageType> will be one of the writable storage types — storage.sync or storage.local

This is a snippet taken from SUSI Firefox add-on where the theme value from settings page is being stored in the browser storage.

if(response.settings.theme){
browser.storage.sync.set({
theme: response.settings.theme
});
}

Retrieving Data

browser.storage.<storageType>.get(keys)  – Retrieves one or more items from the storage area. A key or array of keys is used to identify the item(s) to be retrieved from storage. If an empty string, object or array is passed, an empty object will be retrieved. If you pass null, or an undefined value, the entire storage contents will be retrieved. The function returns a promise.

Note – <storageType> will be one of the writable storage types — storage.sync or storage.local

This is a snippet taken from SUSI Firefox add-on where the settings preferences are being persisted by retrieving setting values from storage.

var buffer = browser.storage.sync.get(null);
buffer.then(function(res){
if(res["theme"]){
if(res["theme"]=="dark"){
$("#theme").val("dark");
}
else{
$("#theme").val("light");
}
}
if(res["loggedUser"]){
loginForm.style.display="none";
logoutButton.style.display="block";
}
else{
loginForm.style.display="block";
logoutButton.style.display="none";
}

});

Null values are being passed in the get function.

Key Points To Remember

  • Storage API is asynchronous. For all storage related transaction, you will need to manage the promises. So it is to carry out any kind of memory related action by using then() method to avoid spurious results
  • Values are scoped to the extension, not to a specific domain (i.e. the same set of key/value pairs are available to all scripts in the background context and content scripts). So the values can be used across different scripts and it acts like a common data store for the scripts.
  • The values stored can be any JSON-ifiable value, not just String. This includes Array and Object, but only when their contents can be represented as JSON, which does not include DOM nodes.

Resources

Enhancing Settings Menu in SUSI Webchat using Material-UI Menu React Component

Material-UI is a great library for react developers since you can directly use the material components in your app. The SUSI.AI Webchat uses Material-UI (https://github.com/callemall/material-ui). In this blog we’ll see how a Menu component is implemented in settings page of susi’s web chat app.

Menu & MenuItem Component

Menu component allows you execute an action on selecting from a list. In the settings menu we want to change the state variable to which setting details is binded (ie. on change of state variable the setting details corresponding to selected menu changes).

A simple menu component is defined like this –

<Menu>
        <MenuItem primaryText="Item 1" />
        <MenuItem primaryText="Item 2" />
        <MenuItem primaryText="Item 3" />
        <MenuItem primaryText="Item 4" />
</Menu>

Menu component and MenuItem accepts some properties too. Like if you add disable={true} then the MenuItem it will disable onClick action of MenuItem.

Adding Icon

MenuItem can contain icons through defining leftIcon and rightIcon properties.

Example snippet:

<MenuItem primaryText="Download" leftIcon={<Download />} />

Output:

You can also add style to the leftIcon or rightIcon in style property of MenuItem.

Active State of MenuItem

You must be interested in assigning a different style to the active MenuItem in the Menu. This can be achieved through selectedMenuItemStyle property. It allows overriding the inline-style property of selected MenuItem.

To implement this we need to use the concept of ‘controlled component’. Each MenuItem has to be assigned a value. Also, assign the Menu with a state variable.

<Menu 
 selectedMenuItemStyle={{color: '#FFFFFF'} }   
 value={this.state.selectedItem} > 
    <MenuItem primaryText="Item 1" value='1'/> 
    <MenuItem primaryText="Item 2" value='2' /> 
</Menu>

This way the state variable will control Menu’s value and the selectedMenuItemStyle property will override the inline-style of the corresponding MenuItem.

Implement onClick function for MenuItem and change the state value.

This way you can add style to active MenuItem.

You can see the demo of how it was implemented in chat settings at https://chat.susi.ai/settings

Also, you can check out the github repo https://github.com/fossasia/chat.susi.ai

Note – Make sure that you define the state change function outside render else it will get a warning like this.

Warning: setState(…): Cannot update during an existing state transition (such as within `render` or another component’s constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.

This will result in abnormal behaviour in runtime. So keep that mind in while creating the function to change the state.

Resources