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
+}