diff --git a/MaterialSkin/HTML/material/html/js/browse-functions.js b/MaterialSkin/HTML/material/html/js/browse-functions.js index 22b89af31..c57faa1be 100644 --- a/MaterialSkin/HTML/material/html/js/browse-functions.js +++ b/MaterialSkin/HTML/material/html/js/browse-functions.js @@ -1876,12 +1876,70 @@ function browseHeaderAction(view, act, event, ignoreOpenMenus) { } else if (USE_GRID_ACTION==act) { view.changeLayout(true); } else if (ALBUM_SORTS_ACTION==act || TRACK_SORTS_ACTION==act) { - var sort=ALBUM_SORTS_ACTION==act ? getAlbumSort(view.command, view.inGenre) : getTrackSort(item.stdItem); +console.log("DK item.id="+item.id); + var sort=ALBUM_SORTS_ACTION==act ? getAlbumSort(view.command, view.inGenre, view.current.roleArray) : getTrackSort(item.stdItem); var menuItems=[]; var sorts=ALBUM_SORTS_ACTION==act ? B_ALBUM_SORTS : B_TRACK_SORTS; +// var gotSelection; for (var i=0,len=sorts.length; i=90100 && ALBUM_SORTS_ACTION==act) { + if (view.current.roleSortItems!=undefined && this.lmsLastScan==view.current.lmsLastScan) { +console.log("DK using stored role list"); + for (var i=0,len=view.current.roleSortItems.length; i { + logJsonMessage("RESP", data); + if (data.result && undefined!=data.result.roles_loop) { + let excludeRole = [1,5,6]; // don't want artist, albumartist, trackartist + if (id.startsWith('work_id:')) { + excludeRole.push(2); // don't want composer if we're already viewing a work + } + view.current.roleArray = data.result.roles_loop.map(e => e.role_id).filter(e => !excludeRole.includes(e)); + for (let r=0, loop=data.result.roles_loop, len=loop.length; r e.key).indexOf('album')].label}); + menuItems.push({key:loop[r].role_id, label:roleDisplayName(loop[r].role_id,1)+', '+sorts[sorts.map(e => e.key).indexOf('album')].label, selected:sort.by==loop[r].role_id}); + } + } +// if (!gotSelection) { +// // this means the stored sort is not available for the current list, so set the selected sort to 'album'. +// menuItems[0].selected = 1; +// } + } + }).catch(err => { + //???? + }); + } + } + showMenu(view, {show:true, x:event ? event.clientX : window.innerWidth, y:event ? event.clientY : 52, sortItems:menuItems, reverseSort:sort.rev, isAlbums:ALBUM_SORTS_ACTION==act, name:'sort'}); } else if (VLIB_ACTION==act) { @@ -2540,7 +2598,8 @@ function browseReplaceCommandTerms(view, cmd, item) { } } else if (cmd.params[i].startsWith(SORT_KEY+ALBUM_SORT_PLACEHOLDER) || cmd.params[i].startsWith(SORT_KEY+ARTIST_ALBUM_SORT_PLACEHOLDER)) { - var sort=getAlbumSort(cmd, view.inGenre); +console.log("DK item.id="+item.id); + var sort=getAlbumSort(cmd, view.inGenre, undefined, item.id=='mm:/myMusicAlbums'); // Remove "sort:album" from "playlistcontrol" - LMS fails on this. if (LMS_VERSION<80500 && 'album'==sort.by && isPlayListControl) { cmd.params.splice(i, 1); diff --git a/MaterialSkin/HTML/material/html/js/browse-page.js b/MaterialSkin/HTML/material/html/js/browse-page.js index e779b5b9c..c769506e3 100644 --- a/MaterialSkin/HTML/material/html/js/browse-page.js +++ b/MaterialSkin/HTML/material/html/js/browse-page.js @@ -1091,7 +1091,7 @@ var lmsBrowse = Vue.component("lms-browse", { (INSERT_ACTION==loop[i].action && this.wide>=WIDE_MIX_BTN && this.showDetailedSubtoolbar && !lmsOptions.playShuffle) || (this.tbarActions.length<2 && (i<(this.tbarActions.length<2 ? 2 : 1))) || ((ALBUM_SORTS_ACTION==loop[i].action || TRACK_SORTS_ACTION==loop[i].action) && this.items.length<2) || - ((ALBUM_SORTS_ACTION==loop[i].action || ADD_RANDOM_ALBUM_ACTION==loop[i].action) && this.current && this.current.stdItem==STD_ITEM_WORK) || +// ((ALBUM_SORTS_ACTION==loop[i].action || ADD_RANDOM_ALBUM_ACTION==loop[i].action) && this.current && this.current.stdItem==STD_ITEM_WORK) || (SCROLL_TO_ACTION==loop[i].action && (!this.items[0].id.startsWith(FILTER_PREFIX) || (this.items.length < (this.grid.use ? (this.grid.numColumns*10) : 50) ) ) ) || diff --git a/MaterialSkin/HTML/material/html/js/browse-resp.js b/MaterialSkin/HTML/material/html/js/browse-resp.js index 4995c9c1c..88ffc0815 100644 --- a/MaterialSkin/HTML/material/html/js/browse-resp.js +++ b/MaterialSkin/HTML/material/html/js/browse-resp.js @@ -1011,7 +1011,15 @@ function parseBrowseResp(data, parent, options, cacheKey, parentCommand, parentG } } if (reverse && !isNewMusic) { - data.result.albums_loop = data.result.albums_loop.reverse(); + // sort field for role sorting might be null, if so make sure nulls stay below non-nulls even when reversed. + let loopNotNulls = []; + let loopNulls = []; + const firstNullPos = data.result.albums_loop.map(e => e.rolesort_name).indexOf(''); + if (firstNullPos>0) { + loopNotNulls = data.result.albums_loop.slice(0,firstNullPos); + loopNulls = data.result.albums_loop.slice(firstNullPos); + } + data.result.albums_loop = loopNulls.length ? loopNotNulls.reverse().concat(loopNulls) : data.result.albums_loop.reverse(); } } var albumGroups = !isWorksAlbums && (groupReleases && haveReleaseType && lmsOptions.supportReleaseTypes && lmsOptions.groupByReleaseType>0) ? {} : undefined; diff --git a/MaterialSkin/HTML/material/html/js/standarditems.js b/MaterialSkin/HTML/material/html/js/standarditems.js index 5bc98e5f0..6fdcf5e0a 100644 --- a/MaterialSkin/HTML/material/html/js/standarditems.js +++ b/MaterialSkin/HTML/material/html/js/standarditems.js @@ -61,7 +61,7 @@ const STD_ITEMS=[ }, { command: ["albums"], - params: [ALBUM_TAGS_PLACEHOLDER/*, SORT_KEY+ALBUM_SORT_PLACEHOLDER*/], + params: [ALBUM_TAGS_PLACEHOLDER, SORT_KEY+ALBUM_SORT_PLACEHOLDER], menu: [PLAY_ACTION, INSERT_ACTION, PLAY_SHUFFLE_ACTION, ADD_ACTION, ADD_RANDOM_ALBUM_ACTION, DIVIDER, ADD_TO_FAV_ACTION, SELECT_ACTION, COPY_DETAILS_ACTION/*, CUSTOM_ACTIONS, MORE_LIB_ACTION*/], actionMenu: [DIVIDER, INSERT_ACTION, PLAY_SHUFFLE_ACTION, ADD_RANDOM_ALBUM_ACTION, DIVIDER, ADD_TO_FAV_ACTION/*, CUSTOM_ACTIONS, MORE_LIB_ACTION*/] }, diff --git a/MaterialSkin/HTML/material/html/js/utils-deferred.js b/MaterialSkin/HTML/material/html/js/utils-deferred.js index a44d26a7e..f116cef18 100644 --- a/MaterialSkin/HTML/material/html/js/utils-deferred.js +++ b/MaterialSkin/HTML/material/html/js/utils-deferred.js @@ -499,13 +499,18 @@ function commandAlbumSortKey(command, genre) { const VALID_ALBUM_SORTS = new Set(["album", "artistalbum", "artflow", "yearalbum", "yearartistalbum"]); const VALID_TRACK_SORTS = new Set(["title", "tracknum", "albumtrack", "yearalbumtrack", "artisttitle", "yeartitle"]); -function getAlbumSort(command, genre) { +function getAlbumSort(command, genre, roleArray, allroles) { let key = commandAlbumSortKey(command, genre); let def = ALBUM_SORT_KEY==key || (ALBUM_SORT_KEY+"C")==key ? "album" : "yearalbum"; let parts = getLocalStorageVal(key, def).split("."); let val = {by:parts[0], rev:parts.length>1}; - if (!VALID_ALBUM_SORTS.has(val.by)) { +// let rolesort = LMS_VERSION>=90100 && (BASE_ARTIST_TYPE_IDS.map(String).includes(val.by) || lmsOptions.userDefinedRoles[val.by]!=undefined) ? 1 : 0; + let rolesort = allroles + ? LMS_VERSION>=90100 && (BASE_ARTIST_TYPE_IDS.map(String).includes(val.by) || lmsOptions.userDefinedRoles[val.by]!=undefined) + : roleArray && roleArray.map(String).includes(val.by); + if (!VALID_ALBUM_SORTS.has(val.by) && !rolesort) { val.by = def; + setLocalStorageVal(key, def); } return val; } @@ -810,7 +815,7 @@ function isSameArtistsL(item, rolea, roleList) { return false; } -function roleDisplayName(role) { +function roleDisplayName(role, includeArtists) { if (undefined==role) { return undefined; } @@ -818,9 +823,18 @@ function roleDisplayName(role) { if (val<=0) { return undefined; } - if (val==ARTIST_ROLE || val==ALBUM_ARTIST_ROLE || val==TRACK_ARTIST_ROLE) { + if (!includeArtists && (val==ARTIST_ROLE || val==ALBUM_ARTIST_ROLE || val==TRACK_ARTIST_ROLE)) { return undefined; } + if (val==ARTIST_ROLE) { + return i18n("Artist"); + } + if (val==ALBUM_ARTIST_ROLE) { + return i18n("Album artist"); + } + if (val==TRACK_ARTIST_ROLE) { + return i18n("Track artist"); + } if (val==BAND_ARTIST_ROLE) { return i18n("Band/orchestra"); } @@ -868,4 +882,4 @@ function arraysEqual(a, b) { } } return true; -} \ No newline at end of file +}