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,358 @@
'use strict';
/* exported DownloadUI */
/* global DownloadFormatter */
/* global LazyLoader */
/* global MimeMapper */
/**
* This file defines a component to show download confirmations
*
* - Stop download (Are you sure you want to stop the download?)
* - Download stopped (Download was stopped. Try downloading again?)
* - Download failed (xfile failed to download. Try downloading again?)
* - Delete download (Delete xfile?)
* - Unsupported file type
* - File not found
* - File open error
* - No provider to share file
*
* var request = DownloadUI.show(DownloadUI.TYPE.STOP, download);
*
* request.oncancel = function() {
* alert('CANCEL');
* };
*
* request.onconfirm = function() {
* alert('CONFIRM');
* };
*
* WARNING: To use this library you need to include 'shared/js/l10n.js'
*
*/
var DownloadUI = (function() {
/**
* Download type constructor
*
* @param {String} Type name
* @param {Array} CSS classes to confirm button
* @param {Boolean} Message without parameters
*/
var DownloadType = function(name, classes, isPlainMessage) {
this.name = name;
this.classes = classes;
this.isPlainMessage = isPlainMessage;
this.numberOfButtons = classes.indexOf('full') !== -1 ? 1 : 2;
};
/**
* Errors reported by the Downloads API.
*/
var ERRORS = {
NO_MEMORY: 2152857616,
NO_SDCARD: 2152857618,
UNMOUNTED_SDCARD: 2152857621
};
var TYPES = {
STOP: new DownloadType('stop', ['danger'], true),
STOPPED: new DownloadType('stopped', ['recommend'], true),
FAILED: new DownloadType('failed', ['recommend']),
DELETE: new DownloadType('delete', ['danger']),
DELETE_ALL: new DownloadType('delete_all', ['danger']),
UNSUPPORTED_FILE_TYPE: new DownloadType('unsupported_file_type',
['danger']),
FILE_NOT_FOUND: new DownloadType('file_not_found', ['recommend', 'full'],
true),
FILE_OPEN_ERROR: new DownloadType('file_open_error', ['danger']),
NO_SDCARD: new DownloadType('no_sdcard_found_2', ['recommend', 'full'],
true),
UNMOUNTED_SDCARD: new DownloadType('unmounted_sdcard_2', ['recommend',
'full'], true),
NO_PROVIDER: new DownloadType('no_provider', ['recommend', 'full'], true),
NO_MEMORY: new DownloadType('no_memory', ['recommend', 'full'], true)
};
var DownloadAction = function(id, type) {
this.id = id;
this.name = id.toLowerCase();
this.title = this.name + '_downloaded_file';
this.type = type;
};
var ACTIONS = {
OPEN: new DownloadAction('OPEN', 'confirm'),
SHARE: new DownloadAction('SHARE', 'confirm'),
WALLPAPER: new DownloadAction('WALLPAPER', 'confirm'),
RINGTONE: new DownloadAction('RINGTONE', 'confirm')
};
// Confirm dialog containers
var confirm = null;
var actionMenu = null;
/**
* Request auxiliary object to support asynchronous calls
*/
var Request = function() {
this.cancel = function() {
removeContainers();
if (typeof this.oncancel === 'function') {
this.oncancel();
}
};
this.confirm = function(result) {
removeContainers();
if (typeof this.onconfirm === 'function') {
this.result = result;
this.onconfirm({
target: this
});
}
};
};
function removeContainers() {
removeConfirm();
removeActionMenu();
}
function addConfirm() {
if (confirm !== null) {
confirm.parentNode.removeChild(confirm);
}
confirm = document.createElement('form');
confirm.id = 'downloadConfirmUI';
confirm.setAttribute('role', 'dialog');
confirm.setAttribute('data-type', 'confirm');
confirm.setAttribute('data-z-index-level', '100');
var screen = document.getElementById('screen');
var container = screen || document.body;
container.appendChild(confirm);
}
function removeConfirm() {
if (confirm === null) {
return;
}
confirm.innerHTML = '';
confirm.style.display = 'none';
}
// When users click or hold on home button UIs should be removed
window.addEventListener('home', removeContainers);
window.addEventListener('holdhome', removeContainers);
function l10n(element, l10nid, l10nargs) {
// First set our args.
if (l10nargs) {
element.setAttribute('data-l10n-args', JSON.stringify(l10nargs));
}
// Then localize.
element.setAttribute('data-l10n-id', l10nid);
return element;
}
function createConfirm(type, req, downloads) {
addConfirm();
var dialog = document.createElement('section');
// Header
var header = document.createElement('h1');
l10n(header, type.name + '_download_title');
dialog.appendChild(header);
// Message
var message = document.createElement('p');
if (type.isPlainMessage) {
l10n(message, type.name + '_download_message');
} else {
var args = Object.create(null);
if (type === TYPES.DELETE_ALL) {
args.number = downloads.length;
} else {
args.name = DownloadFormatter.getFileName(downloads[0]);
}
l10n(message, type.name + '_download_message', args);
}
dialog.appendChild(message);
var menu = document.createElement('menu');
menu.dataset.items = type.numberOfButtons;
if (type.numberOfButtons === 2) {
// Left button
var lButton = document.createElement('button');
lButton.type = 'button';
lButton.setAttribute('data-l10n-id',
type.name + '_download_left_button');
lButton.onclick = function l_cancel() {
lButton.onclick = null;
req.cancel();
};
menu.appendChild(lButton);
}
// Right button
var rButton = document.createElement('button');
rButton.type = 'button';
type.classes.forEach(function(clazz) {
rButton.classList.add(clazz);
});
rButton.setAttribute('data-l10n-id',
type.name + '_download_right_button');
rButton.onclick = function r_confirm() {
rButton.onclick = null;
req.confirm();
};
menu.appendChild(rButton);
dialog.appendChild(menu);
confirm.appendChild(dialog);
confirm.style.display = 'block';
}
function addActionMenu() {
// If we have an actionMenu, empty it and re-create it.
if (actionMenu !== null) {
document.body.removeChild(actionMenu);
}
actionMenu = document.createElement('gaia-menu');
actionMenu.id = 'downloadActionMenuUI';
actionMenu.className = 'actions';
}
function removeActionMenu() {
if (actionMenu === null) {
return;
}
actionMenu.hide();
document.body.removeChild(actionMenu);
actionMenu = null;
}
function createActionMenu(req, download) {
var actions = [ACTIONS.OPEN, ACTIONS.SHARE];
var fileName = DownloadFormatter.getFileName(download);
var type = MimeMapper.guessTypeFromFileProperties(fileName,
download.contentType);
if (type.length > 0) {
if (type.startsWith('image/')) {
actions.push(ACTIONS.WALLPAPER);
} else if (type.startsWith('audio/')) {
actions.push(ACTIONS.RINGTONE);
}
}
doCreateActionMenu(req, fileName, actions);
}
function doCreateActionMenu(req, fileName, actions) {
addActionMenu();
var header = document.createElement('header');
header.textContent = fileName;
actionMenu.appendChild(header);
actions.forEach(function addActionButton(action) {
var button = document.createElement('button');
button.id = action.id;
l10n(button, action.title);
button.dataset.type = action.type;
actionMenu.appendChild(button);
button.addEventListener('click', function buttonCliked(evt) {
button.removeEventListener('click', buttonCliked);
req[evt.target.dataset.type](ACTIONS[evt.target.id]);
});
});
document.body.appendChild(actionMenu);
actionMenu.removeAttribute('hidden');
}
var styleSheets = [
'shared/style/buttons.css',
'shared/style/headers.css',
'shared/style/confirm.css'
];
/*
* Shows a confirmation depending on type. It returns a request object with
* oncancel and onconfirm callbacks
*
* @param {String} Confirmation type
*
* @param {Array} It represents the download(s) object(s)
*
* @param {Boolean} This optional parameter indicates if the library should
* include BBs
*/
function show(type, downloads, ignoreStyles) {
var req = new Request();
downloads = Array.isArray(downloads) ? downloads : [downloads];
window.setTimeout(function() {
var libs = ['shared/js/download/download_formatter.js'];
if (!ignoreStyles) {
libs.push.apply(libs, styleSheets);
}
// We have to discover the type of UI depending on state when type is null
if (type === null) {
type = TYPES.STOPPED;
var download = downloads[0];
if (download.state === 'finalized' ||
download.state === 'stopped' && download.error !== null) {
type = TYPES.FAILED;
}
}
LazyLoader.load(libs, createConfirm.call(this, type, req, downloads));
}, 0);
return req;
}
function showActions(download) {
var req = new Request();
window.setTimeout(function() {
LazyLoader.load(['shared/js/mime_mapper.js',
'shared/js/download/download_formatter.js',
'shared/js/component_utils.js',
'shared/elements/gaia_menu/script.js'],
createActionMenu.call(this, req, download));
}, 0);
return req;
}
return {
show: show,
showActions: showActions,
hide: removeContainers,
get ERRORS() {
return ERRORS;
},
get TYPE() {
return TYPES;
}
};
}());