"use strict";
// SPDX-License-Identifier: GPL-3.0-or-later
// myMPD (c) 2018-2024 Juergen Mang <mail@jcgames.de>
// https://github.com/jcorporation/mympd
/** @module viewBrowseDatabase_js */
/**
* BrowseDatabaseAlbumList handler
* @returns {void}
*/
function handleBrowseDatabaseAlbumList() {
handleSearchExpression('BrowseDatabaseAlbumList');
selectTag('BrowseDatabaseAlbumListTagDropdown', 'btnBrowseDatabaseAlbumListTagDesc', app.current.tag);
toggleBtnChkId('BrowseDatabaseAlbumListSortDesc', app.current.sort.desc);
selectTag('BrowseDatabaseAlbumListSortTags', undefined, app.current.sort.tag);
sendAPI("MYMPD_API_DATABASE_ALBUM_LIST", {
"offset": app.current.offset,
"limit": app.current.limit,
"expression": app.current.search,
"sort": app.current.sort.tag,
"sortdesc": app.current.sort.desc,
"fields": settings.viewBrowseDatabaseAlbumListFetch.fields
}, parseDatabaseAlbumList, true);
}
/**
* BrowseDatabaseTagList handler
* @returns {void}
*/
function handleBrowseDatabaseTagList() {
handleSearchSimple('BrowseDatabaseTag');
selectTag('BrowseDatabaseTagListTagDropdown', 'btnBrowseDatabaseTagListTagDesc', app.current.tag);
mirrorBtnId('BrowseDatabaseTagListSortDesc', app.current.sort.desc);
sendAPI("MYMPD_API_DATABASE_TAG_LIST", {
"offset": app.current.offset,
"limit": app.current.limit,
"searchstr": app.current.search,
"tag": app.current.tag,
"sortdesc": app.current.sort.desc
}, parseDatabaseTagList, true);
}
/**
* Handles BrowseDatabaseAlbumDetail
* @returns {void}
*/
function handleBrowseDatabaseAlbumDetail() {
sendAPI("MYMPD_API_DATABASE_ALBUM_DETAIL", {
"albumid": app.current.filter,
"fields": settings.viewBrowseDatabaseAlbumDetailFetch.fields
}, parseAlbumDetails, true);
}
/**
* Initializes the browse database elements
* @returns {void}
*/
function initViewBrowseDatabase() {
initSearchSimple('BrowseDatabaseTag');
elGetById('BrowseDatabaseTagListSortDesc').addEventListener('click', function(event) {
event.stopPropagation();
event.preventDefault();
app.current.sort.desc = app.current.sort.desc === true ? false : true;
appGoto(app.current.card, app.current.tab, app.current.view, 0, app.current.limit, app.current.filter, app.current.sort, app.current.tag, app.current.search);
}, false);
initSortBtns('BrowseDatabaseAlbumList');
initSearchExpression('BrowseDatabaseAlbumList');
setView('BrowseDatabaseAlbumList');
setView('BrowseDatabaseAlbumDetail');
setView('BrowseDatabaseTagList');
}
/**
* Click event handler for database tag list
* @param {MouseEvent} event click event
* @param {HTMLElement} target calculated target
* @returns {void}
*/
function viewBrowseDatabaseTagListListClickHandler(event, target) {
event.preventDefault();
event.stopPropagation();
app.current.search = '';
const tag = getData(target, 'tag');
if (settings.tagListAlbum.includes(tag)) {
elGetById('BrowseDatabaseTagSearchStr').value = '';
// clear album search input
elGetById('BrowseDatabaseAlbumListSearchStr').value = '';
gotoBrowse(event);
}
else {
elGetById('SearchSearchStr').value = '';
const value = getData(event.target.parentNode, 'name');
gotoSearch(tag, value);
}
}
/**
* Click event handler for database album list
* @param {MouseEvent} event click event
* @param {HTMLElement} target calculated target
* @returns {void}
*/
function viewBrowseDatabaseAlbumListListClickHandler(event, target) {
appGoto('Browse', 'Database', 'AlbumDetail', 0, undefined, getData(target, 'AlbumId'));
}
/**
* Click event handler for database album detail song list
* @param {MouseEvent} event click event
* @param {HTMLElement} target calculated target
* @returns {void}
*/
function viewBrowseDatabaseAlbumDetailListClickHandler(event, target) {
clickSong(getData(target, 'uri'), event);
}
/**
* Parses the MYMPD_API_DATABASE_ALBUM_LIST response
* @param {object} obj jsonrpc response object
* @returns {void}
*/
function parseDatabaseAlbumList(obj) {
const cardContainer = elGetById('BrowseDatabaseAlbumListList');
if (checkResult(obj, cardContainer, undefined) === false) {
return;
}
if (settings['view' + app.id].mode === 'table') {
const tfoot = cardContainer.querySelector('tfoot');
elClear(tfoot);
updateTable(obj, app.id, function(row, data) {
parseDatabaseAlbumListUpdate(row, data);
});
addTblFooter(tfoot,
elCreateTextTnNr('span', {}, 'Num entries', obj.result.totalEntities)
);
return;
}
if (settings['view' + app.id].mode === 'grid') {
updateGrid(obj, app.id, function(card, data) {
parseDatabaseAlbumListUpdate(card, data);
});
return;
}
updateList(obj, app.id, function(card, data) {
parseDatabaseAlbumListUpdate(card, data);
});
}
/**
* Callback function for row or card
* @param {HTMLElement} card Row or card
* @param {object} data Data object
* @returns {void}
*/
function parseDatabaseAlbumListUpdate(card, data) {
setData(card, 'uri', data.FirstSongUri.replace(/\/[^/]+$/, ''));
setData(card, 'type', 'album');
setData(card, 'name', data.Album);
setData(card, 'Album', data.Album);
setData(card, tagAlbumArtist, data[tagAlbumArtist]);
setData(card, 'AlbumId', data.AlbumId);
card.setAttribute('title', tn('Show album'));
}
/**
* Parsed the MYMPD_API_DATABASE_TAG_LIST response
* @param {object} obj jsonrpc response object
* @returns {void}
*/
function parseDatabaseTagList(obj) {
const cardContainer = elGetById('BrowseDatabaseTagListList');
if (checkResult(obj, cardContainer, undefined) === false) {
return;
}
elGetById('BrowseDatabaseTagListTitle').textContent = tn(obj.result.tag);
if (settings['view' + app.id].mode === 'table') {
const tfoot = cardContainer.querySelector('tfoot');
const colspan = settings['view' + app.id].fields.length;
const smallWidth = uiSmallWidthTagRows();
const actionTd = elCreateEmpty('td', {"data-col": "Action"});
addActionLinks(actionTd, obj.result.tag);
elClear(tfoot);
updateTable(obj, app.id, function(row, data, result) {
parseDatabaseTagListUpdate(row, data, result);
}, function(row, data) {
tableRow(row, data, app.id, colspan, smallWidth, actionTd);
});
addTblFooter(tfoot,
elCreateTextTnNr('span', {}, 'Num entries', obj.result.totalEntities)
);
return;
}
if (settings['view' + app.id].mode === 'grid') {
updateGrid(obj, app.id, function(card, data, result) {
parseDatabaseTagListUpdate(card, data, result);
}, undefined, function(footer, data, result) {
addActionLinks(footer, result.tag);
});
return;
}
updateList(obj, app.id, function(card, data, result) {
parseDatabaseTagListUpdate(card, data, result);
}, undefined, function(footer, data, result) {
addActionLinks(footer, result.tag);
});
}
/**
* Callback function for row or card
* @param {HTMLElement} card Row or card
* @param {object} data Data object
* @param {object} result Jsonrpc result
* @returns {void}
*/
function parseDatabaseTagListUpdate(card, data, result) {
if (result.pics === true) {
data.Thumbnail = getCssImageUri('/tagart?tag=' + myEncodeURIComponent(result.tag) + '&value=' + myEncodeURIComponent(data.Value));
}
setData(card, 'tag', result.tag);
setData(card, 'name', data.Value);
const rowTitle = tn(settings.tagListAlbum.includes(result.tag) ? 'Show albums' : 'Show songs');
card.setAttribute('title', rowTitle);
card.classList.add('no-contextmenu');
}
/**
* Shows the edit sticker modal for the current album
* @param {Event} event triggering click event
* @returns {void}
*/
//eslint-disable-next-line no-unused-vars
function showAlbumSticker(event) {
event.preventDefault();
const uri = getDataId('viewDatabaseAlbumDetailCover', 'AlbumId');
showStickerModal(uri, 'mympd_album');
}
/**
* Parses the MYMPD_API_DATABASE_ALBUM_DETAIL response
* @param {object} obj jsonrpc response object
* @returns {void}
*/
function parseAlbumDetails(obj) {
const table = elGetById('BrowseDatabaseAlbumDetailList');
const tfoot = table.querySelector('tfoot');
const colspan = settings.viewBrowseDatabaseAlbumDetail.fields.length;
const infoEl = elGetById('viewDatabaseAlbumDetailInfoTags');
if (checkResultId(obj, 'BrowseDatabaseAlbumDetailList', 'grid') === false) {
elClear(infoEl);
return;
}
const coverEl = elGetById('viewDatabaseAlbumDetailCover');
coverEl.style.backgroundImage = getCssImageUri('/albumart?offset=0&uri=' + myEncodeURIComponent(obj.result.data[0].uri));
setData(coverEl, 'images', obj.result.images);
setData(coverEl, 'embeddedImageCount', obj.result.embeddedImageCount);
setData(coverEl, 'uri', obj.result.data[0].uri);
setData(coverEl, 'AlbumId', obj.result.AlbumId);
if (features.featStickers === true) {
const feedbackGrp = elGetById('BrowseDatabaseAlbumDetailFeedback').firstElementChild;
setData(feedbackGrp, 'uri', obj.result.AlbumId);
setFeedback(feedbackGrp, obj.result.like, obj.result.rating);
}
elClear(infoEl);
infoEl.appendChild(
elCreateText('h1', {}, obj.result.Album)
);
for (const col of settings.viewBrowseDatabaseAlbumDetailInfo.fields) {
infoEl.appendChild(
elCreateNodes('div', {"class": ["col-xl-6"]}, [
elCreateTextTn('small', {}, col),
elCreateNode('p', {},
printValue(col, obj.result[col])
)
])
);
}
if (obj.result.bookletPath !== '') {
infoEl.appendChild(
elCreateNodes('div', {"class": ["col-xl-6"]}, [
elCreateText('span', {"class": ["mi", "me-2"]}, 'description'),
elCreateTextTn('a', {"target": "_blank", "href": subdir + myEncodeURI(obj.result.bookletPath)}, 'Download booklet')
])
);
}
if (obj.result.infoTxtPath !== '') {
const infoTxtEl = elCreateNodes('div', {"class": ["col-xl-6"]}, [
elCreateText('span', {"class": ["mi", "me-2"]}, 'article'),
elCreateTextTn('span', {"class": ["clickable"]}, 'Album info')
]);
setData(infoTxtEl, 'uri', obj.result.infoTxtPath);
infoTxtEl.addEventListener('click', function(event) {
showInfoTxt(event.target);
}, false);
infoEl.appendChild(infoTxtEl);
}
const mbField = addMusicbrainzFields(obj.result, false);
if (mbField !== null) {
infoEl.appendChild(mbField);
}
if (obj.result.lastPlayedSong.uri !== '' &&
obj.result.lastPlayedSong.pos < obj.result.totalEntities - 1)
{
const resumeBtn = pEl.resumeBtn.cloneNode(true);
resumeBtn.classList.add('ms-3', 'dropdown');
resumeBtn.classList.remove('dropup');
setData(resumeBtn, 'pos', obj.result.lastPlayedSong.pos);
new BSN.Dropdown(resumeBtn.firstElementChild);
resumeBtn.lastElementChild.firstElementChild.addEventListener('click', function(event) {
clickResumeAlbum(event);
}, false);
infoEl.appendChild(
elCreateNodes('div', {"class": ["col-xl-6"]}, [
elCreateTextTn('small', {}, 'Last played'),
elCreateNodes('p', {}, [
document.createTextNode(obj.result.lastPlayedSong.title),
resumeBtn
])
])
);
}
const rowTitle = tn(settingsWebuiFields.clickSong.validValues[settings.webuiSettings.clickSong]);
updateTable(obj, 'BrowseDatabaseAlbumDetail', function(row, data) {
setData(row, 'type', 'song');
setData(row, 'name', data.Title);
setData(row, 'uri', data.uri);
row.setAttribute('title', rowTitle);
});
elReplaceChild(tfoot,
elCreateNode('tr', {"class": ["not-clickable"]},
elCreateNode('td', {"colspan": colspan + 1},
elCreateNodes('small', {}, [
elCreateTextTnNr('span', {}, 'Num songs', obj.result.returnedEntities),
elCreateText('span', {}, smallSpace + nDash + smallSpace + fmtDuration(obj.result.Duration))
])
)
)
);
}
/**
* Go's to the last browse database grid view
* @returns {void}
*/
//eslint-disable-next-line no-unused-vars
function backToAlbumGrid() {
appGoto('Browse', 'Database', 'AlbumList');
}
/**
* Wrapper for add buttons in the album detail view
* @param {string} action action to perform
* @returns {void}
*/
//eslint-disable-next-line no-unused-vars
function currentAlbumAdd(action) {
switch(action) {
case 'appendQueue':
appendQueue('album', [app.current.filter]);
break;
case 'appendPlayQueue':
appendPlayQueue('album', [app.current.filter]);
break;
case 'insertAfterCurrentQueue':
insertAfterCurrentQueue('album', [app.current.filter]);
break;
case 'replaceQueue':
replaceQueue('album', [app.current.filter]);
break;
case 'replacePlayQueue':
replacePlayQueue('album', [app.current.filter]);
break;
case 'addPlaylist':
showAddToPlaylist('album', [app.current.filter]);
break;
case 'addAlbumToHome': {
const name = document.querySelector('#viewDatabaseAlbumDetailInfoTags > h1').textContent;
const images = getDataId('viewDatabaseAlbumDetailCover', 'images');
addAlbumToHome(app.current.filter, name, (images.length > 0 ? images[0]: ''));
break;
}
default:
logError('Invalid action: ' + action);
}
}