From 608efb1d8576d9bcf68fb4a1bd8c58cee87681f9 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Sat, 13 Jun 2026 08:35:02 -0700 Subject: [PATCH] =?UTF-8?q?Server=20playlists:=20M3U=20export=20now=20down?= =?UTF-8?q?loads=20the=20.m3u=20to=20the=20browser=20too=20(was=20only=20s?= =?UTF-8?q?aving=20server-side)=20=E2=80=94=20matches=20the=20other=20Expo?= =?UTF-8?q?rt-as-M3U=20buttons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webui/static/pages-extra.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/webui/static/pages-extra.js b/webui/static/pages-extra.js index 4294dff4..4e2633a9 100644 --- a/webui/static/pages-extra.js +++ b/webui/static/pages-extra.js @@ -1688,6 +1688,18 @@ async function exportServerPlaylistM3U() { if (!res.ok || data.success === false) { throw new Error(data.error || 'Export failed'); } + // Download the .m3u to the browser (same as the other Export-as-M3U + // buttons) — force=true also saved it server-side for media servers. + const name = (st.playlistName || 'Playlist').replace(/[/\\?%*:|"<>]/g, '-'); + const blob = new Blob([data.m3u_content || ''], { type: 'audio/x-mpegurl;charset=utf-8' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = `${name}.m3u`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); // `found` = server tracks resolved to a real library file path; any not in // SoulSync's library are skipped (can't write a path for them). const found = data.stats && data.stats.found != null ? data.stats.found : tracks.length;