From 7c85c31e8be7ee8effeb867f40e4ffe5048474c8 Mon Sep 17 00:00:00 2001
From: Broque Thomas <26755000+Nezreka@users.noreply.github.com>
Date: Thu, 2 Apr 2026 12:05:53 -0700
Subject: [PATCH] =?UTF-8?q?Skip=20auto=20M3U=20export=20for=20album=20down?=
=?UTF-8?q?loads=20=E2=80=94=20playlists=20only=20(#241)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- autoSavePlaylistM3U() returns early for album downloads (detected by
playlistId prefix) — albums are already grouped by media servers,
M3U just creates empty duplicate playlists (Navidrome auto-imports them)
- Fix broken isAlbum detection — data-context was always "playlist",
now uses reliable playlistId prefix matching
- Update toggle label: "playlists and albums" → "playlists"
- Update hint text to explain albums are skipped and why
- Manual Export M3U button still works for both (explicit user action)
---
webui/index.html | 4 ++--
webui/static/script.js | 21 +++++++++++----------
2 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/webui/index.html b/webui/index.html
index 98475985..2eb4a527 100644
--- a/webui/index.html
+++ b/webui/index.html
@@ -5295,11 +5295,11 @@
- Saves an M3U playlist file to the same folder as the downloaded tracks.
+ Saves an M3U playlist file alongside your music. Albums are skipped — they're already grouped by your media server.
diff --git a/webui/static/script.js b/webui/static/script.js
index 83dbc74c..92e65f71 100644
--- a/webui/static/script.js
+++ b/webui/static/script.js
@@ -11464,7 +11464,8 @@ async function openDownloadMissingModal(playlistId) {
async function autoSavePlaylistM3U(playlistId) {
/**
- * Automatically save M3U file server-side for playlist and album modals.
+ * Automatically save M3U file server-side for playlist modals only.
+ * Albums are skipped — they're already grouped by media servers.
* The server checks the m3u_export.enabled setting before writing.
*/
const process = activeDownloadProcesses[playlistId];
@@ -11478,9 +11479,10 @@ async function autoSavePlaylistM3U(playlistId) {
const m3uContent = generateM3UContent(playlistId);
if (!m3uContent) return;
- // Determine context type and gather metadata
- const dataContext = modal.querySelector('.download-missing-modal-content')?.getAttribute('data-context');
- const isAlbum = dataContext === 'artist_album';
+ // Skip M3U for albums — albums are already naturally grouped in media servers
+ const albumPrefixes = ['artist_album_', 'discover_album_', 'enhanced_search_album_', 'seasonal_album_', 'spotify_library_', 'beatport_release_', 'discover_cache_'];
+ if (albumPrefixes.some(p => playlistId.startsWith(p))) return;
+
const playlistName = process.playlist?.name || process.playlistName || 'Playlist';
const artistName = process.artist?.name || '';
const albumName = process.album?.name || '';
@@ -11494,7 +11496,7 @@ async function autoSavePlaylistM3U(playlistId) {
body: JSON.stringify({
playlist_name: playlistName,
m3u_content: m3uContent,
- context_type: isAlbum ? 'album' : 'playlist',
+ context_type: 'playlist',
artist_name: artistName,
album_name: albumName,
year: year
@@ -11502,7 +11504,7 @@ async function autoSavePlaylistM3U(playlistId) {
});
if (response.ok) {
- console.log(`✅ Auto-saved M3U for ${isAlbum ? 'album' : 'playlist'}: ${playlistName}`);
+ console.log(`✅ Auto-saved M3U for playlist: ${playlistName}`);
} else {
console.warn(`⚠️ Failed to auto-save M3U for ${playlistName}`);
}
@@ -11623,9 +11625,8 @@ async function exportPlaylistAsM3U(playlistId) {
URL.revokeObjectURL(url);
// Also save server-side to the relevant folder (force=true bypasses setting check)
- const modal = document.getElementById(`download-missing-modal-${playlistId}`);
- const dataContext = modal?.querySelector('.download-missing-modal-content')?.getAttribute('data-context');
- const isAlbum = dataContext === 'artist_album';
+ const albumPrefixes = ['artist_album_', 'discover_album_', 'enhanced_search_album_', 'seasonal_album_', 'spotify_library_', 'beatport_release_', 'discover_cache_'];
+ const isAlbumExport = albumPrefixes.some(p => playlistId.startsWith(p));
try {
const releaseDate = process.album?.release_date || '';
@@ -11636,7 +11637,7 @@ async function exportPlaylistAsM3U(playlistId) {
body: JSON.stringify({
playlist_name: playlistName,
m3u_content: m3uContent,
- context_type: isAlbum ? 'album' : 'playlist',
+ context_type: isAlbumExport ? 'album' : 'playlist',
artist_name: process.artist?.name || '',
album_name: process.album?.name || '',
year: year,