aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/music-app.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/music-app.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/music-app.js45
1 files changed, 44 insertions, 1 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/music-app.js b/packages/meshbay-hub/src/meshbay_hub/static/music-app.js
index ae482ad..dd354d9 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/music-app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/music-app.js
@@ -86,6 +86,46 @@ function groupMusicEntries(entries, audioRoot) {
const byTitle = (a, b) => (a.display_title || a.name).localeCompare(b.display_title || b.name);
tracks.sort(byTitle);
+ // A various-artists compilation (a real film/game soundtrack is the
+ // common shape: dozens of genuinely different per-track artists sharing
+ // one correctly-tagged album name, confirmed against a real ~20-track
+ // soundtrack rip with no separate "album artist" tag at all -- this era
+ // of rip never wrote one). Grouping by artist first, as above, can never
+ // recognize this: every track lands alone in its own artist's bucket as
+ // a one-track "album", each one then folded below into that artist's own
+ // singleton pile -- the same release rendered as a wall of disconnected
+ // one-track cards under a dozen different artist headings instead of one.
+ // Detected the only way the data actually supports here (no album-artist
+ // tag survived): the same album key reappears under two or more
+ // genuinely different artist keys. Pulled out and merged *before* the
+ // per-artist singleton folding below, so those tracks never reach it
+ // under their original artist bucket.
+ const albumKeyArtists = new Map(); // albumKey -> Set(artistKey)
+ for (const [artistKey, bucket] of byArtistKey) {
+ for (const albumKey of bucket.albumsByKey.keys()) {
+ if (!albumKeyArtists.has(albumKey)) albumKeyArtists.set(albumKey, new Set());
+ albumKeyArtists.get(albumKey).add(artistKey);
+ }
+ }
+ const compilations = [];
+ for (const [albumKey, artistKeys] of albumKeyArtists) {
+ if (artistKeys.size < 2) continue;
+ const compTracks = [];
+ let albumDisplay = null;
+ for (const artistKey of artistKeys) {
+ const bucket = byArtistKey.get(artistKey);
+ const album = bucket.albumsByKey.get(albumKey);
+ if (albumDisplay == null) albumDisplay = album.album;
+ compTracks.push(...album.tracks);
+ bucket.albumsByKey.delete(albumKey);
+ }
+ compTracks.sort((a, b) => (trackNo(a) - trackNo(b)) || byTitle(a, b));
+ compilations.push({
+ artist: t('music.various'), album: albumDisplay, isUnknown: false, tracks: compTracks,
+ });
+ }
+ compilations.sort((a, b) => a.album.localeCompare(b.album));
+
const artists = [...byArtistKey.values()].map(({ artist, albumsByKey, loose }) => {
const sortedAlbums = [...albumsByKey.values()].sort((a, b) => a.album.localeCompare(b.album));
@@ -123,7 +163,10 @@ function groupMusicEntries(entries, audioRoot) {
});
}
return { artist, albums: realAlbums };
- }).sort((a, b) => a.artist.localeCompare(b.artist));
+ }).filter((a) => a.albums.length > 0);
+
+ if (compilations.length > 0) artists.push({ artist: t('music.various'), albums: compilations });
+ artists.sort((a, b) => a.artist.localeCompare(b.artist));
const albums = artists.flatMap((a) => a.albums);
return { tracks, artists, albums };