From f30b27b58866a7110b40a0b7aa4fd5d9e482a93d Mon Sep 17 00:00:00 2001 From: BlackSigkill Date: Thu, 5 Feb 2026 19:16:24 +0100 Subject: [PATCH 1/6] fix broken "sort" button popup --- styles.css | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/styles.css b/styles.css index 61f1968..f96e54b 100644 --- a/styles.css +++ b/styles.css @@ -2179,7 +2179,8 @@ input:checked + .slider::before { pointer-events: none; } -#context-menu { +#context-menu, +#sort-menu { display: none; position: fixed; background-color: var(--card); @@ -2191,7 +2192,8 @@ input:checked + .slider::before { min-width: 160px; } -#context-menu ul { +#context-menu ul, +#sort-menu ul { list-style: none; } From cf499baeb469e4c1289366dbef1dc00060c90027 Mon Sep 17 00:00:00 2001 From: BlackSigkill Date: Thu, 5 Feb 2026 19:17:52 +0100 Subject: [PATCH 2/6] add sort option to any playlist --- index.html | 6 ++-- js/ui.js | 86 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/index.html b/index.html index 45112b8..27d8158 100644 --- a/index.html +++ b/index.html @@ -53,10 +53,12 @@ diff --git a/js/ui.js b/js/ui.js index 124e206..012ecea 100644 --- a/js/ui.js +++ b/js/ui.js @@ -2188,6 +2188,17 @@ export class UIRenderer { const artistB = b.artist?.name || b.artists?.[0]?.name || ''; return artistA.localeCompare(artistB); }); + } else if (sortType === 'album') { + currentTracks = [...originalTracks].sort((a, b) => { + const albumA = a.album?.title || ''; + const albumB = b.album?.title || ''; + const albumCompare = albumA.localeCompare(albumB); + if (albumCompare !== 0) return albumCompare; + // If same album, sort by track number + const trackNumA = a.trackNumber || a.position || 0; + const trackNumB = b.trackNumber || b.position || 0; + return trackNumA - trackNumB; + }); } renderTracks(); }; @@ -2276,16 +2287,61 @@ export class UIRenderer { metaEl.textContent = `${playlist.numberOfTracks} tracks • ${formatDuration(totalDuration)}`; descEl.textContent = playlist.description || ''; - tracklistContainer.innerHTML = ` -
- # - Title - Duration - Menu -
- `; + const originalTracks = [...tracks]; + let currentTracks = [...tracks]; + let currentSort = 'custom'; - this.renderListWithTracks(tracklistContainer, tracks, true, true); + const renderTracks = () => { + tracklistContainer.innerHTML = ` +
+ # + Title + Duration + Menu +
+ `; + this.renderListWithTracks(tracklistContainer, currentTracks, true, true); + }; + + const applySort = (sortType) => { + currentSort = sortType; + if (sortType === 'custom') { + currentTracks = [...originalTracks]; + } else if (sortType === 'added-newest') { + currentTracks = [...originalTracks].sort((a, b) => (b.addedAt || 0) - (a.addedAt || 0)); + } else if (sortType === 'added-oldest') { + currentTracks = [...originalTracks].sort((a, b) => (a.addedAt || 0) - (b.addedAt || 0)); + } else if (sortType === 'title') { + currentTracks = [...originalTracks].sort((a, b) => + (a.title || '').localeCompare(b.title || '') + ); + } else if (sortType === 'artist') { + currentTracks = [...originalTracks].sort((a, b) => { + const artistA = a.artist?.name || a.artists?.[0]?.name || ''; + const artistB = b.artist?.name || b.artists?.[0]?.name || ''; + return artistA.localeCompare(artistB); + }); + } else if (sortType === 'album') { + currentTracks = [...originalTracks].sort((a, b) => { + const albumA = a.album?.title || ''; + const albumB = b.album?.title || ''; + const albumCompare = albumA.localeCompare(albumB); + if (albumCompare !== 0) return albumCompare; + // If same album, sort by track number + const trackNumA = a.trackNumber || a.position || 0; + const trackNumB = b.trackNumber || b.position || 0; + return trackNumA - trackNumB; + }); + } + renderTracks(); + }; + + renderTracks(); + + playBtn.onclick = () => { + this.player.setQueue(currentTracks, 0); + this.player.playTrackFromQueue(); + }; // Update header like button const playlistLikeBtn = document.getElementById('like-playlist-btn'); @@ -2308,8 +2364,8 @@ export class UIRenderer { recommendedSection.style.display = 'none'; } - // Render Actions (Shuffle + Share) - this.updatePlaylistHeaderActions(playlist, false, tracks, false); + // Render Actions (Shuffle + Sort + Share) + this.updatePlaylistHeaderActions(playlist, false, currentTracks, false, applySort); recentActivityManager.addPlaylist(playlist); document.title = playlist.title || 'Artist Mix'; @@ -2847,6 +2903,7 @@ export class UIRenderer { }; fragment.appendChild(shuffleBtn); + // Sort button (always available if onSort is provided) if (onSort) { const sortBtn = document.createElement('button'); sortBtn.id = 'sort-playlist-btn'; @@ -2858,6 +2915,13 @@ export class UIRenderer { e.stopPropagation(); const menu = document.getElementById('sort-menu'); + // Check if any track has addedAt data + const hasAddedDate = tracks.some((t) => t.addedAt); + const dateOptions = menu.querySelectorAll('.requires-added-date'); + dateOptions.forEach((opt) => { + opt.style.display = hasAddedDate ? '' : 'none'; + }); + const rect = sortBtn.getBoundingClientRect(); menu.style.top = `${rect.bottom + 5}px`; menu.style.left = `${rect.left}px`; From 26acd4b225581df0f2f3bab6e505de8c67a9b442 Mon Sep 17 00:00:00 2001 From: BlackSigkill Date: Fri, 6 Feb 2026 11:25:02 +0100 Subject: [PATCH 3/6] fix sorting on monochrome's playlists --- index.html | 2 +- js/ui.js | 188 +++++++++++++++++++++++++---------------------------- styles.css | 4 ++ 3 files changed, 93 insertions(+), 101 deletions(-) diff --git a/index.html b/index.html index 27d8158..b03f375 100644 --- a/index.html +++ b/index.html @@ -53,7 +53,7 @@