Depot for App Preferences

From WebOS101

Jump to: navigation, search

Here we will implement Palm's Depot database wrapper to store and retrieve application preferences. Sure, cookies are simpler but they're also limited to a size of no more than 4k.

Depot storage doesn't have a similar limitation. On the other hand, Depot the depot methods, like SQLite database transactions, are asynchronous, which means you can't set a value directly from a Depot.get() call like you can with cookies. You have to provide an onSuccess callback function, then use the results of the .get() in the callback to set the value. This makes Depot a bit more complicated to use than cookies and you have to plan your app a little differently in order to use Depot. Here's one way to accomplish the same result as cookies using Depot.

Depot is used to store an entire Javascript object. In this case, our Preferences object...

Create a New Depot and Get the Prefs Object

We'll start in the StageAssistant (or AppAssistant) by setting up global object to store Application Preferences. This is done outside the StageAssistant constructor.

Next, we'll create(or load) the Depot by using the new Depot() constructor in the StageAssistant's setup().

// Create a global object to store preferences, etc.
// This is done outside the StageAssistant constructor function
// so that it can be accessed anywhere in the application
MyAPP = {};
MyAPP.prefs = {
firstSetting : true,
email : 'me@email.com',
numberOfThings : 50
};
// Add more settings to the object if you want...
MyAPP.prefs.secondSetting = false;
 
function StageAssistant() {
}
 
StageAssistant.prototype.setup = function() {
 
// Use properties from appinfo.json to provide names for our Depot storage
// using Mojo.appInfo.xxxx
var options = {
name: Mojo.appInfo.id + ".prefs",
version: 0.4,
displayName: Mojo.appInfo.title + " prefs DB"
};
 
MyAPP.prefsDb = new Mojo.Depot(options, this.gotPrefsDb.bind(this), this.dbFailure.bind(this));
 
//DON'T DO THIS!!! PREFS ARE NOT YET LOADED!!!
//this.controller.pushScene('myScene');
};

MyAPP.prefsDb stores the handle to the Depot in a global variable that we can access elsewhere in the app to add and retrieve objects. The second and third arguments to Mojo.Depot() are the onSuccess and onFailure functions. We have to define the two callbacks in the StageAssistant.

The gotPrefsDb() method is called if the Depot is created (or loaded) successfully. Since we now have the Depot, we can next retrieve any values that were stored using MyAPP.prefsDb.get().

StageAssistant.prototype.gotPrefsDb = function (event) {
//Mojo.Log.info("DB Event: %j", event);
MyAPP.prefsDb.get('prefs', this.gotPrefs.bind(this), this.dbFailure.bind(this));
};
 
StageAssistant.prototype.dbFailure = function (event) {
Mojo.Log.info("Prefs DB failure %j", event);
};

Of course, the MyAPP.prefsDb.get() also requires onSuccess and onFailure callback functions. We can reuse the same onFailure function, but need to add the onSuccess to our StageAssistant prototype. In the gotPrefs() function, we receive an object from the Depot.get() that contains our preferences. We'll use a for - in loop to assign the properties of args to our MyAPP.prefs object. This allows adding new prefs in later versions of the code without worrying about whether they're stored in an existing Depot - simply add the new pref in the MyAPP.prefs definition (above the StageAssistant constructor) and if that property doesn't exist in the Depot the default value will be used.

StageAssistant.prototype.gotPrefs = function (args) {
if (args) {
for (value in args) {
MyAPP.prefs[value] = args[value];
//Mojo.Log.info("Pref: ", value, args[value], MyAPP.prefs[value]);
}
}
Mojo.Log.info("Prefs: %j", MyAPP.prefs);
 
//Prefs are loaded, now we can push our first scene!
this.controller.pushScene('myScene');
};

The final line in the gotPrefs() function pushes our scene. This is the key to dealing with the asynchronicity of the Depot methods. We want to make sure that our prefs are loaded before they might potentially be needed - perhaps in the setup() function of a scene. If we had left the pushScene() in the StageAssistant.setup(), there is no guarantee that the prefs would be loaded before the SceneAssistant.setup() is called!

Adding an object to the Depot

So, we know how to get the object from the Depot, but how did it get in there? Using the Mojo.Depot.add() method!

The following code might go in the deactivate() of your preferences scene. Or anywhere that a user can change a preference. Again, remember that the Depot methods are asynchronous. If you're concerned that a user might swipe away a preferences scene, then deactivate() isn't a good place to store prefs changes in the Depot. Consider adding a propertyChanged event handler for the widgets in the prefs scene and storing to the Depot on each propertyChanged event.

MyPrefsScene.storePrefs = function () {
MyAPP.prefsDb.add('prefs', MyAPP.prefs,
function () {},
function (event) {
Mojo.Log.info("Prefs DB failure %j", event);
});
};

And that's it. Using Depot to store app preferences is really not much more difficult than using cookies. And it can store a whole lot more information!

More Help

Depot docs

Personal tools