Restore Gaia settings and media workflows, extend native network adapters, and align the APK payload. Generate French/English changelogs and website entries from the simplified JSON source. Validation: shared JS and Tundra unit tests; desktop workflows and persistence; signed APK payload parity; Sargo RAM and installed startup with boot readback. Android runtime qualification is recorded separately.
508 lines
No EOL
33 KiB
JavaScript
508 lines
No EOL
33 KiB
JavaScript
|
|
var Normalizer={initAsciiNormalizer:function normalizer_init(){var equivalentChars={'a':'áăǎâäȧạȁàảȃāąåḁⱥãǽǣæ','A':'ÁĂǍÂÄȦẠȀÀẢȂĀĄÅḀȺÃǼǢÆ','b':'ḃḅɓḇƀƃ','B':'ḂḄƁḆɃƂ','c':'ćčçĉċƈȼ','C':'ĆČÇĈĊƇȻ','d':'ďḑḓḋḍɗḏđƌð','D':'ĎḐḒḊḌƊḎĐƋ','e':'éĕěȩêḙëėẹȅèẻȇēę','E':'ÉĔĚȨÊḘËĖẸȄÈẺȆĒĘ','f':'ḟƒ','F':'ḞƑ','g':'ǵğǧģĝġɠḡǥ','G':'ǴĞǦĢĜĠƓḠǤ','h':'ḫȟḩĥⱨḧḣḥħ','H':'ḪȞḨĤⱧḦḢḤĦ','i':'íĭǐîïịȉìỉȋīįɨĩḭı','I':'ÍĬǏÎÏỊȈÌỈȊĪĮƗĨḬ','j':'ĵɉ','J':'ĴɈ','k':'ḱǩķⱪꝃḳƙḵꝁ','K':'ḰǨĶⱩꝂḲƘḴꝀ','l':'ĺƚľļḽḷⱡꝉḻŀɫł','L':'ĹȽĽĻḼḶⱠꝈḺĿⱢŁ','m':'ḿṁṃɱ','M':'ḾṀṂⱮ','n':'ńňņṋṅṇǹɲṉƞñ','N':'ŃŇŅṊṄṆǸƝṈȠÑ','o':'óŏǒôöȯọőȍòỏơȏꝋꝍōǫøõœ','O':'ÓŎǑÔÖȮỌŐȌÒỎƠȎꝊꝌŌǪØÕŒ','p':'ṕṗꝓƥᵽꝑ','P':'ṔṖꝒƤⱣꝐ','q':'ꝗ','Q':'Ꝗ','r':'ŕřŗṙṛȑȓṟɍɽ','R':'ŔŘŖṘṚȐȒṞɌⱤ','s':'śšşŝșṡṣß','S':'ŚŠŞŜȘṠṢ','t':'ťţṱțⱦṫṭƭṯʈŧ','T':'ŤŢṰȚȾṪṬƬṮƮŦ','u':'úŭǔûṷüṳụűȕùủưȗūųůũṵ','U':'ÚŬǓÛṶÜṲỤŰȔÙỦƯȖŪŲŮŨṴ','v':'ṿʋṽ','V':'ṾƲṼ','w':'ẃŵẅẇẉẁⱳ','W':'ẂŴẄẆẈẀⱲ','x':'ẍẋ','X':'ẌẊ','y':'ýŷÿẏỵỳƴỷỿȳɏỹ','Y':'ÝŶŸẎỴỲƳỶỾȲɎỸ','z':'źžẑⱬżẓȥẕƶ','Z':'ŹŽẐⱫŻẒȤẔƵ'};this._toAsciiForm={};for(var letter in equivalentChars){var accentedForms=equivalentChars[letter];for(var i=accentedForms.length-1;i>=0;i--){this._toAsciiForm[accentedForms[i]]=letter;}}},toAscii:function normalizer_toAscii(str){if(!str||typeof str!='string'){return'';}
|
|
if(!this._toAsciiForm){Normalizer.initAsciiNormalizer();}
|
|
var result='';for(var i=0,len=str.length;i<len;i++){result+=this._toAsciiForm[str.charAt(i)]||str.charAt(i);}
|
|
return result;},escapeHTML:function normalizer_escapeHTML(str,escapeQuotes){if(Array.isArray(str)){return Normalizer.escapeHTML(str.join(' '),escapeQuotes);}
|
|
if(!str||typeof str!='string'){return'';}
|
|
var escaped=str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');if(escapeQuotes){return escaped.replace(/"/g,'"').replace(/'/g,''');}
|
|
return escaped;},unescapeHTML:function normalizer_unescapeHTML(text){return text.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,'\'');},escapeRegExp:function normalizer_escapeRegExp(str){return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,'\\$&');}};define("shared/text_normalizer",(function(global){return function(){var ret,fn;return ret||global.Normalizer;};}(this)));var FxAccountsIACHelper=function FxAccountsIACHelper(){var DEFAULT_CONNECTION_STRING='fxa-mgmt';var default_rules={'manifestURLs':['app://system.gaiamobile.org/manifest.webapp','app://smart-system.gaiamobile.org/manifest.webapp']};var CONNECTION_STRING=DEFAULT_CONNECTION_STRING;var rules=default_rules;var port;var callbacks={};var eventListeners={};var init=function init(options){if(!options){return;}
|
|
if(options.keyword&&typeof(options.keyword)=='string'&&options.keyword.length>0){CONNECTION_STRING=options.keyword;}
|
|
if(options.rules&&typeof(options.rules)=='object'){rules=options.rules;}};var addEventListener=function addEventListener(eventName,listener){if(!eventListeners[eventName]){eventListeners[eventName]=[];}
|
|
eventListeners[eventName].push(listener);};var removeEventListener=function removeEventListener(eventName,listener){var listeners=eventListeners[eventName];if(!listeners){return;}
|
|
var index=listeners.indexOf(listener);if(index===-1){return;}
|
|
listeners.splice(index,1);};var reset=function reset(){CONNECTION_STRING=DEFAULT_CONNECTION_STRING;rules=default_rules;eventListeners={};callbacks={};port=null;};var onMessage=function onMessage(evt){if(evt&&evt.data){var message=evt.data;if(message.eventName){var listeners=eventListeners[message.eventName];if(!listeners){return;}
|
|
for(var listener in listeners){if(listeners[listener]&&typeof listeners[listener]==='function'){listeners[listener]();}}
|
|
return;}
|
|
var cbs,cb;if(message.methodName){cbs=callbacks[message.methodName];if(!cbs||!cbs.length){console.warn('No callbacks for method '+message.methodName);return;}
|
|
while(cbs.length){cb=cbs.shift();if(!message.error){cb.successCb(message.data);}else{cb.errorCb(message.error);}}}}else{console.error('Unknown');}};var getSelf=function getSelf(cb,error){var request=navigator.mozApps.getSelf();request.onsuccess=function onSuccess(evt){cb(evt.target.result);};request.onerror=function onError(){if(error&&typeof(error)==='function'){error();}};};var requestQueue=[];var isConnecting=false;var connect=function connect(cb){if(isConnecting){return requestQueue.push(cb);}
|
|
isConnecting=true;_connect(function onConnect(err){var next;isConnecting=false;if(typeof cb==='function'){cb(err);}
|
|
while(!!(next=requestQueue.shift())){next&&next(err);}});};var _connect=function _connect(callback){getSelf(function onApp(app){if(!app){return;}
|
|
app.connect(CONNECTION_STRING,rules).then(function(ports){if(!ports||ports.length!==1){return;}
|
|
port=ports[0];callback&&callback();});});};var sendMessage=function sendMessage(message,successCb,errorCb){if(port){_sendMessage(message,successCb,errorCb);return;}
|
|
connect(function(){_sendMessage(message,successCb,errorCb);});};var _sendMessage=function _sendMessage(message,successCb,errorCb){var name=message.name;if(!name){return;}
|
|
if(!callbacks[name]){callbacks[name]=[];}
|
|
callbacks[name].push({successCb:successCb,errorCb:errorCb});port.onmessage=onMessage;port.postMessage(message);};var getAccount=function getAccount(successCb,errorCb){sendMessage({'name':'getAccount'},successCb,errorCb);};var openFlow=function openFlow(successCb,errorCb){sendMessage({'name':'openFlow'},successCb,errorCb);};var logout=function logout(successCb,errorCb){sendMessage({'name':'logout'},successCb,errorCb);};var refreshAuthentication=function refreshAuthentication(email,successCb,errorCb){sendMessage({'name':'refreshAuthentication','email':email},successCb,errorCb);};var resendVerificationEmail=function resendVerificationEmail(email,successCb,errorCb){sendMessage({'name':'resendVerificationEmail','email':email},successCb,errorCb);};connect();return{'addEventListener':addEventListener,'getAccount':getAccount,'init':init,'logout':logout,'openFlow':openFlow,'refreshAuthentication':refreshAuthentication,'removeEventListener':removeEventListener,'resendVerificationEmail':resendVerificationEmail,'reset':reset};}();define("shared/fxa_iac_client",(function(global){return function(){var ret,fn;return ret||global.FxAccountsIACHelper;};}(this)));define('modules/dialog_manager',["require", "modules/panel_cache", "shared/lazy_loader"],function(require) {
|
|
'use strict';
|
|
|
|
var PanelCache = require('modules/panel_cache');
|
|
var LazyLoader = require('shared/lazy_loader');
|
|
|
|
var DialogManager = function() {
|
|
this.OVERLAY_SELECTOR = '.settings-dialog-overlay';
|
|
|
|
this._overlayDOM = document.querySelector(this.OVERLAY_SELECTOR);
|
|
};
|
|
|
|
DialogManager.prototype = {
|
|
/**
|
|
* load panel based on passed in panelId
|
|
*
|
|
* @memberOf DialogManager
|
|
* @access private
|
|
* @param {String} panelId
|
|
* @return {Promise}
|
|
*/
|
|
_loadPanel: function dm__loadPanel(panelId) {
|
|
var promise = new Promise(function(resolve, reject) {
|
|
var panelElement = document.getElementById(panelId);
|
|
if (panelElement.dataset.rendered) { // already initialized
|
|
resolve();
|
|
return;
|
|
}
|
|
|
|
panelElement.dataset.rendered = true;
|
|
|
|
// XXX remove SubPanel loader once sub panel are modulized
|
|
if (panelElement.dataset.requireSubPanels) {
|
|
// load the panel and its sub-panels (dependencies)
|
|
// (load the main panel last because it contains the scripts)
|
|
var selector = 'section[id^="' + panelElement.id + '-"]';
|
|
var subPanels = document.querySelectorAll(selector);
|
|
for (var i = 0, il = subPanels.length; i < il; i++) {
|
|
LazyLoader.load([subPanels[i]]);
|
|
}
|
|
LazyLoader.load([panelElement], resolve);
|
|
} else {
|
|
LazyLoader.load([panelElement], resolve);
|
|
}
|
|
});
|
|
return promise;
|
|
},
|
|
|
|
/**
|
|
* promised version of PanelCache.get()
|
|
*
|
|
* @memberOf DialogManager
|
|
* @access private
|
|
* @param {String} panelId
|
|
* @return {Promise}
|
|
*/
|
|
_getPanel: function dm__getPanel(panelId) {
|
|
var promise = new Promise(function(resolve) {
|
|
PanelCache.get(panelId, function(panel) {
|
|
resolve(panel);
|
|
});
|
|
});
|
|
return promise;
|
|
},
|
|
|
|
/**
|
|
* this is used to control visibility of overlayDOM
|
|
*
|
|
* @memberOf DialogManager
|
|
* @access private
|
|
* @param {Boolean} show
|
|
*/
|
|
_showOverlay: function dm__showOverlay(show) {
|
|
this._overlayDOM.hidden = !show;
|
|
},
|
|
|
|
/**
|
|
* It is used to control the timing of transitions so that we can make sure
|
|
* whether animation is done or not.
|
|
*
|
|
* @memberOf DialogManager
|
|
* @access private
|
|
* @param {String} method
|
|
* @param {BaseDialog} dialog
|
|
* @param {Object} options
|
|
* @return {Promise}
|
|
*/
|
|
_transit: function dm__transit(method, dialog, options) {
|
|
var promise = new Promise(function(resolve) {
|
|
var panel = dialog.panel;
|
|
var completed = false;
|
|
var fallback;
|
|
function finish(event) {
|
|
if (event && (event.target !== panel || event.propertyName !== 'visibility')) return;
|
|
if (completed) return;
|
|
completed = true;
|
|
clearTimeout(fallback);
|
|
panel.removeEventListener('transitionend', finish);
|
|
panel.removeEventListener('transitioncancel', finish);
|
|
if (method === 'close') panel.hidden = true;
|
|
resolve();
|
|
}
|
|
if (method === 'open') panel.hidden = false;
|
|
setTimeout(function() {
|
|
panel.addEventListener('transitionend', finish);
|
|
panel.addEventListener('transitioncancel', finish);
|
|
panel.classList.toggle('current', method === 'open');
|
|
var style = window.getComputedStyle(panel);
|
|
function milliseconds(value) {
|
|
return parseFloat(value) * (value.trim().endsWith('ms') ? 1 : 1000) || 0;
|
|
}
|
|
var durations = style.transitionDuration.split(',').map(milliseconds);
|
|
var delays = style.transitionDelay.split(',').map(milliseconds);
|
|
var duration = Math.max.apply(Math, durations.map(function(value, index) {
|
|
return value + delays[index % delays.length];
|
|
}));
|
|
// Reduced motion, display changes or interrupted transitions may
|
|
// omit the visibility event. Always release the dialog queue.
|
|
fallback = setTimeout(finish, Math.max(0, duration) + 100);
|
|
}, 150);
|
|
});
|
|
return promise;
|
|
},
|
|
|
|
/**
|
|
* Do necessary works to open panel like loading panel, doing transition
|
|
* and call related functions.
|
|
*
|
|
* @memberOf DialogManager
|
|
* @access private
|
|
* @param {BaseDialog} dialog
|
|
* @param {Object} options
|
|
* @return {Promise}
|
|
*/
|
|
_open: function dm__open(dialog, options) {
|
|
var self = this;
|
|
var foundPanel;
|
|
|
|
return Promise.resolve()
|
|
.then(function() {
|
|
// 1: load panel
|
|
return self._loadPanel(dialog.panel.id);
|
|
})
|
|
.then(function() {
|
|
// 2: Get that panel
|
|
return self._getPanel(dialog.panel.id);
|
|
})
|
|
.then(function(panel) {
|
|
// 3: call beforeShow
|
|
foundPanel = panel;
|
|
return foundPanel.beforeShow(dialog.panel, options);
|
|
})
|
|
.then(function() {
|
|
// 4. UI stuffs + transition
|
|
dialog.init();
|
|
dialog.initUI();
|
|
dialog.bindEvents();
|
|
|
|
if (dialog.TRANSITION_CLASS === 'zoom-in-80') {
|
|
self._showOverlay(true);
|
|
}
|
|
|
|
return self._transit('open', dialog, options);
|
|
})
|
|
.then(function() {
|
|
// 5. show that panel as a dialog
|
|
return foundPanel.show(dialog.panel, options);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Do necessary works to close panel like loading panel, doing transition
|
|
* and call related functions.
|
|
*
|
|
* @memberOf DialogManager
|
|
* @access private
|
|
* @param {BaseDialog} dialog
|
|
* @param {Object} options
|
|
* @return {Promise}
|
|
*/
|
|
_close: function dm__close(dialog, options) {
|
|
var self = this;
|
|
var foundPanel;
|
|
var cachedResult;
|
|
|
|
return Promise.resolve()
|
|
.then(function() {
|
|
// 1: Get that panel
|
|
return self._getPanel(dialog.panel.id);
|
|
})
|
|
.then(function(panel) {
|
|
// 2: Let's validate to see whether we can close this dialog or not.
|
|
foundPanel = panel;
|
|
|
|
var promise;
|
|
// custom dialog - onSubmit
|
|
if (foundPanel.onSubmit && options._type === 'submit') {
|
|
promise = foundPanel.onSubmit();
|
|
// custom dialog - onCancel
|
|
} else if (foundPanel.onCancel && options._type === 'cancel') {
|
|
promise = foundPanel.onCancel();
|
|
// if no onSubmit & onCancel, pass directly
|
|
} else {
|
|
promise = Promise.resolve();
|
|
}
|
|
|
|
return promise;
|
|
})
|
|
.then(function(result) {
|
|
cachedResult = result;
|
|
|
|
// 3: call beforeHide
|
|
return foundPanel.beforeHide();
|
|
})
|
|
.then(function() {
|
|
// 4. transition
|
|
return self._transit('close', dialog, options);
|
|
})
|
|
.then(function() {
|
|
// 5. call hide
|
|
return foundPanel.hide();
|
|
})
|
|
.then(function() {
|
|
// 6. Get result and cleanup dialog
|
|
var result;
|
|
|
|
// for prompt dialog, we have to get its own result from input text.
|
|
if (dialog.DIALOG_CLASS === 'prompt-dialog') {
|
|
result = dialog.getResult();
|
|
} else if (cachedResult) {
|
|
result = cachedResult;
|
|
}
|
|
|
|
dialog.cleanup();
|
|
|
|
if (dialog.TRANSITION_CLASS === 'zoom-in-80') {
|
|
self._showOverlay(false);
|
|
}
|
|
|
|
return result;
|
|
});
|
|
},
|
|
|
|
/**
|
|
* It is a bridge to call open or close function.
|
|
*
|
|
* @memberOf DialogManager
|
|
* @access private
|
|
* @param {String} method
|
|
* @param {BaseDialog} dialog
|
|
* @param {Object} options
|
|
* @return {Promise}
|
|
*/
|
|
_navigate: function dm__navigate(method, dialog, options) {
|
|
method = (method === 'open') ? '_open' : '_close';
|
|
return this[method](dialog, options);
|
|
},
|
|
|
|
/**
|
|
* DialogService would use this exposed API to open dialog.
|
|
*
|
|
* @memberOf DialogManager
|
|
* @access public
|
|
* @param {BaseDialog} dialog
|
|
* @param {Object} options
|
|
* @return {Promise}
|
|
*/
|
|
open: function dm_open(dialog, options) {
|
|
return this._navigate('open', dialog, options);
|
|
},
|
|
|
|
/**
|
|
* DialogService would use this exposed API to close dialog.
|
|
*
|
|
* @memberOf DialogManager
|
|
* @access public
|
|
* @param {BaseDialog} dialog
|
|
* @param {Object} options
|
|
* @return {Promise}
|
|
*/
|
|
close: function dm_close(dialog, type, options) {
|
|
options._type = type;
|
|
return this._navigate('close', dialog, options);
|
|
}
|
|
};
|
|
|
|
var dialogManager = new DialogManager();
|
|
return dialogManager;
|
|
});
|
|
define('modules/dialog/base_dialog',['require'],function(require){'use strict';var BaseDialog=function(panelDOM,options){this.panel=panelDOM;this._options=options||{};};BaseDialog.prototype.DIALOG_CLASS='dialog';BaseDialog.prototype.TRANSITION_CLASS='fade';BaseDialog.prototype.SUBMIT_BUTTON_SELECTOR='[type="submit"]';BaseDialog.prototype.CANCEL_BUTTON_SELECTOR='[type="reset"]';BaseDialog.prototype.MESSAGE_SELECTOR='.settings-dialog-message';BaseDialog.prototype.TITLE_SELECTOR='.settings-dialog-title';BaseDialog.prototype.init=function bd_init(){this.TRANSITION_CLASS=this._options.transition||this.TRANSITION_CLASS;this.panel.classList.add(this.DIALOG_CLASS);this.panel.classList.add(this.TRANSITION_CLASS);};BaseDialog.prototype.initUI=function bd_initUI(){var message=this._options.message;var title=this._options.title;var submitButton=this._options.submitButton;var cancelButton=this._options.cancelButton;this._updateMessage(message);this._updateTitle(title);this._updateSubmitButton(submitButton);this._updateCancelButton(cancelButton);};BaseDialog.prototype.bindEvents=function bd_bindEvent(){var self=this;this.getSubmitButton().onclick=function(){self._options.onWrapSubmit();};this.getCancelButton().onclick=function(){self._options.onWrapCancel();};};BaseDialog.prototype._updateMessage=function bd__updateMessage(message){var messageDOM=this.panel.querySelector(this.MESSAGE_SELECTOR);if(messageDOM&&message){message=this._getWrapL10nObject(message);document.l10n.setAttributes(messageDOM,message.id,message.args);}};BaseDialog.prototype._updateTitle=function bd__updateTitle(title){var titleDOM=this.panel.querySelector(this.TITLE_SELECTOR);if(titleDOM&&title){title=this._getWrapL10nObject(title);document.l10n.setAttributes(titleDOM,title.id,title.args);}};BaseDialog.prototype._updateSubmitButton=function bd__update(options){var buttonDOM=this.getSubmitButton();if(buttonDOM&&options){options=this._getWrapL10nObject(options);document.l10n.setAttributes(buttonDOM,options.id,options.args);buttonDOM.className=options.style||'recommend';}};BaseDialog.prototype._updateCancelButton=function bd__updateText(options){var buttonDOM=this.getCancelButton();if(buttonDOM&&options){options=this._getWrapL10nObject(options);document.l10n.setAttributes(buttonDOM,options.id,options.args);buttonDOM.className=options.style||'';}};BaseDialog.prototype._getWrapL10nObject=function bd__getWrapL10nObject(input){if(typeof input==='string'){return{id:input,args:null};}else if(typeof input==='object'){if(typeof input.id==='undefined'){throw new Error('You forgot to put l10nId - '+
|
|
JSON.stringify(input));}else{return{id:input.id,args:input.args||null,style:input.style};}}else{throw new Error('You are using the wrong L10nObject, '+'please check its format again');}};BaseDialog.prototype.getDOM=function bd_getDOM(){return this.panel;};BaseDialog.prototype.getSubmitButton=function bd_getSubmitButton(){return this.panel.querySelector(this.SUBMIT_BUTTON_SELECTOR);};BaseDialog.prototype.getCancelButton=function bd_getCancelButton(){return this.panel.querySelector(this.CANCEL_BUTTON_SELECTOR);};BaseDialog.prototype.cleanup=function bd_cleanup(){if(this.DIALOG_CLASS!=='panel-dialog'){this._updateTitle('settings-'+this.DIALOG_CLASS+'-header');this._updateSubmitButton('ok');this._updateCancelButton('cancel');}
|
|
this.panel.classList.remove(this.DIALOG_CLASS);this.panel.classList.remove(this.TRANSITION_CLASS);};return BaseDialog;});define('modules/dialog/panel_dialog',['require','modules/dialog/base_dialog'],function(require){'use strict';var BaseDialog=require('modules/dialog/base_dialog');var PanelDialog=function(panelDOM,options){BaseDialog.call(this,panelDOM,options);};PanelDialog.prototype=Object.create(BaseDialog.prototype);PanelDialog.prototype.constructor=PanelDialog;PanelDialog.prototype.DIALOG_CLASS='panel-dialog';PanelDialog.prototype.TRANSITION_CLASS='fade';return function ctor_PanelDialog(panelDOM,options){return new PanelDialog(panelDOM,options);};});define('modules/dialog/alert_dialog',['require','modules/dialog/base_dialog'],function(require){'use strict';var BaseDialog=require('modules/dialog/base_dialog');var AlertDialog=function(panelDOM,options){BaseDialog.call(this,panelDOM,options);};AlertDialog.prototype=Object.create(BaseDialog.prototype);AlertDialog.prototype.constructor=AlertDialog;AlertDialog.prototype.DIALOG_CLASS='alert-dialog';AlertDialog.prototype.TRANSITION_CLASS='fade';AlertDialog.prototype.bindEvents=function(){var self=this;this.getSubmitButton().onclick=function(){self._options.onWrapSubmit();};};return function ctor_alertDialog(panelDOM,options){return new AlertDialog(panelDOM,options);};});define('modules/dialog/confirm_dialog',['require','modules/dialog/base_dialog'],function(require){'use strict';var BaseDialog=require('modules/dialog/base_dialog');var ConfirmDialog=function(panelDOM,options){BaseDialog.call(this,panelDOM,options);};ConfirmDialog.prototype=Object.create(BaseDialog.prototype);ConfirmDialog.prototype.constructor=ConfirmDialog;ConfirmDialog.prototype.DIALOG_CLASS='confirm-dialog';ConfirmDialog.prototype.TRANSITION_CLASS='fade';ConfirmDialog.prototype.bindEvents=function(){var self=this;this.getSubmitButton().onclick=function(){self._options.onWrapSubmit();};this.getCancelButton().onclick=function(){self._options.onWrapCancel();};};return function ctor_confirmDialog(panelDOM,options){return new ConfirmDialog(panelDOM,options);};});define('modules/dialog/prompt_dialog',['require','modules/dialog/base_dialog'],function(require){'use strict';var BaseDialog=require('modules/dialog/base_dialog');var PromptDialog=function(panelDOM,options){BaseDialog.call(this,panelDOM,options);};PromptDialog.prototype=Object.create(BaseDialog.prototype);PromptDialog.prototype.constructor=PromptDialog;PromptDialog.prototype.DIALOG_CLASS='prompt-dialog';PromptDialog.prototype.TRANSITION_CLASS='fade';PromptDialog.prototype.INPUT_SELECTOR='.settings-dialog-input';PromptDialog.prototype.bindEvents=function(){var self=this;this.getSubmitButton().onclick=function(){self._options.onWrapSubmit();};this.getCancelButton().onclick=function(){self._options.onWrapCancel();};};PromptDialog.prototype.initUI=function(){BaseDialog.prototype.initUI.call(this);this.getInput().value=this._options.defaultValue||'';};PromptDialog.prototype.getInput=function(){return this.panel.querySelector(this.INPUT_SELECTOR);};PromptDialog.prototype.getResult=function(){return this.getInput().value;};return function ctor_promptDialog(panelDOM,options){return new PromptDialog(panelDOM,options);};});define('modules/dialog_service',["require", "settings", "modules/defer", "modules/dialog_manager", "modules/dialog/panel_dialog", "modules/dialog/alert_dialog", "modules/dialog/confirm_dialog", "modules/dialog/prompt_dialog"],function(require) {
|
|
'use strict';
|
|
|
|
var Settings = require('settings');
|
|
var Defer = require('modules/defer');
|
|
var DialogManager = require('modules/dialog_manager');
|
|
|
|
var PanelDialog = require('modules/dialog/panel_dialog');
|
|
var AlertDialog = require('modules/dialog/alert_dialog');
|
|
var ConfirmDialog = require('modules/dialog/confirm_dialog');
|
|
var PromptDialog = require('modules/dialog/prompt_dialog');
|
|
|
|
var DialogService = function() {
|
|
this._navigating = false;
|
|
this._pendingRequests = [];
|
|
this._settingsAlertDialogId = 'settings-alert-dialog';
|
|
this._settingsBaseDialogId = 'settings-base-dialog';
|
|
this._settingsConfirmDialogId = 'settings-confirm-dialog';
|
|
this._settingsPromptDialogId = 'settings-prompt-dialog';
|
|
};
|
|
|
|
DialogService.prototype = {
|
|
/**
|
|
* Alert dialog with more controls.
|
|
*
|
|
* @memberOf DialogService
|
|
* @access public
|
|
* @param {String} message
|
|
* @param {Object} userOptions
|
|
* @return {Promise}
|
|
*/
|
|
alert: function(message, userOptions) {
|
|
var options = userOptions || {};
|
|
return this.show(this._settingsAlertDialogId, {
|
|
type: 'alert',
|
|
message: message,
|
|
title: options.title,
|
|
submitButton: options.submitButton
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Confirm dialog with more controls.
|
|
*
|
|
* @memberOf DialogService
|
|
* @access public
|
|
* @param {String} message
|
|
* @param {Object} userOptions
|
|
* @return {Promise}
|
|
*/
|
|
confirm: function(message, userOptions) {
|
|
var options = userOptions || {};
|
|
return this.show(this._settingsConfirmDialogId, {
|
|
type: 'confirm',
|
|
message: message,
|
|
title: options.title,
|
|
submitButton: options.submitButton,
|
|
cancelButton: options.cancelButton
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Prompt dialog with more controls.
|
|
*
|
|
* @memberOf DialogService
|
|
* @access public
|
|
* @param {String} message
|
|
* @param {Object} userOptions
|
|
* @return {Promise}
|
|
*/
|
|
prompt: function(message, userOptions) {
|
|
var options = userOptions || {};
|
|
return this.show(this._settingsPromptDialogId, {
|
|
type: 'prompt',
|
|
message: message,
|
|
title: options.title,
|
|
defaultValue: options.defaultValue,
|
|
submitButton: options.submitButton,
|
|
cancelButton: options.cancelButton
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Panel dialog. If you are going to show any panel as a dialog,
|
|
* you have to use this method to show them.
|
|
*
|
|
* @memberOf DialogService
|
|
* @access public
|
|
* @param {String} panelId
|
|
* @param {Object} userOptions
|
|
* @return {Promise}
|
|
*/
|
|
show: function dm_show(panelId, userOptions, _pendingDefer) {
|
|
var self = this;
|
|
var defer;
|
|
var dialog;
|
|
var dialogDOM = document.getElementById(panelId);
|
|
var currentPanel = Settings.currentPanel;
|
|
var options = userOptions || {};
|
|
|
|
if (_pendingDefer) {
|
|
defer = _pendingDefer;
|
|
} else {
|
|
defer = Defer();
|
|
}
|
|
|
|
if (this._navigating) {
|
|
this._pendingRequests.push({
|
|
defer: defer,
|
|
panelId: panelId,
|
|
userOptions: userOptions
|
|
});
|
|
} else {
|
|
if ('#' + panelId === currentPanel) {
|
|
defer.reject('You are showing the same panel #' + panelId);
|
|
} else {
|
|
var opening;
|
|
var closing = false;
|
|
function close(type) {
|
|
if (closing) return;
|
|
closing = true;
|
|
// A tap during the opening animation must not run hide/show
|
|
// concurrently, or a queued dialog can inherit stale form values.
|
|
Promise.resolve(opening).then(function() {
|
|
return DialogManager.close(dialog, type, options);
|
|
}).then(function(result) {
|
|
self._navigating = false;
|
|
defer.resolve({type: type, value: result});
|
|
self._execPendingRequest();
|
|
}, function(error) {
|
|
// Panel validation rejects to keep the form open. Allow a
|
|
// correction or cancellation without rejecting the show promise.
|
|
closing = false;
|
|
dialogDOM.dispatchEvent(new CustomEvent('dialogvalidationfailed', {
|
|
detail: error
|
|
}));
|
|
});
|
|
}
|
|
options.onWrapSubmit = function() { close('submit'); };
|
|
options.onWrapCancel = function() { close('cancel'); };
|
|
|
|
switch (options.type) {
|
|
case 'alert':
|
|
dialog = AlertDialog(dialogDOM, options);
|
|
break;
|
|
case 'confirm':
|
|
dialog = ConfirmDialog(dialogDOM, options);
|
|
break;
|
|
case 'prompt':
|
|
dialog = PromptDialog(dialogDOM, options);
|
|
break;
|
|
default:
|
|
dialog = PanelDialog(dialogDOM, options);
|
|
break;
|
|
}
|
|
this._navigating = true;
|
|
opening = DialogManager.open(dialog, options);
|
|
opening.catch(function(error) {
|
|
// A missing host API must not lock every later Settings dialog.
|
|
dialogDOM.classList.remove('current');
|
|
dialogDOM.hidden = true;
|
|
var overlay = document.querySelector('.settings-dialog-overlay');
|
|
if (overlay) overlay.hidden = true;
|
|
self._navigating = false;
|
|
defer.reject(error);
|
|
self._execPendingRequest();
|
|
});
|
|
}
|
|
}
|
|
|
|
return defer.promise;
|
|
},
|
|
|
|
/**
|
|
* This method can help us pop up any pending request and would try to
|
|
* show it after previous request was done.
|
|
*
|
|
* @memberOf DialogService
|
|
* @access private
|
|
*/
|
|
_execPendingRequest: function() {
|
|
var request = this._pendingRequests.pop();
|
|
if (request) {
|
|
this.show(request.panelId, request.userOptions, request.defer);
|
|
}
|
|
}
|
|
};
|
|
|
|
var dialogService = new DialogService();
|
|
return dialogService;
|
|
});
|
|
define('panels/firefox_accounts/firefox_accounts',['require','shared/text_normalizer','shared/fxa_iac_client','modules/dialog_service'],function(require){var normalizer=require('shared/text_normalizer');var fxaHelper=require('shared/fxa_iac_client');var dialogService=require('modules/dialog_service');var FirefoxAccounts=function(){this._boundRefreshStatus=this._boundRefreshStatus||this.refreshStatus.bind(this);};FirefoxAccounts.prototype={onInit:function fxa_init(elements){this._elements=elements;},onBeforeShow:function fxa_beforeShow(){fxaHelper.addEventListener('onlogin',this._boundRefreshStatus);fxaHelper.addEventListener('onverified',this._boundRefreshStatus);fxaHelper.addEventListener('onlogout',this._boundRefreshStatus);this._boundRefreshStatus();},onBeforeHide:function fxa_beforeHide(){fxaHelper.removeEventListener('onlogin',this._boundRefreshStatus);fxaHelper.removeEventListener('onverified',this._boundRefreshStatus);fxaHelper.removeEventListener('onlogout',this._boundRefreshStatus);},refreshStatus:function fxa_refreshStatus(){fxaHelper.getAccount(this._onFxAccountStateChange.bind(this),this._onFxAccountError.bind(this));},_onFxAccountStateChange:function fxa_onFxAccountStateChange(e){var email=e?normalizer.escapeHTML(e.email):'';if(!e){this._hideLoggedInPanel();this._hideUnverifiedPanel();this._showLoggedOutPanel();}else if(e.verified){this._hideLoggedOutPanel();this._hideUnverifiedPanel();this._showLoggedInPanel(email);}else{this._hideLoggedOutPanel();this._hideLoggedInPanel();this._showUnverifiedPanel(email);}},_onFxAccountError:function fxa_onFxAccountError(err){console.error('FxaPanel: Error getting Firefox Account: '+err.error);},_hideLoggedOutPanel:function fxa_hideLoggedOutPanel(){this._elements.loginBtn.onclick=null;this._elements.loggedOutPanel.hidden=true;},_showLoggedOutPanel:function fxa_showLoggedOutPanel(){this._elements.loginBtn.onclick=this._onLoginClick.bind(this);this._elements.loggedOutPanel.hidden=false;},_hideLoggedInPanel:function fxa_hideLoggedInPanel(){this._elements.loggedInPanel.hidden=true;this._elements.loggedInEmail.textContent='';this._elements.logoutBtn.onclick=null;},_showLoggedInPanel:function fxa_showLoggedInPanel(email){document.l10n.setAttributes(this._elements.loggedInEmail,'fxa-logged-in-text',{email:email});this._elements.loggedInPanel.hidden=false;this._elements.logoutBtn.onclick=this._onLogoutClick.bind(this);},_hideUnverifiedPanel:function fxa_hideUnverifiedPanel(){this._elements.unverifiedPanel.hidden=true;this._elements.unverifiedEmail.textContent='';this._elements.cancelBtn.onclick=null;if(this._elements.resendLink){this._elements.resendLink.onclick=null;}},_showUnverifiedPanel:function fxa_showUnverifiedPanel(email){this._elements.unverifiedPanel.hidden=false;this._elements.cancelBtn.onclick=this._onLogoutClick.bind(this);document.l10n.setAttributes(this._elements.unverifiedEmail,'fxa-verification-email-sent-msg',{email:email});this._elements.resendLink.onclick=this._onResendClick.bind(this);},_onLogoutClick:function fxa_onLogoutClick(e){e.stopPropagation();e.preventDefault();fxaHelper.logout(this._onFxAccountStateChange.bind(this),this._onFxAccountError.bind(this));},_onResendClick:function fxa__onResendClick(e){e.stopPropagation();e.preventDefault();if(e.target.classList.contains('disabled')){return;}
|
|
fxaHelper.getAccount((accts)=>{var email=accts&&accts.email;if(!email){return this._onFxAccountStateChange(accts);}
|
|
fxaHelper.resendVerificationEmail(email,this._onResend.bind(this,email),this._onFxAccountError.bind(this));},this._onFxAccountError.bind(this));},_onResend:function fxa__onResend(email){dialogService.alert({id:'fxa-resend-alert',args:{email:email}});this._elements.resendLink.classList.add('disabled');setTimeout(()=>{this._elements.resendLink.classList.remove('disabled');},60000);},_onLoginClick:function fxa_onLoginClick(e){e.stopPropagation();e.preventDefault();fxaHelper.openFlow(this._onFxAccountStateChange.bind(this),this._onFxAccountError.bind(this));}};return function ctor_firefox_accounts(){return new FirefoxAccounts();};});define('panels/firefox_accounts/panel',['require','modules/settings_panel','panels/firefox_accounts/firefox_accounts'],function(require){var SettingsPanel=require('modules/settings_panel');var FirefoxAccounts=require('panels/firefox_accounts/firefox_accounts');return function ctor_firefox_account_panel(){var elements;var firefoxAccounts=FirefoxAccounts();return SettingsPanel({onInit:function(panel){elements={fxaContainer:document.getElementById('fxa'),loggedOutPanel:document.getElementById('fxa-logged-out'),loggedInPanel:document.getElementById('fxa-logged-in'),unverifiedPanel:document.getElementById('fxa-unverified'),resendEmail:document.getElementById('fxa-resend-email'),cancelBtn:document.getElementById('fxa-cancel-confirmation'),loginBtn:document.getElementById('fxa-login'),logoutBtn:document.getElementById('fxa-logout'),loggedInEmail:document.getElementById('fxa-logged-in-text'),unverifiedEmail:document.getElementById('fxa-unverified-text'),resendLink:document.getElementById('fxa-resend')};firefoxAccounts.onInit(elements);},onBeforeShow:function(){firefoxAccounts.onBeforeShow();},onBeforeHide:function(){firefoxAccounts.onBeforeHide();}});};}); |