Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Bug 1073495 - merge pull request #27502 from fcampo:remember_default_…
Browse files Browse the repository at this point in the history
…activity_1073495 to mozilla-b2g:master
  • Loading branch information
mozilla-autolander-deprecated committed Mar 9, 2015
2 parents fd2a4d1 + 896f392 commit dcb2595
Show file tree
Hide file tree
Showing 19 changed files with 1,034 additions and 93 deletions.
61 changes: 61 additions & 0 deletions apps/sharedtest/test/unit/default_activity_helper_test.js
@@ -0,0 +1,61 @@
'use strict';

/* global DefaultActivityHelper, MockSettingsHelper, SettingsHelper */

require('/shared/js/default_activity_helper.js');
require('/shared/test/unit/mocks/mock_settings_helper.js');

suite('Default Activity Helper', function() {
var realSettingsHelper;

suiteSetup(function() {
realSettingsHelper = window.SettingsHelper;
window.SettingsHelper = MockSettingsHelper;
});

suiteTeardown(function() {
window.SettingsHelper = realSettingsHelper;
});

suite('getDefaultConfig', function() {
test('returns config if supported', function() {
var config = DefaultActivityHelper.getDefaultConfig('view', 'url');
assert.ok(config);
assert.equal(config.settingsId, 'activity.default.openurl');
});

test('returns undefined if not supported', function() {
var config = DefaultActivityHelper.getDefaultConfig('aaa', 'bbbb');
assert.equal(config, undefined);
});
});

suite('getDefaultAction', function(done) {
test('setting is recovered for supported activity', function(done) {
var settingsHelper = SettingsHelper('activity.default.openurl', null);
settingsHelper.set('manifest');
DefaultActivityHelper.getDefaultAction('view', 'url').then((action) => {
assert.equal(action, 'manifest');
done();
});
});

test('cb is called with null if not supported', function(done) {
DefaultActivityHelper.getDefaultAction('aaaa', 'bbb').then((action) => {
assert.equal(action, null);
done();
});
});
});

suite('setDefaultAction', function(done) {
test('setting is set for supported action', function(done) {
var settingsHelper = SettingsHelper('activity.default.openurl', null);
DefaultActivityHelper.setDefaultAction('view', 'url', 'testmanifest');
settingsHelper.get(function(value) {
assert.equal(value, 'testmanifest');
done();
});
});
});
});
2 changes: 2 additions & 0 deletions apps/system/index.html
Expand Up @@ -25,6 +25,7 @@
<script defer src="shared/js/manifest_helper.js"></script>
<!-- We need this before we can show the boot animation -->
<script src="shared/js/settings_helper.js"></script>
<script defer src="shared/js/default_activity_helper.js"></script>
<script defer src="shared/js/icc_helper.js"></script>
<script defer src="shared/js/stk_helper.js"></script>
<script defer src="shared/js/mime_mapper.js"></script>
Expand Down Expand Up @@ -329,6 +330,7 @@
<link rel="localization" href="/shared/locales/download/download.{locale}.properties">
<link rel="localization" href="/shared/locales/voicemail/voicemail.{locale}.properties">
<link rel="localization" href="/shared/locales/lockscreen/lockscreen.{locale}.properties">
<link rel="localization" href="/shared/locales/activities/activities.{locale}.properties">
<link rel="localization" href="/shared/elements/gaia_menu/locales/gaia_menu.{locale}.properties">

<!-- Payment -->
Expand Down
63 changes: 57 additions & 6 deletions apps/system/js/action_menu.js
Expand Up @@ -15,11 +15,12 @@
* @param {Boolean} preventFocusChange Set to true to prevent focus changing.
*/
function ActionMenu(listItems, titleL10nId, successCb, cancelCb,
preventFocusChange) {
preventFocusChange, askForDefaultChoice) {
this.onselected = successCb || function() {};
this.oncancel = cancelCb || function() {};
this.listItems = listItems;
this.titleL10nId = titleL10nId;
this.askForDefaultChoice = askForDefaultChoice;
}

ActionMenu.prototype = {
Expand Down Expand Up @@ -52,6 +53,23 @@

this.container.appendChild(this.header);

// And a default choice button if asked
if (this.askForDefaultChoice) {
this.defaultChoice = document.createElement('label');
this.defaultChoice.setAttribute('class', 'pack-checkbox');
this.defaultChoice.setAttribute('data-action', 'set-default-action');

this.defaultChoiceInput = document.createElement('input');
this.defaultChoiceInput.setAttribute('type', 'checkbox');

this.defaultChoiceSpan = document.createElement('span');
this.defaultChoiceSpan.setAttribute('data-l10n-id',
'set-default-action');

this.defaultChoice.appendChild(this.defaultChoiceInput);
this.defaultChoice.appendChild(this.defaultChoiceSpan);
}

// Following our paradigm we need a cancel
this.cancel = document.createElement('button');
this.cancel.setAttribute('data-l10n-id', 'cancel');
Expand Down Expand Up @@ -104,6 +122,19 @@
}
},

/**
* This changes the input to be checked or unchecked
* @memberof ActionMenu.prototype
*/
toggleSetDefaultAction: function() {
var checked = this.defaultChoiceInput.checked;
if (checked) {
this.defaultChoiceInput.removeAttribute('checked');
} else {
this.defaultChoiceInput.setAttribute('checked', true);
}
},

/**
* Builds the dom for the menu.
* @memberof ActionMenu.prototype
Expand All @@ -113,6 +144,7 @@
items.forEach(function traveseItems(item) {
var action = document.createElement('button');
action.dataset.value = item.value;
action.dataset.manifest = item.manifest;
action.textContent = item.label;

if (item.icon) {
Expand All @@ -121,6 +153,13 @@
}
this.menu.appendChild(action);
}, this);

if (this.askForDefaultChoice) {
this.defaultChoiceSpan.setAttribute('data-l10n-id',
'set-default-action');
this.menu.appendChild(this.defaultChoice);
}

this.menu.appendChild(this.cancel);
},

Expand Down Expand Up @@ -173,18 +212,30 @@
case 'click':
evt.preventDefault();
var action = target.dataset.action;
if (action && action === 'cancel') {
this.hide();
this.oncancel();
return;
if (action) {
switch (action) {
case 'cancel':
this.hide();
this.oncancel();
break;
case 'set-default-action':
this.toggleSetDefaultAction();
break;
}
return;
}

var defaultSelected = false;
if (this.askForDefaultChoice) {
defaultSelected = !!this.defaultChoiceInput.getAttribute('checked');
}

var value = target.dataset.value;
if (!value) {
return;
}
value = parseInt(value);
this.hide(this.onselected.bind(this, value));
this.hide(this.onselected.bind(this, value, defaultSelected));
break;

case 'home':
Expand Down
113 changes: 100 additions & 13 deletions apps/system/js/activities.js
@@ -1,5 +1,5 @@
'use strict';
/* global ActionMenu, applications, ManifestHelper */
/* global ActionMenu, applications, ManifestHelper, DefaultActivityHelper */

(function(exports) {

Expand All @@ -12,6 +12,7 @@
function Activities() {
window.addEventListener('mozChromeEvent', this);
window.addEventListener('appopened', this);
window.addEventListener('applicationinstall', this);
this.actionMenu = null;
}

Expand Down Expand Up @@ -39,20 +40,86 @@
this.actionMenu.hide();
}
break;
case 'applicationinstall':
this._onNewAppInstalled(evt.detail.application);
break;
}
},

_onNewAppInstalled: function(app) {
var activities = app && app.manifest && app.manifest.activities;

Object.keys(activities).forEach(function(activity) {
var filters = activities[activity].filters;

// Type can be single value, array, or a definition object (with value)
var type = filters && filters.type && filters.type.value ||
filters && filters.type;

if (!type) {
return;
}

if (typeof type === 'string') {
// single value, change to Array
type = type.split(',');
}

// Now that it's an array, we check all the elements
type.forEach((diff) => {
DefaultActivityHelper.getDefaultAction(activity, diff)
.then((defApp) => {
// If default launch app is set for the type
if (defApp) {
// Delete the current default app
DefaultActivityHelper.setDefaultAction(activity, diff, null);
}
});
});
});
},

/**
* This gets the index from the defaultChoice in the choices
* list.
* @param {Object} defaultChoice The default choice
* @return {Integer} The index where the default
* choice is located. -1 if it
* is not found
*/
_choiceFromDefaultAction: function(defaultChoiceManifest, detail) {
var index = -1;
if (defaultChoiceManifest) {
index = detail.choices.findIndex(function(choice) {
return choice.manifest.indexOf(defaultChoiceManifest) !== -1;
});
}

return index;
},

/**
* Displays the activity menu if needed.
* If there is only one option, the activity is automatically launched.
* @memberof Activities.prototype
* @param {Object} detail The activity choose event detail.
*/
chooseActivity: function(detail) {
this._id = detail.id;
var choices = detail.choices;
var name = detail && detail.name;
var type = detail && detail.activityType;
this._detail = detail;
this.publish('activityrequesting');
if (choices.length === 1) {

DefaultActivityHelper.getDefaultAction(name, type).then(
this._gotDefaultAction.bind(this));
},

_gotDefaultAction: function(defaultChoice) {
var choices = this._detail.choices;
var index = this._choiceFromDefaultAction(defaultChoice, this._detail);
if (index > -1) {
this.choose(index);
} else if (choices.length === 1) {
this.choose('0');
} else {
//
Expand All @@ -75,7 +142,7 @@
// activity, but it is much simpler to restrict to the FL app
// only.
//
if (detail.name === 'view') {
if (this._detail.name === 'view') {
var flAppIndex = choices.findIndex(function(choice) {
var matchingRegex =
/^(http|https|app)\:\/\/fl\.gaiamobile\.org\//;
Expand All @@ -95,11 +162,21 @@
// shows
window.dispatchEvent(new CustomEvent('activitymenuwillopen'));

var activityNameL10nId = 'activity-' + detail.name;
var name = this._detail.name;
var type = this._detail.activityType;
var config = DefaultActivityHelper.getDefaultConfig(name, type);

var activityNameL10nId;
if (config) {
activityNameL10nId = config.l10nId;
} else {
activityNameL10nId = 'activity-' + this._detail.name;
}

if (!this.actionMenu) {
this.actionMenu = new ActionMenu(this._listItems(choices),
activityNameL10nId, this.choose.bind(this),
this.cancel.bind(this));
this.cancel.bind(this), null, config !== undefined);
this.actionMenu.start();
}
}).bind(this));
Expand All @@ -110,18 +187,27 @@
* The user chooses an activity from the activity menu.
* @memberof Activities.prototype
* @param {Number} choice The activity choice.
* @param {Boolean} setAsDefault Should this be set as the default activity.
*/
choose: function(choice) {
choose: function(choice, setAsDefault) {
this.actionMenu = null;

var returnedChoice = {
id: this._id,
id: this._detail.id,
type: 'activity-choice',
value: choice
value: choice,
setAsDefault: setAsDefault
};
var name = this._detail.name;
var type = this._detail.activityType;

if (setAsDefault) {
DefaultActivityHelper.setDefaultAction(name, type,
this._detail.choices[choice].manifest);
}

this._sendEvent(returnedChoice);
delete this._id;
delete this._detail;
},

/**
Expand All @@ -132,13 +218,13 @@
this.actionMenu = null;

var returnedChoice = {
id: this._id,
id: this._detail.id,
type: 'activity-choice',
value: -1
};

this._sendEvent(returnedChoice);
delete this._id;
delete this._detail;
},

publish: function(eventName) {
Expand Down Expand Up @@ -176,6 +262,7 @@
items.push({
label: new ManifestHelper(app.manifest).name,
icon: choice.icon,
manifest: choice.manifest,
value: index
});
});
Expand Down
1 change: 1 addition & 0 deletions apps/system/locales/system.en-US.properties
Expand Up @@ -467,6 +467,7 @@ activity-record=Record from:
activity-browse=Browse with:
activity-configure=Configure with:
activity-dial=Dial from:
set-default-action=Use from now on

# Persona dialog and Identity
persona-signin=Sign In
Expand Down

0 comments on commit dcb2595

Please sign in to comment.