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
|
|
@ -139,10 +139,6 @@ define(function(require) {
|
|||
*/
|
||||
DateTime.prototype._init = function() {
|
||||
this._mozTime = window.navigator.mozTime;
|
||||
if (!this._mozTime) {
|
||||
console.error('Could not get window.navigator.mozTime');
|
||||
return;
|
||||
}
|
||||
|
||||
this._boundSetTimeAutoEnabled = function(event) {
|
||||
this._clockAutoEnabled = event.settingValue;
|
||||
|
|
@ -320,9 +316,7 @@ define(function(require) {
|
|||
switch (type) {
|
||||
case 'date':
|
||||
tokens = value.split('-');
|
||||
newDate.setYear(tokens[0]);
|
||||
newDate.setMonth(tokens[1] - 1);
|
||||
newDate.setDate(tokens[2]);
|
||||
newDate.setFullYear(Number(tokens[0]), Number(tokens[1]) - 1, Number(tokens[2]));
|
||||
break;
|
||||
|
||||
case 'time':
|
||||
|
|
@ -331,7 +325,8 @@ define(function(require) {
|
|||
newDate.setMinutes(parseInt(tokens[1]));
|
||||
break;
|
||||
}
|
||||
this._mozTime.set(newDate);
|
||||
if (!this._mozTime) return;
|
||||
return this._mozTime.set(newDate);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -99,37 +99,35 @@ define(function(require) {
|
|||
_transit: function dm__transit(method, dialog, options) {
|
||||
var promise = new Promise(function(resolve) {
|
||||
var panel = dialog.panel;
|
||||
|
||||
panel.addEventListener('transitionend', function paintWait(evt) {
|
||||
if ((method === 'close' || method === 'open') &&
|
||||
evt.propertyName === 'visibility') {
|
||||
// After transition, we have to `hide` the panel, otherwise
|
||||
// the panel would still exist on the layer and would block
|
||||
// the scrolling event.
|
||||
if (method === 'close') {
|
||||
panel.hidden = true;
|
||||
}
|
||||
panel.removeEventListener('transitionend', paintWait);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
// Before transition, we have to `show` the panel, otherwise
|
||||
// the panel before applying transition class.
|
||||
if (method === 'open') {
|
||||
panel.hidden = false;
|
||||
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();
|
||||
}
|
||||
|
||||
// We need to apply class later otherwise Gecko can't apply
|
||||
// this transition and 150ms is an approximate number after doing
|
||||
// several rounds of manual tests.
|
||||
if (method === 'open') panel.hidden = false;
|
||||
setTimeout(function() {
|
||||
if (method === 'open') {
|
||||
// Let's unhide the panel first
|
||||
panel.classList.add('current');
|
||||
} else {
|
||||
panel.classList.remove('current');
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -190,29 +190,30 @@ define(function(require) {
|
|||
if ('#' + panelId === currentPanel) {
|
||||
defer.reject('You are showing the same panel #' + panelId);
|
||||
} else {
|
||||
options.onWrapSubmit = function() {
|
||||
DialogManager.close(dialog, 'submit', options)
|
||||
.then(function(result) {
|
||||
defer.resolve({
|
||||
type: 'submit',
|
||||
value: result
|
||||
});
|
||||
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.onWrapCancel = function() {
|
||||
DialogManager.close(dialog, 'cancel', options)
|
||||
.then(function(result) {
|
||||
defer.resolve({
|
||||
type: 'cancel',
|
||||
value: result
|
||||
});
|
||||
self._navigating = false;
|
||||
self._execPendingRequest();
|
||||
});
|
||||
};
|
||||
}
|
||||
options.onWrapSubmit = function() { close('submit'); };
|
||||
options.onWrapCancel = function() { close('cancel'); };
|
||||
|
||||
switch (options.type) {
|
||||
case 'alert':
|
||||
|
|
@ -229,7 +230,17 @@ define(function(require) {
|
|||
break;
|
||||
}
|
||||
this._navigating = true;
|
||||
DialogManager.open(dialog, options);
|
||||
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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -246,6 +246,17 @@ define(function(require) {
|
|||
// directly
|
||||
Settings._currentPanel = '#' + panelId;
|
||||
callback();
|
||||
}).catch(function(error) {
|
||||
console.error('Settings panel ' + panelId + ':', error);
|
||||
newPanelElement.classList.remove('current');
|
||||
if (currentPanelElement) currentPanelElement.classList.add('current');
|
||||
// Release the navigation lock even when a hardware query fails.
|
||||
callback(error);
|
||||
if (window.VulpesGaiaUI) {
|
||||
window.VulpesGaiaUI.notice(document.documentElement.lang.indexOf('fr') === 0 ?
|
||||
'Ce panneau n’a pas pu être chargé. Vous pouvez revenir aux autres paramètres.' :
|
||||
'This panel could not be loaded. You can return to the other settings.');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue