Skip to content

keyboard_helper_test fix #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: settings2_bubble_tea
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .jshintignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ apps/keyboard/js/layouts/**
apps/music/js/metadata_scripts.js
apps/keyboard/js/imes/jszhuyin/tools/cook.js
apps/keyboard/build/keyboard-config.js
apps/settings/js/vendor/alameda.js
8 changes: 8 additions & 0 deletions apps/settings/.jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../../.jshintrc",
"predef": [
"define",
"require",
"Settings"
]
}
49 changes: 43 additions & 6 deletions apps/settings/Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
-include $(PWD)/build/common.mk

GAIA_ROOT_PATH?=../..

.PHONY: all build stamp-commit-hash
all: build stamp-commit-hash
ifdef XPCSHELLSDK
JS_RUN_ENVIRONMENT := $(XULRUNNERSDK) $(XPCSHELLSDK)
else ifndef JS_RUN_ENVIRONMENT
NODEJS := $(shell which node)
JS_RUN_ENVIRONMENT := $(NODEJS)
endif

build:
@echo 'Building settings app...'
@$(call run-app-js-command, build)
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

SHARED_SOURCES := $(call rwildcard,../../shared/,*)
JS_SOURCES := $(call rwildcard,js/,*)
LOCALES_SOURCES := $(call rwildcard,locales/,*)
RESOURCES_SOURCES := $(call rwildcard,resources/,*)
STYLE_SOURCES := $(call rwildcard,style/,*)
BUILD_SOURCES := $(call rwildcard,build/,*)

BUILD_DIR=../../build_stage/settings

.PHONY: all clean

all: js_environment_available stamp-commit-hash settings_configuration $(BUILD_DIR)/js/main.js

clean:
rm -rf $(BUILD_DIR)

js_environment_available:
ifndef JS_RUN_ENVIRONMENT
$(error Environment to run r.js is not available. Please Install NodeJS -- (use aptitude on linux or homebrew on osx))
endif

GAIA_ROOT_PATH?=../..

# Generate a text file containing the current changeset of Gaia
stamp-commit-hash:
Expand All @@ -19,3 +43,16 @@ stamp-commit-hash:
echo 'Unknown Git commit; build date shown here.' > ./resources/gaia_commit.txt; \
date +%s >> ./resources/gaia_commit.txt; \
fi)

$(BUILD_DIR)/js/main.js: manifest.webapp index.html $(SHARED_SOURCES) $(JS_SOURCES) $(LOCALES_SOURCES) $(RESOURCES_SOURCES) $(STYLE_SOURCES) $(BUILD_SOURCES)
@rm -rf $(BUILD_DIR)
@mkdir -p $(BUILD_DIR)
cp -rp ../../shared $(BUILD_DIR)/shared
$(JS_RUN_ENVIRONMENT) ../../build/r.js -o build/require_config.jslike

settings_configuration:
ifdef XPCSHELLSDK
@$(call run-app-js-command, build)
else ifndef JS_RUN_ENVIRONMENT
@$(NODEJS) build/configure.js
endif
151 changes: 151 additions & 0 deletions apps/settings/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Settings

- Allows the user to configure device settings
- Responds to **incoming activities** ('configure'), which allows the user to navigate to a specific panel to configure from another app (eg. show the wifi settings panel if no data connection is available).

## Current Status

Currently basic settings services (mozSettings/UI bindings, panel navigation...) used by all panels and root panel specific logic were mixed and defined in a few modules (Settings, Connectivity).

The goal is to break the panel dependency. This should be done by breaking existing modules into smaller ones, which enables each panel to load only the necessary codes. And new panels should follow the new code structure so we will achieve:

1. Module separation
2. Panel separation
3. Inline activities
4. View/logic separation

## Modules

We are using [AMD](http://en.wikipedia.org/wiki/Asynchronous_module_definition) modules, loaded using 'Alemeda' (a lighter version of [RequireJS](http://requirejs.org)) and building/optimizing using ['r.js'](http://requirejs.org/docs/optimization.html) (the RequireJS optimizer). We have dependencies on files (`shared/js`) which aren't AMD modules. For those we use the ['shim'](http://requirejs.org/docs/api.html#config-shim) options in our [`requirejs_config.js`](js/config/require.js)

## module/settings_service.js
`SettingsService` provides a navigate function for panel navigation. It gets the corresponding panel module from `PanelCache` and call to its show and hide functions when navigating (see the module/panel.js section).

## module/panel_cache.js
`PanelCache` loads panel modules based on panel IDs and caches the loaded modules. If there is no corresponding panel module, it returns `SettingsPanel`.

## module/panel.js
`Panel` defines Six basic functions: show, hide, beforeShow, beforeHide, init, and uninit for navigation. These functions are called by `SettingsService` during the navigation.
- show: called when the panel is navigated into the viewport
- hide: called when the panel is navigated out of the viewport
- beforeShow: called when the panel is about to be navigated into the viewport
- beforeHide: called when the panel is about to be navigated out of the viewport
- init: called at the first time when the beforeShow function gets called
- uninit: called when cleanup

The internal functions, _onShow, _onHide, _onBeforeShow, _onBeforeHide, _onInit, and _onUninit, are called respectively in the basic functions. The syntax of the functions are:
```sh
function onShow(panelElement [, showOptions])
function onHide()
function onBeforeShow(panelElement [, beforeShowOptions])
function onBeforeHide()
function onInit(panelElement [, initOptions])
function onUninit()
```

We are able to override the internal functions by passing an option object into the constructor of `Panel`. For example,
```sh
Panel({
onShow: function(panelElement, showOptions) { //... },
onHide: function() { //... },
onBeforeShow: function(panelElement, beforeShowOptions) { //... },
onBeforeHide: function() { //... },
onInit: function(panelElement, initOptions) { //... },
onUninit: function() { //... }
})
```

Typically we can create DOM element references in onInit, update UI elements and add listeners in onShow or onBeforeShow, remove listeners in onHide, and do cleanup in onUninit. The difference between onShow and onBeforeShow is that onBeforeShow is called before the transition, which makes updating the UI before displaying it to users possible.

Note that the transition happens right after onBeforeShow, please avoid heavy things in onBeforeShow and onBeforeHide, or it may drag down the performance of the transition.

## module/settings_panel.js
`SettingsPanel` extends `Panel` with basic settings services. It presets the UI elements based on the values in mozSettings and add listeners responding to mozSettings changes in onBeforeShow. In onInit it parses the panel element for activating links. It also removes listeners in onHide so that we can avoid unwanted UI updates when the panel is outside of the viewport.

As we are using require.js for module management, scripts used in a panel should be wrapped in an AMD module or loaded from it, and which should extends from `SettingsPanel` to have basic settings services. Similar to `Panel`, we are able override onShow, onHide, onBeforeShow, onBeforeHide, onInit, and onUninit by passing an option object to the constructor of `SettingsPanel`.

## Implement Guide
###How to create a new panel in Settings?
1. Create an HTML template file with the following format and place it in the elements/ folder.
```sh
<element name="{panel_name}" extends="section">
<template>
<!-- UI elements -->
</template>
</element>
```

2. Add the following `link` tag in the head element of index.html.
```sh
<link rel="import" href="{path_to_html_template}">
```

3. Add the following `section` tag in the body element of index.html.
```sh
<section is="{panel_name}" role="region" id="{panel_id}"></section>
```

### How to load scripts for a panel?
1. Define an AMD module that extends from `SettingsPanel`. You can add other needed modules in the dependency list. A simple module looks like:
```sh
define('panels/SamplePanel', ['modules/SettingsPanel', 'modules/Module1', 'modules/Module2'],
function(SettingsPanel, Module1, Module2) {
return SettingsPanel({
onInit: function(rootElement, initOptions) {
//...
},
onUninit: function() {
//...
},
onShow: function(rootElement, showOptions) {
//...
},
onHide: function() {
//...
}
});
});
```

2. Add a <panel> tag with a "data-path" attrbute specifying the panel module in the end of the panel template. The HTML file looks like:
```sh
<element name="{panel_name}" extends="section">
<template>
<!-- UI elements -->
<panel data-path="panels/SamplePanel"></panel>
</template>
</element>
```

###How to port old panel to new structure in Settings?

1. find panel href={element} in index.html

2. find panel element in element/{element}.html
replace the line
```
<script src="js/<panel name>.js"></script>
```
to
```
<panel data-path="panels/<Capital panel name>Panel"></panel>
```
for `support` panel, it denotes replace `js/support.js` to `panels/SupportPanel`.

3. create `modules/Support.js`

4. create new `panels/SupportPanel.js` and include module/Support

5. test with command for integration test
`sudo make test-integration APP=settings`

## Build step

The settings app has it's own [`Makefile`](Makefile). A Makefile is similar to Grunt, but written in bash, it is essentially a list of tasks that can be run (via `make <task-name>`). When a Gaia application has its own `apps/<app-name>/Makefile`, it will be automatically run when Gaia builds.

Our `Makefile` has two tasks, one to **'build'** and one to **'clean'** (delete the build). The build steps are as follows:

1. Remove any previous settings build from the `build_stage/`
2. Create an new directory `build_stage/settings`
3. Run the `r.js` (RequireJS optimizer), pointing it at our `require_config.jslike` file (`.jslike` because we don't want Gaia builds to mess with it [I think]). This copies our entire application (JS and all) and bundles our JS (tracing `require()` calls) and CSS (tracing `@import`) in two single files.

29 changes: 29 additions & 0 deletions apps/settings/build/require_config.jslike
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
appDir: '..',
baseUrl: 'js',
mainConfigFile: '../js/config/require.js',
dir: '../../../build_stage/settings',

findNestedDependencies: true,

// Set to 'uglify2' to get uglify to run using the
// uglify2 settings below.
optimize: 'none',

// Just strip comments, no code compression or mangling.
// Only active if optimize: 'uglify2'
uglify2: {
// Comment out the output section to get rid of line
// returns and tabs spacing.
output: {
beautify: true
},
compress: false,
mangle: false
},

// Keeping build dir since Makefile cleans it up and
// preps build dir with the shared directory
keepBuildDir: true,
removeCombined: true
}
1 change: 1 addition & 0 deletions apps/settings/elements/carrier.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ <h2 data-l10n-id="advancedSettings"> Advanced Settings </h2>
</ul>
</div>

<script src="shared/js/settings_helper.js"></script>
<script src="js/carrier.js"></script>

</template>
Expand Down
10 changes: 3 additions & 7 deletions apps/settings/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,8 @@
<!-- For perf-measurement related utilities -->
<script defer="" src="/shared/js/performance_testing_helper.js"></script>

<!-- Lazy loader -->
<script defer="" src="/shared/js/lazy_loader.js"></script>

<!-- Screen layout watcher -->
<script defer="" src="/shared/js/screen_layout.js"></script>

<!-- Specific code -->
<script defer="" src="js/settings.js"></script>
<script data-main="js/main" src="js/vendor/alameda.js"></script>

<!-- shared helper library -->
<!--<script defer src="shared/js/download/download_store.js"></script>-->
Expand All @@ -80,6 +74,8 @@
<!--<script defer src="shared/js/settings_listener.js"></script> -->
<!--<script defer src="shared/js/airplane_mode_helper.js"></script> -->
<!--<script defer src="shared/js/toaster.js"></script> -->
<!--<script defer src="shared/js/lazy_loader.js"></script> -->
<!--<script defer src="shared/js/screen_layout.js"></script> -->

<!-- all non-#root panels will lazy-load their own scripts -->
<link rel="import" href="/elements/wifi_status.html">
Expand Down
2 changes: 1 addition & 1 deletion apps/settings/js/carrier.js
Original file line number Diff line number Diff line change
Expand Up @@ -1240,8 +1240,8 @@ navigator.mozL10n.ready(function loadWhenIdle() {
var idleObserver = {
time: 3,
onidle: function() {
CarrierSettings.init();
navigator.removeIdleObserver(idleObserver);
CarrierSettings.init();
}
};
navigator.addIdleObserver(idleObserver);
Expand Down
23 changes: 23 additions & 0 deletions apps/settings/js/config/require.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require.config({
baseUrl: '/js',
paths: {
'modules': 'modules',
'shared': '../shared/js'
},
shim: {
'settings': {
exports: 'Settings'
},
'shared/lazy_loader': {
exports: 'LazyLoader'
},
'shared/screen_layout': {
exports: 'ScreenLayout'
}
},
modules: [
{
name: 'main'
}
]
});
42 changes: 42 additions & 0 deletions apps/settings/js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require(['config/require'], function() {
'use strict';

define('boot', function(require) {
var SettingsService = require('modules/settings_service'),
SettingsCache = require('modules/settings_cache'),
PageTransitions = require('modules/page_transitions'),
LazyLoader = require('shared/lazy_loader'),
ScreenLayout = require('shared/screen_layout'),
Settings = require('settings');

/**
* In two column layout, the root panel should not be deactivated. We pass
* the id of the root panel to SettingsService so that it won't deacivate
* the root panel when in two column.
* XXX: Currently we don't separate the navigation logic of one column and
* two column layout, so that the root panel will not be deactivated
* in in one column layout.
*/
SettingsService.init('root');

var options = {
SettingsService: SettingsService,
SettingsCache: SettingsCache,
PageTransitions: PageTransitions,
LazyLoader: LazyLoader,
ScreenLayout: ScreenLayout
};

if (document && (document.readyState === 'complete' ||
document.readyState === 'interactive')) {
Settings.init(options);
} else {
window.addEventListener('load', function onload() {
window.removeEventListener('load', onload);
Settings.init(options);
});
}
});

require(['boot']);
});
Loading