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:
OverSu 2026-10-13 00:19:45 +02:00
commit 1311bed5e9
170 changed files with 19698 additions and 2495 deletions

View file

@ -272,7 +272,7 @@ ActivityController.prototype.onActivityConfirmed = function(newMedia) {
// Video
if (newMedia.isVideo) {
media.type = 'video/3gpp';
media.type = media.blob.type || 'video/3gpp';
media.poster = newMedia.poster.blob;
activity.postResult(media);
this.app.clearSpinner();

View file

@ -107,7 +107,7 @@ OverlayController.prototype.updateOverlay = function(type, enabled, reason) {
return;
}
var closable = self.activity.pick && type !== 'request-fail';
var closable = self.activity.pick || reason === 'request-fail';
var view = new OverlayView({
type: reason,
closable: closable,
@ -118,6 +118,10 @@ OverlayController.prototype.updateOverlay = function(type, enabled, reason) {
overlay.view = view.appendTo(document.body)
.on('click:close-btn', function() {
if (reason === 'request-fail' && !self.activity.pick) {
self.updateOverlay(type, false);
return;
}
self.app.emit('activitycanceled');
});

View file

@ -147,7 +147,7 @@ StorageController.prototype.storeVideo = function(video) {
var self = this;
// Add the poster image to the image storage
poster.filepath = video.filepath.replace('.3gp', '.jpg');
poster.filepath = video.filepath.replace(/\.(?:3gp|mp4|webm)$/, '.jpg');
video.isVideo = true;
this.storage.addPicture(

View file

@ -102,6 +102,7 @@ ViewfinderController.prototype.hideGrid = function() {
* @private
*/
ViewfinderController.prototype.bindEvents = function() {
window.addEventListener('resize', this.configurePreview);
// View
this.views.viewfinder.on('fadedin', this.app.firer('viewfinder:visible'));

View file

@ -25,7 +25,7 @@ var dcfConfig = {
seq: null,
postFix: 'MZLLA',
prefix: {video: 'VID_', image: 'IMG_'},
ext: {video: '3gp', image: 'jpg'}
ext: {video: window.VulpesVideoExtension || '3gp', image: 'jpg'}
};
exports.init = function() {

View file

@ -252,7 +252,7 @@ Storage.prototype.checkFilepath = function(filepath) {
// image and get the video filepath by changing '.jpg' to '.3gp'
if (filepath.indexOf('VID') != -1 &&
filepath.lastIndexOf('.jpg') === filepath.length - 4) {
filepath = filepath.replace('.jpg', '.3gp');
filepath = filepath.replace('.jpg', '.' + (window.VulpesVideoExtension || '3gp'));
}
return filepath;
@ -380,7 +380,7 @@ Storage.prototype.deletePicture = function(filepath, done) {
* @param {String} filepath
*/
Storage.prototype.deleteVideo = function(filepath) {
var poster = filepath.replace('.3gp', '.jpg');
var poster = filepath.replace(/\.(?:3gp|mp4|webm)$/, '.jpg');
this.video.delete(filepath).onerror = function(e) {
console.warn(

View file

@ -205,6 +205,9 @@ module.exports = View.extend({
*/
updatePreview: function(preview, sensorAngle, mirrored) {
if (!preview) { return; }
// An embedded app can initialize before its window is visible.
this.getSize();
if (!this.width || !this.height) { return; }
var aspect;
// Invert dimensions if the camera's `sensorAngle` is