VulpesOS/assets/webapps/communications.gaiamobile.org/dialer/js/telephony_helper.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

225 lines
6.8 KiB
JavaScript

'use strict';
/* global LazyLoader, ConfirmDialog, MmiManager, TelephonyCall,
TelephonyMessages */
/* exported TelephonyHelper */
var TelephonyHelper = (function() {
// DTMF control digit separator length (ms) as defined in GSM ETSI GSM 02.07
const DTMF_SEPARATOR_PAUSE_DURATION = 3000;
var confirmLoaded = false;
var loadTelephonyMessages = function(callback) {
LazyLoader.load(['/shared/js/dialer/telephony_messages.js'], callback);
};
var call = function t_call(number, cardIndex, oncall, onconnected,
ondisconnected) {
var sanitizedNumber = number.replace(/(\s|-|\.|\(|\))/g, '');
if (!isValid(sanitizedNumber)) {
loadTelephonyMessages(function() {
TelephonyMessages.displayMessage('BadNumber');
});
return Promise.reject();
}
var conn = navigator.mozMobileConnections &&
navigator.mozMobileConnections[cardIndex];
if (!conn || !conn.voice) {
// No voice connection, the call won't make it
loadTelephonyMessages(function() {
TelephonyMessages.displayMessage('NoNetwork');
});
return Promise.reject();
}
return startDial(
cardIndex, conn, sanitizedNumber, oncall, onconnected, ondisconnected
);
};
function getNumberAsDtmfToneGroups(number) {
return number.split(',');
}
function playDtmfToneGroups(dtmfToneGroups, cardIndex) {
var length;
// Remove the dialed number from the beginning of the array.
dtmfToneGroups = dtmfToneGroups.slice(1);
length = dtmfToneGroups.length;
// Remove the latest entries from dtmfToneGroups corresponding to ','
// characters not to play those pauses.
var lastCommaIndex = length - 1;
while (dtmfToneGroups[lastCommaIndex] === '') {
lastCommaIndex--;
}
dtmfToneGroups = dtmfToneGroups.slice(0, ++lastCommaIndex);
length = dtmfToneGroups.length;
var promise = Promise.resolve(),
counter = 0,
pauses;
// Traverse the dtmfToneGroups array.
while (counter < length) {
// Reset the number of pauses before each group of tones.
pauses = 1;
while (dtmfToneGroups[counter] === '') {
// Add a new pause for each '' in the dtmfToneGroups array.
pauses++;
counter++;
}
// Send a new group of tones as well as the pauses to play before it.
promise = promise.then(playDtmfToneGroup.bind(null,
dtmfToneGroups[counter++], pauses, cardIndex));
}
return promise;
}
function playDtmfToneGroup(toneGroup, pauses, cardIndex) {
return navigator.mozTelephony.sendTones(
toneGroup,
DTMF_SEPARATOR_PAUSE_DURATION * pauses,
null /* tone duration */,
cardIndex
);
}
function startDial(cardIndex, conn, sanitizedNumber, oncall, onconnected,
ondisconnected) {
var telephony = navigator.mozTelephony;
if (!telephony) {
return Promise.reject();
}
var emergencyOnly = conn.voice.emergencyCallsOnly;
var hasCard = (conn.iccId !== null);
var callPromise;
var baseNumber = getNumberAsDtmfToneGroups(sanitizedNumber)[0];
if (emergencyOnly) {
loadConfirm(function() {
ConfirmDialog.show(
'connectingEllipsis',
'',
{
title: 'emergencyDialogBtnOk',
callback: function() {
ConfirmDialog.hide();
}
}
);
document.addEventListener('visibilitychange', function hideDialog() {
document.removeEventListener('visibilitychange', hideDialog);
/* In tests this event can happen after the ConfirmDialog mock has
* been removed so check that it's still there. */
ConfirmDialog && ConfirmDialog.hide();
});
});
// If the mobileConnection has a sim card we let gecko take the
// default service, otherwise we force the first slot.
cardIndex = hasCard ? undefined : 0;
callPromise = telephony.dialEmergency(baseNumber);
} else {
callPromise = telephony.dial(baseNumber, cardIndex);
}
callPromise.then(function(obj) {
if (obj instanceof TelephonyCall) {
installHandlers(obj, sanitizedNumber, emergencyOnly, cardIndex,
oncall, onconnected, ondisconnected);
} else {
/* This is an MMICall object, manually invoke the handlers to provide
* feedback to the user, the rest of the UX will be dealt with by the
* MMI manager. */
oncall();
onconnected();
MmiManager.handleDialing(conn, sanitizedNumber, obj.result);
}
}, function(errorName) {
loadTelephonyMessages(function() {
var messageType = emergencyOnly ? TelephonyMessages.NO_NETWORK :
TelephonyMessages.REGULAR_CALL;
TelephonyMessages.handleError(
errorName, sanitizedNumber, messageType);
});
});
return callPromise;
}
function installHandlers(call, number, emergencyOnly, cardIndex,
oncall, onconnected, ondisconnected) {
if (oncall) {
oncall();
}
var dtmfToneGroups = getNumberAsDtmfToneGroups(number);
if (dtmfToneGroups.length > 1) {
call.addEventListener('connected', function dtmfToneGroupPlayer() {
call.removeEventListener('connected', dtmfToneGroupPlayer);
playDtmfToneGroups(dtmfToneGroups, cardIndex);
});
}
call.addEventListener('connected', onconnected);
call.addEventListener('disconnected', function handleDisconnect(evt) {
loadTelephonyMessages(function() {
TelephonyMessages.handleDisconnect(
evt.call.disconnectedReason, number, emergencyOnly
);
});
ondisconnected && ondisconnected();
});
}
var isValid = function t_isValid(sanitizedNumber) {
var validExp = /^(?!,)([0-9#+*,]){1,50}$/;
return validExp.test(sanitizedNumber);
};
var loadConfirm = function t_loadConfirm(cb) {
if (confirmLoaded) {
cb();
return;
}
var confMsg = document.getElementById('confirmation-message');
LazyLoader.load(['/shared/js/confirm.js', confMsg], function() {
confirmLoaded = true;
cb();
});
};
var getInUseSim = function t_getInUseSim() {
var telephony = navigator.mozTelephony;
if (telephony) {
var isInCall = !!telephony.calls.length;
var isInConference = !!telephony.conferenceGroup &&
!!telephony.conferenceGroup.calls.length;
if (isInCall || isInConference) {
return isInCall ?
navigator.mozTelephony.calls[0].serviceId :
navigator.mozTelephony.conferenceGroup.calls[0].serviceId;
}
}
return null;
};
window.TelephonyHelper = TelephonyHelper;
return {
call: call,
getInUseSim: getInUseSim
};
})();