VulpesOS/gaia/dev_apps/music-oga/js/utils.js
OverSu b38dea0597 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.
2026-09-30 23:13:03 +02:00

216 lines
6.5 KiB
JavaScript
Executable file

/* exported formatTime, createListElement */
/* global AlbumArtCache, LazyLoader, Normalizer, Sanitizer */
'use strict';
function formatTime(secs) {
if (isNaN(secs)) {
return;
}
secs = Math.floor(secs);
var formatedTime;
var seconds = secs % 60;
var minutes = Math.floor(secs / 60) % 60;
var hours = Math.floor(secs / 3600);
if (hours === 0) {
formatedTime =
(minutes < 10 ? '0' + minutes : minutes) + ':' +
(seconds < 10 ? '0' + seconds : seconds);
} else {
formatedTime =
(hours < 10 ? '0' + hours : hours) + ':' +
(minutes < 10 ? '0' + minutes : minutes) + ':' +
(seconds < 10 ? '0' + seconds : seconds);
}
return formatedTime;
}
// In Music, visually we have three styles of list
// Here we use one function to create different style lists
function createListElement(option, data, index, highlight) {
var li = document.createElement('li');
li.className = 'list-item';
li.setAttribute('role', 'presentation');
var a = document.createElement('a');
a.dataset.index = index;
a.dataset.option = option;
a.setAttribute('role', 'option');
var titleBdi;
li.appendChild(a);
function highlightText(result, text) {
var textContent = result.textContent;
var textLowerCased = textContent.toLocaleLowerCase();
var index = Normalizer.toAscii(textLowerCased).indexOf(text);
if (index >= 0) {
var innerHTML = Sanitizer.createSafeHTML`
${textContent.substring(0, index)}
<span class="search-highlight">
${textContent.substring(index, index + text.length)}
</span>
${textContent.substring(index + text.length)}`;
result.innerHTML = Sanitizer.unwrapSafeHTML(innerHTML);
}
}
switch (option) {
case 'playlist':
titleBdi = document.createElement('bdi');
titleBdi.className = 'list-playlist-title';
if (data.metadata.l10nId) {
titleBdi.textContent = navigator.mozL10n.get(data.metadata.l10nId);
titleBdi.dataset.l10nId = data.metadata.l10nId;
} else {
titleBdi.textContent =
data.metadata.title || navigator.mozL10n.get('unknownTitle');
titleBdi.dataset.l10nId =
data.metadata.title ? '' : 'unknownTitle';
}
a.dataset.keyRange = 'all';
a.dataset.option = data.option;
a.appendChild(titleBdi);
if (index === 0) {
var shuffleIcon = document.createElement('div');
shuffleIcon.className = 'list-playlist-icon';
shuffleIcon.dataset.icon = 'shuffle';
shuffleIcon.setAttribute('data-l10n-id', 'shuffle-toggle');
a.appendChild(shuffleIcon);
}
break;
case 'artist':
case 'album':
case 'title':
var artistBdi;
var albumImg;
albumImg = document.createElement('img');
albumImg.className = 'list-album-art';
li.appendChild(albumImg);
LazyLoader.load('js/metadata/album_art_cache.js').then(() => {
return AlbumArtCache.getThumbnailURL(data);
}).then((url) => {
showImage(albumImg, url);
});
if (option === 'artist') {
artistBdi = document.createElement('bdi');
artistBdi.className = 'list-single-title';
artistBdi.textContent =
data.metadata.artist || navigator.mozL10n.get('unknownArtist');
artistBdi.dataset.l10nId =
data.metadata.artist ? '' : 'unknownArtist';
// Highlight the text when the highlight argument is passed
// This should only happens when we are creating searched results
if (highlight) {
highlightText(artistBdi, highlight);
}
a.appendChild(artistBdi);
} else {
var albumOrTitleBdi = document.createElement('bdi');
artistBdi = document.createElement('bdi');
albumOrTitleBdi.className = 'list-main-title';
artistBdi.className = 'list-sub-title';
if (option === 'album') {
albumOrTitleBdi.textContent =
data.metadata.album || navigator.mozL10n.get('unknownAlbum');
albumOrTitleBdi.dataset.l10nId =
data.metadata.album ? '' : 'unknownAlbum';
} else {
albumOrTitleBdi.textContent =
data.metadata.title || navigator.mozL10n.get('unknownTitle');
albumOrTitleBdi.dataset.l10nId =
data.metadata.title ? '' : 'unknownTitle';
}
artistBdi.textContent =
data.metadata.artist || navigator.mozL10n.get('unknownArtist');
artistBdi.dataset.l10nId =
data.metadata.artist ? '' : 'unknownArtist';
// Highlight the text when the highlight argument is passed
// This should only happens when we are creating searched results
if (highlight) {
highlightText(albumOrTitleBdi, highlight);
}
a.appendChild(albumOrTitleBdi);
a.appendChild(artistBdi);
}
a.dataset.keyRange = data.metadata[option];
a.dataset.option = option;
break;
case 'song':
case 'song-index':
var songTitle =
data.metadata.title || navigator.mozL10n.get('unknownTitle');
var indexBdi = document.createElement('bdi');
indexBdi.className = 'list-song-index';
// 'song-index' mean we want the index and not the track #
if (option === 'song-index') {
indexBdi.textContent = index + 1;
} else {
var trackNum = data.metadata.tracknum;
if (data.metadata.discnum && data.multidisc) {
trackNum = data.metadata.discnum + '.' +
(trackNum < 10 ? '0' + trackNum : trackNum);
}
indexBdi.textContent = trackNum;
}
titleBdi = document.createElement('bdi');
titleBdi.className = 'list-song-title';
titleBdi.textContent = songTitle;
titleBdi.dataset.l10nId = data.metadata.title ? '' : 'unknownTitle';
var lengthBdi = document.createElement('bdi');
lengthBdi.className = 'list-song-length';
a.appendChild(indexBdi);
a.appendChild(titleBdi);
a.appendChild(lengthBdi);
break;
}
return li;
}
function showImage(image, url, option) {
// Reset the image element.
image.classList.remove(option);
image.src = '';
// We could probably have several animation options.
// Add them here in the future.
if (option === 'fadeIn') {
image.style.opacity = 0;
}
image.addEventListener('load', handler);
function handler(evt) {
/* jshint validthis:true */
evt.target.removeEventListener('load', handler);
image.classList.add(option);
}
image.src = url;
}