Remember User Settings (Local Storage)

After many hours of trial and error, I’ve found a way to store user settings.
For the time being, user settings can be any app var that is true/false.
If anyone knows a way to store more complex settings feel free to add more info on this thread.

On my app I have 2 settings: one for changing the theme and another for the language.

  1. Create app vars true/false. These can be changed globally on app via buttons and logic.

  1. Install from marketplace the “Set item to storage & Get item from storage”

  2. On global canvas set the logic according to attached photo.

  1. The “item key” is a text but it must be the same on both logics (set & get)

  2. As soon as the app launches, we Get item from storage and we give a name to ‘item key’.
    We set 2 blocks of ‘Set app variable’ both with the same appvar name. One which will be true and the other one false.

We set a ‘Receive Event’ logic with the appropriate appvar ‘changed’ and then we set the ‘Set item to storage’ block with the same item key we set the ‘Get item from storage’ and the ‘Data to store’ with the appropriate app var.

I hope this helps many of you.

1 Like

Since you can use the set item storage flow with a json object. In fact what you can do is to set the value of the settings to

ENCODE_JSON(appVars.settings)

And create the appVars.settings as an object. Add properties as you required, “set initial value” and then add a logic where the user can modify that.

The rest should be the same. Only when getting the item from storage bind the appVars.settings to a formula.

DECODE_JSON(outputs["Get item from storage"]...)

*Check for correct syntax. I might update this reply with more details later.

Hi Mihaly, thanks for sharing this. I might try a more compact way setting-up the user settings as you mentioned it.

Do you know a way to store locally data being pulled from airtable, that is texts and photos, for offline use? User doesn’t have to download all the data from backend every time they open the app.

So here I am back with a more concise summary.

Saving anything to local storage might seem to be overwhelming… Now let’s again start with a few basic concepts. Data records are in fact JSON-stringifiable objects. So they have a schema of property name and property value. They look like this:

{
firstProperty: valueOfFirstProperty,
secondProperty: valueOfSecondProperty,
}

Usually, when we talk about a data record, it has at least one property: the “id” or “key”. This property is required to identify a data record inside a collection.
When a data resource is connected (Firebase, Airtable, etc…) we get the data via these “id” or “key”. (Or if we get a list of records then the method is a little bit different of course…)

To understand the local storage it is important to make a clear differentiation between the “On-device storage” that can be configured in the “Data” tab of Composer and the so-called “Persistent storage”.

In fact, the “On-device storage” is also saved in the “Persistent storage”, but it has been designed to represent a similar structure to any other data resource for easier data management. This is best used for data records with several data records (lists)…

If we have some unique data that doesn’t have different separate items we can and should use the “Set item to storage” and “Get item from storage” logic flows (installable from the marketplace as mentioned in a post above).
These flows allow us, the developer to specify a “key” or “id” to the data that we want to save. Also, they can store anything that is JSON-stringifiable. Any variable that is defined in Composer’s variable view is JSON-stringifiable, thus all of them can be set to storage. It can be an object, a list of objects, a list of texts, or anything that you can imagine and define. BUT there is one important step. To convert that data to a JSON string upon saving to local storage and to “parse” the JSON string when loading the data.
*The term “parse” means to iterate through the JSON string and create a variable based on the schema of the string. (To put it in an easy-to-understand manner…)

So how would you go about this in Composer? The following screenshots should help:

  1. Create the variable that You want to save:

  2. Add the logic “Set item to storage” (in this case it is under a button tap, but can be really anywhere…)

In this step set the “key” to any name that You want to have this resource to be saved as. I called it “setting”.
And finally set the value data to store to this formula:

ENCODE_JSON(appVars.settings)

Of course, change your variable inside the formula. This will create a JSON string that can be easily stored.

  1. Now let’s get this data back. I get this on my global canvas, but this also can be placed anywhere.

This step consists of two logic flows. The first is to get the data from the storage with Your specified “key” (In our case “setting”). And the other step is to set this data to a variable that is used inside the app… Inside the value of that variable use this formula:

DECODE_JSON(outputs["Get item from storage"].item)

This will throw 2 warnings, but since we have the same schema for the variable that we used to Set item and Get item we can ignore those.

And this is how You save some unique data to the persistent storage and retrieve that.
Note, that this also has some limitations (I am not sure what are those, but in most cases, we would not exceed those…)

As for the Airtable “caching” question… Well. It is just some design question. Is it a native app only?
If yes, then you could use this “Set item” approach to save even a list of data records in the following way:

  • “Get record collection” from Airtbale
  • “Set item to storage” - ENCODE_JSON(outputs["Get record collection"].records)
    This applies only to the data records. For images, You can make use of the “Create file/directory” flows in the following way:
  • Do an IF flow to check if the directory exists (use the “File/directory exists” flow)
  • if yes then use the “Download files” flow to save the image into that directory (keep in mind that in this case, you will somehow need to manage the new path to the image in your image components…)
  • if the directory doesn’t exist then you’ll need to use the “Create file/directory flow” to first create the directory and then go back to the “yes” branch…

Hope this all helps at least a little bit…

5 Likes

Mihaly thank you for your time.
I will try your methods and let you know.