diff --git a/database/music_database.py b/database/music_database.py index 8a95c172..4addff94 100644 --- a/database/music_database.py +++ b/database/music_database.py @@ -10289,6 +10289,17 @@ class MusicDatabase: logger.debug(f"Error deleting sync history entry: {e}") return False + def get_sync_history_playlist_names(self): + """Return distinct playlist names ever synced (for server playlist filtering).""" + try: + conn = self._get_connection() + cursor = conn.cursor() + cursor.execute("SELECT DISTINCT playlist_name FROM sync_history WHERE playlist_name != ''") + return [row[0] for row in cursor.fetchall()] + except Exception as e: + logger.error(f"Error getting sync history playlist names: {e}") + return [] + def get_sync_history_stats(self): """Return counts grouped by source.""" try: diff --git a/web_server.py b/web_server.py index 27d623f9..9ba663df 100644 --- a/web_server.py +++ b/web_server.py @@ -30405,6 +30405,16 @@ def delete_sync_history_entry_api(entry_id): except Exception as e: return jsonify({"success": False, "error": str(e)}), 500 +@app.route('/api/sync/history/names', methods=['GET']) +def get_sync_history_playlist_names(): + """Return distinct playlist names ever synced, for server playlist cross-reference.""" + try: + db = MusicDatabase() + names = db.get_sync_history_playlist_names() + return jsonify(names) + except Exception as e: + return jsonify([]) + # =============================== # == UNIFIED MISSING TRACKS API == # =============================== diff --git a/webui/static/script.js b/webui/static/script.js index 1a29503b..194dd5a5 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -72385,31 +72385,39 @@ async function loadServerPlaylists() { } try { - // Fetch server playlists and mirrored playlists in parallel - const [serverRes, mirroredRes] = await Promise.all([ + // Fetch server playlists, mirrored playlists, and sync history names in parallel + const [serverRes, mirroredRes, historyNamesRes] = await Promise.all([ fetch('/api/server/playlists'), fetch('/api/mirrored-playlists'), + fetch('/api/sync/history/names'), ]); const data = await serverRes.json(); let mirroredAll = []; try { mirroredAll = await mirroredRes.json(); } catch (_) { } if (!Array.isArray(mirroredAll)) mirroredAll = []; + let historyNames = []; + try { historyNames = await historyNamesRes.json(); } catch (_) { } + if (!Array.isArray(historyNames)) historyNames = []; if (!data.success || !data.playlists) { if (container) container.innerHTML = `
${data.error || 'Could not load server playlists'}
`; return; } - // Only show server playlists that have a matching mirrored playlist + // Only show server playlists that have a matching mirrored playlist or sync history entry const mirroredNames = new Set(mirroredAll.map(p => p.name.trim().toLowerCase())); - const filtered = data.playlists.filter(pl => mirroredNames.has(pl.name.trim().toLowerCase())); + const syncedNames = new Set(historyNames.map(n => n.trim().toLowerCase())); + const filtered = data.playlists.filter(pl => { + const key = pl.name.trim().toLowerCase(); + return mirroredNames.has(key) || syncedNames.has(key); + }); _serverPlaylists = filtered; const title = document.getElementById('server-tab-title'); if (title) title.textContent = `Server Playlists (${data.server_type ? data.server_type.charAt(0).toUpperCase() + data.server_type.slice(1) : ''})`; if (filtered.length === 0) { - if (container) container.innerHTML = '
No synced playlists found. Only server playlists that match your mirrored playlists are shown here.
'; + if (container) container.innerHTML = '
No synced playlists found. Only server playlists that have been synced via SoulSync are shown here.
'; return; }