diff --git a/htdocs/js/grid.js b/htdocs/js/grid.js index 205c18c22..bf6ea9e9d 100644 --- a/htdocs/js/grid.js +++ b/htdocs/js/grid.js @@ -181,3 +181,18 @@ function gridClickHandler(event) { } return target; } + +/** + * Adds the quick play button to a grid element + * @param {ChildNode} parentEl the containing element + * @returns {void} + */ +function addGridQuickPlayButton(parentEl) { + const div = pEl.coverPlayBtn.cloneNode(true); + parentEl.appendChild(div); + div.addEventListener('click', function(event) { + event.preventDefault(); + event.stopPropagation(); + clickQuickPlay(event.target); + }, false); +} diff --git a/htdocs/js/result.js b/htdocs/js/result.js index 9706d7b2a..e9cfa10c6 100644 --- a/htdocs/js/result.js +++ b/htdocs/js/result.js @@ -105,11 +105,16 @@ function checkResult(obj, parent, mode) { if (mode === undefined) { mode = settings['view' + app.id].mode; } - //remove old alerts + //remove old alert const alert = parent.querySelector('.alert'); let colspan = 0; if (alert) { - alert.parentNode.parentNode.remove(); + if (mode === 'table') { + alert.parentNode.parentNode.remove(); + } + else { + alert.remove(); + } } if (obj.error || obj.result.returnedEntities === 0) diff --git a/htdocs/js/viewBrowseDatabase.js b/htdocs/js/viewBrowseDatabase.js index 9c7a7fc44..7d524412c 100644 --- a/htdocs/js/viewBrowseDatabase.js +++ b/htdocs/js/viewBrowseDatabase.js @@ -122,31 +122,13 @@ function initViewBrowseDatabase() { */ function parseDatabaseAlbumList(obj) { const cardContainer = elGetById('BrowseDatabaseAlbumListList'); - unsetUpdateView(cardContainer); - - if (obj.error !== undefined) { - elReplaceChild(cardContainer, - elCreateTextTn('div', {"class": ["col", "not-clickable", "alert", "alert-warning"]}, obj.error.message, obj.error.data) - ); - setPagination(0, 0); - return; - } - - - const nrItems = obj.result.returnedEntities; - if (nrItems === 0) { - elReplaceChild(cardContainer, - elCreateTextTn('div', {"class": ["col", "not-clickable", "alert", "alert-secondary"]}, 'Empty list') - ); - setPagination(0, 0); + if (checkResult(obj, cardContainer, undefined) === false) { return; } - if (cardContainer.querySelector('.not-clickable') !== null) { - elClear(cardContainer); - } + unsetUpdateView(cardContainer); let cols = cardContainer.querySelectorAll('.col'); - for (let i = 0; i < nrItems; i++) { + for (let i = 0; i < obj.result.returnedEntities; i++) { const card = elCreateEmpty('div', {"data-contextmenu": "album", "class": ["card", "card-grid", "clickable"]}); const image = obj.result.data[i].FirstSongUri !== 'albumid' ? '/albumart-thumb?offset=0&uri=' + myEncodeURIComponent(obj.result.data[i].FirstSongUri) @@ -175,7 +157,7 @@ function parseDatabaseAlbumList(obj) { setData(card, 'Album', obj.result.data[i].Album); setData(card, tagAlbumArtist, obj.result.data[i][tagAlbumArtist]); setData(card, 'AlbumId', obj.result.data[i].AlbumId); - addAlbumPlayButton(card.firstChild); + addGridQuickPlayButton(card.firstChild); const col = elCreateNode('div', {"class": ["col", "px-0", "mb-2", "flex-grow-0"]}, card); if (i < cols.length) { @@ -195,7 +177,7 @@ function parseDatabaseAlbumList(obj) { } //remove obsolete cards cols = cardContainer.querySelectorAll('.col'); - for (let i = cols.length - 1; i >= nrItems; i--) { + for (let i = cols.length - 1; i >= obj.result.returnedEntities; i--) { cols[i].remove(); } @@ -211,32 +193,14 @@ function parseDatabaseAlbumList(obj) { */ function parseDatabaseTagList(obj) { const cardContainer = elGetById('BrowseDatabaseTagListList'); - unsetUpdateView(cardContainer); - - if (obj.error !== undefined) { - elReplaceChild(cardContainer, - elCreateTextTn('div', {"class": ["col", "not-clickable", "alert", "alert-warning"]}, obj.error.message, obj.error.data) - ); - setPagination(0, 0); - return; - } - - const nrItems = obj.result.returnedEntities; - if (nrItems === 0) { - elReplaceChild(cardContainer, - elCreateTextTn('div', {"class": ["col", "not-clickable", "alert", "alert-secondary"]}, 'Empty list') - ); - setPagination(0, 0); + if (checkResult(obj, cardContainer, undefined) === false) { return; } + unsetUpdateView(cardContainer); const listAlbums = settings.tagListAlbum.includes(obj.result.tag); - - if (cardContainer.querySelector('.not-clickable') !== null) { - elClear(cardContainer); - } let cols = cardContainer.querySelectorAll('.col'); - for (let i = 0; i < nrItems; i++) { + for (let i = 0; i < obj.result.returnedEntities; i++) { if (cols[i] !== undefined && getData(cols[i].firstChild,'tag') === obj.result.data[i].value) { @@ -286,7 +250,7 @@ function parseDatabaseAlbumList(obj) { } //remove obsolete cards cols = cardContainer.querySelectorAll('.col'); - for (let i = cols.length - 1; i >= nrItems; i--) { + for (let i = cols.length - 1; i >= obj.result.returnedEntities; i--) { cols[i].remove(); } @@ -295,21 +259,6 @@ function parseDatabaseAlbumList(obj) { scrollToPosY(cardContainer.parentNode, app.current.scrollPos); } -/** - * Adds the album play button - * @param {ChildNode | HTMLElement} parentEl parent element for the button - * @returns {void} - */ -function addAlbumPlayButton(parentEl) { - const playBtn = pEl.coverPlayBtn.cloneNode(true); - parentEl.appendChild(playBtn); - playBtn.addEventListener('click', function(event) { - event.preventDefault(); - event.stopPropagation(); - clickQuickPlay(event.target); - }, false); -} - /** * Parses the MYMPD_API_DATABASE_ALBUM_DETAIL response * @param {object} obj jsonrpc response object diff --git a/htdocs/js/viewBrowseRadioFavorites.js b/htdocs/js/viewBrowseRadioFavorites.js index 1053184cf..ee70cd422 100644 --- a/htdocs/js/viewBrowseRadioFavorites.js +++ b/htdocs/js/viewBrowseRadioFavorites.js @@ -49,31 +49,14 @@ function getRadioFavoriteList() { */ function parseRadioFavoritesList(obj) { const cardContainer = elGetById('BrowseRadioFavoritesList'); - unsetUpdateView(cardContainer); - - if (obj.error !== undefined) { - elReplaceChild(cardContainer, - elCreateTextTn('div', {"class": ["col", "not-clickable", "alert", "alert-danger"]}, obj.error.message, obj.error.data) - ); - setPagination(0, 0); + if (checkResult(obj, cardContainer, undefined) === false) { return; } - const nrItems = obj.result.returnedEntities; - if (nrItems === 0) { - elReplaceChild(cardContainer, - elCreateTextTn('div', {"class": ["col", "not-clickable", "alert", "alert-secondary"]}, 'Empty list') - ); - setPagination(0, 0); - return; - } - - if (cardContainer.querySelector('.not-clickable') !== null) { - elClear(cardContainer); - } + unsetUpdateView(cardContainer); let cols = cardContainer.querySelectorAll('.col'); const rowTitle = tn(settingsWebuiFields.clickRadioFavorites.validValues[settings.webuiSettings.clickRadioFavorites]); - for (let i = 0; i < nrItems; i++) { + for (let i = 0; i < obj.result.returnedEntities; i++) { const card = elCreateNodes('div', {"data-contextmenu": "webradio", "class": ["card", "card-grid", "clickable"], "tabindex": 0}, [ elCreateEmpty('div', {"class": ["card-body", "album-cover-loading", "album-cover-grid", "d-flex"], "title": rowTitle}), elCreateNodes('div', {"class": ["card-footer", "card-footer-grid", "p-2"]}, [ @@ -93,7 +76,7 @@ function parseRadioFavoritesList(obj) { setData(card, 'uri', obj.result.data[i].filename); setData(card, 'name', obj.result.data[i].Name); setData(card, 'type', 'webradio'); - addRadioFavoritesPlayButton(card.firstChild); + addGridQuickPlayButton(card.firstChild); const col = elCreateNode('div', {"class": ["col", "px-0", "mb-2", "flex-grow-0"]}, card); @@ -118,7 +101,7 @@ function parseRadioFavoritesList(obj) { } //remove obsolete cards cols = cardContainer.querySelectorAll('.col'); - for (let i = cols.length - 1; i >= nrItems; i--) { + for (let i = cols.length - 1; i >= obj.result.returnedEntities; i--) { cols[i].remove(); } @@ -126,18 +109,3 @@ function parseRadioFavoritesList(obj) { setScrollViewHeight(cardContainer); scrollToPosY(cardContainer.parentNode, app.current.scrollPos); } - -/** - * Adds the quick play button to the webradio favorite icon - * @param {ChildNode} parentEl the containing element - * @returns {void} - */ -function addRadioFavoritesPlayButton(parentEl) { - const div = pEl.coverPlayBtn.cloneNode(true); - parentEl.appendChild(div); - div.addEventListener('click', function(event) { - event.preventDefault(); - event.stopPropagation(); - clickQuickPlay(event.target); - }, false); -} diff --git a/src/compile_time.h.in b/src/compile_time.h.in index 8b31a744b..dfdfc62fc 100644 --- a/src/compile_time.h.in +++ b/src/compile_time.h.in @@ -173,6 +173,7 @@ extern struct t_mympd_queue *mympd_script_queue; #define MYMPD_VIEW_BROWSE_DATABASE_ALBUM_DETAIL_INFO "{\"mode\":\"table\",\"fields\":[\"Album\",\"AlbumArtist\",\"Genre\"]}" #define MYMPD_VIEW_BROWSE_DATABASE_ALBUM_DETAIL "{\"mode\":\"table\",\"fields\":[\"Track\",\"Title\",\"Duration\"]}" #define MYMPD_VIEW_BROWSE_DATABASE_ALBUM_LIST "{\"mode\":\"grid\",\"fields\":[\"Album\",\"AlbumArtist\"]}" +#define MYMPD_VIEW_BROWSE_DATABASE_TAG_LIST "{\"mode\":\"grid\",\"fields\":[\"value\"]}" #define MYMPD_VIEW_BROWSE_PLAYLIST_DETAIL "{\"mode\":\"table\",\"fields\":[\"Pos\",\"Title\",\"Artist\",\"Album\",\"Duration\"]}" #define MYMPD_VIEW_BROWSE_PLAYLIST_LIST "{\"mode\":\"table\",\"fields\":[\"Type\",\"Name\",\"Last-Modified\"]}" #define MYMPD_VIEW_BROWSE_FILESYSTEM "{\"mode\":\"table\",\"fields\":[\"Pos\",\"Title\",\"Artist\",\"Album\",\"Duration\"]}" @@ -182,6 +183,7 @@ extern struct t_mympd_queue *mympd_script_queue; #define MYMPD_VIEW_QUEUE_JUKEBOX_ALBUM "{\"mode\":\"table\",\"fields\":[\"Pos\",\"Album\",\"AlbumArtist\"]}" #define MYMPD_VIEW_BROWSE_RADIO_WEBRADIODB "{\"mode\":\"table\",\"fields\":[\"Name\",\"Country\",\"Language\",\"Genre\"]}" #define MYMPD_VIEW_BROWSE_RADIO_RADIOBROWSER "{\"mode\":\"table\",\"fields\":[\"name\",\"country\",\"language\",\"tags\"]}" +#define MYMPD_VIEW_BROWSE_RADIO_FAVORITES "{\"mode\":\"grid\",\"fields\":[\"Name\",\"Genre\",\"Country\"]}" #define MYMPD_VOLUME_MIN 0 //prct #define MYMPD_VOLUME_MAX 100 //prct #define MYMPD_VOLUME_STEP 5 //prct diff --git a/src/lib/mympd_state.c b/src/lib/mympd_state.c index 1eab4a864..0a4d1a7b5 100644 --- a/src/lib/mympd_state.c +++ b/src/lib/mympd_state.c @@ -70,6 +70,7 @@ void mympd_state_default(struct t_mympd_state *mympd_state, struct t_config *con mympd_state->view_browse_database_album_detail_info = sdsnew(MYMPD_VIEW_BROWSE_DATABASE_ALBUM_DETAIL_INFO); mympd_state->view_browse_database_album_detail = sdsnew(MYMPD_VIEW_BROWSE_DATABASE_ALBUM_DETAIL); mympd_state->view_browse_database_album_list = sdsnew(MYMPD_VIEW_BROWSE_DATABASE_ALBUM_LIST); + mympd_state->view_browse_database_tag_list = sdsnew(MYMPD_VIEW_BROWSE_DATABASE_TAG_LIST); mympd_state->view_browse_playlist_list = sdsnew(MYMPD_VIEW_BROWSE_PLAYLIST_LIST); mympd_state->view_browse_playlist_detail = sdsnew(MYMPD_VIEW_BROWSE_PLAYLIST_DETAIL); mympd_state->view_browse_filesystem = sdsnew(MYMPD_VIEW_BROWSE_FILESYSTEM); @@ -79,6 +80,7 @@ void mympd_state_default(struct t_mympd_state *mympd_state, struct t_config *con mympd_state->view_queue_jukebox_album = sdsnew(MYMPD_VIEW_QUEUE_JUKEBOX_ALBUM); mympd_state->view_browse_radio_webradiodb = sdsnew(MYMPD_VIEW_BROWSE_RADIO_WEBRADIODB); mympd_state->view_browse_radio_radiobrowser = sdsnew(MYMPD_VIEW_BROWSE_RADIO_RADIOBROWSER); + mympd_state->view_browse_radio_favorites = sdsnew(MYMPD_VIEW_BROWSE_RADIO_FAVORITES); mympd_state->volume_min = MYMPD_VOLUME_MIN; mympd_state->volume_max = MYMPD_VOLUME_MAX; mympd_state->volume_step = MYMPD_VOLUME_STEP; @@ -155,6 +157,7 @@ void mympd_state_free(struct t_mympd_state *mympd_state) { FREE_SDS(mympd_state->view_browse_database_album_detail_info); FREE_SDS(mympd_state->view_browse_database_album_detail); FREE_SDS(mympd_state->view_browse_database_album_list); + FREE_SDS(mympd_state->view_browse_database_tag_list); FREE_SDS(mympd_state->view_browse_playlist_list); FREE_SDS(mympd_state->view_browse_playlist_detail); FREE_SDS(mympd_state->view_browse_filesystem); @@ -164,6 +167,7 @@ void mympd_state_free(struct t_mympd_state *mympd_state) { FREE_SDS(mympd_state->view_queue_jukebox_album); FREE_SDS(mympd_state->view_browse_radio_webradiodb); FREE_SDS(mympd_state->view_browse_radio_radiobrowser); + FREE_SDS(mympd_state->view_browse_radio_favorites); FREE_SDS(mympd_state->coverimage_names); FREE_SDS(mympd_state->thumbnail_names); FREE_SDS(mympd_state->music_directory); diff --git a/src/lib/mympd_state.h b/src/lib/mympd_state.h index 4c2ebf13b..8ecfa5dd6 100644 --- a/src/lib/mympd_state.h +++ b/src/lib/mympd_state.h @@ -231,20 +231,22 @@ struct t_mympd_state { int smartpls_interval; //!< interval to refresh smart playlists in seconds struct t_tags smartpls_generate_tag_types; //!< generate smart playlists for each value for this tag sds smartpls_generate_tag_list; //!< generate smart playlists for each value for this tag (string representation) - sds view_queue_current; //!< columns for the queue view - sds view_search; //!< columns for the search view - sds view_browse_database_album_detail_info; //!< columns for the album detail view - sds view_browse_database_album_detail; //!< columns for the album detail title list - sds view_browse_database_album_list; //!< columns for the album list view - sds view_browse_playlist_list; //!< columns for the listing of playlists - sds view_browse_playlist_detail; //!< columns for the listing of playlist contents - sds view_browse_filesystem; //!< columns for filesystem listing - sds view_playback; //!< columns for playback view - sds view_queue_last_played; //!< columns for last played view - sds view_queue_jukebox_song; //!< columns for the jukebox queue view for songs - sds view_queue_jukebox_album; //!< columns for the jukebox queue view for albums - sds view_browse_radio_webradiodb; //!< columns for the webradiodb view - sds view_browse_radio_radiobrowser; //!< columns for the radiobrowser view + sds view_queue_current; //!< view settings for the queue view + sds view_search; //!< view settings for the search view + sds view_browse_database_album_detail_info; //!< view settings for the album detail view + sds view_browse_database_album_detail; //!< view settings for the album detail title list + sds view_browse_database_album_list; //!< view settings for the album list view + sds view_browse_database_tag_list; //!< view settings for the album list view + sds view_browse_playlist_list; //!< view settings for the listing of playlists + sds view_browse_playlist_detail; //!< view settings for the listing of playlist contents + sds view_browse_filesystem; //!< view settings for filesystem listing + sds view_playback; //!< view settings for playback view + sds view_queue_last_played; //!< view settings for last played view + sds view_queue_jukebox_song; //!< view settings for the jukebox queue view for songs + sds view_queue_jukebox_album; //!< view settings for the jukebox queue view for albums + sds view_browse_radio_webradiodb; //!< view settings for the webradiodb view + sds view_browse_radio_radiobrowser; //!< view settings for the radiobrowser view + sds view_browse_radio_favorites; //!< view settings for the radio favorites view sds music_directory; //!< mpd music directory setting (real value is in mpd_state) sds playlist_directory; //!< mpd playlist directory (real value is in mpd_state) sds navbar_icons; //!< json string of navigation bar icons diff --git a/src/mympd_api/settings.c b/src/mympd_api/settings.c index 237d05b68..a45d7de35 100644 --- a/src/mympd_api/settings.c +++ b/src/mympd_api/settings.c @@ -262,6 +262,9 @@ bool mympd_api_settings_view_save(struct t_mympd_state *mympd_state, sds view, s else if (strcmp(view, "viewBrowseDatabaseAlbumList") == 0) { mympd_state->view_browse_database_album_list = sds_replace(mympd_state->view_browse_database_album_list, def); } + else if (strcmp(view, "viewBrowseDatabaseTagList") == 0) { + mympd_state->view_browse_database_tag_list = sds_replace(mympd_state->view_browse_database_tag_list, def); + } else if (strcmp(view, "viewBrowsePlaylistDetail") == 0) { mympd_state->view_browse_playlist_detail = sds_replace(mympd_state->view_browse_playlist_detail, def); } @@ -286,6 +289,9 @@ bool mympd_api_settings_view_save(struct t_mympd_state *mympd_state, sds view, s else if (strcmp(view, "viewBrowseRadioRadiobrowser") == 0) { mympd_state->view_browse_radio_radiobrowser = sds_replace(mympd_state->view_browse_radio_radiobrowser, def); } + else if (strcmp(view, "viewBrowseRadioFavorites") == 0) { + mympd_state->view_browse_radio_favorites = sds_replace(mympd_state->view_browse_radio_favorites, def); + } else { MYMPD_LOG_ERROR(NULL, "MYMPD_API_VIEW_SAVE: Unknown view \"%s\"", view); return false; @@ -866,6 +872,7 @@ void mympd_api_settings_statefiles_global_read(struct t_mympd_state *mympd_state mympd_state->view_browse_database_album_detail_info = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_database_album_detail_info", mympd_state->view_browse_database_album_detail_info, vcb_isname, true); mympd_state->view_browse_database_album_detail = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_database_album_detail", mympd_state->view_browse_database_album_detail, vcb_isname, true); mympd_state->view_browse_database_album_list = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_database_album_list", mympd_state->view_browse_database_album_list, vcb_isname, true); + mympd_state->view_browse_database_tag_list = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_database_tag_list", mympd_state->view_browse_database_tag_list, vcb_isname, true); mympd_state->view_browse_playlist_list = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_playlist_list", mympd_state->view_browse_playlist_list, vcb_isname, true); mympd_state->view_browse_playlist_detail = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_playlist_detail", mympd_state->view_browse_playlist_detail, vcb_isname, true); mympd_state->view_browse_filesystem = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_filesystem", mympd_state->view_browse_filesystem, vcb_isname, true); @@ -875,6 +882,7 @@ void mympd_api_settings_statefiles_global_read(struct t_mympd_state *mympd_state mympd_state->view_queue_jukebox_album = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_queue_jukebox_album", mympd_state->view_queue_jukebox_album, vcb_isname, true); mympd_state->view_browse_radio_webradiodb = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_radio_webradiodb", mympd_state->view_browse_radio_webradiodb, vcb_isname, true); mympd_state->view_browse_radio_radiobrowser = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_radio_radiobrowser", mympd_state->view_browse_radio_radiobrowser, vcb_isname, true); + mympd_state->view_browse_radio_favorites = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "view_browse_radio_favorites", mympd_state->view_browse_radio_favorites, vcb_isname, true); mympd_state->coverimage_names = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "coverimage_names", mympd_state->coverimage_names, vcb_isfilename, true); mympd_state->thumbnail_names = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "thumbnail_names", mympd_state->thumbnail_names, vcb_isfilename, true); mympd_state->music_directory = state_file_rw_string_sds(workdir, DIR_WORK_STATE, "music_directory", mympd_state->music_directory, vcb_isfilepath, true); @@ -977,6 +985,7 @@ sds mympd_api_settings_get(struct t_mympd_state *mympd_state, struct t_partition buffer = tojson_raw(buffer, "viewBrowseDatabaseAlbumDetailInfo", mympd_state->view_browse_database_album_detail_info, true); buffer = tojson_raw(buffer, "viewBrowseDatabaseAlbumDetail", mympd_state->view_browse_database_album_detail, true); buffer = tojson_raw(buffer, "viewBrowseDatabaseAlbumList", mympd_state->view_browse_database_album_list, true); + buffer = tojson_raw(buffer, "viewBrowseDatabaseTagList", mympd_state->view_browse_database_tag_list, true); buffer = tojson_raw(buffer, "viewBrowsePlaylistList", mympd_state->view_browse_playlist_list, true); buffer = tojson_raw(buffer, "viewBrowsePlaylistDetail", mympd_state->view_browse_playlist_detail, true); buffer = tojson_raw(buffer, "viewBrowseFilesystem", mympd_state->view_browse_filesystem, true); @@ -986,6 +995,7 @@ sds mympd_api_settings_get(struct t_mympd_state *mympd_state, struct t_partition buffer = tojson_raw(buffer, "viewQueueJukeboxAlbum", mympd_state->view_queue_jukebox_album, true); buffer = tojson_raw(buffer, "viewBrowseRadioWebradiodb", mympd_state->view_browse_radio_webradiodb, true); buffer = tojson_raw(buffer, "viewBrowseRadioRadiobrowser", mympd_state->view_browse_radio_radiobrowser, true); + buffer = tojson_raw(buffer, "viewBrowseRadioFavorites", mympd_state->view_browse_radio_favorites, true); buffer = tojson_raw(buffer, "navbarIcons", mympd_state->navbar_icons, true); buffer = tojson_sds(buffer, "listenbrainzToken", mympd_state->listenbrainz_token, true); buffer = tojson_bool(buffer, "tagDiscEmptyIsFirst", mympd_state->tag_disc_empty_is_first, true);