Release Preview 20 shared desktop, Android and Sargo updates
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.
This commit is contained in:
parent
be2cdce823
commit
1311bed5e9
170 changed files with 19698 additions and 2495 deletions
419
overrides/settings.gaiamobile.org/js/modules/date_time.js
Normal file
419
overrides/settings.gaiamobile.org/js/modules/date_time.js
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
/**
|
||||
* DateTime is a singleton that caches date, time, timezone values for
|
||||
* Date & Time panel fast access
|
||||
*
|
||||
* @module DateTime
|
||||
*/
|
||||
/**
|
||||
* DateTime is a singleton that caches date, time, timezone values for
|
||||
* Date & Time panel fast access
|
||||
*
|
||||
* @module DateTime
|
||||
*/
|
||||
/**
|
||||
* DateTime is a singleton that caches date, time, timezone values for
|
||||
* Date & Time panel fast access
|
||||
*
|
||||
* @module DateTime
|
||||
*/
|
||||
/**
|
||||
* DateTime is a singleton that caches date, time, timezone values for
|
||||
* Date & Time panel fast access
|
||||
*
|
||||
* @module DateTime
|
||||
*/
|
||||
/**
|
||||
* DateTime is a singleton that caches date, time, timezone values for
|
||||
* Date & Time panel fast access
|
||||
*
|
||||
* @module DateTime
|
||||
*/
|
||||
/**
|
||||
* DateTime is a singleton that caches date, time, timezone values for
|
||||
* Date & Time panel fast access
|
||||
*
|
||||
* @module DateTime
|
||||
*/
|
||||
/**
|
||||
* DateTime is a singleton that caches date, time, timezone values for
|
||||
* Date & Time panel fast access
|
||||
*
|
||||
* @module DateTime
|
||||
*/
|
||||
/**
|
||||
* DateTime is a singleton that caches date, time, timezone values for
|
||||
* Date & Time panel fast access
|
||||
*
|
||||
* @module DateTime
|
||||
*/
|
||||
define('modules/date_time',["require", "modules/settings_cache", "modules/base/module", "modules/mvvm/observable"],function(require) {
|
||||
'use strict';
|
||||
|
||||
var SettingsCache = require('modules/settings_cache');
|
||||
var Module = require('modules/base/module');
|
||||
var Observable = require('modules/mvvm/observable');
|
||||
var settings = window.navigator.mozSettings;
|
||||
|
||||
// keys
|
||||
var _kClockAutoEnabled = 'time.clock.automatic-update.enabled';
|
||||
var _kTimezoneAutoEnabled = 'time.timezone.automatic-update.enabled';
|
||||
var _kClockAutoAvailable = 'time.clock.automatic-update.available';
|
||||
var _kTimezoneAutoAvailable = 'time.timezone.automatic-update.available';
|
||||
var _kTimezone = 'time.timezone';
|
||||
var _kUserSelected = 'time.timezone.user-selected';
|
||||
var _kLocaleTime = 'locale.hour12';
|
||||
|
||||
// handler
|
||||
var _updateDateTimeout = null;
|
||||
var _updateTimeTimeout = null;
|
||||
|
||||
var DateTime = Module.create(function DateTime() {
|
||||
this.super(Observable).call(this);
|
||||
this._init();
|
||||
}).extend(Observable);
|
||||
|
||||
|
||||
// public observers
|
||||
/**
|
||||
* Auto setting Date & Time.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
* @type {Boolean}
|
||||
*/
|
||||
Observable.defineObservableProperty(DateTime.prototype, 'clockAutoEnabled', {
|
||||
readonly: true,
|
||||
value: true
|
||||
});
|
||||
|
||||
/**
|
||||
* SIM provide Auto clock function.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
* @type {Boolean}
|
||||
*/
|
||||
Observable.defineObservableProperty(DateTime.prototype,
|
||||
'clockAutoAvailable', {
|
||||
readonly: true,
|
||||
value: true
|
||||
});
|
||||
|
||||
/**
|
||||
* SIM provide Auto timezone function.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
* @type {Boolean}
|
||||
*/
|
||||
Observable.defineObservableProperty(DateTime.prototype,
|
||||
'timezoneAutoAvailable', {
|
||||
readonly: true,
|
||||
value: true
|
||||
});
|
||||
|
||||
/**
|
||||
* Current Timezone.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
* @type {String}
|
||||
*/
|
||||
Observable.defineObservableProperty(DateTime.prototype, 'timezone', {
|
||||
readonly: true,
|
||||
value: ''
|
||||
});
|
||||
|
||||
/**
|
||||
* User Selected Timezone.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
* @type {String}
|
||||
*/
|
||||
Observable.defineObservableProperty(DateTime.prototype,
|
||||
'userSelectedTimezone', {
|
||||
readonly: true,
|
||||
value: ''
|
||||
});
|
||||
|
||||
/**
|
||||
* Current Date string.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
* @type {String}
|
||||
*/
|
||||
Observable.defineObservableProperty(DateTime.prototype, 'date', {
|
||||
readonly: true,
|
||||
value: ''
|
||||
});
|
||||
|
||||
/**
|
||||
* Localized current time string.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
* @type {String}
|
||||
*/
|
||||
Observable.defineObservableProperty(DateTime.prototype, 'time', {
|
||||
readonly: true,
|
||||
value: ''
|
||||
});
|
||||
|
||||
/**
|
||||
* Current AM/PM or 24 state.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
* @type {Boolean}
|
||||
*/
|
||||
Observable.defineObservableProperty(DateTime.prototype, 'currentHour12', {
|
||||
readonly: true,
|
||||
value: true
|
||||
});
|
||||
|
||||
/**
|
||||
* Init DateTime module.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf DateTime
|
||||
*/
|
||||
DateTime.prototype._init = function() {
|
||||
this._mozTime = window.navigator.mozTime;
|
||||
|
||||
this._boundSetTimeAutoEnabled = function(event) {
|
||||
this._clockAutoEnabled = event.settingValue;
|
||||
// also set timezoneAutoEnabled
|
||||
this._setTimezoneAutoEnabled(event.settingValue);
|
||||
}.bind(this);
|
||||
this._boundSetClockAutoAvailable = function(event) {
|
||||
this._clockAutoAvailable = event.settingValue;
|
||||
}.bind(this);
|
||||
this._boundSetTimezoneAutoAvailable = function(event) {
|
||||
this._timezoneAutoAvailable = event.settingValue;
|
||||
}.bind(this);
|
||||
this._boundSetTimezone = function(event) {
|
||||
this._timezone = event.settingValue;
|
||||
}.bind(this);
|
||||
this._boundUserSelectedTimezone = function(event) {
|
||||
this._userSelectedTimezone = event.settingValue;
|
||||
}.bind(this);
|
||||
this._boundCurrentHour12 = function(event) {
|
||||
this._currentHour12 = event.settingValue;
|
||||
|
||||
this._autoUpdateDateTime();
|
||||
}.bind(this);
|
||||
|
||||
this._getDefaults();
|
||||
this._attachListeners();
|
||||
};
|
||||
|
||||
DateTime.prototype._attachListeners = function() {
|
||||
window.navigator.mozSettings.addObserver(_kClockAutoEnabled,
|
||||
this._boundSetTimeAutoEnabled);
|
||||
window.navigator.mozSettings.addObserver(_kClockAutoAvailable,
|
||||
this._boundSetClockAutoAvailable);
|
||||
window.navigator.mozSettings.addObserver(_kTimezoneAutoAvailable,
|
||||
this._boundSetTimezoneAutoAvailable);
|
||||
window.navigator.mozSettings.addObserver(_kTimezone,
|
||||
this._boundSetTimezone);
|
||||
window.navigator.mozSettings.addObserver(_kUserSelected,
|
||||
this._boundUserSelectedTimezone);
|
||||
window.navigator.mozSettings.addObserver(_kLocaleTime,
|
||||
this._boundCurrentHour12);
|
||||
// Listen to 'DOMRetranslated' to get the latest l10n resource.
|
||||
document.addEventListener('DOMRetranslated', this);
|
||||
// Listen to 'moztimechange' to update clock
|
||||
window.addEventListener('moztimechange', this);
|
||||
};
|
||||
|
||||
DateTime.prototype.handleEvent = function(evt) {
|
||||
switch (evt.type) {
|
||||
case 'moztimechange':
|
||||
this._autoUpdateDateTime();
|
||||
break;
|
||||
case 'DOMRetranslated':
|
||||
var d = new Date();
|
||||
this._date = this._formatDate(d);
|
||||
this._time = this._formatTime(d);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* fill in default values to public observers
|
||||
*
|
||||
* @access private
|
||||
* @memberOf DateTime
|
||||
*/
|
||||
DateTime.prototype._getDefaults = function() {
|
||||
SettingsCache.getSettings(function(results) {
|
||||
this._clockAutoEnabled = results[_kClockAutoEnabled];
|
||||
this._clockAutoAvailable = results[_kClockAutoAvailable];
|
||||
this._timezoneAutoAvailable = results[_kTimezoneAutoAvailable];
|
||||
this._timezone = results[_kTimezone];
|
||||
this._currentHour12 = results[_kLocaleTime];
|
||||
// render date/time after get proper format
|
||||
this._autoUpdateDateTime();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Auto update date and time
|
||||
*
|
||||
* @access private
|
||||
* @memberOf DateTime
|
||||
*/
|
||||
DateTime.prototype._autoUpdateDateTime = function() {
|
||||
window.clearTimeout(_updateDateTimeout);
|
||||
window.clearTimeout(_updateTimeTimeout);
|
||||
this._autoUpdateDate();
|
||||
this._autoUpdateTime();
|
||||
};
|
||||
|
||||
/**
|
||||
* Update Date periodically.
|
||||
*
|
||||
* DONT call this function directly,
|
||||
* call _autoUpdateDateTime instead.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf DateTime
|
||||
*/
|
||||
DateTime.prototype._autoUpdateDate = function() {
|
||||
var d = new Date();
|
||||
this._date = this._formatDate(d);
|
||||
|
||||
var remainMillisecond = (24 - d.getHours()) * 3600 * 1000 -
|
||||
d.getMinutes() * 60 * 1000 - d.getMilliseconds();
|
||||
_updateDateTimeout = window.setTimeout(
|
||||
function updateDateTimeout() {
|
||||
this._autoUpdateDate();
|
||||
}.bind(this), remainMillisecond);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update Time periodically.
|
||||
*
|
||||
* DONT call this function directly,
|
||||
* call _autoUpdateDateTime instead.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf DateTime
|
||||
*/
|
||||
DateTime.prototype._autoUpdateTime = function() {
|
||||
var d = new Date();
|
||||
this._time = this._formatTime(d);
|
||||
|
||||
var remainMillisecond = (60 - d.getSeconds()) * 1000;
|
||||
_updateTimeTimeout = window.setTimeout(
|
||||
function updateTimeTimeout() {
|
||||
this._autoUpdateTime();
|
||||
}.bind(this), remainMillisecond);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return preffered date format.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf DateTime
|
||||
* @param {Date} input as Date
|
||||
* @returns {String}
|
||||
*/
|
||||
DateTime.prototype._formatDate = function(d) {
|
||||
return d.toLocaleString(navigator.languages, {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Return preffered time format.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf DateTime
|
||||
* @param {Date} input as Date
|
||||
* @returns {String}
|
||||
*/
|
||||
DateTime.prototype._formatTime = function(d) {
|
||||
return d.toLocaleString(navigator.languages, {
|
||||
hour12: navigator.mozHour12,
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Change system time
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
*/
|
||||
DateTime.prototype.setTime = function(type, value) {
|
||||
var newDate = new Date();
|
||||
var tokens;
|
||||
|
||||
switch (type) {
|
||||
case 'date':
|
||||
tokens = value.split('-');
|
||||
newDate.setFullYear(Number(tokens[0]), Number(tokens[1]) - 1, Number(tokens[2]));
|
||||
break;
|
||||
|
||||
case 'time':
|
||||
tokens = value.split(':');
|
||||
newDate.setHours(parseInt(tokens[0]));
|
||||
newDate.setMinutes(parseInt(tokens[1]));
|
||||
break;
|
||||
}
|
||||
if (!this._mozTime) return;
|
||||
return this._mozTime.set(newDate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Change TimezoneAutoEnabled settings.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf DateTime
|
||||
*/
|
||||
DateTime.prototype._setTimezoneAutoEnabled = function(enabled) {
|
||||
var cset = {};
|
||||
cset[_kTimezoneAutoEnabled] = enabled;
|
||||
settings.createLock().set(cset);
|
||||
},
|
||||
|
||||
/**
|
||||
* Change UserSelectedTimezone settings.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
*/
|
||||
DateTime.prototype.setUserSelectedTimezone = function(selected) {
|
||||
var cset = {};
|
||||
cset[_kTimezone] = selected;
|
||||
settings.createLock().set(cset);
|
||||
};
|
||||
|
||||
/**
|
||||
* Change hour12 settings.
|
||||
* this valie is used to determine 12 or 24 time format.
|
||||
*
|
||||
* @access public
|
||||
* @memberOf DateTime
|
||||
*/
|
||||
DateTime.prototype.setCurrentHour12 = function(selected) {
|
||||
var cset = {};
|
||||
cset[_kLocaleTime] = selected;
|
||||
settings.createLock().set(cset);
|
||||
};
|
||||
|
||||
DateTime.prototype.getHour12ForCurrentLocale = function() {
|
||||
var format = new Intl.DateTimeFormat(navigator.languages, {
|
||||
hour: 'numeric'
|
||||
});
|
||||
return format.resolvedOptions().hour12;
|
||||
};
|
||||
|
||||
return DateTime();
|
||||
});
|
||||
483
overrides/settings.gaiamobile.org/js/modules/dialog_service.js
Normal file
483
overrides/settings.gaiamobile.org/js/modules/dialog_service.js
Normal file
|
|
@ -0,0 +1,483 @@
|
|||
|
||||
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;
|
||||
});
|
||||
Loading…
Reference in a new issue