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,195 @@
/* exported ToneList */
/* global Templates */
'use strict';
var ToneList = (function() {
// Make sure to keep this in sync with the value in null_ringtone.js!
// (We copy the value here so that you don't need to load null_ringtone.js
// if you don't need it.)
var NONE_ID = 'none:none';
/**
* Compare two tone objects, sorting first on their title, and then their
* subtitle. Note: The empty ringtone is always the "smallest".
*
* @param {Tone} a The first tone.
* @param {Tone} b The second tone.
* @param {Number} <0 if a < b, 0 if a == b, and >0 if a > b.
*/
function toneCompare(a, b) {
// Make sure the empty ringtone is always first.
if (a.id === NONE_ID && b.id === NONE_ID) {
return 0;
} else if (a.id === NONE_ID) {
return -1;
} else if (b.id === NONE_ID) {
return 1;
}
var aName = a.name.toLocaleLowerCase();
var bName = b.name.toLocaleLowerCase();
var cmp = aName.localeCompare(bName);
if (cmp) {
return cmp;
}
var aSubtitle = (a.subtitle || '').toLocaleLowerCase();
var bSubtitle = (b.subtitle || '').toLocaleLowerCase();
return aSubtitle.localeCompare(bSubtitle);
}
/**
* Convert a string of HTML to a DOM node and translate any l10n IDs as
* appropriate. Assumes that mozL10n has already been fully initialized.
*
* @param {String} htmlText The HTML text to turn into a proper DOM node.
* @return {Node} The converted DOM node.
*/
function domify(htmlText) {
var dummyDiv = document.createElement('div');
dummyDiv.innerHTML = htmlText;
var element = dummyDiv.firstElementChild;
return element;
}
/**
* Create a new list of tones. Assumes that mozL10n has already been fully
* initialized. This class is meant to be subclassed by consumers; feel free
* to extend makeItem() to do whatever you need!
*
* @param {String} titleID The l10n ID of the list's header
* @param {Node} parent (optional) The parent node to append this list to.
*/
function ToneList(titleID, parent) {
this.element = domify(Templates.soundList({l10nID: titleID}));
if (parent) {
parent.appendChild(this.element);
}
this._ul = this.element.querySelector('ul');
// This maps tone IDs to an object containing the tone object and the DOM
// node for it. We have to keep the tone objects around anyway, so we're
// not wasting (much) memory with this.
this._toneMap = {};
}
ToneList.prototype = {
/**
* Create and return a list item for a tone.
*
* @param {Object} tone The tone to use for the list item.
* @return {Node} The list item.
*/
makeItem: function(tone) {
var templateArgs = {};
if (tone.l10nID) {
templateArgs.l10nID = tone.l10nID;
} else {
templateArgs.name = tone.name;
}
var item = domify(Templates.soundItem(templateArgs));
item.dataset.id = tone.id;
var detailNode = item.querySelector('details');
if (detailNode && tone.subtitle) {
detailNode.textContent = tone.subtitle;
} else if (detailNode) {
detailNode.parentNode.hideDetails();
} else if (tone.subtitle) {
var subtitle = document.createElement('p');
subtitle.classList.add('subtitle');
var bdi = document.createElement('bdi');
bdi.textContent = tone.subtitle;
subtitle.appendChild(bdi);
item.querySelector('.name').parentNode.appendChild(subtitle);
}
return item;
},
/**
* Insert a tone or array of tones in sorted order into the list.
*
* @param {Object} tones A single tone object or an array thereof.
*/
add: function(tones) {
// If we have no children yet, we can be speedy and sort our new tones
// first, and then append them to the end of the list.
if (this._ul.children.length === 0) {
if (Array.isArray(tones)) {
tones.sort(toneCompare);
tones.forEach(this._append.bind(this));
} else {
this._append(tones); // tones is really just a single tone here!
}
} else {
if (Array.isArray(tones)) {
tones.forEach(this._insertSorted.bind(this));
} else {
this._insertSorted(tones); // tones is really just a single tone here!
}
}
},
/**
* Remove an item from the list.
*
* @param {Tone} tone The tone to remove.
*/
remove: function(tone) {
this._ul.removeChild(this._toneMap[tone.id].element);
if (!this._ul.firstChild) {
this.element.hidden = true;
}
},
/**
* Append a tone object to the end of the list. Useful when we know it
* belongs at the end.
*
* @param {Tone} tone The tone to append.
*/
_append: function(tone) {
if (tone.id in this._toneMap) {
throw new Error('A tone with this ID is already in the list: ' +
tone.id);
}
var newItem = this.makeItem(tone);
this._toneMap[tone.id] = {tone: tone, element: newItem};
this.element.hidden = false;
this._ul.appendChild(newItem);
},
/**
* Insert a tone object into the list based on its sort order.
*
* @param {Tone} tone The tone to insert.
*/
_insertSorted: function(tone) {
if (tone.id in this._toneMap) {
throw new Error('A tone with this ID is already in the list: ' +
tone.id);
}
var newItem = this.makeItem(tone);
this._toneMap[tone.id] = {tone: tone, element: newItem};
this.element.hidden = false;
var items = this._ul.querySelectorAll('li');
for (var i = 0; i < items.length; i++) {
var currTone = this._toneMap[items[i].dataset.id].tone;
if (toneCompare(tone, currTone) < 0) {
this._ul.insertBefore(newItem, items[i]);
return;
}
}
this._ul.appendChild(newItem);
}
};
return ToneList;
})();