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.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,14 @@
;this.asyncStorage=(function(){'use strict';var DBNAME='asyncStorage';var DBVERSION=1;var STORENAME='keyvaluepairs';var db=null;function withDatabase(f){if(db){f();}else{var openreq=indexedDB.open(DBNAME,DBVERSION);openreq.onerror=function withStoreOnError(){console.error('asyncStorage: can\'t open database:',openreq.error.name);};openreq.onupgradeneeded=function withStoreOnUpgradeNeeded(){openreq.result.createObjectStore(STORENAME);};openreq.onsuccess=function withStoreOnSuccess(){db=openreq.result;f();};}}
function withStore(type,callback,oncomplete){withDatabase(function(){var transaction=db.transaction(STORENAME,type);if(oncomplete){transaction.oncomplete=oncomplete;}
callback(transaction.objectStore(STORENAME));});}
function getItem(key,callback){var req;withStore('readonly',function getItemBody(store){req=store.get(key);req.onerror=function getItemOnError(){console.error('Error in asyncStorage.getItem(): ',req.error.name);};},function onComplete(){var value=req.result;if(value===undefined){value=null;}
callback(value);});}
function setItem(key,value,callback){withStore('readwrite',function setItemBody(store){var req=store.put(value,key);req.onerror=function setItemOnError(){console.error('Error in asyncStorage.setItem(): ',req.error.name);};},callback);}
function removeItem(key,callback){withStore('readwrite',function removeItemBody(store){var req=store.delete(key);req.onerror=function removeItemOnError(){console.error('Error in asyncStorage.removeItem(): ',req.error.name);};},callback);}
function clear(callback){withStore('readwrite',function clearBody(store){var req=store.clear();req.onerror=function clearOnError(){console.error('Error in asyncStorage.clear(): ',req.error.name);};},callback);}
function length(callback){var req;withStore('readonly',function lengthBody(store){req=store.count();req.onerror=function lengthOnError(){console.error('Error in asyncStorage.length(): ',req.error.name);};},function onComplete(){callback(req.result);});}
function key(n,callback){if(n<0){callback(null);return;}
var req;withStore('readonly',function keyBody(store){var advanced=false;req=store.openCursor();req.onsuccess=function keyOnSuccess(){var cursor=req.result;if(!cursor){return;}
if(n===0||advanced){return;}
advanced=true;cursor.advance(n);};req.onerror=function keyOnError(){console.error('Error in asyncStorage.key(): ',req.error.name);};},function onComplete(){var cursor=req.result;callback(cursor?cursor.key:null);});}
return{getItem:getItem,setItem:setItem,removeItem:removeItem,clear:clear,length:length,key:key};}());

View file

@ -0,0 +1,13 @@
;'use strict';var BluetoothHelper=function(){var profiles={'HFP':0x111E,'A2DP':0x110D};var _bluetooth=window.navigator.mozBluetooth;var _isReady=false;var _callbacks=[];var _adapter=null;var _oldAdapter=null;var _v2=true;var _ready=function(callback){if(!callback||!_bluetooth){return;}
if(_isReady){callback();}else{_callbacks.push(callback);}};var _handleRequest=function(request,callback,errorcb){request.onsuccess=function(){if(callback){callback(request.result);}};request.onerror=function(){console.log('Error handling bluetooth request');if(errorcb){errorcb();}};};var _processCallbacks=function(){if(_adapter){_isReady=true;_callbacks.forEach(function(callback){callback();});_callbacks=[];}else{console.log('BluetoothHelper(): connot get default adapter yet');}};var _fetchAdapterV2=function(){_bluetooth.onattributechanged=function onManagerAttributeChanged(evt){for(var i in evt.attrs){switch(evt.attrs[i]){case'defaultAdapter':console.log('defaultAdapter changed. address:',_bluetooth.defaultAdapter.address);_adapter=_bluetooth.defaultAdapter;_processCallbacks();break;default:break;}}};_adapter=_bluetooth.defaultAdapter;if(_adapter){_processCallbacks();}};var _fetchAdapter=function(){var req=_bluetooth.getDefaultAdapter();if(req){req.onsuccess=function(){if(_adapter){_oldAdapter=_adapter;}
_isReady=true;_adapter=req.result;if(_oldAdapter&&_oldAdapter.onpairedstatuschanged){_adapter.onpairedstatuschanged=_oldAdapter.onpairedstatuschanged;}
_callbacks.forEach(function(callback){callback();});_callbacks=[];};req.onerror=function(){console.log('BluetoothHelper(): connot get default adapter!!!');};}};var _getAdapter=function(){if(_v2){_fetchAdapterV2();}else{_fetchAdapter();}};var _resetAdapter=function(){if(_adapter){_oldAdapter=_adapter;}
_isReady=false;_adapter=null;};if(_bluetooth){if(typeof(_bluetooth.onattributechanged)==='undefined'){_v2=false;}
if(_v2){_bluetooth.onadapteradded=function onAdapterAdded(evt){_getAdapter();};}else{_bluetooth.addEventListener('enabled',_getAdapter);_bluetooth.addEventListener('adapteradded',_getAdapter);_bluetooth.addEventListener('disabled',_resetAdapter);}
_getAdapter();}
return{profiles:profiles,answerWaitingCall:function(){_ready(function(){_adapter.answerWaitingCall();});},ignoreWaitingCall:function(){_ready(function(){_adapter.ignoreWaitingCall();});},toggleCalls:function(){_ready(function(){_adapter.toggleCalls();});},getConnectedDevicesByProfile:function(profileID,cb){_ready(function(){_handleRequest(_adapter.getConnectedDevices(profileID),cb);});},connectSco:function(cb){_ready(function(){_handleRequest(_adapter.connectSco(),cb);});},disconnectSco:function(cb){_ready(function(){_handleRequest(_adapter.disconnectSco(),cb);});},getPairedDevices:function(cb){_ready(function(){_handleRequest(_adapter.getPairedDevices(),cb);});},getAddress:function(cb){if(_v2){console.log('getAddress function is deprecated');return;}
_ready(function(){var address=_adapter.address;cb(address);});},setPairingConfirmation:function(address,confirmed){if(_v2){console.log('setPairingConfirmation API is deprecated');return;}
_ready(function(){_adapter.setPairingConfirmation(address,confirmed);});},setPinCode:function(address,pincode){if(_v2){console.log('setPairingConfirmation API is deprecated');return;}
_ready(function(){_adapter.setPinCode(address,pincode);});},setPasskey:function(address,key){if(_v2){console.log('setPairingConfirmation API is deprecated');return;}
_ready(function(){_adapter.setPasskey(address,key);});},isScoConnected:function(cb,errorcb){_ready(function(){_handleRequest(_adapter.isScoConnected(),cb,errorcb);});},sendMediaMetaData:function(metadata,cb,errorcb){_ready(function(){_handleRequest(_adapter.sendMediaMetaData(metadata),cb,errorcb);});},sendMediaPlayStatus:function(metadata,cb,errorcb){_ready(function(){_handleRequest(_adapter.sendMediaPlayStatus(metadata),cb,errorcb);});},set onhfpstatuschanged(callback){_ready(function(){_adapter.onhfpstatuschanged=callback;});},set onscostatuschanged(callback){_ready(function(){_adapter.onscostatuschanged=callback;});},set ona2dpstatuschanged(callback){_ready(function(){_adapter.ona2dpstatuschanged=callback;});},set onrequestmediaplaystatus(callback){_ready(function(){_adapter.onrequestmediaplaystatus=callback;});},set onpairedstatuschanged(callback){if(_v2){console.log('onpairedstatuschanged API is deprecated');return;}
_ready(function(){_adapter.onpairedstatuschanged=callback;});},v2:_v2,enable:function(){if(_v2){_ready(function(){_adapter.enable();});}else{console.log('enable is not support in v1 API!');}},disable:function(){if(_v2){_ready(function(){_adapter.disable();});}else{console.log('disable is not support in v1 API!');}}};};

View file

@ -0,0 +1,13 @@
;(function(exports){'use strict';function getThumbnail(contact){return getOnePhoto(contact,'begin');}
function getFullResolution(contact){return getOnePhoto(contact,'end');}
function getOnePhoto(contact,position){if(!contact||!contact.photo||!contact.photo.length){return null;}
if(contact.photo.length===1){return contact.photo[0];}
var photos=contact.photo;var category=contact.category;if(Array.isArray(category)&&category.indexOf('fb_linked')!==-1){if(photos.length>=4){return photos[(position=='begin')?1:0];}
return photos[0];}
photos=photosBySize(contact);var index=(position=='begin')?0:photos.length-1;return photos[index];}
function photosBySize(contact){var photos=contact.photo.slice(0);photos.sort(function(p1,p2){if(size(p1)<size(p2)){return-1;}
if(size(p1)>size(p2)){return 1;}
return 0;});return photos;}
function size(photo){if(typeof photo=='string'){return photo.length;}
return photo.size;}
exports.ContactPhotoHelper={getThumbnail:getThumbnail,getFullResolution:getFullResolution};})(window);

View file

@ -0,0 +1,3 @@
;(function(){'use strict';if(window.navigator.mozHour12||window.navigator.hour12){return;}
window.navigator.mozHour12=undefined;var _setMozHour12=function(result){if(result===null){result=undefined;}
if(window.navigator.mozHour12!==result){window.navigator.mozHour12=result;window.dispatchEvent(new CustomEvent('timeformatchange'));}};var _hour12Handler=function(event){_setMozHour12(event.settingValue);};var _kLocaleTime='locale.hour12';var req=window.navigator.mozSettings.createLock().get(_kLocaleTime);req.onsuccess=function(){_setMozHour12(req.result[_kLocaleTime]);};window.navigator.mozSettings.addObserver(_kLocaleTime,_hour12Handler);})();

View file

@ -0,0 +1,15 @@
;'use strict';var Contacts={_FB_FILES:['/shared/js/fb/fb_request.js','/shared/js/fb/fb_data_reader.js','/shared/js/fb/fb_reader_utils.js'],getRevision:function getRevision(callback){var mozContacts=navigator.mozContacts;if(!mozContacts){callback(null);return;}
var req=mozContacts.getRevision();req.onsuccess=function onsuccess(event){callback(event.target.result);};req.onerror=function onerror(event){console.log('Error '+event.target.error);callback(null);};},findByNumber:function findByNumber(number,callback){LazyLoader.load(this._FB_FILES,this._findByNumber.bind(this,number,callback));},_findByNumber:function _findByNumber(number,callback){if(!number){callback(null);return;}
var options;var variants;if(number.length<7){variants=[number];options={filterBy:['tel'],filterOp:'equals',filterValue:number};}else{variants=SimplePhoneMatcher.generateVariants(number);var sanitizedNumber=SimplePhoneMatcher.sanitizedNumber(number);options={filterBy:['tel'],filterOp:'match',filterValue:sanitizedNumber};}
var mozContacts=navigator.mozContacts;if(!mozContacts){callback(null);return;}
var request=mozContacts.find(options);request.onsuccess=function findCallback(){var contacts=request.result;if(contacts.length===0){fb.getContactByNumber(number,function fb_ready(finalContact){var objMatching=null;if(finalContact){objMatching={value:number,type:'personal',carrier:null};}
callback(finalContact,objMatching);},function fb_err(err){callback(null);});return;}
var matches=contacts.map(function getTels(contact){return contact.tel.map(function getNumber(tel){return tel.value;});});var matchResult=SimplePhoneMatcher.bestMatch(variants,matches);var contact=contacts[matchResult.bestMatchIndex];var contactsWithSameNumber;if(contacts.length>1){contactsWithSameNumber=contacts.length-1;}
var matchingTel=contact.tel[matchResult.localIndex];if(fb.isFbLinked(contact)){var req=fb.getData(contact);req.onsuccess=function(){callback(req.result,matchingTel,contactsWithSameNumber);};req.onerror=function(){window.console.error('Error while getting FB Data');callback(contact,matchingTel,contactsWithSameNumber);};}
else{callback(contact,matchingTel,contactsWithSameNumber);}};request.onerror=function findError(){callback(null);};},_mergeOneFbContact:function _mergeOneFbContact(contacts,index){return new Promise(function(resolve,reject){var fbReq=fb.getData(contacts[index]);fbReq.onsuccess=function(){var originalTel=contacts[index].tel;contacts[index]=fbReq.result;contacts[index].tel=originalTel;resolve();};fbReq.onerror=function(){console.error('Could not merge Facebook data for',contacts[index].id);reject();};});},_mergeFbContacts:function _mergeFbContacts(contacts,callback){if(!callback||!(callback instanceof Function)){return;}
if(!contacts){callback(null);}
LazyLoader.load(this._FB_FILES,function(){var pending=contacts.length;var onContactMerged=function(){if(--pending===0){callback(contacts);}};for(var i=0,length=contacts.length;i<length;i++){if(fb.isFbContact(contacts[i])){this._mergeOneFbContact(contacts,i).then(onContactMerged,onContactMerged);}else{onContactMerged();}}}.bind(this));},_findContacts:function _findContacts(options,callback){if(!callback||!(callback instanceof Function)){return;}
if(!navigator.mozContacts||!options){callback(null);return;}
var self=this;var req=navigator.mozContacts.find(options);req.onsuccess=function onsuccess(){var contacts=req.result;if(!contacts.length){callback(null);return;}
self._mergeFbContacts(contacts,callback);};req.onerror=function onerror(){console.error('Contact finding error. Error: '+req.errorCode);callback(null);};},findListByNumber:function findListByNumber(number,limit,callback){var self=this;asyncStorage.getItem('order.lastname',function(value){var sortKey=value?'familyName':'givenName';var options={filterBy:['tel'],filterOp:'contains',filterValue:number,sortBy:sortKey,sortOrder:'ascending',filterLimit:limit};self._findContacts(options,callback);});},getLength:function getLength(prop){if(!prop||!prop.length){return 0;}
return prop.length;},sendEmailOrPick:function sendEmailOrPick(address){try{new MozActivity({name:'new',data:{type:'mail',URI:'mailto:'+address}});}catch(e){console.error('WebActivities unavailable? : '+e);}}};

View file

@ -0,0 +1,2 @@
;'use strict';function DtmfTone(tone,short,serviceId){this.tone=tone;this.short=short;this.serviceId=serviceId;this.timer=0;}
DtmfTone.kShortToneLength=120;DtmfTone.prototype={play:function dt_play(){clearTimeout(this.timer);navigator.mozTelephony.stopTone(this.serviceId);navigator.mozTelephony.startTone(this.tone,this.serviceId);if(this.short){this.timer=window.setTimeout(function dt_stopTone(serviceId){navigator.mozTelephony.stopTone(serviceId);},DtmfTone.kShortToneLength,this.serviceId);}},stop:function dt_stop(){clearTimeout(this.timer);navigator.mozTelephony.stopTone(this.serviceId);}};

View file

@ -0,0 +1,17 @@
;'use strict';var FontSizeManager=(function fontSizeManager(){var DIAL_PAD=0,SINGLE_CALL=1,CALL_WAITING=2,STATUS_BAR=3,SECOND_INCOMING_CALL=4;var _sizes={};_sizes[DIAL_PAD]={min:2.6,max:4.1};_sizes[SINGLE_CALL]={min:2.3,max:3.4,line:3.4};_sizes[CALL_WAITING]={min:2.3,max:2.5,line:1.3};_sizes[STATUS_BAR]={min:1.7,max:1.7};_sizes[SECOND_INCOMING_CALL]={min:2.3,max:2.5,line:3.7};var _defaultFontSize;function _getRootFontSize(){_defaultFontSize=_defaultFontSize||parseInt(window.getComputedStyle(document.body,null).getPropertyValue('font-size'));return _defaultFontSize;}
function _getMinFontSize(scenario){return Math.round(_sizes[scenario].min*_getRootFontSize());}
function _getMaxFontSize(scenario){return Math.round(_sizes[scenario].max*_getRootFontSize());}
function _getAllowedFontSizes(scenario){var minFontSize=_getMinFontSize(scenario);var maxFontSize=_getMaxFontSize(scenario);var allowedSizes=[];for(var size=minFontSize;size<=maxFontSize;size+=4){allowedSizes.push(size);}
if(allowedSizes.indexOf(maxFontSize)===-1){allowedSizes.push(maxFontSize);}
return allowedSizes;}
function adaptToSpace(scenario,view,forceMaxFontSize,ellipsisSide){var computedStyle=window.getComputedStyle(view);if((!view.value&&!view.textContent)||!computedStyle){return;}
var viewWidth=view.getBoundingClientRect().width;var viewFont=computedStyle.fontFamily;var allowedSizes;if(forceMaxFontSize){allowedSizes=[_getMaxFontSize(scenario)];}else{allowedSizes=_getAllowedFontSizes(scenario);}
var infos=FontSizeUtils.getMaxFontSizeInfo(view.value||view.textContent,allowedSizes,viewFont,viewWidth);var newFontSize=infos.fontSize;if(view.style.fontSize!==newFontSize){view.style.fontSize=newFontSize+'px';}
if(infos&&infos.overflow){var overflowCount=FontSizeUtils.getOverflowCount(view.value||view.textContent,newFontSize,viewFont,viewWidth);overflowCount+=2;_useEllipsis(view,overflowCount,ellipsisSide);view.dataset.ellipsedCharacters=overflowCount;}else{view.dataset.ellipsedCharacters=0;}}
function _useEllipsis(view,overflowCount,ellipsisSide){var side=ellipsisSide||'begin';var localizedSide=(side==='begin'?'left':'right');var value=view.value||view.textContent;if(localizedSide=='left'){value='\u2026'+value.substr(-value.length+overflowCount);}else if(localizedSide=='right'){value=value.substr(0,value.length-overflowCount)+'\u2026';}
if(view.value){view.value=value;}else{var el=view.querySelector('bdi')||view;el.textContent=value;}}
function ensureFixedBaseline(scenario,view){var initialLineHeight=_sizes[scenario].line;if(!initialLineHeight){return;}
var maxFontSize=_getMaxFontSize(scenario);var fontSize=parseInt(window.getComputedStyle(view).fontSize,10);view.style.lineHeight=initialLineHeight*_getRootFontSize()+
(maxFontSize-fontSize)/2+'px';}
function resetFixedBaseline(view){view.style.removeProperty('line-height');}
return{DIAL_PAD:DIAL_PAD,SINGLE_CALL:SINGLE_CALL,CALL_WAITING:CALL_WAITING,STATUS_BAR:STATUS_BAR,SECOND_INCOMING_CALL:SECOND_INCOMING_CALL,adaptToSpace:adaptToSpace,ensureFixedBaseline:ensureFixedBaseline,resetFixedBaseline:resetFixedBaseline};})();

View file

@ -0,0 +1,47 @@
;'use strict';var gTonesFrequencies={'1':[697,1209],'2':[697,1336],'3':[697,1477],'4':[770,1209],'5':[770,1336],'6':[770,1477],'7':[852,1209],'8':[852,1336],'9':[852,1477],'*':[941,1209],'0':[941,1336],'#':[941,1477]};var KeypadManager={kMaxDigits:50,_phoneNumber:'',_onCall:false,_keypadSoundIsEnabled:false,_shortTone:false,_vibrationEnabled:false,kVibrationDuration:50,_insertPosition:null,onValueChanged:null,get phoneNumberView(){delete this.phoneNumberView;this.phoneNumberView=document.getElementById('phone-number-view');return this.phoneNumberView;},get phoneNumberViewContainer(){delete this.phoneNumberViewContainer;this.phoneNumberViewContainer=document.getElementById('phone-number-view-container');return this.phoneNumberViewContainer;},get keypad(){delete this.keypad;this.keypad=document.getElementById('keypad');return this.keypad;},get callBar(){delete this.callBar;this.callBar=document.getElementById('keypad-callbar');return this.callBar;},get hideBar(){delete this.hideBar;this.hideBar=document.getElementById('keypad-hidebar');return this.hideBar;},get callBarAddContact(){delete this.callBarAddContact;this.callBarAddContact=document.getElementById('keypad-callbar-add-contact');return this.callBarAddContact;},get callBarCallAction(){delete this.callBarCallAction;this.callBarCallAction=document.getElementById('keypad-callbar-call-action');return this.callBarCallAction;},get callBarCancelAction(){delete this.callBarCancelAction;this.callBarCancelAction=document.getElementById('keypad-callbar-cancel');return this.callBarCancelAction;},get deleteButton(){delete this.deleteButton;this.deleteButton=document.getElementById('keypad-delete');return this.deleteButton;},get hideBarHangUpAction(){delete this.hideBarHangUpAction;this.hideBarHangUpAction=document.getElementById('keypad-hidebar-hang-up-action-wrapper');return this.hideBarHangUpAction;},get hideBarHideAction(){delete this.hideBarHideAction;this.hideBarHideAction=document.getElementById('keypad-hidebar-hide-keypad-action');return this.hideBarHideAction;},multiSimActionButton:null,init:function kh_init(oncall){this._onCall=!!oncall;this._lastPressedKey=null;this.phoneNumberView.value='';this.phoneNumberView.addEventListener('click',this._updateInsertPosition.bind(this));this._phoneNumber='';var keyHandler=this.keyHandler.bind(this);this.keypad.addEventListener('contextmenu',keyHandler);this.keypad.addEventListener('touchstart',keyHandler,true);this.keypad.addEventListener('touchmove',keyHandler,true);this.keypad.addEventListener('touchend',keyHandler,true);this.keypad.addEventListener('touchcancel',keyHandler,true);this.deleteButton.addEventListener('touchstart',keyHandler);this.deleteButton.addEventListener('touchend',keyHandler);if(this.callBarAddContact){this.callBarAddContact.addEventListener('click',this.addContact.bind(this));}
if(this.callBarCallAction){if(typeof MultiSimActionButton!=='undefined'){this.multiSimActionButton=new MultiSimActionButton(this.callBarCallAction,CallHandler.call,'ril.telephony.defaultServiceId',this.phoneNumber.bind(this));}
this.callBarCallAction.addEventListener('click',this.fetchLastCalled.bind(this));}
if(this.callBarCancelAction){this.callBarCancelAction.addEventListener('click',function(){window.parent.LockScreen.switchPanel();});}
if(this.hideBarHideAction){this.hideBarHideAction.addEventListener('click',this.callbarBackAction);}
if(this.hideBarHangUpAction){this.hideBarHangUpAction.addEventListener('click',this.hangUpCallFromKeypad);}
TonePlayer.init('system');this.render();LazyLoader.load(['/shared/style/action_menu.css','/dialer/js/suggestion_bar.js']);this._observePreferences();},render:function hk_render(layoutType){if(layoutType=='oncall'){if(CallsHandler.activeCall){var activeCall=CallsHandler.activeCall.call;this._phoneNumber=activeCall.id.number;}
this._isKeypadClicked=false;this.phoneNumberViewContainer.classList.add('keypad-visible');if(this.callBar){this.callBar.classList.add('hide');}
if(this.hideBar){this.hideBar.classList.remove('hide');}
this.deleteButton.classList.add('hide');}else{this.phoneNumberViewContainer.classList.remove('keypad-visible');if(this.callBar){this.callBar.classList.remove('hide');}
if(this.hideBar){this.hideBar.classList.add('hide');}
this.deleteButton.classList.remove('hide');}},phoneNumber:function hk_phoneNumber(){return this._phoneNumber;},fetchLastCalled:function hk_fetchLastCalled(){if(this._phoneNumber!==''){return;}
var self=this;CallLogDBManager.getGroupAtPosition(1,'lastEntryDate',true,'dialing',function hk_ggap_callback(result){if(result&&(typeof result==='object')&&result.number){self.updatePhoneNumber(result.number);}});},addContact:function hk_addContact(event){var number=this._phoneNumber;if(!number){return;}
LazyLoader.load(['/dialer/js/add_contact_menu.js'],function(){AddContactMenu.show(number);});},callbarBackAction:function hk_callbarBackAction(event){CallScreen.hideKeypad();},hangUpCallFromKeypad:function hk_hangUpCallFromKeypad(event){CallScreen.hideKeypad();CallsHandler.end();},_lastPressedKey:null,_dtmfTone:null,_playDtmfTone:function kh_playDtmfTone(key){var serviceId=0;if(!this._onCall){return;}
if(CallsHandler.activeCall){serviceId=CallsHandler.activeCall.call.serviceId;}else{serviceId=navigator.mozTelephony.active.calls[0].serviceId;}
if(this._dtmfTone){this._dtmfTone.stop();this._dtmfTone=null;}
this._dtmfTone=new DtmfTone(key,this._shortTone,serviceId);this._dtmfTone.play();},_stopDtmfTone:function kh_stopDtmfTone(){if(!this._dtmfTone){return;}
this._dtmfTone.stop();this._dtmfTone=null;},_touchStart:function kh_touchStart(key){this._longPress=false;this._lastPressedKey=key;if(key!=='delete'&&!this._onCall&&(this._phoneNumber.length>=this.kMaxDigits)){return;}
if(key!='delete'){if(this._keypadSoundIsEnabled){TonePlayer.start(gTonesFrequencies[key],!this._onCall||this._shortTone);}
if(this._vibrationEnabled){navigator.vibrate(this.kVibrationDuration);}
this._playDtmfTone(key);}
if(((key=='0'||key=='*')&&!this._onCall)||key=='delete'){this._holdTimer=setTimeout(function(self){self.restoreCaretPosition();if(key=='delete'){self._clearPhoneNumber();}else if(key==='0'){self._replaceLastKey('+');}else if(key==='*'){var isAtTheEnd=self._insertPosition===null;var isFirst=self._insertPosition===1||(isAtTheEnd&&self._phoneNumber.length===1);if(!isFirst){self._replaceLastKey(',');}else{self._deleteAtInsertPosition();}}
self._longPress=true;self._updatePhoneNumberView('begin',false);},400,this);}
if(key==='1'&&this._phoneNumber===''){this._holdTimer=setTimeout(function vm_call(self){self._longPress=true;self._callVoicemail();self._phoneNumber='';self._updatePhoneNumberView('begin',false);},400,this);}
if(key=='delete'){this._deleteAtInsertPosition();}else if(this.phoneNumberViewContainer.classList.contains('keypad-visible')){if(!this._isKeypadClicked){this._isKeypadClicked=true;this._phoneNumber=key;this.replaceAdditionalContactInfo('');}else{this._insertAtCaret(key);}}else{this._insertAtCaret(key);}
if(key==='#'&&!this._onCall){if(this._phoneNumber==='*#06#'){this.multiSimActionButton.performAction();return;}else if(this._isSpeedDialNumber(this._phoneNumber)){this._handleSpeedDial(this._phoneNumber.slice(0,-1));return;}}
setTimeout(function(self){self._updatePhoneNumberView('begin',false);},0,this);},_touchMove:function kh_touchMove(touch){var target=document.elementFromPoint(touch.pageX,touch.pageY);var key=(target&&target.dataset)?target.dataset.value:null;if(key!==this._lastPressedKey||key==='delete'){this._stopDtmfTone();}},_touchEnd:function kh_touchEnd(key){this._lastPressedKey=null;if(key!=='delete'){this._stopDtmfTone();}
if(this._keypadSoundIsEnabled){TonePlayer.stop();}
this.restoreCaretPosition();if(this._longPress){this._longPress=false;this._holdTimer=null;return;}
if(this._holdTimer){clearTimeout(this._holdTimer);}},keyHandler:function kh_keyHandler(event){event.preventDefault();if(event.type=='contextmenu'){return;}
var key=event.target.dataset.value;if(!key){return;}
event.stopPropagation();switch(event.type){case'touchstart':if(this._lastPressedKey){return;}
event.target.classList.add('active');this._touchStart(key);break;case'touchmove':this._touchMove(event.touches[0]);break;case'touchend':case'touchcancel':if(key!==this._lastPressedKey){return;}
event.target.classList.remove('active');this._touchEnd(key);break;}},_isSpeedDialNumber:function(number){return!!number.match(/^[0-9][0-9]{0,2}\#$/);},_getSpeedDialNumber:function(index){var self=this;var cardIndex;index--;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('noContactsWereFound');}});});},_handleSpeedDial:function(index){var self=this;this.updatePhoneNumber('','begin',false);this._getSpeedDialNumber(+index).then(function(number){self.updatePhoneNumber(number,'begin',false);},function(error){if(error){ConfirmDialog.show(error,null,{title:'noContactsFoundDialogOk',callback:ConfirmDialog.hide});}});},_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;},_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);if(!icc){reject('noSimCardToLoadContactsFrom');return;}
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('noContactsWereFound');};ConfirmDialog.show('loadingSimContacts',null,{title:'cancel',callback:function(){canceled=true;ConfirmDialog.hide();reject();}});});});},sanitizePhoneNumber:function(number){return number.replace(/\s+/g,'');},updatePhoneNumber:function kh_updatePhoneNumber(number,ellipsisSide,forceMaxFontSize){number=this.sanitizePhoneNumber(number);this._phoneNumber=number;this._updatePhoneNumberView(ellipsisSide,forceMaxFontSize);},press:function(value){this._playDtmfTone(value);TonePlayer.start(gTonesFrequencies[value],true);setTimeout((function nextTick(){TonePlayer.stop();this._stopDtmfTone();}).bind(this));},_updatePhoneNumberView:function kh_updatePhoneNumberview(ellipsisSide,forceMaxFontSize){var phoneNumber=this._phoneNumber;if(this._onCall){this.renderPhoneNumber(phoneNumber,ellipsisSide);}else{var visibility;if(phoneNumber.length>0){visibility='visible';this.callBarAddContact.removeAttribute('disabled');}else{visibility='hidden';this.callBarAddContact.setAttribute('disabled','disabled');}
this.deleteButton.style.visibility=visibility;this.phoneNumberView.blur();this.phoneNumberView.value=phoneNumber;FontSizeManager.adaptToSpace(FontSizeManager.DIAL_PAD,this.phoneNumberView,forceMaxFontSize,ellipsisSide);}
if(this.onValueChanged){this.onValueChanged(this._phoneNumber);}},renderPhoneNumber:function kh_replacePhoneNumber(phoneNumber,ellipsisSide){if(this._onCall&&CallsHandler.activeCall){CallsHandler.activeCall.renderPhoneNumber({raw:phoneNumber},ellipsisSide);}},restorePhoneNumber:function kh_restorePhoneNumber(){if(this._onCall&&CallsHandler.activeCall){CallsHandler.activeCall.restorePhoneNumber();}},replaceAdditionalContactInfo:function kh_replaceAdditionalContactInfo(additionalContactInfo){var call=CallsHandler.activeCall;if(this._onCall&&call){call.replaceAdditionalContactInfo(additionalContactInfo);}},restoreAdditionalContactInfo:function kh_restoreAdditionalContactInfo(){if(this._onCall&&CallsHandler.activeCall){CallsHandler.activeCall.restoreAdditionalContactInfo();}},_callVoicemail:function(){if(navigator.mozIccManager.iccIds.length<=1){this._callVoicemailForSim(0);return;}
var self=this;var key='ril.voicemail.defaultServiceId';var req=navigator.mozSettings.createLock().get(key);req.onsuccess=function(){LazyLoader.load(['/shared/js/component_utils.js','/shared/elements/gaia_sim_picker/script.js'],function(){var simPicker=document.getElementById('sim-picker');navigator.mozL10n.formatValue('voiceMail').then(string=>{simPicker.getOrPick(req.result[key],string,self._callVoicemailForSim.bind(self));});});};},_callVoicemailForSim:function(cardIndex){var settings=navigator.mozSettings;if(!settings){return;}
var transaction=settings.createLock();var request=transaction.get('ril.iccInfo.mbdn');request.onsuccess=(function(){var numbers=request.result['ril.iccInfo.mbdn'];var number;if(typeof numbers=='string'){number=numbers;}else{number=numbers&&numbers[cardIndex];}
var voicemail=navigator.mozVoicemail;if(!number&&voicemail){number=voicemail.getNumber(cardIndex);}
if(number){CallHandler.call(number,cardIndex);}else{this._showNoVoicemailDialog();}}).bind(this);request.onerror=function(){};},_showNoVoicemailDialog:function hk_showNoVoicemailDialog(){var voicemailDialog={title:'voicemailNoNumberTitle',text:'voicemailNoNumberText',confirm:{title:'voicemailNoNumberSettings',recommend:true,callback:this.showVoicemailSettings},cancel:{title:'voicemailNoNumberCancel',callback:this._hideNoVoicemailDialog}};LazyLoader.load(['/shared/js/custom_dialog.js'],function(){CustomDialog.show(voicemailDialog.title,voicemailDialog.text,voicemailDialog.cancel,voicemailDialog.confirm);});},_hideNoVoicemailDialog:function kh_hideNoVoicemailDialog(){CustomDialog.hide();},showVoicemailSettings:function kh_showVoicemailSettings(){var activity=new window.MozActivity({name:'configure',data:{target:'device',section:'call'}});activity.onerror=function(){console.warn('Configure activity error:',activity.error.name);};},_observePreferences:function kh_observePreferences(){var self=this;LazyLoader.load('/shared/js/settings_listener.js',function(){SettingsListener.observe('phone.ring.keypad',false,function(value){self._keypadSoundIsEnabled=!!value;});SettingsListener.observe('phone.dtmf.type','long',function(value){self._shortTone=(value==='short');});SettingsListener.observe('keyboard.vibration',false,function(value){self._vibrationEnabled=!!value;});});},_updateInsertPosition:function kh_updateInsertPosition(){this._insertPosition=this._realStartPosition();},_replaceLastKey:function kh_replaceLastKey(newKey){this._deleteAtInsertPosition();this.restoreCaretPosition();this._insertAtCaret(newKey);},_insertAtCaret:function kh_insertAtCaret(key){if(this._insertPosition===null){this._phoneNumber+=key;}else{var start=this._realStartPosition();var end=this._realEndPosition();this._phoneNumber=this._phoneNumber.substring(0,start)+key+
this._phoneNumber.substring(end);this._insertPosition=start+1;}},_deleteAtInsertPosition:function kh_deleteAtInsertPosition(){if(this._insertPosition===null){this._phoneNumber=this._phoneNumber.slice(0,-1);}else{var start=this._realStartPosition();var end=this._realEndPosition();if(start>0&&start===end){start=end-1;}
this._phoneNumber=this._phoneNumber.substring(0,start)+
this._phoneNumber.substring(end);this._insertPosition=this._phoneNumber?start:null;}},_clearPhoneNumber:function kh_clearPhoneNumber(){if(this._insertPosition===null){this._phoneNumber='';}else{var start=this._realStartPosition();this._phoneNumber=this._phoneNumber.substring(start);this._insertPosition=this._phoneNumber?0:null;}},restoreCaretPosition:function kh_restoreCaretPosition(){if(this._insertPosition!==null){var caretPosition=this._caretPosition(this._insertPosition);this.phoneNumberView.selectionStart=caretPosition;this.phoneNumberView.selectionEnd=caretPosition;this.phoneNumberView.focus();}else{this.phoneNumberView.blur();}},_realStartPosition:function kh_realStartPosition(){var start=this.phoneNumberView.selectionStart;return this._realPosition(this.phoneNumberView,start);},_realEndPosition:function kh_realEndPosition(){var end=this.phoneNumberView.selectionEnd;return this._realPosition(this.phoneNumberView,end);},_caretPosition:function kh_caretPosition(realPosition){return realPosition-this._ellipsisOffset(this.phoneNumberView);},_realPosition:function kh_realPosition(input,position){return position+this._ellipsisOffset(this.phoneNumberView);},_ellipsisOffset:function kh_ellipsisOffset(input){var ellipsedCharacters=+input.dataset.ellipsedCharacters;return ellipsedCharacters?(ellipsedCharacters-1):0;}};

View file

@ -0,0 +1,9 @@
;'use strict';const kMasterVolume=0.5;const kToneVolume=0.7;const kShortPressDuration=0.15;const kAttackDuration=0.025;const kDecayDuration=0.025;const kReleaseDuration=0.05;var TonePlayer={_audioContext:null,_channel:null,_gainNode:null,_playingNodes:[],_maybeTrashAudio:null,_initialized:false,init:function tp_init(channel){var telephony=navigator.mozTelephony;this._reset();this._channel=channel;this._maybeTrashAudio=(function tp_maybeTrashAudio(){var callIsActive=telephony&&(telephony.calls.length||telephony.conferenceGroup.calls.length);if(document.hidden&&!((this._channel==='telephony')&&callIsActive)){this._trashAudio();}}).bind(this);window.addEventListener('visibilitychange',this._maybeTrashAudio);telephony&&telephony.addEventListener('callschanged',this._maybeTrashAudio);this._initialized=true;},teardown:function tp_teardown(){var telephony=navigator.mozTelephony;telephony&&telephony.removeEventListener('callschanged',this._maybeTrashAudio);window.removeEventListener('visibilitychange',this._maybeTrashAudio);this._reset();this._initialized=false;},_reset:function tp_reset(){this._audioContext=null;this._channel=null;this._gainNode=null;this._playingNodes=[];this._maybeTrashAudio=null;},_ensureAudio:function tp_ensureAudio(){if(this._audioContext||!this._initialized){return;}
this._audioContext=new AudioContext();},_trashAudio:function tp_trashAudio(){this.stop();this._audioContext=null;},_startAt:function tp_startAt(frequencies,when,duration){var context=this._audioContext;var sampleRate=context.sampleRate;var envelope=context.createBuffer(1,(duration?duration:0.05)*sampleRate,sampleRate);for(var i=0;i<envelope.length;i++){var factor=kToneVolume;var t=i/sampleRate;if(t<=kAttackDuration){factor=t/kAttackDuration;}else if(t-kAttackDuration<=kDecayDuration){factor=1.0-(1.0-kToneVolume)*(t-kAttackDuration)/kDecayDuration;}
if(!duration){factor-=kToneVolume;}else if(t>duration-kReleaseDuration){factor*=(duration-t)/kReleaseDuration;}
envelope.getChannelData(0)[i]=factor*kMasterVolume;}
var gainNode=context.createGain();gainNode.connect(context.destination);if(!duration){this._gainNode=gainNode;}
var envelopeNode=context.createBufferSource();envelopeNode.buffer=envelope;envelopeNode.start(when);envelopeNode.connect(gainNode.gain);gainNode.gain.setValueAtTime(duration?0.0:kToneVolume*kMasterVolume,0.0);for(i=0;i<frequencies.length;++i){var oscNode=this._audioContext.createOscillator();oscNode.type='sine';oscNode.frequency.value=frequencies[i];oscNode.start(when);if(duration){oscNode.stop(Math.max(when,context.currentTime+0.5)+duration);}else{this._playingNodes.push(oscNode);}
oscNode.connect(gainNode);}},start:function tp_start(frequencies,shortPress){this._ensureAudio();this._startAt(frequencies,0,shortPress?kShortPressDuration:0);},stop:function tp_stop(){if(!this._gainNode){return;}
var context=this._audioContext;var sampleRate=context.sampleRate;var gain=this._gainNode.gain;this._gainNode=null;var ramp=context.createBuffer(1,kReleaseDuration*sampleRate,sampleRate);for(var i=0;i<ramp.length;i++){ramp.getChannelData(0)[i]=(ramp.length-i-1)/ramp.length*kToneVolume*kMasterVolume;}
var rampNode=context.createBufferSource();rampNode.buffer=ramp;rampNode.start();rampNode.connect(gain);gain.setValueAtTime(0.0,0.0);while(this._playingNodes.length){this._playingNodes.pop().stop(context.currentTime+kReleaseDuration+0.5);}},playSequence:function tp_playSequence(sequence){this._ensureAudio();var when=this._audioContext.currentTime+0.2;for(var index=0;index<sequence.length;++index){var step=sequence[index];var frequencies=step.slice(0,2);var duration=step[2]/1000;this._startAt(frequencies,when,duration);when+=duration;}}};

View file

@ -0,0 +1,9 @@
;'use strict';var Utils={prettyDate:function ut_prettyDate(time){var f=Intl.DateTimeFormat(navigator.languages,{hour12:navigator.mozHour12,hour:'numeric',minute:'numeric'});return f.format(new Date(time));},prettyDuration:function(node,duration,l10nPrefix){var elapsed=new Date(duration);var h=elapsed.getUTCHours();var m=elapsed.getUTCMinutes();var s=elapsed.getUTCSeconds();var l10nId=l10nPrefix||'callDuration';var durationL10n={h:h+'',m:m+'',s:s+''};if(l10nId==='callDuration'){durationL10n={h:(h>9?'':'0')+h,m:(m>9?'':'0')+m,s:(s>9?'':'0')+s};}
if(l10nPrefix==='callDurationTextFormat'&&h===0&&m===0){l10nId+='Seconds';}else{l10nId+=h>0?'Hours':'Minutes';}
navigator.mozL10n.setAttributes(node,l10nId,durationL10n);},setHeaderDate:function ut_setHeaderDate(elem,time){var diff=(Date.now()-time)/1000;var day_diff=Math.floor(diff/86400);var formattedTime;if(isNaN(day_diff)){elem.setAttribute('data-l10n-id','incorrectDate');return;}else if(day_diff===0){elem.setAttribute('data-l10n-id','today');return;}else if(day_diff===1){elem.setAttribute('data-l10n-id','yesterday');return;}else if(day_diff<6){formattedTime=(new Date(time)).toLocaleString(navigator.languages,{weekday:'long',});}else{formattedTime=(new Date(time)).toLocaleString(navigator.languages,{year:'2-digit',month:'2-digit',day:'2-digit'});}
elem.removeAttribute('data-l10n-id');elem.textContent=formattedTime;},getPhoneNumberPrimaryInfo:function ut_getPhoneNumberPrimaryInfo(matchingTel,contact){if(contact){if(contact.name&&contact.name.length&&contact.name[0]!==''){return contact.name;}else if(contact.org&&contact.org.length&&contact.org[0]!==''){return contact.org;}}
if(matchingTel){return matchingTel.value;}
return null;},toCamelCase:function ut_toCamelCase(str){return str.replace(/\-(.)/g,function replacer(str,p1){return p1.toUpperCase();});},_phoneTypesL10n:{'mobile':'phone_type_mobile','home':'phone_type_home','work':'phone_type_work','personal':'phone_type_personal','faxHome':'phone_type_fax_home','faxOffice':'phone_type_fax_office','faxOther':'phone_type_fax_other','other':'phone_type_other'},getPhoneNumberAdditionalInfo:function ut_getPhoneNumberAdditionalInfo(matchingTel){var type=matchingTel.type||'mobile';var carrier=matchingTel.carrier;if(Array.isArray(type)){type=type[0];}
var id;var args={};if(this._phoneTypesL10n.hasOwnProperty(type)){id=this._phoneTypesL10n[type];}else{id='phone_type_custom';args.type=type;}
if(carrier){id+='_and_carrier';args.carrier=carrier;}
return{id:id,args:Object.keys(args).length?args:null};},isPhoneType:function ut_isPhoneType(type){return this._phoneTypesL10n.hasOwnProperty(type);}};

View file

@ -0,0 +1,5 @@
;'use strict';(function(exports){var Voicemail={check:function vm_check(number,cardIndex){return new Promise(function(resolve,reject){if(!number){resolve(false);return;}
var serviceId=cardIndex;var voicemail=navigator.mozVoicemail;if(voicemail){var voicemailNumber=voicemail.getNumber(serviceId);if(voicemailNumber===number){resolve(true);return;}}
var settings=navigator.mozSettings;var req=settings.createLock().get('ril.iccInfo.mbdn');req.onsuccess=function getVoicemailNumber(){var isVoicemailNumber=false;var voicemailNumbers=req.result['ril.iccInfo.mbdn'];var voicemailNumber;if(typeof voicemailNumbers==='string'){voicemailNumber=voicemailNumbers;}else{voicemailNumber=voicemailNumbers&&voicemailNumbers[serviceId];}
if(voicemailNumber===number){isVoicemailNumber=true;}
resolve(isVoicemailNumber);};req.onerror=function getVoicemailNumberError(){resolve(false);};});}};exports.Voicemail=Voicemail;}(window));

View file

@ -0,0 +1,423 @@
'use strict';
/* global LazyLoader, TelIndexer */
// Reader Module for FB Data in a Datastore
// To use this library you need to include 'shared/js/fb/fb_request.js'
// WARNING: This file lazy loads 'shared/js/fb/fb_tel_index.js'
var fb = self.fb || {};
self.fb = fb;
(function() {
var contacts = fb.contacts || {};
fb.contacts = contacts;
var datastore;
// Datastore name declared on the manifest.webapp
var DATASTORE_NAME = 'Gaia_Facebook_Friends';
// Record Id for the index
var INDEX_ID = 1;
// Indicates the initialization state
var readyState = 'notInitialized';
// Custom event for notifying initializations
var INITIALIZE_EVENT = 'fb_ds_init';
// Last known revision Id. Used to determine whether the index has to
// be reloaded or not
var revisionId;
// Creates the internal Object in the datastore that will act as an index
function createIndex() {
return {
// By tel number and all its possible variants
// (We are not supporting dups right now)
byTel: Object.create(null),
// Prefix tree for enabling searching by partial tel numbers
treeTel: []
};
}
// The index we need to keep the correspondance between FB Friends and
// datastore Ids
var index;
// Ensures a proper error object is returned
function safeError(err) {
if (err && err.name) {
return err;
}
return {
name: 'UnknownError'
};
}
function notifyOpenSuccess(cb) {
readyState = 'initialized';
if (typeof cb === 'function') {
window.setTimeout(cb, 0);
}
var ev = new CustomEvent(INITIALIZE_EVENT);
document.dispatchEvent(ev);
}
function initError(outRequest, error) {
outRequest.failed(error);
}
function handleInitError(err, errorCb) {
readyState = 'error';
contacts.error = err;
if (typeof errorCb === 'function') {
window.setTimeout(function() {
errorCb(err);
}, 0);
}
// We resume other callers state
document.dispatchEvent(new CustomEvent(INITIALIZE_EVENT));
}
// Creates a default handler for errors
function defaultError(request) {
return defaultErrorCb.bind(null, request);
}
// Creates a default handler for success
function defaultErrorCb(request, error) {
request.failed(error);
}
function setIndex(obj) {
index = (obj || createIndex());
}
function successGet(outReq, data) {
outReq.done(data);
}
function errorGet(outReq, uid, err) {
window.console.error('Error while getting object for UID: ', uid);
outReq.failed(err.name);
}
Object.defineProperty(contacts, 'datastore', {
get: function getDataStore() { return datastore; },
enumerable: false,
configurable: false
});
Object.defineProperty(contacts, 'dsIndex', {
get: function getIndex() { return index; },
set: setIndex,
enumerable: false,
configurable: false
});
/**
* Allows to obtain the FB friend information by UID
*
*
*/
contacts.get = function(uid) {
var outRequest = new fb.utils.Request();
window.setTimeout(function get() {
contacts.init(function() {
doGet(uid, outRequest);
}, function(err) {
initError(outRequest, err);
});
}, 0);
return outRequest;
};
function doGet(uid, outRequest) {
var successCb = successGet.bind(null, outRequest);
var errorCb = errorGet.bind(null, outRequest, uid);
datastore.get(uid).then(successCb, errorCb);
}
/**
* Allows to get FB information by tel number (short or long)
* The tel number must be complete
*
*/
contacts.getByPhone = function(tel) {
var outRequest = new fb.utils.Request();
window.setTimeout(function get_by_phone() {
contacts.init(function get_by_phone() {
doGetByPhone(tel, outRequest);
},
function(err) {
initError(outRequest, err);
});
}, 0);
return outRequest;
};
function doGetByPhone(tel, outRequest) {
var dsId;
var normalizedNumber = navigator.mozPhoneNumberService.normalize(tel);
if (datastore.revisionId !== revisionId) {
window.console.info('Datastore revision id has changed!');
// Refreshing the index just in case
datastore.get(INDEX_ID).then(function success(obj) {
setIndex(obj);
revisionId = datastore.revisionId;
dsId = index.byTel[normalizedNumber];
if (typeof dsId !== 'undefined') {
datastore.get(dsId).then(function success(friend) {
outRequest.done(friend);
}, defaultError(outRequest));
}
else {
outRequest.done(null);
}
}, function(err) {
err = safeError(err);
window.console.error('The index cannot be refreshed: ', err.name);
outRequest.failed(err);
});
}
else {
dsId = index.byTel[normalizedNumber];
if (typeof dsId !== 'undefined') {
datastore.get(dsId).then(function success(friend) {
outRequest.done(friend);
}, defaultError(outRequest));
}
else {
outRequest.done(null);
}
}
}
/**
* Allows to search for friends by different criteria.
* Numbers can be partial and partial matchings will be found
*
* by === tel : By Tel number
*
*/
contacts.search = function(by, number) {
var outRequest = new fb.utils.Request();
window.setTimeout(function do_search() {
contacts.init(function do_search_init() {
if (by === 'phone') {
doSearchByPhone(number, outRequest);
}
},
function(err) {
initError(outRequest, err);
});
}, 0);
return outRequest;
};
function doSearchByPhone(number, outRequest) {
var normalizedNumber = navigator.mozPhoneNumberService.normalize(number);
LazyLoader.load(['/shared/js/fb/fb_tel_index.js',
'/shared/js/binary_search.js'], function() {
var toSearchNumber = normalizedNumber;
// TODO: Temporal way of searching for international numbers
// A follow-up is needed by using PhoneNumber.js exposed to Gaia
if (number.charAt(0) === '+') {
toSearchNumber = number.substring(1);
}
if (datastore.revisionId !== revisionId) {
window.console.info('Datastore revision id has changed!');
// Refreshing the index
datastore.get(INDEX_ID).then(function success(obj) {
setIndex(obj);
revisionId = datastore.revisionId;
var results = TelIndexer.search(index.treeTel, toSearchNumber);
var out = null;
if (results.length > 0) {
out = datastore.get.apply(datastore, results);
}
return out;
},function(err) {
err = safeError(err);
window.console.error('The index cannot be refreshed: ', err.name);
outRequest.failed(err);
}).then(function success(objList) {
if (objList && !Array.isArray(objList)) {
objList = [objList];
}
else {
objList = [];
}
outRequest.done(objList);
}, function error(err) {
err = safeError(err);
window.console.error('Error while retrieving result data: ',
err.name);
outRequest.failed(err);
});
}
else {
var results = TelIndexer.search(index.treeTel, toSearchNumber);
if (results.length > 0) {
datastore.get.apply(datastore, results).then(
function success(objList) {
if (!Array.isArray(objList)) {
objList = [objList];
}
outRequest.done(objList);
}, function error(err) {
err = safeError(err);
window.console.error('Error while retrieving result data: ',
err.name);
outRequest.failed(err);
});
}
else {
outRequest.done(results);
}
}
});
}
/**
* Refreshes the index data
*
*/
contacts.refresh = function() {
var outRequest = new fb.utils.Request();
window.setTimeout(function clear() {
contacts.init(function() {
doRefresh(outRequest);
},
function(err) {
initError(outRequest, err);
});
}, 0);
return outRequest;
};
function doRefresh(outRequest) {
datastore.get(INDEX_ID).then(function success(obj) {
setIndex(obj);
outRequest.done();
}, defaultError(outRequest));
}
/**
* Allows to obtain how many records contain he FB Database
*
*/
contacts.getLength = function() {
var retRequest = new fb.utils.Request();
window.setTimeout(function() {
contacts.init(function get_all() {
doGetLength(retRequest);
},
function(err) {
initError(retRequest, err);
});
}, 0);
return retRequest;
};
/**
* Allows to return the total number of records in the DataStore (minus 1)
* That's because the index object also counts
*
*/
function doGetLength(outRequest) {
datastore.getLength().then(function success(length) {
outRequest.done(length - 1);
},
function error(err) {
outRequest.failed(safeError(err));
});
}
// Needed only for testing purposes
contacts.restart = function() {
readyState = 'notInitialized';
};
/**
* Initialization function
*
*/
contacts.init = function(cb, errorCb) {
if (!navigator.getDataStores) {
handleInitError({ name: 'DatastoreNotFound' }, errorCb);
return;
}
if (readyState === 'initialized') {
cb();
return;
}
if (readyState === 'initializing') {
document.addEventListener(INITIALIZE_EVENT, function oninitalized() {
cb();
document.removeEventListener(INITIALIZE_EVENT, oninitalized);
});
return;
}
readyState = 'initializing';
navigator.getDataStores(DATASTORE_NAME).then(function success(ds) {
if (ds.length < 1) {
handleInitError({ name: 'DatastoreNotFound' }, errorCb);
return;
}
datastore = ds[0];
// Checking the length as the index should be there
datastore.getLength().then(function(length) {
if (length === 0 && datastore.readOnly === false) {
window.console.info('Adding index as length is 0');
setIndex(createIndex());
return datastore.add(index);
}
else if (length > 0) {
return datastore.get(INDEX_ID);
}
else if (datastore.readOnly === true) {
window.console.warn('The datastore is empty and readonly');
}
return null;
}).then(function add_index_success(v) {
// Index is created in order not to cause errors
if (typeof v !== 'number') {
setIndex(v);
}
revisionId = datastore.revisionId;
notifyOpenSuccess(cb);
}, function add_index_error(err) {
err = safeError(err);
window.console.error('Error while setting the index: ', err.name);
handleInitError(err, errorCb);
});
}, function error(err) {
err = safeError(err);
window.console.error('FB: Error while opening the DataStore: ',
err.name);
handleInitError(err, errorCb);
});
};
})();

View file

@ -0,0 +1,325 @@
'use strict';
// Includes convenience functions for FB Contact Data
// To use this library you need to include:
// 'shared/js/fb/fb_request.js' and 'shared/js/fb/fb_data_reader.js'
var fb = self.fb || {};
self.fb = fb;
if (!self.AuxFB) {
self.AuxFb = (function() {
var CATEGORY = 'facebook';
var NOT_LINKED = 'not_linked';
var LINKED = 'fb_linked';
// Shallow copy from source to target object
function populate(source, target, propertyNames) {
propertyNames.forEach(function(property) {
var propertyValue = source[property];
if (propertyValue) {
if (Array.isArray(propertyValue)) {
target[property] = propertyValue.slice(0, propertyValue.length);
} else {
target[property] = propertyValue;
}
}
});
}
// Auxiliary function for merging
function mergeFbData(dcontact, fbdata) {
var multipleFields = ['email', 'tel', 'photo', 'org', 'adr'];
multipleFields.forEach(function(field) {
if (!dcontact[field]) {
dcontact[field] = [];
}
var items = fbdata[field];
if (items) {
items.forEach(function(item) {
// If there are no duplicates the merge is done
var dupList = checkDuplicates(field, item, dcontact[field],
fbdata.shortTelephone);
if (dupList.length === 0) {
dcontact[field].push(item);
}
});
}
});
var singleFields = ['bday', 'anniversary'];
singleFields.forEach(function(field) {
if (!dcontact[field]) {
dcontact[field] = fbdata[field];
}
});
// To support the case in which the contact does not have a local name
mergeNames(dcontact, fbdata);
}
// Auxiliary function for merging names
function mergeNames(devContact, fbContact) {
var namesChanged = false;
var nameFields = ['givenName', 'familyName'];
nameFields.forEach(function(anameField) {
// If the device contact does not have name fields setted
// we use the Facebook ones
var fieldValue = devContact[anameField];
var fbValue = fbContact[anameField];
if ((!Array.isArray(fieldValue) || fieldValue.length === 0) &&
Array.isArray(fbValue) && fbValue.length > 0) {
namesChanged = true;
devContact[anameField] = (fieldValue && fieldValue[0]) || [];
devContact[anameField].push(fbValue[0]);
}
});
if (namesChanged) {
var givenName = devContact.givenName[0] || '';
var familyName = devContact.familyName[0] || '';
devContact.name = [givenName + ' ' + familyName];
}
}
/**
* Returns truthy if the device contact is a FB Friend
*
*/
function isFbContact(devContact) {
return (devContact && devContact.category &&
devContact.category.indexOf(CATEGORY) !== -1);
}
/**
* Returns truthy if the device contact is linked to a FB Friend
*
*/
function isFbLinked(devContact) {
return (devContact && devContact.category &&
devContact.category.indexOf(LINKED) !== -1);
}
/**
* Gets all the data enriching the local contact with FB information
*
*/
function getData(devContact) {
var outReq = new fb.utils.Request();
window.setTimeout(function do_getData() {
var uid = getFriendUid(devContact);
if (uid) {
var fbreq = fb.contacts.get(uid);
fbreq.onsuccess = function() {
var fbdata = fbreq.result;
var out = mergeContact(devContact, fbdata);
outReq.done(out);
};
fbreq.onerror = function() {
outReq.failed(fbreq.error);
};
}
else {
outReq.done(devContact);
}
}, 0);
return outReq;
}
/**
* Returns the FB Friend UID associated to a device contact
*
*/
function getFriendUid(devContact) {
var out = devContact.uid;
if (!out) {
if (isFbLinked(devContact)) {
out = getLinkedTo(devContact);
}
else if (devContact.category) {
var idx = devContact.category.indexOf(CATEGORY);
if (idx !== -1) {
out = devContact.category[idx + 2];
}
}
}
return out;
}
/**
* Gets the UID of the FB Friend a device contact is linked to
*
*/
function getLinkedTo(devContact) {
var out;
if (devContact.category) {
var idx = devContact.category.indexOf(LINKED);
if (idx !== -1) {
out = devContact.category[idx + 1];
}
}
return out;
}
/**
* Merge a device contact with a FB Friend
*
*/
function mergeContact(devContact, fbContact) {
var out = devContact;
if (fbContact) {
out = Object.create(null);
out.updated = devContact.updated;
out.published = devContact.published;
// The id comes from devContact and the rest of properties like
// familyName, propertyName, etc... are defined in the proto object
populate(devContact, out, Object.getOwnPropertyNames(devContact));
populate(devContact, out,
Object.getOwnPropertyNames(Object.getPrototypeOf(devContact)));
mergeFbData(out, fbContact);
}
return out;
}
/**
* Returns a FB Contact (enriched with FB info) which has the tel number
*
*/
function getContactByNumber(number, onsuccess, onerror) {
var req = fb.contacts.getByPhone(number);
req.onsuccess = function get_by_phone_success(e) {
var fbData = req.result;
if (fbData) {
fb.getMozContactByUid(fbData.uid, function merge(result) {
if (Array.isArray(result) && result[0]) {
var finalContact = fb.mergeContact(result[0], fbData);
onsuccess(finalContact);
}
else {
onsuccess(null);
}
}, function error_get_mozContact(err) {
console.error('Error getting mozContact: ', err.name);
onerror(err);
});
}
else {
onsuccess(null);
}
};
req.onerror = function() {
onerror(req.error);
};
}
// Checks whether there is a duplicate for the field value
// both in FB and in the local device Contact data
// Returns an array with the values which are duplicated or empty if
// no duplicates were found
// Parameters are: field on which to search, the corresponding fbItem
// the local device items, and extra FB Items which corresp to the short
// telephone numbers allowing to filter out dups with intl-ed numbers
function checkDuplicates(field, fbItem, devContactItems, extraFbItems) {
var potentialDuplicatesFields = ['email', 'tel'];
var out = [];
if (devContactItems &&
potentialDuplicatesFields.indexOf(field) !== -1) {
var total = devContactItems.length;
for (var i = 0; i < total; i++) {
var localValue = devContactItems[i].value;
var fbValue = fbItem.value;
// Checking for telephone international number matching
if (localValue) {
var trimedLocal = localValue.trim();
if (trimedLocal === fbValue ||
(field === 'tel' && Array.isArray(extraFbItems) &&
extraFbItems.indexOf(trimedLocal) !== -1)) {
out.push(trimedLocal);
out.push(fbValue);
}
} // if(localValue)
} // for
} // if(devContactItems)
return out;
}
/**
* Returns the mozContact associated to a certain FB UID
*
*/
function getMozContactByUid(uid, onsuccess, onerror) {
var filter = {
filterBy: ['category'],
filterValue: uid,
filterOp: 'contains'
};
var req = navigator.mozContacts.find(filter);
req.onsuccess = function() {
onsuccess(req.result);
};
req.onerror = function() {
onerror(req.error);
};
}
return {
'isFbContact': isFbContact,
'isFbLinked': isFbLinked,
'getData': getData,
'getFriendUid': getFriendUid,
'getLinkedTo': getLinkedTo,
'mergeContact': mergeContact,
'getContactByNumber': getContactByNumber,
'getMozContactByUid': getMozContactByUid,
'checkDuplicates': checkDuplicates,
get CATEGORY() {
return CATEGORY;
},
get LINKED() {
return LINKED;
},
get NOT_LINKED() {
return NOT_LINKED;
}
};
})();
// This boilerplate code sets the AuxFb properties to the fb object
var props = Object.keys(self.AuxFb);
for (var j = 0, end = props.length; j < end; j++) {
/* jshint loopfunc: true */
var prop = props[j];
if (typeof self.fb[prop] === 'function') {
self.fb[prop] = self.AuxFb[prop];
}
else {
Object.defineProperty(self.fb, prop, {
value: (function() {
return self.AuxFb[prop];
})(), writable: false, enumerable: true, configurable: false
});
}
}
}

View file

@ -0,0 +1,39 @@
'use strict';
var fb = self.fb || {};
self.fb = fb;
// Only will be executed in the case of not loading fb.utils previously
// i.e. dialer and call log FB integration
fb.utils = self.fb.utils || {};
self.fb.utils = fb.utils;
if (typeof fb.utils.Request !== 'function') {
/**
* Request auxiliary object to support asynchronous calls
*
*/
fb.utils.Request = function() {
this.done = function(result) {
this.result = result;
if (typeof this.onsuccess === 'function') {
var ev = {};
ev.target = this;
window.setTimeout(function() {
this.onsuccess(ev);
}.bind(this), 0);
}
};
this.failed = function(error) {
this.error = error;
if (typeof this.onerror === 'function') {
var ev = {};
ev.target = this;
window.setTimeout(function() {
this.onerror(ev);
}.bind(this), 0);
}
};
};
}

View file

@ -0,0 +1,8 @@
;(function(exports){'use strict';var FontSizeUtils={_cachedContexts:{},_getCachedContext:function(fontSize,fontFamily,fontStyle){fontStyle=fontStyle||'italic';var cache=this._cachedContexts;var ctx=cache[fontSize]&&cache[fontSize][fontFamily]?cache[fontSize][fontFamily][fontStyle]:null;if(!ctx){var canvas=document.createElement('canvas');canvas.setAttribute('moz-opaque','true');canvas.setAttribute('width','1');canvas.setAttribute('height','1');ctx=canvas.getContext('2d',{willReadFrequently:true});ctx.font=fontStyle+' '+fontSize+'px '+fontFamily;if(!cache[fontSize]){cache[fontSize]={};}
if(!cache[fontSize][fontFamily]){cache[fontSize][fontFamily]={};}
cache[fontSize][fontFamily][fontStyle]=ctx;}
return ctx;},resetCache:function(){this._cachedContexts={};},getFontWidth:function(string,fontSize,fontFamily,fontStyle){var ctx=this._getCachedContext(fontSize,fontFamily,fontStyle);return ctx.measureText(string).width;},getMaxFontSizeInfo:function(string,allowedSizes,fontFamily,maxWidth){var fontSize;var resultWidth;var i=allowedSizes.length-1;do{fontSize=allowedSizes[i];resultWidth=this.getFontWidth(string,fontSize,fontFamily);i--;}while(resultWidth>maxWidth&&i>=0);return{fontSize:fontSize,overflow:resultWidth>maxWidth,textWidth:resultWidth};},_overflowCountCache:-1,getOverflowCount:function(string,fontSize,fontFamily,maxWidth){var substring;var resultWidth;var overflowCount=-1;if(string.length>this._overflowCountCache){substring=string.substr(0,string.length-this._overflowCountCache);resultWidth=this.getFontWidth(substring,fontSize,fontFamily);if(resultWidth>maxWidth){overflowCount=this._overflowCountCache;}}
do{overflowCount++;substring=string.substr(0,string.length-overflowCount);resultWidth=this.getFontWidth(substring,fontSize,fontFamily);}while(substring.length>0&&resultWidth>maxWidth);this._overflowCountCache=overflowCount;return overflowCount;},getContentWidth:function(style){var width=parseInt(style.width,10);if(style.boxSizing==='border-box'){width-=(parseInt(style.paddingRight,10)+
parseInt(style.paddingLeft,10));}
return width;},getStyleProperties:function(element){var style=window.getComputedStyle(element);var contentWidth=this.getContentWidth(style);if(isNaN(contentWidth)){contentWidth=0;}
return{fontFamily:style.fontFamily,contentWidth:contentWidth,paddingRight:parseInt(style.paddingRight,10),paddingLeft:parseInt(style.paddingLeft,10),offsetLeft:element.offsetLeft};},getWindowWidth:function(){return window.innerWidth;}};exports.FontSizeUtils=FontSizeUtils;}(this));

View file

@ -0,0 +1,245 @@
;(function(window,undefined){'use strict';function L10nError(message,id,loc){this.name='L10nError';this.message=message;this.id=id;this.loc=loc;}
L10nError.prototype=Object.create(Error.prototype);L10nError.prototype.constructor=L10nError;var io={_load:function(type,url,callback,sync){var xhr=new XMLHttpRequest();var needParse;if(xhr.overrideMimeType){xhr.overrideMimeType(type);}
xhr.open('GET',url,!sync);if(type==='application/json'){if(sync){needParse=true;}else{xhr.responseType='json';}}
xhr.addEventListener('load',function io_onload(e){if(e.target.status===200||e.target.status===0){var res=e.target.response||e.target.responseText;callback(null,needParse?JSON.parse(res):res);}else{callback(new L10nError('Not found: '+url));}});xhr.addEventListener('error',callback);xhr.addEventListener('timeout',callback);try{xhr.send(null);}catch(e){if(e.name==='NS_ERROR_FILE_NOT_FOUND'){callback(new L10nError('Not found: '+url));}else{throw e;}}},load:function(url,callback,sync){return io._load('text/plain',url,callback,sync);},loadJSON:function(url,callback,sync){return io._load('application/json',url,callback,sync);}};function EventEmitter(){}
EventEmitter.prototype.emit=function ee_emit(){if(!this._listeners){return;}
var args=Array.prototype.slice.call(arguments);var type=args.shift();if(!this._listeners[type]){return;}
var typeListeners=this._listeners[type].slice();for(var i=0;i<typeListeners.length;i++){typeListeners[i].apply(this,args);}};EventEmitter.prototype.addEventListener=function ee_add(type,listener){if(!this._listeners){this._listeners={};}
if(!(type in this._listeners)){this._listeners[type]=[];}
this._listeners[type].push(listener);};EventEmitter.prototype.removeEventListener=function ee_rm(type,listener){if(!this._listeners){return;}
var typeListeners=this._listeners[type];var pos=typeListeners.indexOf(listener);if(pos===-1){return;}
typeListeners.splice(pos,1);};function getPluralRule(lang){var locales2rules={'af':3,'ak':4,'am':4,'ar':1,'asa':3,'az':0,'be':11,'bem':3,'bez':3,'bg':3,'bh':4,'bm':0,'bn':3,'bo':0,'br':20,'brx':3,'bs':11,'ca':3,'cgg':3,'chr':3,'cs':12,'cy':17,'da':3,'de':3,'dv':3,'dz':0,'ee':3,'el':3,'en':3,'eo':3,'es':3,'et':3,'eu':3,'fa':0,'ff':5,'fi':3,'fil':4,'fo':3,'fr':5,'fur':3,'fy':3,'ga':8,'gd':24,'gl':3,'gsw':3,'gu':3,'guw':4,'gv':23,'ha':3,'haw':3,'he':2,'hi':4,'hr':11,'hu':0,'id':0,'ig':0,'ii':0,'is':3,'it':3,'iu':7,'ja':0,'jmc':3,'jv':0,'ka':0,'kab':5,'kaj':3,'kcg':3,'kde':0,'kea':0,'kk':3,'kl':3,'km':0,'kn':0,'ko':0,'ksb':3,'ksh':21,'ku':3,'kw':7,'lag':18,'lb':3,'lg':3,'ln':4,'lo':0,'lt':10,'lv':6,'mas':3,'mg':4,'mk':16,'ml':3,'mn':3,'mo':9,'mr':3,'ms':0,'mt':15,'my':0,'nah':3,'naq':7,'nb':3,'nd':3,'ne':3,'nl':3,'nn':3,'no':3,'nr':3,'nso':4,'ny':3,'nyn':3,'om':3,'or':3,'pa':3,'pap':3,'pl':13,'ps':3,'pt':3,'rm':3,'ro':9,'rof':3,'ru':11,'rwk':3,'sah':0,'saq':3,'se':7,'seh':3,'ses':0,'sg':0,'sh':11,'shi':19,'sk':12,'sl':14,'sma':7,'smi':7,'smj':7,'smn':7,'sms':7,'sn':3,'so':3,'sq':3,'sr':11,'ss':3,'ssy':3,'st':3,'sv':3,'sw':3,'syr':3,'ta':3,'te':3,'teo':3,'th':0,'ti':4,'tig':3,'tk':3,'tl':4,'tn':3,'to':0,'tr':0,'ts':3,'tzm':22,'uk':11,'ur':3,'ve':3,'vi':0,'vun':3,'wa':4,'wae':3,'wo':0,'xh':3,'xog':3,'yo':0,'zh':0,'zu':3};function isIn(n,list){return list.indexOf(n)!==-1;}
function isBetween(n,start,end){return typeof n===typeof start&&start<=n&&n<=end;}
var pluralRules={'0':function(){return'other';},'1':function(n){if((isBetween((n%100),3,10))){return'few';}
if(n===0){return'zero';}
if((isBetween((n%100),11,99))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'2':function(n){if(n!==0&&(n%10)===0){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'3':function(n){if(n===1){return'one';}
return'other';},'4':function(n){if((isBetween(n,0,1))){return'one';}
return'other';},'5':function(n){if((isBetween(n,0,2))&&n!==2){return'one';}
return'other';},'6':function(n){if(n===0){return'zero';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'7':function(n){if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'8':function(n){if((isBetween(n,3,6))){return'few';}
if((isBetween(n,7,10))){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'9':function(n){if(n===0||n!==1&&(isBetween((n%100),1,19))){return'few';}
if(n===1){return'one';}
return'other';},'10':function(n){if((isBetween((n%10),2,9))&&!(isBetween((n%100),11,19))){return'few';}
if((n%10)===1&&!(isBetween((n%100),11,19))){return'one';}
return'other';},'11':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if((n%10)===0||(isBetween((n%10),5,9))||(isBetween((n%100),11,14))){return'many';}
if((n%10)===1&&(n%100)!==11){return'one';}
return'other';},'12':function(n){if((isBetween(n,2,4))){return'few';}
if(n===1){return'one';}
return'other';},'13':function(n){if((isBetween((n%10),2,4))&&!(isBetween((n%100),12,14))){return'few';}
if(n!==1&&(isBetween((n%10),0,1))||(isBetween((n%10),5,9))||(isBetween((n%100),12,14))){return'many';}
if(n===1){return'one';}
return'other';},'14':function(n){if((isBetween((n%100),3,4))){return'few';}
if((n%100)===2){return'two';}
if((n%100)===1){return'one';}
return'other';},'15':function(n){if(n===0||(isBetween((n%100),2,10))){return'few';}
if((isBetween((n%100),11,19))){return'many';}
if(n===1){return'one';}
return'other';},'16':function(n){if((n%10)===1&&n!==11){return'one';}
return'other';},'17':function(n){if(n===3){return'few';}
if(n===0){return'zero';}
if(n===6){return'many';}
if(n===2){return'two';}
if(n===1){return'one';}
return'other';},'18':function(n){if(n===0){return'zero';}
if((isBetween(n,0,2))&&n!==0&&n!==2){return'one';}
return'other';},'19':function(n){if((isBetween(n,2,10))){return'few';}
if((isBetween(n,0,1))){return'one';}
return'other';},'20':function(n){if((isBetween((n%10),3,4)||((n%10)===9))&&!(isBetween((n%100),10,19)||isBetween((n%100),70,79)||isBetween((n%100),90,99))){return'few';}
if((n%1000000)===0&&n!==0){return'many';}
if((n%10)===2&&!isIn((n%100),[12,72,92])){return'two';}
if((n%10)===1&&!isIn((n%100),[11,71,91])){return'one';}
return'other';},'21':function(n){if(n===0){return'zero';}
if(n===1){return'one';}
return'other';},'22':function(n){if((isBetween(n,0,1))||(isBetween(n,11,99))){return'one';}
return'other';},'23':function(n){if((isBetween((n%10),1,2))||(n%20)===0){return'one';}
return'other';},'24':function(n){if((isBetween(n,3,10)||isBetween(n,13,19))){return'few';}
if(isIn(n,[2,12])){return'two';}
if(isIn(n,[1,11])){return'one';}
return'other';}};var index=locales2rules[lang.replace(/-.*$/,'')];if(!(index in pluralRules)){return function(){return'other';};}
return pluralRules[index];}
var MAX_PLACEABLES=100;var PropertiesParser={patterns:null,entryIds:null,init:function(){this.patterns={comment:/^\s*#|^\s*$/,entity:/^([^=\s]+)\s*=\s*(.*)$/,multiline:/[^\\]\\$/,index:/\{\[\s*(\w+)(?:\(([^\)]*)\))?\s*\]\}/i,unicode:/\\u([0-9a-fA-F]{1,4})/g,entries:/[^\r\n]+/g,controlChars:/\\([\\\n\r\t\b\f\{\}\"\'])/g,placeables:/\{\{\s*([^\s]*?)\s*\}\}/,};},parse:function(ctx,source){if(!this.patterns){this.init();}
var ast=[];this.entryIds=Object.create(null);var entries=source.match(this.patterns.entries);if(!entries){return ast;}
for(var i=0;i<entries.length;i++){var line=entries[i];if(this.patterns.comment.test(line)){continue;}
while(this.patterns.multiline.test(line)&&i<entries.length){line=line.slice(0,-1)+entries[++i].trim();}
var entityMatch=line.match(this.patterns.entity);if(entityMatch){try{this.parseEntity(entityMatch[1],entityMatch[2],ast);}catch(e){if(ctx){ctx._emitter.emit('parseerror',e);}else{throw e;}}}}
return ast;},parseEntity:function(id,value,ast){var name,key;var pos=id.indexOf('[');if(pos!==-1){name=id.substr(0,pos);key=id.substring(pos+1,id.length-1);}else{name=id;key=null;}
var nameElements=name.split('.');if(nameElements.length>2){throw new L10nError('Error in ID: "'+name+'".'+' Nested attributes are not supported.');}
var attr;if(nameElements.length>1){name=nameElements[0];attr=nameElements[1];if(attr[0]==='$'){throw new L10nError('Attribute can\'t start with "$"',id);}}else{attr=null;}
this.setEntityValue(name,attr,key,this.unescapeString(value),ast);},setEntityValue:function(id,attr,key,rawValue,ast){var pos,v;var value=rawValue.indexOf('{{')>-1?this.parseString(rawValue):rawValue;if(attr){pos=this.entryIds[id];if(pos===undefined){v={$i:id};if(key){v[attr]={};v[attr][key]=value;}else{v[attr]=value;}
ast.push(v);this.entryIds[id]=ast.length-1;return;}
if(key){if(typeof(ast[pos][attr])==='string'){ast[pos][attr]={$x:this.parseIndex(ast[pos][attr]),$v:{}};}
ast[pos][attr].$v[key]=value;return;}
ast[pos][attr]=value;return;}
if(key){pos=this.entryIds[id];if(pos===undefined){v={};v[key]=value;ast.push({$i:id,$v:v});this.entryIds[id]=ast.length-1;return;}
if(typeof(ast[pos].$v)==='string'){ast[pos].$x=this.parseIndex(ast[pos].$v);ast[pos].$v={};}
ast[pos].$v[key]=value;return;}
ast.push({$i:id,$v:value});this.entryIds[id]=ast.length-1;},parseString:function(str){var chunks=str.split(this.patterns.placeables);var complexStr=[];var len=chunks.length;var placeablesCount=(len-1)/2;if(placeablesCount>=MAX_PLACEABLES){throw new L10nError('Too many placeables ('+placeablesCount+', max allowed is '+MAX_PLACEABLES+')');}
for(var i=0;i<chunks.length;i++){if(chunks[i].length===0){continue;}
if(i%2===1){complexStr.push({t:'idOrVar',v:chunks[i]});}else{complexStr.push(chunks[i]);}}
return complexStr;},unescapeString:function(str){if(str.lastIndexOf('\\')!==-1){str=str.replace(this.patterns.controlChars,'$1');}
return str.replace(this.patterns.unicode,function(match,token){return unescape('%u'+'0000'.slice(token.length)+token);});},parseIndex:function(str){var match=str.match(this.patterns.index);if(!match){throw new L10nError('Malformed index');}
if(match[2]){return[{t:'idOrVar',v:match[1]},match[2]];}else{return[{t:'idOrVar',v:match[1]}];}}};var KNOWN_MACROS=['plural'];var MAX_PLACEABLE_LENGTH=2500;var rePlaceables=/\{\{\s*(.+?)\s*\}\}/g;var nonLatin1=/[^\x01-\xFF]/;var FSI='\u2068';var PDI='\u2069';function createEntry(node,env){var keys=Object.keys(node);if(typeof node.$v==='string'&&keys.length===2){return node.$v;}
var attrs;for(var i=0,key;key=keys[i];i++){if(key[0]==='$'){continue;}
if(!attrs){attrs=Object.create(null);}
attrs[key]=createAttribute(node[key],env,node.$i+'.'+key);}
return{id:node.$i,value:node.$v!==undefined?node.$v:null,index:node.$x||null,attrs:attrs||null,env:env,dirty:false};}
function createAttribute(node,env,id){if(typeof node==='string'){return node;}
return{id:id,value:node.$v||(node!==undefined?node:null),index:node.$x||null,env:env,dirty:false};}
function format(args,entity){if(typeof entity==='string'){return[{},entity];}
if(entity.dirty){throw new L10nError('Cyclic reference detected: '+entity.id);}
entity.dirty=true;var rv;try{rv=resolveValue({},args,entity.env,entity.value,entity.index);}finally{entity.dirty=false;}
return rv;}
function resolveIdentifier(args,env,id){if(KNOWN_MACROS.indexOf(id)>-1){return[{},env['__'+id]];}
if(args&&args.hasOwnProperty(id)){if(typeof args[id]==='string'||(typeof args[id]==='number'&&!isNaN(args[id]))){return[{},args[id]];}else{throw new L10nError('Arg must be a string or a number: '+id);}}
if(id in env&&id!=='__proto__'){return format(args,env[id]);}
throw new L10nError('Unknown reference: '+id);}
function subPlaceable(locals,args,env,id){var res;try{res=resolveIdentifier(args,env,id);}catch(err){return[{error:err},'{{ '+id+' }}'];}
var value=res[1];if(typeof value==='number'){return res;}
if(typeof value==='string'){if(value.length>=MAX_PLACEABLE_LENGTH){throw new L10nError('Too many characters in placeable ('+
value.length+', max allowed is '+
MAX_PLACEABLE_LENGTH+')');}
if(locals.contextIsNonLatin1||value.match(nonLatin1)){res[1]=FSI+value+PDI;}
return res;}
return[{},'{{ '+id+' }}'];}
function interpolate(locals,args,env,arr){return arr.reduce(function(prev,cur){if(typeof cur==='string'){return[prev[0],prev[1]+cur];}else if(cur.t==='idOrVar'){var placeable=subPlaceable(locals,args,env,cur.v);return[prev[0],prev[1]+placeable[1]];}},[locals,'']);}
function resolveSelector(args,env,expr,index){var selectorName=index[0].v;var selector=resolveIdentifier(args,env,selectorName)[1];if(typeof selector!=='function'){return selector;}
var argValue=index[1]?resolveIdentifier(args,env,index[1])[1]:undefined;if(selector===env.__plural){if(argValue===0&&'zero'in expr){return'zero';}
if(argValue===1&&'one'in expr){return'one';}
if(argValue===2&&'two'in expr){return'two';}}
return selector(argValue);}
function resolveValue(locals,args,env,expr,index){if(!expr){return[locals,expr];}
if(typeof expr==='string'||typeof expr==='boolean'||typeof expr==='number'){return[locals,expr];}
if(Array.isArray(expr)){locals.contextIsNonLatin1=expr.some(function($_){return typeof($_)==='string'&&$_.match(nonLatin1);});return interpolate(locals,args,env,expr);}
if(index){var selector=resolveSelector(args,env,expr,index);if(expr.hasOwnProperty(selector)){return resolveValue(locals,args,env,expr[selector]);}}
if('other'in expr){return resolveValue(locals,args,env,expr.other);}
throw new L10nError('Unresolvable value');}
var Resolver={createEntry:createEntry,format:format,rePlaceables:rePlaceables};function walkContent(node,fn){if(typeof node==='string'){return fn(node);}
if(node.t==='idOrVar'){return node;}
var rv=Array.isArray(node)?[]:{};var keys=Object.keys(node);for(var i=0,key;(key=keys[i]);i++){if(key==='$i'||key==='$x'){rv[key]=node[key];}else{rv[key]=walkContent(node[key],fn);}}
return rv;}
var reAlphas=/[a-zA-Z]/g;var reVowels=/[aeiouAEIOU]/g;var ACCENTED_MAP='\u0226\u0181\u0187\u1E12\u1E16\u0191\u0193\u0126\u012A'+'\u0134\u0136\u013F\u1E3E\u0220\u01FE\u01A4\u024A\u0158'+'\u015E\u0166\u016C\u1E7C\u1E86\u1E8A\u1E8E\u1E90'+'[\\]^_`'+'\u0227\u0180\u0188\u1E13\u1E17\u0192\u0260\u0127\u012B'+'\u0135\u0137\u0140\u1E3F\u019E\u01FF\u01A5\u024B\u0159'+'\u015F\u0167\u016D\u1E7D\u1E87\u1E8B\u1E8F\u1E91';var FLIPPED_MAP='\u2200\u0510\u2183p\u018E\u025F\u05E4HI\u017F'+'\u04FC\u02E5WNO\u0500\xD2\u1D1AS\u22A5\u2229\u0245'+'\uFF2DX\u028EZ'+'[\\]\u1D65_,'+'\u0250q\u0254p\u01DD\u025F\u0183\u0265\u0131\u027E'+'\u029E\u0285\u026Fuodb\u0279s\u0287n\u028C\u028Dx\u028Ez';function makeLonger(val){return val.replace(reVowels,function(match){return match+match.toLowerCase();});}
function replaceChars(map,val){return val.replace(reAlphas,function(match){return map.charAt(match.charCodeAt(0)-65);});}
var reWords=/[^\W0-9_]+/g;function makeRTL(val){return val.replace(reWords,function(match){return'\u202e'+match+'\u202c';});}
var reExcluded=/(%[EO]?\w|\{\s*.+?\s*\}|&[#\w]+;|<\s*.+?\s*>)/;function mapContent(fn,val){if(!val){return val;}
var parts=val.split(reExcluded);var modified=parts.map(function(part){if(reExcluded.test(part)){return part;}
return fn(part);});return modified.join('');}
function Pseudo(id,name,charMap,modFn){this.id=id;this.translate=mapContent.bind(null,function(val){return replaceChars(charMap,modFn(val));});this.name=this.translate(name);}
var PSEUDO={'fr-x-psaccent':new Pseudo('fr-x-psaccent','Runtime Accented',ACCENTED_MAP,makeLonger),'ar-x-psbidi':new Pseudo('ar-x-psbidi','Runtime Bidi',FLIPPED_MAP,makeRTL)};function Locale(id,ctx){this.id=id;this.ctx=ctx;this.isReady=false;this.entries=Object.create(null);this.entries.__plural=getPluralRule(this.isPseudo()?this.ctx.defaultLocale:id);}
Locale.prototype.isPseudo=function(){return this.ctx.qps.indexOf(this.id)!==-1;};var bindingsIO={extra:function(id,ver,path,type,callback,errback){if(type==='properties'){type='text';}
navigator.mozApps.getLocalizationResource(id,ver,path,type).then(callback.bind(null,null),errback);},app:function(id,ver,path,type,callback,errback,sync){switch(type){case'properties':io.load(path,callback,sync);break;case'json':io.loadJSON(path,callback,sync);break;}},};Locale.prototype.build=function L_build(callback){var sync=!callback;var ctx=this.ctx;var self=this;var l10nLoads=ctx.resLinks.length;function onL10nLoaded(err){if(err){ctx._emitter.emit('fetcherror',err);}
if(--l10nLoads<=0){self.isReady=true;if(callback){callback();}}}
if(l10nLoads===0){onL10nLoaded();return;}
function onJSONLoaded(err,json){if(!err&&json){self.addAST(json);}
onL10nLoaded(err);}
function onPropLoaded(err,source){if(!err&&source){var ast=PropertiesParser.parse(ctx,source);self.addAST(ast);}
onL10nLoaded(err);}
var idToFetch=this.isPseudo()?ctx.defaultLocale:this.id;var appVersion=null;var source='app';if(typeof(navigator)!=='undefined'){source=navigator.mozL10n._config.localeSources[this.id]||'app';appVersion=navigator.mozL10n._config.appVersion;}
for(var i=0;i<ctx.resLinks.length;i++){var resLink=decodeURI(ctx.resLinks[i]);var path=resLink.replace('{locale}',idToFetch);var type=path.substr(path.lastIndexOf('.')+1);var cb;switch(type){case'json':cb=onJSONLoaded;break;case'properties':cb=onPropLoaded;break;}
bindingsIO[source](this.id,appVersion,path,type,cb,onL10nLoaded,sync);}};function createPseudoEntry(node,entries){return Resolver.createEntry(walkContent(node,PSEUDO[this.id].translate),entries);}
Locale.prototype.addAST=function(ast){var createEntry=this.isPseudo()?createPseudoEntry.bind(this):Resolver.createEntry;for(var i=0;i<ast.length;i++){this.entries[ast[i].$i]=createEntry(ast[i],this.entries);}};function Context(id){this.id=id;this.isReady=false;this.isLoading=false;this.defaultLocale='en-US';this.availableLocales=[];this.supportedLocales=[];this.qps=[];this.resLinks=[];this.locales={};this._emitter=new EventEmitter();this._ready=new Promise(this.once.bind(this));}
function reportMissing(id,err){this._emitter.emit('notfounderror',err);return id;}
function getWithFallback(id){var cur=0;var loc;var locale;while(loc=this.supportedLocales[cur]){locale=this.getLocale(loc);if(!locale.isReady){locale.build(null);}
var entry=locale.entries[id];if(entry===undefined){cur++;reportMissing.call(this,id,new L10nError('"'+id+'"'+' not found in '+loc+' in '+this.id,id,loc));continue;}
return entry;}
throw new L10nError('"'+id+'"'+' missing from all supported locales in '+this.id,id);}
function formatTuple(args,entity){try{return Resolver.format(args,entity);}catch(err){this._emitter.emit('resolveerror',err);var locals={error:err};return[locals,entity.id];}}
function formatValue(args,entity){if(typeof entity==='string'){return entity;}
return formatTuple.call(this,args,entity)[1];}
function formatEntity(args,entity){var entityTuple=formatTuple.call(this,args,entity);var value=entityTuple[1];var formatted={value:value,attrs:null,};if(entity.attrs){formatted.attrs=Object.create(null);}
for(var key in entity.attrs){var attrTuple=formatTuple.call(this,args,entity.attrs[key]);formatted.attrs[key]=attrTuple[1];}
return formatted;}
function formatAsync(fn,id,args){return this._ready.then(getWithFallback.bind(this,id)).then(fn.bind(this,args),reportMissing.bind(this,id));}
Context.prototype.formatValue=function(id,args){return formatAsync.call(this,formatValue,id,args);};Context.prototype.formatEntity=function(id,args){return formatAsync.call(this,formatEntity,id,args);};function legacyGet(fn,id,args){if(!this.isReady){throw new L10nError('Context not ready');}
var entry;try{entry=getWithFallback.call(this,id);}catch(err){if(err.loc){throw err;}
reportMissing.call(this,id,err);return'';}
return fn.call(this,args,entry);}
Context.prototype.get=function(id,args){return legacyGet.call(this,formatValue,id,args);};Context.prototype.getEntity=function(id,args){return legacyGet.call(this,formatEntity,id,args);};Context.prototype.getLocale=function getLocale(code){var locales=this.locales;if(locales[code]){return locales[code];}
return locales[code]=new Locale(code,this);};function negotiate(available,requested,defaultLocale){var supportedLocale;for(var i=0;i<requested.length;i++){var locale=requested[i];if(available.indexOf(locale)!==-1){supportedLocale=locale;break;}}
if(!supportedLocale||supportedLocale===defaultLocale){return[defaultLocale];}
return[supportedLocale,defaultLocale];}
function freeze(supported){var locale=this.getLocale(supported[0]);if(locale.isReady){setReady.call(this,supported);}else{locale.build(setReady.bind(this,supported));}}
function setReady(supported){this.supportedLocales=supported;this.isReady=true;this._emitter.emit('ready');}
Context.prototype.registerLocales=function(defLocale,available){if(defLocale){this.defaultLocale=defLocale;}
this.availableLocales=[this.defaultLocale];this.qps=Object.keys(PSEUDO);if(available){for(var i=0,loc;loc=available[i];i++){if(this.availableLocales.indexOf(loc)===-1){this.availableLocales.push(loc);var pos=this.qps.indexOf(loc);if(pos!==-1){this.qps.splice(pos,1);}}}}};Context.prototype.requestLocales=function requestLocales(){if(this.isLoading&&!this.isReady){throw new L10nError('Context not ready');}
this.isLoading=true;var requested=Array.prototype.slice.call(arguments);if(requested.length===0){throw new L10nError('No locales requested');}
var supported=negotiate(this.availableLocales.concat(this.qps),requested,this.defaultLocale);if(this.supportedLocales[0]!==supported[0]){freeze.call(this,supported);}};Context.prototype.addEventListener=function(type,listener){this._emitter.addEventListener(type,listener);};Context.prototype.removeEventListener=function(type,listener){this._emitter.removeEventListener(type,listener);};Context.prototype.ready=function(callback){if(this.isReady){setTimeout(callback);}
this.addEventListener('ready',callback);};Context.prototype.once=function(callback){if(this.isReady){setTimeout(callback);return;}
var callAndRemove=(function(){this.removeEventListener('ready',callAndRemove);callback();}).bind(this);this.addEventListener('ready',callAndRemove);};var allowed={elements:['a','em','strong','small','s','cite','q','dfn','abbr','data','time','code','var','samp','kbd','sub','sup','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','br','wbr'],attributes:{global:['title','aria-label','aria-valuetext','aria-moz-hint'],a:['download'],area:['download','alt'],input:['alt','placeholder'],menuitem:['label'],menu:['label'],optgroup:['label'],option:['label'],track:['label'],img:['alt'],textarea:['placeholder'],th:['abbr']}};var rtlList=['ar','he','fa','ps','ar-x-psbidi','ur'];var nodeObserver=null;var pendingElements=null;var moConfig={attributes:true,characterData:false,childList:true,subtree:true,attributeFilter:['data-l10n-id','data-l10n-args']};navigator.mozL10n={ctx:null,get:function get(id,ctxdata){return navigator.mozL10n.ctx.get(id,ctxdata);},formatValue:function(id,ctxdata){return navigator.mozL10n.ctx.formatValue(id,ctxdata);},formatEntity:function(id,ctxdata){return navigator.mozL10n.ctx.formatEntity(id,ctxdata);},translateFragment:function(fragment){return translateFragment.call(navigator.mozL10n,fragment);},setAttributes:setL10nAttributes,getAttributes:getL10nAttributes,ready:function ready(callback){return navigator.mozL10n.ctx.ready(callback);},once:function once(callback){return navigator.mozL10n.ctx.once(callback);},get readyState(){return navigator.mozL10n.ctx.isReady?'complete':'loading';},language:{set code(lang){navigator.mozL10n.ctx.requestLocales(lang);},get code(){return navigator.mozL10n.ctx.supportedLocales[0];},get direction(){return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);}},qps:PSEUDO,_config:{appVersion:null,localeSources:Object.create(null),isPretranslated:false,},_getInternalAPI:function(){return{Error:L10nError,Context:Context,Locale:Locale,Resolver:Resolver,getPluralRule:getPluralRule,rePlaceables:rePlaceables,translateDocument:translateDocument,onMetaInjected:onMetaInjected,PropertiesParser:PropertiesParser,walkContent:walkContent,buildLocaleList:buildLocaleList};}};function getDirection(lang){return(rtlList.indexOf(lang)>=0)?'rtl':'ltr';}
var readyStates={loading:0,interactive:1,complete:2};function whenInteractive(callback){if(readyStates[document.readyState]>=readyStates.interactive){callback();return;}
document.addEventListener('readystatechange',function l10n_onrsc(){if(readyStates[document.readyState]>=readyStates.interactive){document.removeEventListener('readystatechange',l10n_onrsc);callback();}});}
function initObserver(){nodeObserver=new MutationObserver(onMutations.bind(navigator.mozL10n));nodeObserver.observe(document,moConfig);}
function init(pretranslate){if(!pretranslate){initObserver();}
initResources.call(navigator.mozL10n);}
function initResources(){var meta={};var nodes=document.head.querySelectorAll('link[rel="localization"],'+'meta[name="availableLanguages"],'+'meta[name="defaultLanguage"],'+'meta[name="appVersion"],'+'script[type="application/l10n"]');for(var i=0,node;node=nodes[i];i++){var type=node.getAttribute('rel')||node.nodeName.toLowerCase();switch(type){case'localization':this.ctx.resLinks.push(node.getAttribute('href'));break;case'meta':onMetaInjected.call(this,node,meta);break;case'script':onScriptInjected.call(this,node);break;}}
var additionalLanguagesPromise;if(navigator.mozApps&&navigator.mozApps.getAdditionalLanguages){additionalLanguagesPromise=navigator.mozApps.getAdditionalLanguages().catch(function(e){console.error('Error while loading getAdditionalLanguages',e);});document.addEventListener('additionallanguageschange',function(evt){registerLocales.call(this,meta,evt.detail);this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}else{additionalLanguagesPromise=Promise.resolve();}
additionalLanguagesPromise.then(function(extraLangs){registerLocales.call(this,meta,extraLangs);initLocale.call(this);}.bind(this));}
function registerLocales(meta,extraLangs){var locales=buildLocaleList.call(this,meta,extraLangs);navigator.mozL10n._config.localeSources=locales[1];this.ctx.registerLocales(locales[0],Object.keys(locales[1]));}
function getMatchingLangpack(appVersion,langpacks){for(var i=0,langpack;(langpack=langpacks[i]);i++){if(langpack.target===appVersion){return langpack;}}
return null;}
function buildLocaleList(meta,extraLangs){var loc,lp;var localeSources=Object.create(null);var defaultLocale=meta.defaultLanguage||this.ctx.defaultLocale;if(meta.availableLanguages){for(loc in meta.availableLanguages){localeSources[loc]='app';}}
if(extraLangs){for(loc in extraLangs){lp=getMatchingLangpack(this._config.appVersion,extraLangs[loc]);if(!lp){continue;}
if(!(loc in localeSources)||!meta.availableLanguages[loc]||parseInt(lp.revision)>meta.availableLanguages[loc]){localeSources[loc]='extra';}}}
if(!(defaultLocale in localeSources)){localeSources[defaultLocale]='app';}
return[defaultLocale,localeSources];}
function splitAvailableLanguagesString(str){var langs={};str.split(',').forEach(function(lang){lang=lang.trim().split(':');langs[lang[0]]=parseInt(lang[1]);});return langs;}
function onMetaInjected(node,meta){switch(node.getAttribute('name')){case'availableLanguages':meta.availableLanguages=splitAvailableLanguagesString(node.getAttribute('content'));break;case'defaultLanguage':meta.defaultLanguage=node.getAttribute('content');break;case'appVersion':navigator.mozL10n._config.appVersion=node.getAttribute('content');break;}}
function onScriptInjected(node){var lang=node.getAttribute('lang');var locale=this.ctx.getLocale(lang);locale.addAST(JSON.parse(node.textContent));}
function initLocale(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);window.addEventListener('languagechange',function l10n_langchange(){this.ctx.requestLocales.apply(this.ctx,navigator.languages||[navigator.language]);}.bind(this));}
function localizeMutations(mutations){var mutation;var targets=new Set();for(var i=0;i<mutations.length;i++){mutation=mutations[i];if(mutation.type==='childList'){var addedNode;for(var j=0;j<mutation.addedNodes.length;j++){addedNode=mutation.addedNodes[j];if(addedNode.nodeType!==Node.ELEMENT_NODE){continue;}
targets.add(addedNode);}}
if(mutation.type==='attributes'){targets.add(mutation.target);}}
targets.forEach(function(target){if(target.childElementCount){translateFragment.call(this,target);}else if(target.hasAttribute('data-l10n-id')){translateElement.call(this,target);}},this);}
function onMutations(mutations,self){self.disconnect();localizeMutations.call(this,mutations);self.observe(document,moConfig);}
function onReady(){if(!navigator.mozL10n._config.isPretranslated){translateDocument.call(this);}
navigator.mozL10n._config.isPretranslated=false;if(pendingElements){for(var i=0,element;element=pendingElements[i];i++){translateElement.call(this,element);}
pendingElements=null;}
if(!nodeObserver){initObserver();}
fireLocalizedEvent.call(this);}
function fireLocalizedEvent(){var event=new CustomEvent('localized',{'bubbles':false,'cancelable':false,'detail':{'language':this.ctx.supportedLocales[0]}});window.dispatchEvent(event);}
var reOverlay=/<|&#?\w+;/;var reHtml=/[&<>]/g;var htmlEntities={'&':'&amp;','<':'&lt;','>':'&gt;',};function translateDocument(){document.documentElement.lang=this.language.code;document.documentElement.dir=this.language.direction;translateFragment.call(this,document.documentElement);}
function translateFragment(element){if(typeof element.hasAttribute==='function'&&element.hasAttribute('data-l10n-id')){translateElement.call(this,element);}
var nodes=getTranslatableChildren(element);for(var i=0;i<nodes.length;i++){translateElement.call(this,nodes[i]);}}
function setL10nAttributes(element,id,args){element.setAttribute('data-l10n-id',id);if(args){element.setAttribute('data-l10n-args',JSON.stringify(args));}}
function getL10nAttributes(element){return{id:element.getAttribute('data-l10n-id'),args:JSON.parse(element.getAttribute('data-l10n-args'))};}
function getTranslatableChildren(element){return element?element.querySelectorAll('*[data-l10n-id]'):[];}
function camelCaseToDashed(string){if(string==='ariaValueText'){return'aria-valuetext';}
return string.replace(/[A-Z]/g,function(match){return'-'+match.toLowerCase();}).replace(/^-/,'');}
function escapeL10nArgs(match){return htmlEntities[match];}
function translateElement(element){if(!this.ctx.isReady){if(!pendingElements){pendingElements=[];}
pendingElements.push(element);return;}
var l10nId=element.getAttribute('data-l10n-id');if(!l10nId){return false;}
var l10nArgs=element.getAttribute('data-l10n-args');var entity=this.ctx.getEntity(l10nId,l10nArgs?JSON.parse(l10nArgs.replace(reHtml,escapeL10nArgs)):undefined);var value=entity.value;if(typeof value==='string'){if(!reOverlay.test(value)){element.textContent=value;}else{var translation=element.ownerDocument.createElement('template');translation.innerHTML=value;overlayElement(element,translation.content);}}
for(var key in entity.attrs){var attrName=camelCaseToDashed(key);if(isAttrAllowed({name:attrName},element)){element.setAttribute(attrName,entity.attrs[key]);}}}
function overlayElement(sourceElement,translationElement){var result=translationElement.ownerDocument.createDocumentFragment();var k,attr;var childElement;while((childElement=translationElement.childNodes[0])){translationElement.removeChild(childElement);if(childElement.nodeType===Node.TEXT_NODE){result.appendChild(childElement);continue;}
var index=getIndexOfType(childElement);var sourceChild=getNthElementOfType(sourceElement,childElement,index);if(sourceChild){overlayElement(sourceChild,childElement);result.appendChild(sourceChild);continue;}
if(isElementAllowed(childElement)){var sanitizedChild=childElement.ownerDocument.createElement(childElement.nodeName);overlayElement(sanitizedChild,childElement);result.appendChild(sanitizedChild);continue;}
result.appendChild(document.createTextNode(childElement.textContent));}
sourceElement.textContent='';sourceElement.appendChild(result);if(translationElement.attributes){for(k=0,attr;(attr=translationElement.attributes[k]);k++){if(isAttrAllowed(attr,sourceElement)){sourceElement.setAttribute(attr.name,attr.value);}}}}
function isElementAllowed(element){return allowed.elements.indexOf(element.tagName.toLowerCase())!==-1;}
function isAttrAllowed(attr,element){var attrName=attr.name.toLowerCase();var tagName=element.tagName.toLowerCase();if(allowed.attributes.global.indexOf(attrName)!==-1){return true;}
if(!allowed.attributes[tagName]){return false;}
if(allowed.attributes[tagName].indexOf(attrName)!==-1){return true;}
if(tagName==='input'&&attrName==='value'){var type=element.type.toLowerCase();if(type==='submit'||type==='button'||type==='reset'){return true;}}
return false;}
function getNthElementOfType(context,element,index){var nthOfType=0;for(var i=0,child;child=context.children[i];i++){if(child.nodeType===Node.ELEMENT_NODE&&child.tagName===element.tagName){if(nthOfType===index){return child;}
nthOfType++;}}
return null;}
function getIndexOfType(element){var index=0;var child;while((child=element.previousElementSibling)){if(child.tagName===element.tagName){index++;}}
return index;}
var DEBUG=false;navigator.mozL10n.ctx=new Context(window.document?document.URL:null);navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));navigator.mozL10n.ctx.addEventListener('notfounderror',function reportMissingEntity(e){if(DEBUG||e.loc==='en-US'){console.warn(e.toString());}});if(DEBUG){navigator.mozL10n.ctx.addEventListener('fetcherror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('parseerror',console.error.bind(console));navigator.mozL10n.ctx.addEventListener('resolveerror',console.error.bind(console));}
if(window.document){navigator.mozL10n._config.isPretranslated=document.documentElement.lang===navigator.language;var forcePretranslate=!navigator.mozL10n._config.isPretranslated;whenInteractive(init.bind(navigator.mozL10n,forcePretranslate));}
document.l10n={setAttributes:navigator.mozL10n.setAttributes,getAttributes:navigator.mozL10n.getAttributes,formatValue:function(id,args){return navigator.mozL10n.formatValue(id,args);},translateFragment:function(frag){return Promise.resolve(navigator.mozL10n.translateFragment(frag));},ready:new Promise(function(resolve){navigator.mozL10n.once(resolve);}),formatValues:function(){var keys=arguments;var resp=keys.map(function(key){if(Array.isArray(key)){return navigator.mozL10n.formatValue(key[0],key[1]);}
return navigator.mozL10n.formatValue(key);});return Promise.all(resp);},requestLanguages:function(langs){navigator.mozL10n.ctx.requestLocales.apply(navigator.mozL10n.ctx,langs);},pseudo:{'fr-x-psaccent':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['fr-x-psaccent'].translate(s));}},'ar-x-psbidi':{getName:function(){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].name);},processString:function(s){return Promise.resolve(navigator.mozL10n.qps['ar-x-psbidi'].translate(s));}}},};navigator.mozL10n.ready(function(){document.documentElement.setAttribute('langs',navigator.mozL10n.ctx.supportedLocales.join(' '));});navigator.mozL10n.once(function(){window.addEventListener('localized',function(){document.dispatchEvent(new CustomEvent('DOMRetranslated',{bubbles:false,cancelable:false}));});});})(this);

View file

@ -0,0 +1,11 @@
;'use strict';var LazyLoader=(function(){function LazyLoader(){this._loaded={};this._isLoading={};}
LazyLoader.prototype={_js:function(file,callback){var script=document.createElement('script');script.src=file;script.async=false;script.addEventListener('load',callback);document.head.appendChild(script);this._isLoading[file]=script;},_css:function(file,callback){var style=document.createElement('link');style.type='text/css';style.rel='stylesheet';style.href=file;document.head.appendChild(style);callback();},_html:function(domNode,callback){if(domNode.getAttribute('is')){this.load(['/shared/js/html_imports.js'],function(){HtmlImports.populate(callback);}.bind(this));return;}
for(var i=0;i<domNode.childNodes.length;i++){if(domNode.childNodes[i].nodeType==document.COMMENT_NODE){domNode.innerHTML=domNode.childNodes[i].nodeValue;break;}}
window.dispatchEvent(new CustomEvent('lazyload',{detail:domNode}));callback();},getJSON:function(file,mozSystem){return new Promise(function(resolve,reject){var xhr;if(mozSystem){xhr=new XMLHttpRequest({mozSystem:true});}else{xhr=new XMLHttpRequest();}
xhr.open('GET',file,true);xhr.responseType='json';xhr.onerror=function(error){reject(error);};xhr.onload=function(){if(xhr.response!==null){resolve(xhr.response);}else{reject(new Error('No valid JSON object was found ('+
xhr.status+' '+xhr.statusText+')'));}};xhr.send();});},load:function(files,callback){var deferred={};deferred.promise=new Promise(resolve=>{deferred.resolve=resolve;});if(!Array.isArray(files)){files=[files];}
var loadsRemaining=files.length,self=this;function perFileCallback(file){if(self._isLoading[file]){delete self._isLoading[file];}
self._loaded[file]=true;if(--loadsRemaining===0){deferred.resolve();if(callback){callback();}}}
for(var i=0;i<files.length;i++){var file=files[i];if(this._loaded[file.id||file]){perFileCallback(file);}else if(this._isLoading[file]){this._isLoading[file].addEventListener('load',perFileCallback.bind(null,file));}else{var method,idx;if(typeof file==='string'){method=file.match(/\.([^.]+)$/)[1];idx=file;}else{method='html';idx=file.id;}
this['_'+method](file,perFileCallback.bind(null,idx));}}
return deferred.promise;}};return new LazyLoader();}());

View file

@ -0,0 +1,16 @@
;'use strict';(function(exports){var _lockedStateMsgMap={'unknown':'emergencyCallsOnly-unknownSIMState','pinRequired':'emergencyCallsOnly-pinRequired','pukRequired':'emergencyCallsOnly-pukRequired','networkLocked':'emergencyCallsOnly-networkLocked','serviceProviderLocked':'emergencyCallsOnly-serviceProviderLocked','corporateLocked':'emergencyCallsOnly-corporateLocked','network1Locked':'emergencyCallsOnly-network1Locked','network2Locked':'emergencyCallsOnly-network2Locked','hrpdNetworkLocked':'emergencyCallsOnly-hrpdNetworkLocked','ruimCorporateLocked':'emergencyCallsOnly-ruimCorporateLocked','ruimServiceProviderLocked':'emergencyCallsOnly-ruimServiceProviderLocked'};var _NETWORKS_2G=['gsm','gprs','edge'];var LockScreenConnInfoManager=function(root){if(root){this._initialize(root);}};var LockScreenConnInfoManagerPrototype={_connStates:null,_settings:null,_cellbroadcastLabel:null,_telephonyDefaultServiceId:0,_airplaneMode:false};LockScreenConnInfoManagerPrototype._initialize=function lscs_initialize(root){this._connStates=root;this._settings=navigator.mozSettings;this._connStates.hidden=false;SIMSlotManager.getSlots().forEach(function(simslot,index){this._connStates.appendChild(this._createConnStateElement());simslot.conn.addEventListener('voicechange',(function(index){this.updateConnState(simslot);}).bind(this));},this);this.simSlotCardStateChangeListener=(function(evt){this.updateConnState(evt.detail);}).bind(this);window.addEventListener('simslot-cardstatechange',this.simSlotCardStateChangeListener);this.simSlotIccInfoChangeListener=(function(evt){this.updateConnState(evt.detail);}).bind(this);window.addEventListener('simslot-iccinfochange',this.simSlotIccInfoChangeListener);this.cellBroadcastMsgChangedListener=(function(evt){this._cellbroadcastLabel=evt.detail;this.updateConnStates();}).bind(this);window.addEventListener('cellbroadcastmsgchanged',this.cellBroadcastMsgChangedListener);this._settings.addObserver('ril.radio.disabled',(function(evt){this._airplaneMode=evt.settingValue;this.updateConnStates();}).bind(this));this._settings.addObserver('ril.telephony.defaultServiceId',(function(evt){this._telephonyDefaultServiceId=evt.settingValue;this.updateConnStates();}).bind(this));var req=SettingsListener.getSettingsLock().get('ril.radio.disabled');req.onsuccess=(function(){this._airplaneMode=!!req.result['ril.radio.disabled'];var req2=SettingsListener.getSettingsLock().get('ril.telephony.defaultServiceId');req2.onsuccess=(function(){this._telephonyDefaultServiceId=req2.result['ril.telephony.defaultServiceId']||0;this.updateConnStates();}).bind(this);}).bind(this);this.updateConnStates();};LockScreenConnInfoManagerPrototype.teardown=function lscs_teardown(){window.removeEventListener('simslot-cardstatechange',this.simSlotCardStateChangeListener);window.removeEventListener('simslot-iccinfochange',this.simSlotIccInfoChangeListener);window.removeEventListener('cellbroadcastmsgchanged',this.cellBroadcastMsgChangedListener);};LockScreenConnInfoManagerPrototype._createConnStateElement=function lscs_createConnStateElement(){var div=document.createElement('div');var span=document.createElement('span');var line1=document.createElement('span');var line2=document.createElement('span');line1.className=line2.className='connstate-line';div.appendChild(span);div.appendChild(line1);div.appendChild(line2);return div;};LockScreenConnInfoManagerPrototype.updateConnStates=function lscs_updateConnStates(){SIMSlotManager.getSlots().forEach((function(simslot){this.updateConnState(simslot);}).bind(this));};function lineText(node,l10nId,l10nArgs,text){if(!l10nId&&!text){node.setAttribute('data-content',true);}else{node.removeAttribute('data-content');}
if(l10nId){navigator.mozL10n.setAttributes(node,l10nId,l10nArgs);}else{node.removeAttribute('data-l10n-id');if(text){node.textContent=text;}else{node.textContent='';}}}
LockScreenConnInfoManagerPrototype.updateConnState=function lscs_updateConnState(simslot){var conn=simslot.conn;var index=simslot.index;var connstate=this._connStates.children[index];var simIDLine=connstate.children[0];var connstateLines=Array.prototype.slice.call(connstate.querySelectorAll('.connstate-line'));var iccObj=simslot.simCard;var voice=conn.voice;connstate.hidden=false;if(SIMSlotManager.isMultiSIM()){simIDLine.hidden=false;lineText(simIDLine,'lockscreen-sim-id',{n:(index+1)});}else{simIDLine.hidden=true;}
connstateLines.forEach(function(line){lineText(line);});var nextLine=function(){for(var i=0;i<connstateLines.length;i++){var line=connstateLines[i];if(line.hasAttribute('data-content')){return line;}}
return connstateLines[connstateLines.length-1];};if(this._airplaneMode){if(index===0){lineText(nextLine(),'airplaneMode');}else{connstate.hidden=true;}
simIDLine.hidden=true;return;}
if(SIMSlotManager.noSIMCardOnDevice()){if(index===0){if(voice.emergencyCallsOnly){lineText(nextLine(),'emergencyCallsOnly');lineText(nextLine(),'emergencyCallsOnly-noSIM');}else{lineText(nextLine(),'emergencyCallsOnly-noSIM');}}
simIDLine.hidden=true;return;}else if(SIMSlotManager.noSIMCardConnectedToNetwork()){if(index===0){lineText(nextLine(),'emergencyCallsOnly');}
simIDLine.hidden=true;return;}
if(SIMSlotManager.isMultiSIM()&&navigator.mozIccManager.iccIds.length==1&&simslot.isAbsent()){connstate.hidden=true;return;}
if(voice&&'state'in voice&&voice.state=='notSearching'){lineText(nextLine(),'noNetwork');return;}
if(!voice.connected&&!voice.emergencyCallsOnly){lineText(nextLine(),'searching');return;}
if(voice.emergencyCallsOnly){if(this._telephonyDefaultServiceId==index){lineText(nextLine(),'emergencyCallsOnly');lineText(nextLine(),_lockedStateMsgMap[iccObj.cardState]);}else{connstate.hidden=true;}
return;}
var operatorInfos=MobileOperator.userFacingInfo(conn);var operator=operatorInfos.operator;var is2G=_NETWORKS_2G.some(function checkConnectionType(elem){return(conn.voice.type==elem);});var l10nArgs;if(voice.roaming){l10nArgs={operator:operator};lineText(nextLine(),'roaming',l10nArgs);}else{lineText(nextLine(),null,null,operator);}
if(this._cellbroadcastLabel&&is2G){lineText(nextLine(),null,null,this._cellbroadcastLabel);}else if(operatorInfos.carrier){l10nArgs={carrier:operatorInfos.carrier,region:operatorInfos.region};lineText(nextLine(),'operator-info',l10nArgs);}};LockScreenConnInfoManager.prototype=LockScreenConnInfoManagerPrototype;exports.LockScreenConnInfoManager=LockScreenConnInfoManager;})(window);

View file

@ -0,0 +1,37 @@
;'use strict';(function(exports){var LockScreenSlide=function(opts){this.initialize(opts);};var LockScreenSlidePrototype={stopped:false,canvas:null,layout:'',useNewStyle:false,track:{length:{tiny:'280',large:'410'},color:'rgba(255, 255, 255, 0.4)',backgroundColor:'rgba(0, 0, 0, 0)',from:0,to:0,radius:0,width:0},trackNew:{length:{tiny:'276',large:'406'},strokeColorTop:'rgba(0, 0, 0, 0.2)',strokeColorBottom:'rgba(0, 0, 0, 0)',fillColorTop:'rgba(0, 0, 0, 0.2)',fillColorBottom:'rgba(0, 0, 0, 0)',backColor:'rgba(51, 51, 51, 0.15)',from:0,to:0,radius:0,width:0},arrows:{left:null,right:null,ldraw:{x:null,y:null},rdraw:{x:null,y:null}},iconBG:{radius:20,left:{color:'rgba(255, 255, 255, 0.25)'},right:{color:'rgba(255, 255, 255, 0.25)'}},slides:{left:null,right:null},areas:{left:null,right:null},area:null,overlay:null,width:0,height:80,center:{x:null,y:null},handle:{autoExpand:{accState:'normal',accFactor:1.02,sentinelOffset:40,sentinelWidth:0},bounceBackTime:200,radius:28,lineWidth:1.6,maxWidth:0,touchedColor:'0, 170, 204',touchedColorStop:'178, 229, 239',color:'255, 255, 255',backgroundColor:'255, 255, 255',backgroundAlpha:0},handleNew:{autoExpand:{accState:'normal',accFactor:1.02,sentinelOffset:40,sentinelWidth:0},bounceBackTime:200,radius:30,innerRadius:15,outerColor:'rgba(255, 255, 255, 0.9)',innerColor:'rgba(0, 0, 0, 0.05)',lineWidth:1.6,maxWidth:0,towardLeft:false,touchedColor:'0, 170, 204',touchedColorStop:'178, 229, 239'},colors:{left:{touchedColor:'255, 255, 255',touchedColorStop:'255, 255, 255'},right:{touchedColor:'255, 255, 255',touchedColorStop:'255, 255, 255'}},states:{initialized:false,sliding:false,slideReachEnd:false,slidingColorful:false,slidingColorGradientEnd:false,touch:{id:'',touched:false,initX:-1,pageX:-1,pageY:-1,tx:-1,prevX:-1,deltaX:0}},IDs:{overlay:'lockscreen',area:'lockscreen-area',canvas:'lockscreen-canvas',areas:{left:'lockscreen-area-camera',right:'lockscreen-area-unlock'}},resources:{larrow:'/lockscreen/style/images/larrow.png',rarrow:'/lockscreen/style/images/rarrow.png'},resourcesNew:{larrow:'/lockscreen/style/images/lockscreen_toggle_arrow_left.png',rarrow:'/lockscreen/style/images/lockscreen_toggle_arrow_right.png'}};LockScreenSlidePrototype.initialize=function(opts){if(opts){this._overwriteSettings(opts);}
if(opts.useNewStyle){this.track=this.trackNew;this.handle=this.handleNew;this.resources=this.resourcesNew;}
this._initializeCanvas();this.publish('lockscreenslide-unlocker-initializer');this.states.initialized=true;};LockScreenSlidePrototype.reset=function lss_reset(){this._clearCanvas();this._drawTrack();this._resetHandle();this._resetArrows();this._drawIconBG();};LockScreenSlidePrototype._overwriteSettings=function(options){var iterate=function _iterate(opts,settings){for(var property in opts){if(opts.hasOwnProperty(property)){if('object'===typeof opts[property]){iterate(opts[property],settings[property]);}
else{settings[property]=opts[property];}}}};iterate(options,this);};LockScreenSlidePrototype.handleEvent=function(evt){switch(evt.type){case'screenchange':if(evt.detail.screenOffBy=='proximity'){break;}
this._clearCanvas();this._drawTrack();this._resetHandle();this._resetArrows();this._drawIconBG();break;case'touchstart':evt.preventDefault();if(evt.target!==this.area||evt.touches.length>1){return;}
this.states.touch.id=evt.touches[0].identifier;this._onSlideBegin(this._dpx(evt.touches[0].pageX));window.addEventListener('touchend',this);window.addEventListener('touchmove',this);break;case'touchmove':if(evt.touches.length>1){this._endGesture();return;}
this._onTouchMove(this._dpx(evt.touches[0].pageX),this._dpx(evt.touches[0].pageY));if(this.states.sliding){this._onSliding(this._dpx(evt.touches[0].pageX));}
break;case'touchend':if(evt.changedTouches[0].identifier!==this.states.touch.id){return;}
this._endGesture();break;case'click':if(evt.mozInputSource===0){evt.preventDefault();if(this.areas.left===evt.target){this.publish('lockscreenslide-activate-left');}else if(this.areas.right===evt.target){this.publish('lockscreenslide-activate-right');}}
break;}};LockScreenSlidePrototype._initializeCanvas=function lss_initializeCanvas(){this.overlay=document.getElementById(this.IDs.overlay);this.area=document.getElementById(this.IDs.area);this.canvas=document.getElementById(this.IDs.canvas);this.areas.left=document.getElementById(this.IDs.areas.left);this.areas.right=document.getElementById(this.IDs.areas.right);this.area.addEventListener('touchstart',this);this.areas.left.addEventListener('click',this);this.areas.right.addEventListener('click',this);this.layout=(ScreenLayout&&ScreenLayout.getCurrentLayout&&ScreenLayout.getCurrentLayout())?ScreenLayout.getCurrentLayout():'tiny';var center=this.center;this.arrows.left=new Image();this.arrows.right=new Image();var larrow=this.arrows.left;var rarrow=this.arrows.right;larrow.src=this.resources.larrow;rarrow.src=this.resources.rarrow;larrow.onload=(function(){var offset=this.useNewStyle?(this.arrows.left.width+this.handle.radius):(this.arrows.left.width<<1);this.arrows.ldraw.x=center.x-offset;this.arrows.ldraw.y=center.y-(this.arrows.left.height>>1);var ctx=this.canvas.getContext('2d');ctx.drawImage(this.arrows.left,this.arrows.ldraw.x,this.arrows.ldraw.y,this.arrows.left.width,this.arrows.left.height);}).bind(this);rarrow.onload=(function(){var offset=this.useNewStyle?this.handle.radius:this.arrows.right.width;this.arrows.rdraw.x=center.x+offset;this.arrows.rdraw.y=center.y-(this.arrows.right.height>>1);var ctx=this.canvas.getContext('2d');ctx.drawImage(this.arrows.right,this.arrows.rdraw.x,this.arrows.rdraw.y,this.arrows.right.width,this.arrows.right.height);}).bind(this);this.width=this._dpx(window.innerWidth);this.height=this._dpx(80);this.canvas.width=this.width;this.canvas.height=this.height;this.canvas.style.width=window.innerWidth+'px';this.canvas.style.height=80+'px';this.center.x=this.canvas.offsetLeft+this.canvas.width>>1;this.center.y=this.canvas.offsetTop+this.canvas.height>>1;this.handle.radius=this._dpx(this.handle.radius);if(this.useNewStyle){this.handle.innerRadius=this._dpx(this.handle.innerRadius);}
this.track.radius=this.handle.radius+this._dpx(this.useNewStyle?2:1);this.handle.lineWidth=this._dpx(this.handle.lineWidth);this.handle.autoExpand.sentinelOffset=this._dpx(this.handle.autoExpand.sentinelOffset);this.iconBG.radius=this._dpx(this.iconBG.radius);this.canvas.getContext('2d').save();this.canvas.getContext('2d',this.handle.radius<<1,0);var trackLength='tiny'===this.layout?this.track.length.tiny:this.track.length.large;trackLength=this._dpx(trackLength);var maxWidth=(trackLength-
(this.handle.radius<<1))>>1;maxWidth-=2;this.handle.maxWidth=maxWidth;this.handle.autoExpand.sentinelWidth=maxWidth-this.handle.autoExpand.sentinelOffset;this.track.width=trackLength;this.track.from=this.center.x-maxWidth;this.track.to=this.center.x+maxWidth;this.track.y=this.center.y;this._drawTrack();this._drawIconBG();this._resetHandle();this._resetTouchStates();};LockScreenSlidePrototype._finalizeCanvas=function lss_finalizeCanvas(){this.states.slidingColorful=false;this.states.slidingColorGradientEnd=false,this._clearCanvas();};LockScreenSlidePrototype._onSliding=function lss_onSliding(tx){var mtx=this._mapCoord(tx,0)[0];var isLeft=tx-this.center.x<0;var prevState;var currentState;this._clearCanvas();var expandSentinelR=this.center.x+
this.handle.autoExpand.sentinelWidth;var expandSentinelL=this.center.x-
this.handle.autoExpand.sentinelWidth;if(tx>expandSentinelR||tx<expandSentinelL){prevState=this.handle.autoExpand.accState;this.handle.autoExpand.accState='accelerating';currentState=this.handle.autoExpand.accState;var slow=false;if(isLeft){slow=this.states.touch.deltaX>0;if(prevState!==currentState){this.publish('lockscreenslide-near-left',{'currentState':currentState,'prevState':prevState});}}else{slow=this.states.touch.deltaX<0;if(prevState!==currentState){this.publish('lockscreenslide-near-right',{'currentState':currentState,'prevState':prevState});}}}else{prevState=this.handle.autoExpand.accState;this.handle.autoExpand.accState='normal';currentState=this.handle.autoExpand.accState;if(prevState!==currentState){if(isLeft){if(prevState!==currentState){this.publish('lockscreenslide-near-left',{'currentState':currentState,'prevState':prevState});}}else{if(prevState!==currentState){this.publish('lockscreenslide-near-right',{'currentState':currentState,'prevState':prevState});}}}}
mtx=this._accelerateSlide(tx);this._drawTrack();this._drawArrowsTo(mtx);this._drawIconBG();this._drawSlideTo(mtx);};LockScreenSlidePrototype._onSlideBegin=function lss_onSlideBegin(tx){var center=this.center;var boundaryR=center.x+this.handle.radius;var boundaryL=center.x-this.handle.radius;if(tx>boundaryR||tx<boundaryL){this.states.sliding=false;return;}
this.publish('lockscreenslide-unlocking-start');this.states.touch.initX=tx;this.states.sliding=true;this._lightIcons();};LockScreenSlidePrototype._endGesture=function lss_endGesture(){window.removeEventListener('touchmove',this);window.removeEventListener('touchend',this);this.states.sliding=false;this._onSlideEnd();this._resetTouchStates();this.overlay.classList.remove('touched');this.states.slideReachEnd=false;};LockScreenSlidePrototype._stop=function lss_stop(){if(this._stopped){return;}
window.removeEventListener('touchmove',this);window.removeEventListener('touchend',this);this.area.removeEventListener('touchstart',this);this._stopped=true;};LockScreenSlidePrototype._start=function lss_stop(){if(!this._stopped){return;}
window.addEventListener('touchmove',this);window.addEventListener('touchend',this);this.area.addEventListener('touchstart',this);this._stopped=false;};LockScreenSlidePrototype._onSlideEnd=function lss_onSlideEnd(){var isLeft=this.states.touch.pageX-this.center.x<0;if(false===this.states.slideReachEnd){this._bounceBack(this.states.touch.pageX);}else{var intention=isLeft?'lockscreenslide-activate-left':'lockscreenslide-activate-right';this.publish(intention);}
this.publish('lockscreenslide-unlocking-stop');this._darkIcons();};LockScreenSlidePrototype._onTouchMove=function ls_handleMove(pageX,pageY){var touch=this.states.touch;if(!touch.touched){if(!this.states.sliding){return;}
touch.touched=true;touch.initX=pageX;var overlay=this.overlay;overlay.classList.add('touched');}
touch.tx=pageX-touch.initX;touch.pageX=pageX;if(-1!==touch.pageX){touch.deltaX=pageX-touch.prevX;}
touch.prevX=pageX;};LockScreenSlidePrototype._accelerateSlide=function lss_accelerateSlide(tx){var isLeft=tx-this.center.x<0;var dx=Math.abs(tx-this.center.x);var accFactor=this.handle.autoExpand.accFactor;var acc=Math.pow(dx,accFactor);var accTx=tx+acc;if(isLeft){accTx=tx-acc;}
if(accTx<0){accTx=0;}
return accTx;};LockScreenSlidePrototype._clearCanvas=function lss_clearCanvas(){var canvas=this.canvas;var ctx=canvas.getContext('2d');ctx.clearRect(0,0,canvas.width,canvas.height);};LockScreenSlidePrototype._bounceBack=function lss_bounceBack(tx,cb){var duration=this.handle.bounceBackTime;var center=this.center;var nextTx=tx;var tsBegin=null;var mspf=0;var interval=1;var isLeft=tx-center.x<0;var drawIt=(function _drawIt(ts){if(null===tsBegin){tsBegin=ts;}
if(ts-tsBegin<duration){if(0===mspf){mspf=ts-tsBegin;}
interval=Math.abs(center.x-tx)/(duration/mspf);nextTx=isLeft?nextTx+interval:nextTx-interval;if((isLeft&&nextTx<center.x)||(!isLeft&&nextTx>=center.x)){this._clearCanvas();this._drawTrack();this._drawArrowsTo(nextTx);this._drawIconBG();this._drawSlideTo(nextTx);}
requestAnimationFrame(drawIt);}else{this._clearCanvas();this._drawTrack();this._drawArrowsTo(center.x);this._drawIconBG();this._drawSlideTo(center.x);if(cb){cb();}}}).bind(this);requestAnimationFrame(drawIt);};LockScreenSlidePrototype._darkIcons=function lss_darkIcons(){this.areas.left.classList.add('dark');this.areas.right.classList.add('dark');};LockScreenSlidePrototype._drawArrowsTo=function lss_drawArrows(tx){var canvas=this.canvas;var ctx=canvas.getContext('2d');var center=this.center;var offset=tx-center.x;var isLeft=offset<0;var alpha=1-Math.min(1,Math.abs(offset)/this._dpx(30));var position;var oldAlpha;if(this.handle.maxWidth<Math.abs(offset)){this.states.slideReachEnd=true;return;}
this.states.slideReachEnd=false;if(isLeft){position=this.useNewStyle?(tx-this.arrows.left.width-this.handle.radius):(tx-(this.arrows.left.width<<1));oldAlpha=ctx.globalAlpha;ctx.globalAlpha=alpha;ctx.drawImage(this.arrows.left,position,this.arrows.ldraw.y,this.arrows.left.width,this.arrows.left.height);ctx.globalAlpha=oldAlpha;ctx.drawImage(this.arrows.right,this.arrows.rdraw.x,this.arrows.rdraw.y,this.arrows.right.width,this.arrows.right.height);}else{position=this.useNewStyle?(tx+this.handle.radius):(tx+this.arrows.right.width);oldAlpha=ctx.globalAlpha;ctx.globalAlpha=alpha;ctx.drawImage(this.arrows.right,position,this.arrows.rdraw.y,this.arrows.right.width,this.arrows.right.height);ctx.globalAlpha=oldAlpha;ctx.drawImage(this.arrows.left,this.arrows.ldraw.x,this.arrows.ldraw.y,this.arrows.left.width,this.arrows.left.height);}};LockScreenSlidePrototype._drawTrack=function lss_drawTrack(){var canvas=this.canvas;var ctx=canvas.getContext('2d');var radius=this.track.radius;var startAngle;var endAngle;if(this.useNewStyle){startAngle=1.5*Math.PI;endAngle=0.5*Math.PI;var draw=(function(fillStyle,strokeStyle){ctx.beginPath();ctx.fillStyle=fillStyle;ctx.strokeStyle=strokeStyle;ctx.lineWidth=this.handle.lineWidth;ctx.moveTo(this.track.from,this.track.y-radius);ctx.lineTo(this.track.to,this.track.y-radius);ctx.arc(this.track.to,this.track.y,radius,startAngle,endAngle,false);ctx.lineTo(this.track.from,this.track.y+radius);ctx.arc(this.track.from,this.track.y,radius,endAngle,startAngle,false);ctx.fill();ctx.closePath();ctx.stroke();}).bind(this);draw(this.track.backColor,'transparent');var gradientStroke=ctx.createLinearGradient(this.track.from-radius,this.track.y-radius,this.track.from-radius,this.track.y+radius);var gradientFill=ctx.createLinearGradient(this.track.from-radius,this.track.y-radius,this.track.from-radius,this.track.y+radius);gradientStroke.addColorStop(0,this.track.strokeColorTop);gradientStroke.addColorStop(1,this.track.strokeColorBottom);gradientFill.addColorStop(0,this.track.fillColorTop);gradientFill.addColorStop(1,this.track.fillColorBottom);draw(gradientFill,gradientStroke);}else{startAngle=1.5*Math.PI;endAngle=0.5*Math.PI;var strokeStyle=this.track.color;ctx.fillStyle=this.track.backgroundColor;ctx.lineWidth=this.handle.lineWidth;ctx.strokeStyle=strokeStyle;ctx.beginPath();ctx.arc(this.track.from,this.track.y,radius,endAngle,startAngle,false);ctx.lineTo(this.track.from,this.track.y-radius);ctx.lineTo(this.track.to,this.track.y-radius);ctx.arc(this.track.to,this.track.y,radius,startAngle,endAngle,false);ctx.lineTo(this.track.from,this.track.y+radius);ctx.fill();ctx.stroke();ctx.closePath();}};LockScreenSlidePrototype._drawSlideTo=function lss_drawSlideTo(tx){var canvas=this.canvas;var ctx=canvas.getContext('2d');var maxWidth=this.handle.maxWidth;var offset=tx;var radius=this.handle.radius;var center=this.center;var rw=offset-center.x;var urw=Math.abs(rw);if(this.handle.maxWidth<urw){offset=rw>0?center.x+maxWidth:center.x-maxWidth;}
var counterclock=false;if(offset-center.x<0){counterclock=true;}
var isLeft=counterclock;var isRight=offset-center.x>0;if(isLeft){this.handle.touchedColor=this.colors.left.touchedColor;this.handle.touchedColorStop=this.colors.left.touchedColorStop;}else if(isRight){this.handle.touchedColor=this.colors.right.touchedColor;this.handle.touchedColorStop=this.colors.right.touchedColorStop;}
var startAngle=1.5*Math.PI;var endAngle=0.5*Math.PI;var fillAlpha=0.0;var strokeStyle='white';const GRADIENT_LENGTH=50;if(this.useNewStyle){if(0===urw){ctx.beginPath();ctx.arc(center.x,center.y,radius,0,2*Math.PI,false);ctx.fillStyle=this.handle.outerColor;ctx.closePath();ctx.fill();ctx.beginPath();ctx.arc(center.x,center.y,this.handle.innerRadius,0,2*Math.PI,false);ctx.fillStyle=this.handle.innerColor;ctx.closePath();ctx.fill();}else{fillAlpha=0.9-Math.min(0.7,(urw/this.handle.maxWidth)*0.7);strokeStyle='transparent';ctx.fillStyle='rgba('+this.handle.touchedColor+', '+
fillAlpha+')';ctx.strokeStyle=strokeStyle;ctx.beginPath();ctx.arc(center.x,center.y,radius,endAngle,startAngle,counterclock);ctx.lineTo(center.x,center.y-radius);ctx.lineTo(center.x+(offset-center.x),center.y-radius);ctx.arc(offset,center.y,radius,startAngle,endAngle,counterclock);ctx.lineTo(center.x,center.y+radius);ctx.fill();ctx.stroke();ctx.closePath();}}else{var fillColor;var strokeColor;var borderAlpha;if(urw>15&&true!==this.states.slidingColorful){fillAlpha=(urw-15)/GRADIENT_LENGTH;if(fillAlpha>1.0){fillAlpha=1.0;this.states.slidingColorGradientEnd=true;}
borderAlpha=1.0-fillAlpha;strokeStyle='rgba('+this.handle.touchedColorStop+','+borderAlpha+')';this.states.slidingColorful=true;}else{if(0===urw){fillAlpha=this.handle.backgroundAlpha;strokeColor=this.handle.color;fillColor=this.handle.backgroundColor;}else{fillAlpha=(urw-15)/GRADIENT_LENGTH;if(fillAlpha>1.0){fillAlpha=1.0;}
strokeColor=this.handle.touchedColorStop;fillColor=this.handle.touchedColor;}
borderAlpha=1.0-fillAlpha;strokeStyle='rgba('+strokeColor+','+borderAlpha+')';}
ctx.fillStyle='rgba('+fillColor+','+fillAlpha+')';ctx.lineWidth=this.handle.lineWidth;ctx.strokeStyle=strokeStyle;ctx.beginPath();ctx.arc(center.x,center.y,radius,endAngle,startAngle,counterclock);ctx.lineTo(center.x,center.y-radius);ctx.lineTo(center.x+(offset-center.x),center.y-radius);ctx.arc(offset,center.y,radius,startAngle,endAngle,counterclock);ctx.lineTo(center.x,center.y+radius);ctx.fill();ctx.stroke();ctx.closePath();}};LockScreenSlidePrototype._drawIconBG=function lss_dibg(){if(!this.useNewStyle){return;}
var canvas=this.canvas;var ctx=canvas.getContext('2d');ctx.fillStyle=this.iconBG.left.color;ctx.strokeStyle='transparent';ctx.beginPath();ctx.arc(this.track.from,this.track.y,this.iconBG.radius,0,2*Math.PI,false);ctx.stroke();ctx.closePath();ctx.fill();ctx.fillStyle=this.iconBG.right.color;ctx.beginPath();ctx.arc(this.track.to,this.track.y,this.iconBG.radius,0,2*Math.PI,false);ctx.fill();ctx.stroke();ctx.closePath();};LockScreenSlidePrototype._dpx=function lss_dpx(px){return px*window.devicePixelRatio;};LockScreenSlidePrototype._lightIcons=function lss_lightIcons(){this.areas.left.classList.remove('dark');this.areas.right.classList.remove('dark');};LockScreenSlidePrototype._mapCoord=function lss_mapCoord(x,y){var cw=this.canvas.clientWidth;var ch=this.canvas.clientHeight;return[cw*x/window.innerWidth,ch*y/window.innerHeight];};LockScreenSlidePrototype._resetArrows=function lss_restoreArrows(){var canvas=this.canvas;var ctx=canvas.getContext('2d');ctx.drawImage(this.arrows.left,this.arrows.ldraw.x,this.arrows.ldraw.y,this.arrows.left.width,this.arrows.left.height);ctx.drawImage(this.arrows.right,this.arrows.rdraw.x,this.arrows.rdraw.y,this.arrows.right.width,this.arrows.right.height);};LockScreenSlidePrototype._resetHandle=function lss_resetHandle(){this.states.slidingColorful=false;this.states.slidingColorGradientEnd=false;var centerx=this.center.x;this._drawSlideTo(centerx);};LockScreenSlidePrototype._resetTouchStates=function lss_resetTouchStates(){this.states.touch={id:null,touched:false,initX:this.center.x,pageX:this.center.x,pageY:this.center.y,tx:0,prevX:this.center.x,deltaX:0};};LockScreenSlidePrototype.publish=function lss_publish(type,detail){window.dispatchEvent(new CustomEvent(type,{'detail':detail}));};LockScreenSlide.prototype=LockScreenSlidePrototype;exports.LockScreenSlide=LockScreenSlide;})(window);

View file

@ -0,0 +1,3 @@
;'use strict';var MobileInfo={brazil:{carriers:{'00':'NEXTEL','02':'TIM','03':'TIM','04':'TIM','05':'CLARO','06':'VIVO','07':'CTBC','08':'TIM','10':'VIVO','11':'VIVO','15':'SERCOMTEL','16':'OI','23':'VIVO','24':'OI','31':'OI','32':'CTBC','33':'CTBC','34':'CTBC','37':'AEIOU'},regions:{'11':'SP','12':'SP','13':'SP','14':'SP','15':'SP','16':'SP','17':'SP','18':'SP','19':'SP','21':'RJ','22':'RJ','24':'RJ','27':'ES','28':'ES','31':'MG','32':'MG','33':'MG','34':'MG','35':'MG','37':'MG','38':'MG','41':'PR','42':'PR','43':'PR','44':'PR','45':'PR','46':'PR','47':'SC','48':'SC','49':'SC','51':'RS','53':'RS','54':'RS','55':'RS','61':'DF','62':'GO','63':'TO','64':'GO','65':'MT','66':'MT','67':'MS','68':'AC','69':'RO','71':'BA','73':'BA','74':'BA','75':'BA','77':'BA','79':'SE','81':'PE','82':'AL','83':'PB','84':'RN','85':'CE','86':'PI','87':'PE','88':'CE','89':'PI','91':'PA','92':'AM','93':'PA','94':'PA','95':'RR','96':'AP','97':'AM','98':'MA','99':'MA'}}};var MobileOperator={BRAZIL_MCC:'724',BRAZIL_CELLBROADCAST_CHANNEL:50,userFacingInfo:function mo_userFacingInfo(mobileConnection){var network=mobileConnection.voice.network;var iccid=mobileConnection.iccId;var iccObj=navigator.mozIccManager.getIccById(iccid);var iccInfo=iccObj?iccObj.iccInfo:null;var operator=network?(network.shortName||network.longName):null;if(operator&&iccInfo&&iccInfo.isDisplaySpnRequired&&iccInfo.spn){if(iccInfo.isDisplayNetworkNameRequired&&operator!==iccInfo.spn){operator=operator+' '+iccInfo.spn;}else{operator=iccInfo.spn;}}
var carrier,region;if(this.isBrazil(mobileConnection)){var lac=mobileConnection.voice.cell.gsmLocationAreaCode%100;var carriers=MobileInfo.brazil.carriers;var regions=MobileInfo.brazil.regions;carrier=carriers[network.mnc]||(this.BRAZIL_MCC+network.mnc);region=(regions[lac]?regions[lac]+' '+lac:'');}
return{'operator':operator,'carrier':carrier,'region':region};},isBrazil:function mo_isBrazil(mobileConnection){var cell=mobileConnection.voice.cell;var net=mobileConnection.voice.network;return net?(net.mcc===this.BRAZIL_MCC&&cell&&cell.gsmLocationAreaCode):null;}};

View file

@ -0,0 +1,35 @@
;(function(global){'use strict';global.mozIntl={formatList:function(list){return navigator.mozL10n.formatValue('listSeparator_middle').then(sep=>list.join(sep));},DateTimeFormat:function(locales,options){const resolvedOptions=Object.assign({},options);if(resolvedOptions.dayperiod){if(resolvedOptions.hour===undefined){resolvedOptions.hour='numeric';}}
if(resolvedOptions.hour!==undefined&&resolvedOptions.hour12===undefined){resolvedOptions.hour12=navigator.mozHour12;}
if(resolvedOptions.dayperiod===undefined&&resolvedOptions.hour12===true){resolvedOptions.dayperiod=true;}
var intlFormat=new Intl.DateTimeFormat(locales,resolvedOptions);resolvedOptions.locale=intlFormat.resolvedOptions().locale;resolvedOptions.hour12=intlFormat.resolvedOptions().hour12;var hourFormatter;if(resolvedOptions.dayperiod!==undefined&&resolvedOptions.hour12===true){hourFormatter=Intl.DateTimeFormat(locales,{hour:'numeric',hour12:false});}
return{resolvedOptions(){return resolvedOptions;},format:function(date,tokenFormats){var dayPeriod;var string=intlFormat.format(date);if(resolvedOptions.dayperiod===false&&resolvedOptions.hour12===true){dayPeriod=getDayPeriodTokenForDate(date,hourFormatter);string=string.replace(dayPeriod,'').trim();}else if(resolvedOptions.dayperiod===true&&options.hour===undefined){dayPeriod=getDayPeriodTokenForDate(date,hourFormatter);const hour=date.toLocaleString(navigator.languages,{hour12:true,hour:'numeric'}).replace(dayPeriod,'').trim();string=string.replace(hour,'').trim();}
for(var token in tokenFormats){if(token==='dayperiod'&&resolvedOptions.hour12===false){continue;}
const localOptions={[token]:resolvedOptions[token],};var formatter=global.mozIntl.DateTimeFormat(navigator.languages,localOptions);var tokenString=formatter.format(date);string=string.replace(tokenString,tokenFormats[token]);}
return string;},};},calendarInfo:function(token){switch(token){case'firstDayOfTheWeek':return navigator.mozL10n.formatValue('firstDayOfTheWeek').then(firstDayOfTheWeek=>parseInt(firstDayOfTheWeek)%7);default:throw new Error('Unknown token: '+token);}},DurationFormat:function(locales=navigator.languages,options={}){const resolvedOptions=Object.assign({locale:locales[0],maxUnit:'hour',minUnit:'second',},options);const numFormatter=Intl.NumberFormat(locales,{style:'decimal',useGrouping:false,minimumIntegerDigits:2});const maxUnitIdx=getDurationUnitIdx(resolvedOptions.maxUnit,0);const minUnitIdx=getDurationUnitIdx(resolvedOptions.minUnit,durationFormatOrder.length-1);return navigator.mozL10n.formatValue('durationPattern').then(fmt=>({resolvedOptions:function(){return resolvedOptions;},format:function(input){const minValue=durationFormatElements[resolvedOptions.minUnit].value;input=Math.round(input/minValue)*minValue;const duration=splitIntoTimeUnits(input,maxUnitIdx,minUnitIdx);var string=trimDurationPattern(fmt,resolvedOptions.maxUnit,resolvedOptions.minUnit);for(var unit in duration){const token=durationFormatElements[unit].token;string=string.replace(token,numFormatter.format(duration[unit]));}
if(input<0){return'-'+string;}
return string;}}));},RelativeTimeFormat:function(locales,options){return{resolvedOptions:function(){return options;},format:function(x){const{unit,value}=relativeTimeFormatId(x,options);return navigator.mozL10n.formatValue(unit,{value});},};},UnitFormat:function(locales,options){const unitGroup=getUnitFormatGroupName(options.unit);if(unitGroup===undefined){throw new RangeError(`invalid value ${options.unit} for option unit`);}
if(!unitFormatGroups[unitGroup].styles.includes(options.style)){throw new RangeError(`invalid value ${options.style} for option style`);}
const unit=`${unitGroup}-${options.unit}-${options.style}`;return{format:function(x){return document.l10n.formatValue(unit,{value:x});},};},_gaia:{relativePart:function(milliseconds){const units=computeTimeUnits(milliseconds);const unit=getBestMatchUnit(units);return{unit:unit+'s',value:Math.abs(units[unit])};},RelativeDate:function(locales,options){const style=options&&options.style||'long';const maxFormatter=Intl.DateTimeFormat(locales,{year:'numeric',month:'numeric',day:'numeric'});const relativeFmtOptions={unit:'bestFit',style:style,minUnit:'minute',};return{format:function(time,maxDiff){maxDiff=maxDiff||86400*10;const secDiff=(Date.now()-time)/1000;if(isNaN(secDiff)){return navigator.mozL10n.formatValue('incorrectDate');}
if(secDiff>maxDiff){return Promise.resolve(maxFormatter.format(time));}
const{unit,value}=relativeTimeFormatId(time,relativeFmtOptions);return navigator.mozL10n.formatValue(unit,{value});},formatElement:function(element,time,maxDiff){maxDiff=maxDiff||86400*10;const secDiff=(Date.now()-time)/1000;if(isNaN(secDiff)){element.setAttribute('data-l10n-id','incorrectDate');}
element.removeAttribute('data-l10n-id');if(secDiff>maxDiff){element.textContent=maxFormatter.format(time);}
const{unit,value}=relativeTimeFormatId(time,relativeFmtOptions);navigator.mozL10n.setAttributes(element,unit,{value});},};},getFormattedUnit:function(type,style,v){if(!unitFormatData.hasOwnProperty(type)){throw new RangeError(`invalid type ${type}`);}
if(!unitFormatGroups[type].styles.includes(style)){throw new RangeError(`invalid style ${style} for type ${type}`);}
var units=unitFormatData[type];var scale=0;for(let i=1;i<units.length;i++){if(v<units[i].value*unitFormatGroups[type].rounding){scale=i-1;break;}else if(i===units.length-1){scale=i;}}
var value=Math.round(v/units[scale].value*100)/100;return global.mozIntl.UnitFormat(navigator.languages,{unit:units[scale].name,style:style}).format(value);},}};const durationFormatOrder=['hour','minute','second','millisecond'];const durationFormatElements={'hour':{value:3600000,token:'hh'},'minute':{value:60000,token:'mm'},'second':{value:1000,token:'ss'},'millisecond':{value:10,token:'SS'}};const unitFormatData={'duration':[{'name':'second','value':1},{'name':'minute','value':60},{'name':'hour','value':60*60},{'name':'day','value':24*60*60},{'name':'month','value':30*24*60*60},],'digital':[{'name':'byte','value':1},{'name':'kilobyte','value':1024},{'name':'megabyte','value':1024*1024},{'name':'gigabyte','value':1024*1024*1024},{'name':'terabyte','value':1024*1024*1024*1024},],};const unitFormatGroups={'duration':{'units':['second','minute','hour','day','month'],'styles':['narrow'],'rounding':1},'digital':{'units':['byte','kilobyte','megabyte','gigabyte','terabyte'],'styles':['short'],'rounding':0.8}};function getDurationUnitIdx(name,defaultValue){if(!name){return defaultValue;}
const pos=durationFormatOrder.indexOf(name);if(pos===-1){throw new Error('Unknown unit type: '+name);}
return pos;}
function splitIntoTimeUnits(v,maxUnitIdx,minUnitIdx){const units={};var input=Math.abs(v);for(var i=maxUnitIdx;i<=minUnitIdx;i++){const key=durationFormatOrder[i];const{value}=durationFormatElements[key];units[key]=i==minUnitIdx?Math.round(input/value):Math.floor(input/value);input-=units[key]*value;}
return units;}
function trimDurationPattern(string,maxUnit,minUnit){const maxToken=durationFormatElements[maxUnit].token;const minToken=durationFormatElements[minUnit].token;string=string.substring(string.indexOf(maxToken),string.indexOf(minToken)+minToken.length);return string;}
function getDayPeriodTokenForDate(date,hourFormatter){const hourToken=hourFormatter.format(date);const newDate=new Date(date);newDate.setHours(parseInt(hourToken));return new Intl.DateTimeFormat(navigator.language, {hour:'numeric', hour12:true}).formatToParts(newDate).find(part => part.type === 'dayPeriod').value;}
function computeTimeUnits(v){const units={};const millisecond=Math.round(v);const second=Math.round(millisecond/1000);const minute=Math.round(second/60);const hour=Math.round(minute/60);const day=Math.round(hour/24);const rawYear=day*400/146097;units.millisecond=millisecond;units.second=second;units.minute=minute;units.hour=hour;units.day=day;units.week=Math.round(day/7);units.month=Math.round(rawYear*12);units.quarter=Math.round(rawYear*4);units.year=Math.round(rawYear);return units;}
function getBestMatchUnit(units){if(Math.abs(units.minute)<45){return'minute';}
if(Math.abs(units.hour)<22){return'hour';}
if(Math.abs(units.day)<7){return'day';}
if(Math.abs(units.week)<4){return'week';}
if(Math.abs(units.month)<11){return'month';}
return'year';}
function relativeTimeFormatId(x,options){const ms=x-Date.now();const units=computeTimeUnits(ms);const unit=options.unit==='bestFit'?getBestMatchUnit(units):options.unit;const v=units[unit];const tl=v<0?'-ago':'-until';const style=options.style||'long';const entry=unit+'s'+tl+'-'+style;return{unit:entry,value:Math.abs(v)};}
function getUnitFormatGroupName(unitName){for(let groupName in unitFormatGroups){if(unitFormatGroups[groupName].units.includes(unitName)){return groupName;}}
return undefined;}})(this);

View file

@ -0,0 +1,8 @@
;'use strict';var ScreenLayout={defaultQueries:{tiny:'(max-width: 767px)',small:'(min-width: 768px) and (max-width: 991px)',medium:'(min-width: 992px) and (max-width: 1200px)',large:'(min-width: 1201px)',hardwareHomeButton:window.VulpesCompat?'(min-width: 0px)':'(-moz-physical-home-button)'},init:function sl_init(){this.queries=(function(qs){var result={};for(var key in qs){result[key]=window.matchMedia(qs[key]);}
return result;})(this.defaultQueries);},_isOnRealDevice:undefined,isOnRealDevice:function sl_isOnRealDevice(){if(typeof(this._isOnRealDevice)!=='undefined'){return this._isOnRealDevice;}
if(window.innerWidth===screen.availWidth){this._isOnRealDevice=true;}else{this._isOnRealDevice=false;}
return this._isOnRealDevice;},getCurrentLayout:function sl_getCurrentLayout(type){if(type===undefined){for(var name in this.defaultQueries){if(this.queries[name]&&this.queries[name].matches){return name;}}}
if(typeof this.queries[type]!=='undefined'){return this.queries[type].matches;}
return false;},watch:function sl_watch(name,media){var mediaString=media||this.queries[name].media;if(!mediaString){return;}
this.unwatch(name);this.queries[name]=window.matchMedia(mediaString);this.boundHandleChange=this.handleChange.bind(this);this.queries[name].addListener(this.boundHandleChange);},unwatch:function sl_unwatch(name){if(this.queries[name]){this.queries[name].removeListener(this.boundHandleChange);}},handleChange:function sl_handleChange(evt){for(var key in this.queries){if(this.queries[key].media!==evt.media){continue;}
window.dispatchEvent(new CustomEvent('screenlayoutchange',{detail:{name:key,status:evt.matches}}));}}};ScreenLayout.init();

View file

@ -0,0 +1,4 @@
;;'use strict';var SettingsListener={_lock:null,_observers:[],getSettingsLock:function sl_getSettingsLock(){if(this._lock&&!this._lock.closed){return this._lock;}
var settings=window.navigator.mozSettings;return(this._lock=settings.createLock());},observe:function sl_observe(name,defaultValue,callback){var settings=window.navigator.mozSettings;if(!settings){window.setTimeout(function(){callback(defaultValue);});return;}
var req;try{req=this.getSettingsLock().get(name);}catch(e){console.warn('Stale lock in settings_listener.js.','See https://bugzilla.mozilla.org/show_bug.cgi?id=793239');this._lock=null;req=this.getSettingsLock().get(name);}
req.addEventListener('success',(function onsuccess(){callback(typeof(req.result[name])!='undefined'?req.result[name]:defaultValue);}));var settingChanged=function settingChanged(evt){callback(evt.settingValue);};settings.addObserver(name,settingChanged);this._observers.push({name:name,callback:callback,observer:settingChanged});},unobserve:function sl_unobserve(name,callback){var settings=window.navigator.mozSettings;var that=this;this._observers.forEach(function(value,index){if(value.name===name&&value.callback===callback){settings.removeObserver(name,value.observer);that._observers.splice(index,1);}});}};

View file

@ -0,0 +1,4 @@
;'use strict';function SettingsURL(){this._url=null;this._isBlob=false;}
SettingsURL.prototype={set:function(value){if(this._isBlob){window.URL.revokeObjectURL(this._url);}
if(value instanceof Blob){this._isBlob=true;this._url=window.URL.createObjectURL(value);}else{this._isBlob=false;this._url=value;}
return this._url;},get:function(){return this._url;}};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,5 @@
;'use strict';(function(window){var _start=Date.now();var DEBUG=false;window.SIMSlot=function SIMSlot(conn,index,card){this.index=index;this.conn=conn;if(card){this.update(card);}
this.publish('created');};SIMSlot.EVENTS=['cardstatechange','iccinfochange','stkcommand','stksessionend'];SIMSlot.METHODS=['sendStkResponse','sendStkMenuSelection','sendStkTimerExpiration','sendStkEventDownload'];SIMSlot.DOM_REQUEST_METHODS=['getCardLock','unlockCardLock','setCardLock','getCardLockRetryCount','readContacts','updateContact','iccOpenChannel','iccExchangeAPDU','iccCloseChannel'];SIMSlot.ABSENT_TYPES=['permanentBlocked'];SIMSlot.LOCK_TYPES=['pinRequired','pukRequired','networkLocked','corporateLocked','serviceProviderLocked','network1Locked','network2Locked','hrpdNetworkLocked','ruimCorporateLocked','ruimServiceProviderLocked'];SIMSlot.prototype.update=function ss_update(iccObj){this.simCard=iccObj;this.constructor.EVENTS.forEach(function iterater(evt){iccObj.addEventListener(evt,this);},this);this.constructor.DOM_REQUEST_METHODS.forEach(function iterator(domRequest){this[domRequest]=function(){return iccObj[domRequest].apply(iccObj,arguments);};},this);this.constructor.METHODS.forEach(function iterator(method){this[method]=function(){return iccObj[method].apply(iccObj,arguments);};},this);this.publish('updated');};SIMSlot.prototype.EVENT_PREFIX='simslot-';SIMSlot.prototype.CLASS_NAME='SIMSLOT';SIMSlot.prototype.publish=function ss_publish(eventName){this.debug(' publish: '+eventName);window.dispatchEvent(new CustomEvent(this.EVENT_PREFIX+eventName,{detail:this}));};SIMSlot.prototype.handleEvent=function ss_handleEvent(evt){switch(evt.type){default:this.publish(evt.type);if(this.simCard){this.debug(this.simCard.cardState);}
break;}};SIMSlot.prototype.debug=function(){if(DEBUG){console.log('['+this.CLASS_NAME+']'+'['+(this.index)+']'+'['+(new Date().getTime()/1000-_start).toFixed(3)+']'+
Array.slice(arguments).concat());}};SIMSlot.prototype.isAbsent=function ss_isAbsent(){return(!this.simCard||this.constructor.ABSENT_TYPES.indexOf(this.simCard.cardState)>=0||this.simCard&&this.simCard.iccInfo&&this.simCard.iccInfo.iccid===null);};SIMSlot.prototype.getSmsc=function ss_getSmsc(cb){var mobileMessage=window.navigator.mozMobileMessage;if(!mobileMessage){console.error('can\'t access mozMobileMessage');cb(null);}else{mobileMessage.getSmscAddress(this.index).then((result)=>{var smsc;if(typeof result==='string'||result instanceof String){smsc=result.split(',')[0].replace(/"/g,'');}else{smsc=result.address;}
cb(smsc);},(error)=>{console.error(error);cb(null);});}};SIMSlot.prototype.isUnknownState=function ss_isUnknownState(){var empty=(this.simCard.cardState==='');var unknown=(this.simCard.cardState==='unknown');return!this.simCard.cardState||unknown||empty;};SIMSlot.prototype.isLocked=function ss_isLocked(){return this.constructor.LOCK_TYPES.indexOf(this.simCard.cardState)>=0;};SIMSlot.prototype.getCardState=function ss_getCardState(){return this.simCard.cardState;};}(window));

View file

@ -0,0 +1,9 @@
;'use strict';(function(window){var IccManager=navigator.mozIccManager;window.SIMSlotManager={length:0,_instances:[],TIMEOUT_FOR_SIM2:2000,_timerForSIM2:null,ready:false,init:function ssm_init(){if(!IccManager){return;}
this._conns=Array.prototype.slice.call(navigator.mozMobileConnections);this.length=this._conns.length;if(this._conns.length===0){return;}
var allSIMCardDetected=true;this._conns.forEach(function iterator(conn,index){var slot=new SIMSlot(conn,index,IccManager.getIccById(conn.iccId));this._instances.push(slot);if(slot.isAbsent()){allSIMCardDetected=false;}},this);if(allSIMCardDetected){this.publishSIMSlotIsReady();}else if(this.isMultiSIM()&&this.hasOnlyOneSIMCardDetected()){this.waitForSecondSIM();}
IccManager.addEventListener('iccdetected',this);window.dispatchEvent(new CustomEvent('simslotmanagerstarted'));},isMultiSIM:function(){return(this.length>1);},isSIMCardAbsent:function ssm_isSIMCardAbsent(index){var slot=this.get(index);if(slot){return slot.isAbsent();}else{return true;}},hasOnlyOneSIMCardDetected:function(){var sim0Absent=this.isSIMCardAbsent(0);var sim1Absent=this.isSIMCardAbsent(1);var hasOneSim=(sim0Absent&&!sim1Absent)||(!sim0Absent&&sim1Absent);return hasOneSim;},noSIMCardOnDevice:function ssm_noSIMCardOnDevice(){if(!IccManager||!IccManager.iccIds){return true;}
return(IccManager.iccIds.length===0);},noSIMCardConnectedToNetwork:function ssm_noSIMCardConnectedToNetwork(){if(!IccManager||!IccManager.iccIds){return true;}
return this._instances.every(function iterator(instance){return instance.conn.voice&&instance.conn.voice.emergencyCallsOnly;});},get:function ssm_get(index){if(index>this.length-1){return null;}
return this._instances[index];},getMobileConnection:function ssm_getMobileConnection(index){if(index>this.length-1){return null;}
return this._instances[index].conn;},getSlots:function ssm_getSlots(){return this._instances;},getSlotByIccId:function ssm_getSlotByIccId(iccId){var found=null;this._instances.some(function iterator(slot,index){if(slot.conn.iccId&&slot.conn.iccId===iccId){found=slot;return true;}else{return false;}},this);return found;},waitForSecondSIM:function(){var self=this;this._timerForSIM2=setTimeout(function(){clearTimeout(self._timerForSIM2);self.publishSIMSlotIsReady();},this.TIMEOUT_FOR_SIM2);},publishSIMSlotIsReady:function(){if(!this.ready){this.ready=true;window.dispatchEvent(new CustomEvent('simslotready'));}},handleEvent:function ssm_handleEvent(evt){switch(evt.type){case'iccdetected':var slot=this.getSlotByIccId(evt.iccId);if(slot){slot.update(IccManager.getIccById(evt.iccId));if(!this.isMultiSIM()){this.publishSIMSlotIsReady();}else{if(this.hasOnlyOneSIMCardDetected()){this.waitForSecondSIM();}else{clearTimeout(this._timerForSIM2);this.publishSIMSlotIsReady();}}}
break;}}};SIMSlotManager.init();}(window));

View file

@ -0,0 +1,321 @@
/* ----------------------------------
* Action menu
* ---------------------------------- */
html[dir="ltr"] [role="dialog"][data-type="action"] [dir],
html[dir="ltr"] [role="dialog"][data-type="action"] button {
text-align: left;
}
html[dir="rtl"] [role="dialog"][data-type="action"] [dir],
html[dir="rtl"] [role="dialog"][data-type="action"] button {
text-align: right;
}
/* Main dialog setup */
[role="dialog"][data-type="action"] {
background: #2d2d2d;
overflow: hidden;
position: fixed;
z-index: 100;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 0 0 7rem;
/**
* Using "font-size: 0" to avoid the unwanted visual space (about 3px) created
* by white spaces and line breaks in the code between inline-block elements.
*/
font-size: 0;
color: #fff;
}
[role="dialog"][data-type="action"]:before {
content: '';
display: inline-block;
vertical-align: top;
width: 0.1rem;
height: 100%;
margin-inline-start: -0.1rem;
}
[role="dialog"][data-type="action"] > header {
box-sizing: border-box;
font-size: 1.6rem;
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 10;
height: 5rem;
line-height: 4.9rem;
color: #fff;
white-space: nowrap;
text-overflow: ellipsis;
display: block;
overflow: hidden;
font-weight: normal;
padding: 0 3rem;
border-bottom: 0.1rem solid #616262;
}
[role="dialog"][data-type="action"] > header * {
overflow: hidden;
text-overflow: ellipsis;
}
[role="dialog"][data-type="action"] > header h1 {
font-size: 1.6rem;
line-height: 4.9rem;
color: #fff;
white-space: nowrap;
text-overflow: ellipsis;
display: block;
overflow: hidden;
margin: 0;
height: 100%;
font-weight: normal;
}
/* Generic set of actions in toolbar */
[role="dialog"][data-type="action"] > header menu[type="toolbar"] {
height: 100%;
margin: 0 -3rem;
margin-inline-start: 1rem;
padding: 0;
}
html[dir="ltr"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] { float: right; }
html[dir="rtl"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] { float: left; }
[role="dialog"][data-type="action"] > header menu[type="toolbar"] a,
[role="dialog"][data-type="action"] > header menu[type="toolbar"] button {
box-sizing: border-box;
position: relative;
width: auto;
min-width: 5rem;
height: 4.9rem;
margin-bottom: 0;
padding: 0 1rem;
border-radius: 0;
line-height: 4.9rem;
background: none;
text-align: center;
text-shadow: none;
z-index: 5;
}
html[dir="ltr"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] a,
html[dir="ltr"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] button {
float: left;
}
html[dir="rtl"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] a,
html[dir="rtl"] [role="dialog"][data-type="action"] > header menu[type="toolbar"] button {
float: right;
}
[role="dialog"][data-type="action"] > header a,
[role="dialog"][data-type="action"] > header button {
border: none;
padding: 0;
overflow: hidden;
font-weight: 400;
font-size: 1.5rem;
line-height: 1.1em;
color: #fff;
border-radius: 0;
text-decoration: none;
}
[role="dialog"][data-type="action"] button::-moz-focus-inner {
outline: none;
border: none;
}
/* Pressed state */
[role="dialog"][data-type="action"] > header a:active .icon:after,
[role="dialog"][data-type="action"] > header button:active .icon:after,
[role="dialog"][data-type="action"] > header menu[type="toolbar"] a:active,
[role="dialog"][data-type="action"] > header menu[type="toolbar"] button:active {
background: #008aaa !important;
}
/* Disabled state */
[role="dialog"][data-type="action"] > header menu[type="toolbar"] a[aria-disabled="true"],
[role="dialog"][data-type="action"] > header menu[type="toolbar"] button[disabled] {
opacity: 0.5;
pointer-events: none;
}
/* Icon definitions */
[role="dialog"][data-type="action"] > header .icon {
position: relative;
float: none;
display: inline-block;
vertical-align: top;
width: 4rem;
height: 4.9rem;
margin: 0 -1rem;
background: transparent no-repeat center center / 3rem auto;
font-size: 0;
overflow: hidden;
}
[role="dialog"][data-type="action"] > header .icon.icon-close {
background-image: url(action_menu/images/icons/close.png);
}
html[dir="ltr"] [role="dialog"][data-type="action"] > header .icon.icon-back {
background-image: url(action_menu/images/icons/left.png);
}
html[dir="rtl"] [role="dialog"][data-type="action"] > header .icon.icon-back {
background-image: url(action_menu/images/icons/right.png);
}
/* Navigation links (back, cancel, etc) */
[role="dialog"][data-type="action"] > header > button,
[role="dialog"][data-type="action"] > header > a {
width: 5rem;
height: 4.9rem;
background: none;
overflow: visible;
margin: 0 -1rem;
margin-inline-start: -3rem;
position: relative;
}
html[dir="ltr"] [role="dialog"][data-type="action"] > header > button,
html[dir="ltr"] [role="dialog"][data-type="action"] > header > a {
float: left;
}
html[dir="rtl"] [role="dialog"][data-type="action"] > header > button,
html[dir="rtl"] [role="dialog"][data-type="action"] > header > a {
float: right;
}
[role="dialog"][data-type="action"] > header > button::-moz-focus-inner {
border: 0;
padding: 0;
}
[role="dialog"][data-type="action"] > header > button .icon,
[role="dialog"][data-type="action"] > header > a .icon {
position: static;
display: block;
width: 3rem;
height: 4.9rem;
margin: 0;
overflow: visible;
font-size: 0;
}
[role="dialog"][data-type="action"] > header > button .icon:after,
[role="dialog"][data-type="action"] > header > a .icon:after {
content: "";
position: absolute;
offset-inline-start: 0;
top: 0;
z-index: -1;
width: 3rem;
height: 4.9rem;
}
/* Content */
[role="dialog"][data-type="action"] > section {
color: #fff;
position: absolute;
top: 7rem;
left: 1.5rem;
right: 1.5rem;
bottom: 2rem;
font-size: 1.6rem;
overflow: scroll;
}
/* Specific component code */
[role="dialog"][data-type="action"] > menu {
margin: 0;
padding: 0;
max-height: calc(100% - 13.5rem); /*header(5rem) + footer(7rem) + padding(1.5rem)*/
height: auto;
padding-top: 1.5rem;
overflow: auto;
width: auto;
border: none;
background: none;
position: absolute;
left: 0;
right: 0;
bottom: 7rem;
}
[role="dialog"][data-type="action"] > menu > button {
width: calc(100% - 3rem);
height: 4rem;
box-sizing: border-box;
vertical-align: middle;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-weight: normal;
line-height: 4rem;
outline: none;
font-size: 1.6rem;
text-shadow: none;
padding: 0 1.2rem;
margin: 0 1.5rem 1rem;
background: rgba(87, 87, 87, 0.8);
border: none;
border-radius: 0;
position: relative;
color: #fff;
font-family: sans-serif;
font-style: italic;
}
[role="dialog"][data-type="action"] > menu > .last-button-container {
position: fixed;
width: 100%;
background-color: #4d4d4d;
height: 7rem;
offset-inline-start: 0;
bottom: 0;
}
[role="dialog"][data-type="action"] > menu > .last-button-container button {
width: calc(100% - 3rem);
position: fixed;
bottom: 0;
margin: 0 1.5rem 1.5rem;
offset-inline-start: 0;
color: #333;
background: #d8d8d8;
text-align: center;
border: none;
border-radius: 2rem;
line-height: 4rem;
font-size: 1.6rem;
height: 4rem;
font-family: sans-serif;
font-style: italic;
}
[role="dialog"][data-type="action"] > menu > button:nth-last-child(2) {
margin-bottom: 1.5rem;
}
/* Press state */
[role="dialog"][data-type="action"] > menu button:active {
background: #00aacc;
color: #fff;
}
/* Disabled */
[role="dialog"][data-type="action"] > menu > button[disabled] {
background-color: rgba(87, 87, 87, 0.8);
color: rgba(255, 255, 255, 0.4);
opacity: 0.5;
pointer-events: none;
}
[role="dialog"][data-type="action"] > menu > .last-button-container button[disabled] {
background-color: #e7e7e7;
color: #a6a6a6;
opacity: 1;
}

View file

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Action menu</title>
<meta name="description" content="Presenting a list of actions related to the App content">
<link rel="stylesheet" href="../action_menu.css">
<!--
- This <style> element is only used for the example code;
- it is not required for the real use case.
-->
<style type="text/css">
html, body {
font-family: sans-serif;
margin: 0;
padding: 0;
font-size: 10px;
background-color: #fff;
}
body {
background: none;
}
</style>
</head>
<body role="application">
<p dir="ltr">
<label>
<input type="checkbox"
onchange="document.documentElement.dir = this.checked ? 'rtl' : 'ltr'">
RTL mode
</label>
</p>
<form role="dialog" data-type="action">
<header>
<button><span class="icon icon-close">close</span></button>
<menu type="toolbar">
<button>done</button>
</menu>
<h1>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</h1>
</header>
<section>
<p>Curabitur condimentum diam mollis lacus hendrerit congue. Phasellus porttitor orci elit, ac consequat est mollis ut. Ut consequat ipsum a ullamcorper aliquam.</p>
</section>
</form>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

View file

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="utf-8">
<title>Action menu</title>
<meta name="description" content="Presenting a list of actions related to the App content">
<link rel="stylesheet" href="../action_menu.css">
<!--
- These <style> and <script> elements are only used for the example code;
- they are not required for the real use case.
-->
<style type="text/css">
html, body {
font-family: sans-serif;
margin: 0;
padding: 0;
font-size: 10px;
background-color: #fff;
}
body {
background: none;
}
</style>
<script>
window.onkeypress = event => {
var dir = document.documentElement.dir;
document.documentElement.dir = (dir === 'ltr') ? 'rtl' : 'ltr';
};
</script>
</head>
<body role="application">
<form role="dialog" data-type="action">
<header><span class="icon icon-back"></span>Title</header> <!-- this header is optional -->
<menu type="toolbar">
<button>Action 1</button>
<button disabled> Action 2 (disabled) </button>
<button> Action 3. </button>
<button> الولايات 4</button>
<button disabled> Action 5 (disabled) </button>
<button> Action 6 </button>
<button> Action 7 </button>
<button disabled> Action 8 (disabled) </button>
<button> Action 9 </button>
<button> Cancel </button>
</menu>
</form>
</body>
</html>

View file

@ -0,0 +1,370 @@
/*
* The code is being shared between system/emergency-call/js/keypad.js
* and dialer/js/keypad.js. Be sure to update both files when you commit!
*
* BiDi note: keypads are always displayed in LTR (hardware legacy).
* This stylesheet must *NOT* be mirrored for RTL.
*/
.reset-button {
border: 0;
background: none;
}
.reset-button::-moz-focus-inner {
border: 0;
outline: none;
}
#phone-number-view-container {
width: 100%;
height: 28%;
background: var(--header-background);
text-align: center;
display: flex;
font-weight: 300;
overflow: hidden;
}
#phone-number-view-container .phone-number-view-wrapper-input {
width: 100%;
margin-bottom: 4.5rem;
display: flex;
align-items: center;
padding: 0 1rem 0 2rem;
}
#phone-number-view-container.keypad-visible {
height: calc(100% - 34.5rem);
visibility: hidden;
}
#phone-number-view {
font-size: 4.1rem;
width: 100%;
border: 0;
margin: 0;
background: transparent;
color: var(--header-color);
text-align: left;
cursor: none;
padding: 0;
pointer-events: auto;
-moz-user-select: text;
}
#fake-phone-number-view {
position: absolute;
left: 2rem;
line-height: 0;
visibility: hidden;
}
#keypad-delete {
margin-bottom: 4.5rem;
padding: 0 2.5rem 0 0;
visibility: hidden;
text-align: right;
}
#keypad-delete::before {
content: "";
background: url('keypad/images/keypad/actionicon_dialer_delete.png') no-repeat;
width: 3rem;
height: 2rem;
display: inline-block;
background-size: 100%;
}
#keypad-delete:active {
opacity: 0.6;
}
#keyboard-container {
height: 72%;
padding: 0 1rem;
}
#keypad {
width: 100%;
height: 80%;
display: table;
table-layout: fixed;
}
.keypad-row {
display: table-row;
}
.keypad-key {
display: table-cell;
padding: 1.3rem 0 0 2rem;
box-sizing: border-box;
height: 20%;
vertical-align: middle;
color: #333;
font-weight: 300;
font-size: 5rem;
line-height: 1rem;
overflow: hidden;
text-align: left;
}
.keypad-key span {
width: 1.5rem;
display: inline-block;
overflow: visible;
}
.keypad-key em {
display: inline-block;
font-weight: 300;
font-size: 1.5rem;
color: #038282;
font-style: normal;
width: 4.5rem;
overflow: visible;
text-align: left;
}
.keypad-key.active {
background: #94eee9;
color: #fff;
}
.keypad-key * {
pointer-events: none;
}
#keypad-delete * {
pointer-events: none;
}
.keypad-key .font-size-plus {
font-size: 2rem;
}
.keypad-subicon {
background-repeat: no-repeat;
background-position: center bottom;
-moz-user-select: none;
pointer-events: none;
display: inline-block;
width: 3rem;
height: 2rem;
}
.voicemail {
background-image: url('keypad/images/keypad/actionicon_dialer_voicemail.png');
background-size: 3rem;
background-position: -0.4rem -0.1rem;
}
.asterisk {
width: 4rem;
margin-top: 1rem;
margin-left: 0.2rem;
overflow: visible;
}
.sharp {
font-size: 4.5rem;
width: 4rem;
line-height: 0;
margin-top: -0.5rem;
margin-left: 0.2rem;
overflow: visible;
}
#keypad-callbar {
height: 20%;
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
border-bottom: 0;
border-left: 0;
box-sizing: border-box;
}
.keypad-callbar-button {
position: relative;
width: 9rem;
background: #e7e7e7;
background-size: auto 100%;
border-radius: 2rem;
overflow: hidden;
height: 4rem;
text-align: center;
}
.keypad-callbar-button.cancel {
background: #575757;
line-height: 4rem;
font-size: 1.8rem;
font-style: italic;
}
.keypad-callbar-button.cancel:active {
background: #9ef2e7;
}
#keypad-callbar-call-action {
display: flex;
position: relative;
flex-grow: 1;
align-items: center;
flex-direction: row-reverse;
background-image: url("keypad/images/keypad/actionicon_activecall_pickup.png");
background-color: #00adad;
background-repeat: no-repeat;
background-position: center;
background-size: 4rem 4rem;
border-radius: 2rem;
margin-inline-start: 1rem;
height: 4rem;
}
#keypad-callbar-call-action:active {
background-color: #94eee9;
}
.icon-add-contact::before {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-image: url("keypad/images/keypad/actionicon_activecall_addcontact_40x80.png");
background-repeat: no-repeat;
background-position: top center;
background-size: 4rem 8rem;
}
/* we won't do anything on click but this prevents fluffing/rendering issues */
.icon-add-contact:disabled {
pointer-events: all;
}
.icon-add-contact:disabled::before {
opacity: 0.4;
}
.icon-add-contact:not(:disabled):active::before {
background-position: center -4rem;
}
.js-sim-indication {
display: none;
font-size: 1.3rem;
text-align: right;
margin-right: 0.6rem;
color: #fff;
}
.has-preferred-sim .js-sim-indication {
display: initial;
}
.has-preferred-sim #keypad-callbar-call-action:after {
content: "";
position: absolute;
width: 1.4rem;
height: 1rem;
bottom: 0;
right: 1.7rem;
background-image: url("/shared/elements/gaia_sim_picker/images/long-tap-indicator.png");
background-repeat: no-repeat;
background-size: 1.4rem 1rem;
}
#keypad-hidebar {
border: 0;
box-sizing: border-box;
display: flex;
justify-content: space-around;
height: 7.5rem;
}
.kh__button {
width: 5rem;
height: 5rem;
background: #ded9d6;
border: none;
border-radius: 100%;
margin-top: 1rem;
position: relative;
}
.kh__button::before {
content: "";
position: absolute;
top: .5rem;
left: .5rem;
width: 4rem;
height: 4rem;
background-repeat: no-repeat;
background-position: 0 0;
background-size: cover;
}
.kh__button:active::before {
background-position: 0 -4rem;
}
.kh__button:active {
background-color: #9ef2e7;
}
.kh__button.active-state::before {
background-position: 0 -8rem;
}
.kh__button--mute::before {
background-image: url('keypad/images/keypad/actionicon_activecall_mute.png');
}
.kh__button--hide::before {
background-image: url('keypad/images/keypad/actionicon_activecall_dismisskeyboard.png');
}
.kh__call-end-button {
width: 6.5rem;
height: 6.5rem;
background: #e00;
border: none;
border-radius: 100%;
position: relative;
}
.kh__call-end-button::before {
content: "";
position: absolute;
top: 1.1rem;
left: 1.2rem;
width: 4rem;
height: 4rem;
background-image: url('keypad/images/actionicon_activecall_hangup.png');
background-repeat: no-repeat;
background-position: 0 0;
background-size: cover;
}
.kh__call-end-button:active::before {
background-position: 1.2rem 6rem;
}
.phone-number-font {
color: #fff;
}
.full-height {
height: 100%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

View file

@ -0,0 +1,59 @@
/*
* Extend action menu as an overlay
*/
form.overlay {
font-size: 1.5rem;
opacity: 1;
visibility: hidden;
transform: translateY(-100%);
transition: transform var(--transition-duration) ease-in-out,
visibility var(--transition-duration);
}
form.overlay > menu {
height: 100%;
}
form.overlay.display {
transform: translateY(0%);
visibility: visible;
}
form.overlay menu ul {
height: calc(100% - 13rem);
overflow: auto;
margin-top: 5rem;
padding: 0;
line-height: 2.4rem;
list-style: none outside none;
}
form.overlay menu ul > li,
form.overlay menu ul > section {
height: 4.5rem;
padding: 1rem 2rem;
font-size: 1.7rem;
position: relative;
}
form.overlay menu ul > li:after,
form.overlay menu ul > section:after {
content: ' ';
border-bottom: 0.1rem solid #666;
display: block;
position: absolute;
left: 1rem;
bottom: 0;
right: 1rem;
}
form.overlay menu ul > li:last-child:after,
form.overlay menu ul > section:last-child:after {
display: none;
}
form.overlay menu ul > li:active,
form.overlay menu ul > section:active {
background-color: #00ABCC;
transition: background-color 0.2s ease;
}

View file

@ -0,0 +1,31 @@
/* ----------------------------------
* Status
* ---------------------------------- */
html[dir="ltr"] section[role="status"] [dir] { text-align: left; }
html[dir="rtl"] section[role="status"] [dir] { text-align: right; }
section[role="status"] {
background-color: #4d4d4d;
overflow: hidden;
position: absolute;
z-index: 100;
left: 0;
right: 0;
bottom: 0;
color: #fff;
}
html[dir="ltr"] section[role="status"] { background-position: left top; }
html[dir="rtl"] section[role="status"] { background-position: right top; }
section[role="status"] p {
font-size: 1.8rem;
font-weight: normal;
line-height: 2.2rem;
margin: 1rem 3rem;
padding: 0;
}
section[role="status"] p strong {
font-weight: 500;
}

View file

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="utf-8">
<title>Status</title>
<meta name="description" content="Most common used after Multi-Select edit, to confirm user action, and optional provide 'Undo' input">
<link rel="stylesheet" href="../status.css">
<!--
This <style>, <script> and <link> are only used for the example code,
they are not needed for the real use case
-->
<style>
html, body {
margin: 0;
padding: 0;
font-size: 10px;
background-color: #fff;
}
body {
background: none;
}
</style>
<script>
window.onload = function(){
document.getElementById('dir').checked = false;
};
</script>
</head>
<body role="application">
<p dir="ltr">
<label>
<input id="dir" type="checkbox"
onchange="document.documentElement.dir = this.checked ? 'rtl' : 'ltr'">
RTL mode
</label>
</p>
<section role="status">
<p>The Alarm is set for <strong>7 hours</strong> and <strong>14 minutes</strong> from now</p>
</section>
</body>
</html>