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

149
gaia/apps/email/js/toaster.js Executable file
View file

@ -0,0 +1,149 @@
'use strict';
define(function(require) {
var mozL10n = require('l10n!');
var toasterNode = require('tmpl!./cards/toaster.html');
var transitionEnd = require('transition_end');
/**
* Manages the display of short status notifications, or 'toasts'.
* Each toast may optionally include an action button. Common uses
* may include:
*
* - Displaying notifications about message sending status
* - Allowing the user to undo flags/moves/deletes
* - Allowing the user to retry a failed operation, if applicable
*
* This class is a singleton, because there is only room for one
* toaster on the screen at a time. Subsequent 'toasts' will remove
* any previously-displaying toast.
*/
var toaster = {
defaultTimeout: 5000,
/**
* Tracks the CSS class that was previously applied to the action button,
* so it can be removed on next display.
*/
_previousActionClass: undefined,
/**
* Initialize the Toaster, adding things to the DOM and setting up
* event handlers. The toaster starts out invisible.
*/
init: function(parentEl) {
this.el = toasterNode;
parentEl.appendChild(this.el);
this.text = this.el.querySelector('.toaster-text');
this.actionButton = this.el.querySelector('.toaster-action');
this.el.addEventListener('click', this.hide.bind(this));
transitionEnd(this.el, this.hide.bind(this));
// The target is used for the action to allow a larger tap target than
// just the button.
this.el.querySelector('.toaster-action-target')
.addEventListener('click', this.onAction.bind(this));
this.currentToast = null; // The data for the currently-displayed toast.
},
/**
* Toast a potentially-undoable mail operation. If the operation
* is undoable, an 'Undo' button will be shown, allowing the user
* to undo the action, with one exception: The 'move' and 'delete'
* operations currently do not allow 'undo' per bug 804916, so
* those undo buttons are disabled.
*/
toastOperation: function(op) {
if (!op || !op.affectedCount) {
return; // Nothing to do if no messages were affected.
}
// No undo for move/delete yet. <https://bugzil.la/804916>
var type = op.operation;
var canUndo = (op.undo && type !== 'move' && type !== 'delete');
this.toast({
text: mozL10n.get('toaster-message-' + type, { n: op.affectedCount }),
actionLabel: mozL10n.get('toaster-undo'),
actionClass: 'undo',
action: canUndo && op.undo.bind(op)
});
},
/**
* Called when the user taps the action button (Undo, Retry, etc).
*/
onAction: function() {
var actionFunction = (this.currentToast && this.currentToast.action);
this.hide();
if (actionFunction) {
actionFunction();
}
},
/**
* Display a transient message as a 'toast', with an optional
* action button. The toast dismisses automatically, unless the
* user taps the action button or the toast itself.
*
* @param {object} opts opts
* @param {string} opts.text Localized status text to display.
* @param {function} opts.action Optional function to call when the user
* clicks the action button. If not provided,
* the action button will not be visible.
* @param {string} opts.actionLabel Label to display for the action button.
* Required only if `opts.action` is
* provided.
* @param {string} opts.actionClass a CSS class name to apply to the action
* button.
*/
toast: function(opts) {
opts = opts || {};
console.log('Showing toast:', JSON.stringify(opts));
this.hide(); // Hide in case there was a previous toast already displayed.
this.currentToast = opts;
this.text.textContent = opts.text;
this.actionButton.textContent = opts.actionLabel;
if (this._previousActionClass) {
this.actionButton.classList.remove(this._previousActionClass);
this._previousActionClass = undefined;
}
if (opts.actionClass) {
this._previousActionClass = opts.actionClass;
this.actionButton.classList.add(this._previousActionClass);
}
this.el.classList.toggle('actionable', !opts.action);
this.actionButton.disabled = !opts.action;
this.el.classList.remove('collapsed');
this._fadeTimeout = setTimeout(function() {
// This will hide when the 'fadeout' is complete in 'transitionend'.
this.el.classList.add('fadeout');
}.bind(this), opts.timeout || this.defaultTimeout);
},
isShowing: function() {
return !this.el.classList.contains('collapsed');
},
/**
* Hide the current toast, if one was visible. Idempotent.
*/
hide: function() {
this.currentToast = null;
this.el.classList.add('collapsed');
this.el.classList.remove('fadeout');
window.clearTimeout(this._fadeTimeout);
this._fadeTimeout = null;
}
};
return toaster;
});