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,247 @@
/* global focusManager */
'use strict';
(function(exports) {
/**
* ActionMenu displays a list of user-selectable actions in an overlay.
* An example of this would be when the user selects a single activity form
* a list of several activities. Each ActionMenu instance maintains its own
* dom and event listeners.
* @class ActionMenu
* @param {Array} listItems An array of objects to display.
* @param {String} titleL10nId The l10n id of the header.
* @param {Function} successCb Called when the user selects an option.
* @param {Function} cancelCb Called when the menu is cancelled.
* @param {Boolean} preventFocusChange Set to true to prevent focus changing.
*/
function ActionMenu(listItems, titleL10nId, successCb, cancelCb,
preventFocusChange) {
this.onselected = successCb || function() {};
this.oncancel = cancelCb || function() {};
this.listItems = listItems;
this.titleL10nId = titleL10nId;
}
ActionMenu.prototype = {
/**
* Whether or not the ActionMenu is visible.
* @memberof ActionMenu.prototype
* @return {Boolean} The ActionMenu is visible.
*/
get visible() {
return this.container.classList.contains('visible');
},
/**
* Builds dom and adds event listeners
* @memberof ActionMenu.prototype
*/
start: function() {
// Create the structure
this.container = document.createElement('form');
this.container.dataset.type = 'action';
this.container.setAttribute('role', 'dialog');
this.container.setAttribute('data-z-index-level', 'action-menu');
// An action menu has a mandatory header
this.header = document.createElement('header');
if (this.titleL10nId !== undefined) {
this.header.setAttribute('data-l10n-id', this.titleL10nId);
}
this.container.appendChild(this.header);
// Following our paradigm we need a cancel
this.cancel = document.createElement('button');
this.cancel.dataset.action = 'cancel';
this.cancel.dataset.l10nId = 'cancel';
// We have a menu with all the options
this.menu = document.createElement('menu');
this.container.appendChild(this.menu);
this.container.classList.add('visible');
// We append to System app (actually to '#screen')
var screen = document.getElementById('screen');
screen.appendChild(this.container);
screen.classList.add('action-menu');
this.buildMenu(this.listItems);
this.container.addEventListener('submit', this);
this.menu.addEventListener('click', this);
window.addEventListener('attentionopened', this, true);
window.addEventListener('screenchange', this, true);
window.addEventListener('home', this);
window.addEventListener('holdhome', this);
window.addEventListener('sheets-gesture-begin', this);
focusManager.addUI(this);
focusManager.focus();
if (this.preventFocusChange) {
this.menu.addEventListener('mousedown', this.preventFocusChange);
}
},
/**
* Removes the dom and stops event listeners
* @memberof ActionMenu.prototype
*/
stop: function() {
var screen = document.getElementById('screen');
focusManager.removeUI(this);
screen.removeChild(this.container);
screen.classList.remove('action-menu');
window.removeEventListener('attentionopened', this, true);
window.removeEventListener('screenchange', this, true);
window.removeEventListener('home', this);
window.removeEventListener('holdhome', this);
window.removeEventListener('sheets-gesture-begin', this);
if (this.preventFocusChange) {
this.menu.removeEventListener('mousedown', this.preventFocusChange);
}
},
/**
* Builds the dom for the menu.
* @memberof ActionMenu.prototype
*/
buildMenu: function(items) {
this.menu.innerHTML = '';
items.forEach(function traveseItems(item) {
var action = document.createElement('button');
action.dataset.value = item.value;
action.textContent = item.label;
if (item.icon) {
action.classList.add(item.iconClass || 'icon');
action.style.backgroundImage = 'url(' + item.icon + ')';
}
this.menu.appendChild(action);
}, this);
this.cancel.setAttribute('data-l10n-id', 'cancel');
this.menu.appendChild(this.cancel);
},
/**
* Hides the ActionMenu.
* @memberof ActionMenu.prototype
* @param {Function} callback The callback to call after hiding.
*/
hide: function(callback) {
this.container.classList.remove('visible');
this.stop();
// focus back to the top most window/overlay.
focusManager.focus();
if (callback && typeof callback === 'function') {
setTimeout(callback);
}
},
/**
* When IME switcher shows, prevent the keyboard focus getting changed.
* @memberof ActionMenu.prototype
* @param {DOMEvent} evt The event.
*/
preventFocusChange: function(evt) {
evt.preventDefault();
},
/**
* General event handler interface.
* Handles submission and cancellation events.
* @memberof ActionMenu.prototype
* @param {DOMEvent} evt The event.
*/
handleEvent: function(evt) {
var target = evt.target;
var type = evt.type;
switch (type) {
case 'submit':
evt.preventDefault();
break;
case 'screenchange':
if (!this.visible) {
return;
}
if (!evt.detail.screenEnabled) {
this.hide();
this.oncancel();
}
break;
case 'click':
evt.preventDefault();
var action = target.dataset.action;
if (action && action === 'cancel') {
this.hide();
this.oncancel();
return;
}
var value = target.dataset.value;
if (!value) {
return;
}
value = parseInt(value);
this.hide(this.onselected.bind(this, value));
break;
case 'home':
case 'holdhome':
case 'sheets-gesture-begin':
if (!this.visible) {
return;
}
this.hide();
this.oncancel();
break;
case 'attentionopened':
this.hide();
this.oncancel();
break;
}
},
/**
* Whether or not the ActionMenu is visible.
* @memberof ActionMenu.prototype
* @return {Boolean} if the container is focusible, return true
*/
isFocusable: function() {
return this.container && this.visible;
},
/**
* Get the z-index value of container
* @memberof ActionMenu.prototype
* @return {HTMLElement} the container
*/
getElement: function() {
return this.container;
},
/**
* Focus cancel button in ActionMenu
* @memberof ActionMenu.prototype
*/
focus: function() {
if (this.cancel) {
document.activeElement.blur();
this.cancel.focus();
}
}
};
exports.ActionMenu = ActionMenu;
}(window));