Gaia/Settings/docs: Difference between revisions

From MozillaWiki
< Gaia‎ | Settings
Jump to navigation Jump to search
Line 66: Line 66:
== Panels ==
== Panels ==
=== Root ===
=== Root ===
[[Gaia/Settings/docs/Root]]
=== Airplane Mode ===
=== Airplane Mode ===
[[Gaia/Settings/docs/airplane mode]]
[[Gaia/Settings/docs/airplane mode]]
Line 87: Line 89:
=== Keyboard ===
=== Keyboard ===
=== Media Storage ===
=== Media Storage ===
== Build ==
== Build ==

Revision as of 07:40, 22 June 2015

Settings

Architecture

Settings app comprises panels for configuring various settings of a device. In general the panels responsible for different settings can work independently. Certain settings may require a group of panels, for example, keyboard settings. The architecture was designed to allow new panels to be created easily without worrying about affecting other panels in the app.

Settings app uses requirejs for module definition and management. All scripts should be defined as AMD modules except for ones that we would like them to be executed upon the starting up where requirejs has not been loaded yet.

A panel can be associated with an AMD module implementing a specified interface. In the module we can then require other necessary modules that are used in the panel.

Start Up Path

To present the visuals as fast as possible, we determine the first panel to be displayed and then append the HTML elements of the panel to the DOM tree. Note that at this time the panel is visible but still not interactive because the associated modules of the panel are not loaded yet.

There can be a short gap between the panel being presented and all fundamental modules loaded. The time results from loading and initializing requirejs. InitialPanelHandler was introduced to provide basic interactions until the associated modules get loaded. One can provide their own panel handler if the required interactions are beyond what InitialPanelHandler can provide.

window.LaunchContext is constructed during the starting up. The object has a property called pendingTargetPanel that specifies the panel that a user would like to navigate. When the fundamental modules are loaded, the user is brought to the specific panel.

Panel

A panel comprises HTML elements and an optional associated module. This document shows how to create a new panel.

All panels are delay loaded. HTML elements of a panel are created and appended to the DOM tree only when users navigate to the panel. Settings app then loads the associated module of the panel and execute it.

The associated module is usually deriving from SettingsPanel or Panel. Panel provides the basic functionality that allows settings app to control the visibility and life cycle. In addition to that, SettingsPanel further creates bindings between the UI elements and the settings database when the module is being initialized. Details of creating an associated module please refer to here.

Panel Navigation

navigate#SettingsService is used to navigate to any panel by providing the panel id and the options to be passed to the panel. Note that this function behaves like an url link and there is no way for the target panel to return any result. If you would like to share information among panels, you must create a shared module that can be used in the panels, or consider to use DialogService which allows to return results.

Dialog Service

Gaia/Settings/docs/Dialog Service

Dialog Manager

Gaia/Settings/docs/Dialog Manager

Common Patterns

The basic principals are view/logic separation and creating modules that have clear roles and responsibilities. There are two typical roles: view and model.

A view connects the UI elements to a model. It updates the content of the UI elements based on the values of the properties provided by the model. Meanwhile, when users interact with the UI elements, the view is responsible for calling to the corresponding methods of the model.

A model is designed to support views. It is not a passive model that only stores static data but provides methods for manipulating the data and actively reports the changes of the model. A model is not allowed to touch the UI elements directly and should not hold any reference of a view.

This pattern is especially helpful when encountering subtle UX requirements changes because we can change the view easily without modifying the model. Writing unit tests becomes simple when models do not touch the UI elements and it is no longer required to mock the UI elements.

The key is to make a model actively report the status in terms of events and property changes. The following modules can be useful when designing models: Observable, ObservableArray, and EventEmitter.

Let's use panels/display/wallpaper as an example of models. The idea was to hide the complexity of selecting wallpapers and expose the API that is easy to use in the view module.

The method selectWallpaper is used to trigger wallpaper selection while wallpaperSrc is an observable property representing the path to the current wallpaper. We can make any kind of UI trigger a call to selectWallpaper. When the selection completes, wallpaperSrc gets updated to the latest value. The view can then make use of wallpaperSrc to fulfill various requirements such as displaying the path or showing the entire wallpaper.

Modules in Settings

Define Modules

Settings modules are AMD modules. In addition to following the syntax of AMD modules, settings app also requires that the returning object must not a constructor function. Thus we can expect that all modules are able to be used without a "new" keyword. The other advantage is that the returning functions can be seen as factory methods. A factory method can return different type of objects based on the parameters, which is useful in certain use cases.

Configure Requirejs

Shim

Module

A module can depend on many others and it makes sense to merge them into one script in order to save the loading time. When we declare the modules in require.js, all dependent modules are merged in the build process by r.js. Note that for fundamental modules frequently used by other modules, merging them may lead to duplicated code. We can exclude such modules when declaring.

For example, the following module declaration will create a script containing all dependent modules starting from "modules/apn/apn_settings_manager". The paths in the "exclude" can be ordinary modules or modules just specified in require.js.

 name: 'modules/apn/apn_settings_manager',
 exclude: [
   'main',
   'modules/async_storage',
   'modules/mvvm/observable'
 ]

Panels

Root

Gaia/Settings/docs/Root

Airplane Mode

Gaia/Settings/docs/airplane mode

Wifi

Gaia/Settings/docs/Wifi

Bluetooth

Sim Security

Gaia/Settings/docs/Sim Security

Sim Manager

Gaia/Settings/docs/Sim Manager

Operator Settings

Call Settings

Gaia/Settings/docs/Call Settings

APN Settings

Keyboard

Media Storage

Build