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

Commit

Permalink
Bug 1061130 - Add speed dial functionality to the Dialer. r=thills
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielesvelto committed Jan 19, 2015
1 parent eda2429 commit 67b4246
Show file tree
Hide file tree
Showing 3 changed files with 320 additions and 15 deletions.
150 changes: 144 additions & 6 deletions apps/communications/dialer/test/unit/keypad_test.js
@@ -1,25 +1,26 @@
/* globals CallHandler, CallLogDBManager, FontSizeManager, gTonesFrequencies,
KeypadManager, MockCall, MockCallsHandler, MockIccManager,
MockNavigatorMozTelephony, MockNavigatorSettings,
/* globals CallHandler, CallLogDBManager, ConfirmDialog, FontSizeManager,
gTonesFrequencies, KeypadManager, MockCall, MockCallsHandler,
MockIccManager, MockNavigatorMozTelephony, MockNavigatorSettings,
MockSettingsListener, MocksHelper, MockTonePlayer, telephonyAddCall,
MockMultiSimActionButtonSingleton, MockMozL10n, CustomDialog,
MockMozActivity, CustomElementsHelper
MockMozActivity, SimSettingsHelper, CustomElementsHelper
*/

'use strict';

require('/shared/js/dialer/dtmf_tone.js');
require('/shared/js/dialer/keypad.js');

require('/contacts/test/unit/mock_confirm_dialog.js');
require('/dialer/test/unit/mock_call_handler.js');
require('/dialer/test/unit/mock_call_log_db_manager.js');
require('/shared/test/unit/mocks/mock_confirm_dialog.js');
require('/shared/test/unit/mocks/mock_iccmanager.js');
require('/shared/test/unit/mocks/mock_lazy_loader.js');
require('/shared/test/unit/mocks/mock_multi_sim_action_button.js');
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
require('/shared/test/unit/mocks/mock_navigator_moz_telephony.js');
require('/shared/test/unit/mocks/mock_settings_listener.js');
require('/shared/test/unit/mocks/mock_multi_sim_action_button.js');
require('/shared/test/unit/mocks/mock_sim_settings_helper.js');
require('/shared/test/unit/mocks/dialer/mock_handled_call.js');
require('/shared/test/unit/mocks/dialer/mock_call.js');
require('/shared/test/unit/mocks/dialer/mock_calls_handler.js');
Expand All @@ -41,8 +42,10 @@ var mocksHelperForKeypad = new MocksHelper([
'CallsHandler',
'CallHandler',
'CallLogDBManager',
'ConfirmDialog',
'HandledCall',
'SettingsListener',
'SimSettingsHelper',
'GaiaSimPicker',
'TonePlayer',
'CustomDialog',
Expand Down Expand Up @@ -678,6 +681,141 @@ suite('dialer/keypad', function() {
sinon.assert.notCalled(CallHandler.call);
});
});

suite('Speed dial', function() {
var speedDialNum = '1#';

setup(function() {
subject._phoneNumber = '';
});

test(speedDialNum + ' is a speed dial number', function() {
assert.isTrue(subject._isSpeedDialNumber(speedDialNum));
});

test('123 is not a speed dial number', function() {
assert.isFalse(subject._isSpeedDialNumber('123'));
});

test('*#31# is not a speed dial number', function() {
assert.isFalse(subject._isSpeedDialNumber('*#31#'));
});

test('Starts speed dial upon typing ' + speedDialNum, function() {
var node;
var fakeEventStart;
var fakeEventEnd;

node = document.createElement('div');
fakeEventStart = {
target: node,
stopPropagation: function() {},
type: 'touchstart'
};
fakeEventEnd = {
target: node,
stopPropagation: function() {},
type: 'touchend'
};

this.sinon.stub(KeypadManager, '_getSpeedDialNumber', function() {
return Promise.resolve('123');
});

for (var i = 0, end = speedDialNum.length; i < end; i++) {
fakeEventStart.target.dataset.value = speedDialNum.charAt(i);
subject.keyHandler(fakeEventStart);
fakeEventEnd.target.dataset.value = speedDialNum.charAt(i);
subject.keyHandler(fakeEventEnd);
}

sinon.assert.calledWith(KeypadManager._getSpeedDialNumber, 1);
});

suite('Getting a speed dial number', function() {
var speedDialIndex = '1';
var numbers = [ '123', '456' ];

suiteSetup(function() {
navigator.mozIccManager.adnContacts = [
{
id: numbers[1],
tel: [ { value: numbers[1] } ]
},
{
id: numbers[0],
tel: [ { value: numbers[0] } ]
}
];
});

setup(function() {
this.sinon.spy(ConfirmDialog, 'show');
this.sinon.spy(ConfirmDialog, 'hide');
});

test('The overlay is displayed and then hidden', function(done) {
subject._getSimContactsList(0).then(function() {
sinon.assert.calledOnce(ConfirmDialog.show);
sinon.assert.calledOnce(ConfirmDialog.hide);
}).then(done, done);
});

test('Cancelling the overlay works', function(done) {
navigator.mozIccManager.async = true;

var p = subject._getSimContactsList(0);
ConfirmDialog.executeNo();

p.then(function() {
assert.ok(false, 'Should not succeed');
}, function() {
sinon.assert.calledOnce(ConfirmDialog.show);
sinon.assert.calledOnce(ConfirmDialog.hide);
}).then(done, done);

navigator.mozIccManager.async = false;
});

test('The contacts are returned sorted by ID', function(done) {
subject._getSimContactsList(0).then(function(contacts) {
assert.equal(contacts[0].id, numbers[0]);
assert.equal(contacts[1].id, numbers[1]);
}).then(done, done);
});

test('The proper number is returned', function(done) {
subject._getSpeedDialNumber(speedDialIndex).then(function(number) {
assert.equal(number, numbers[0]);
}).then(done, done);
});

test('0# is ignored', function(done) {
subject._getSpeedDialNumber('0').then(function(number) {
assert.ok(false, 'the promise should be rejected');
}).then(done, done);
});

test('The SIM picker is used when there is no default SIM',
function(done) {
var simPicker = document.getElementById('sim-picker');
navigator.mozIccManager.iccIds[0] = 0;
navigator.mozIccManager.iccIds[1] = 1;

this.sinon.stub(SimSettingsHelper, 'getCardIndexFrom');
this.sinon.spy(simPicker, 'getOrPick');

var p = subject._getSpeedDialNumber(speedDialIndex);
SimSettingsHelper.getCardIndexFrom
.yield(SimSettingsHelper.ALWAYS_ASK_OPTION_VALUE);
simPicker.getOrPick.yield(0);
p.then(function(number) {
sinon.assert.calledOnce(simPicker.getOrPick);
assert.equal(number, numbers[0]);
}).then(done, done);
});
});
});
});

suite('Initializing MultiSimActionButton', function() {
Expand Down
149 changes: 147 additions & 2 deletions shared/js/dialer/keypad.js
@@ -1,8 +1,9 @@
/* exported KeypadManager */

/* globals AddContactMenu, CallHandler, CallLogDBManager, CallsHandler,
CallScreen, CustomDialog, DtmfTone, FontSizeManager, LazyLoader,
LazyL10n, MultiSimActionButton, SettingsListener, TonePlayer */
CallScreen, ConfirmDialog, CustomDialog, DtmfTone, FontSizeManager,
LazyLoader, LazyL10n, MultiSimActionButton, Promise,
SimSettingsHelper, SettingsListener, TonePlayer */

'use strict';

Expand Down Expand Up @@ -436,6 +437,17 @@ var KeypadManager = {
TonePlayer.stop();
}

// Handle speed dial numbers
if (this._isSpeedDialNumber(this._phoneNumber)) {
var self = this;
var index = this._phoneNumber.slice(0, -1); // Remove the trailing '#'

this._getSpeedDialNumber(+index).then(
function(number) {
self.updatePhoneNumber(number, 'begin', false);
});
}

// If it was a long press our work is already done
if (this._longPress) {
this._longPress = false;
Expand Down Expand Up @@ -504,6 +516,139 @@ var KeypadManager = {
}
},

/**
* Returns true if the number is a speed dial code as described in
* 3GPP TS 22.030 6.6.4. Speed dial codes are in the N(N)(N)# format.
*/
_isSpeedDialNumber: function(number) {
return !!number.match(/^[0-9][0-9]{0,2}\#$/);
},

/**
* Returns the telephony number corresponding to the specified index. Speed
* dial numbers are retrieved from the SIM contacts list and not from the
* regular contacts.
*
* @param {Integer} index The index of the speed dial number.
* @returns {Promise} A promise that resolves to the corresponding number.
*/
_getSpeedDialNumber: function(index) {
var self = this;
var cardIndex;

index--; // Speed dial indexes are 1-based

return new Promise(function(resolve, reject) {
LazyLoader.load(['/shared/js/sim_settings_helper.js'], function() {
SimSettingsHelper.getCardIndexFrom('outgoingCall',
function(defaultCardIndex) {
if (defaultCardIndex == SimSettingsHelper.ALWAYS_ASK_OPTION_VALUE) {
LazyLoader.load(['/shared/js/component_utils.js',
'/shared/elements/gaia_sim_picker/script.js'],
function() {
var simPicker = document.getElementById('sim-picker');
simPicker.getOrPick(defaultCardIndex, null,
function(pickedCardIndex) {
cardIndex = pickedCardIndex;
resolve();
});
});
} else {
cardIndex = defaultCardIndex;
resolve();
}
});
});
}).then(function() {
return self._getSimContactsList(cardIndex).then(
function(simContactsList) {
if ((index >= 0) && (index < simContactsList.length)) {
return simContactsList[index].number;
} else {
return Promise.reject();
}
});
});
},

/**
* Creates an array of contacts populated using the ADN contacts retrieved
* from a SIM card. Every contact will contain only the ID and first
* telephone number and the array will be sorted by ID. This array is then
* suitable to be used to pick speed dial numbers.
*
* @param {Array} contacts An array of mozContact elements.
* @returns {Array} An array of telephone numbers / ID couples sorted by ID.
*/
_createSimContactList: function(contacts) {
var numbers = new Array(contacts.length);

for (var i = 0; i < contacts.length; i++) {
numbers[i] = {
id: contacts[i].id,
number: contacts[i].tel[0].value,
};
}

numbers.sort(function(a, b) {
if (a.id.length == b.id.length) {
return (a.id > b.id) ? 1 : 0;
} else {
return (a.id.length > b.id.length) ? 1 : 0;
}
});

return numbers;
},

/**
* Gets the SIM contacts list for the specified SIM card.
*
* @param {Integer} cardIndex The SIM card index.
* @returns {Promise} A promise that is resolved with the contacts list.
*/
_getSimContactsList: function(cardIndex) {
var self = this;
var canceled = false;

return new Promise(function(resolve, reject) {
LazyLoader.load(['/shared/style/confirm.css',
'/shared/js/confirm.js',
document.getElementById('confirmation-message')],
function() {
var iccId = navigator.mozIccManager.iccIds[cardIndex];
var icc = navigator.mozIccManager.getIccById(iccId);
var req = icc.readContacts('adn');

req.onsuccess = function(event) {
var adnContacts = event.target.result;
var contacts = self._createSimContactList(adnContacts);

if (!canceled) {
ConfirmDialog.hide();
}

resolve(contacts);
};
req.onerror = function(error) {
console.error('Could not retrieve the ADN contacts from SIM card ' +
cardIndex + ', got error ' + error.name);
reject();
};

ConfirmDialog.show('loadingContacts', null, {
title: 'cancel',
callback: function() {
canceled = true;
ConfirmDialog.hide();
reject();
}
});
}
);
});
},

sanitizePhoneNumber: function(number) {
return number.replace(/\s+/g, '');
},
Expand Down

0 comments on commit 67b4246

Please sign in to comment.