Add automatic and manual wishlist cleanup features
Introduces backend logic to automatically remove tracks from the wishlist if they already exist in the database after downloads or database updates. Adds a new API endpoint and frontend button for manual wishlist cleanup, allowing users to remove already-owned tracks from the wishlist. Enhances reliability and user experience by keeping the wishlist up-to-date.
This commit is contained in:
parent
219a36c05b
commit
42002d1b45
3 changed files with 468 additions and 0 deletions
|
|
@ -165,6 +165,52 @@ class WishlistService:
|
|||
"""Clear all tracks from the wishlist"""
|
||||
return self.database.clear_wishlist()
|
||||
|
||||
def check_track_in_wishlist(self, spotify_track_id: str) -> bool:
|
||||
"""Check if a track exists in the wishlist by Spotify track ID"""
|
||||
try:
|
||||
wishlist_tracks = self.get_wishlist_tracks_for_download()
|
||||
for track in wishlist_tracks:
|
||||
if track.get('spotify_track_id') == spotify_track_id or track.get('id') == spotify_track_id:
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"Error checking track in wishlist: {e}")
|
||||
return False
|
||||
|
||||
def find_matching_wishlist_track(self, track_name: str, artist_name: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Find a matching track in the wishlist using fuzzy matching on name and artist.
|
||||
Returns the first matching wishlist track or None if no match found.
|
||||
"""
|
||||
try:
|
||||
wishlist_tracks = self.get_wishlist_tracks_for_download()
|
||||
|
||||
# Normalize input for comparison
|
||||
normalized_track_name = track_name.lower().strip()
|
||||
normalized_artist_name = artist_name.lower().strip()
|
||||
|
||||
for wl_track in wishlist_tracks:
|
||||
wl_name = wl_track.get('name', '').lower().strip()
|
||||
wl_artists = wl_track.get('artists', [])
|
||||
|
||||
# Extract artist name from wishlist track
|
||||
wl_artist_name = ''
|
||||
if wl_artists:
|
||||
if isinstance(wl_artists[0], dict):
|
||||
wl_artist_name = wl_artists[0].get('name', '').lower().strip()
|
||||
else:
|
||||
wl_artist_name = str(wl_artists[0]).lower().strip()
|
||||
|
||||
# Simple exact matching (could be enhanced with fuzzy matching algorithms)
|
||||
if wl_name == normalized_track_name and wl_artist_name == normalized_artist_name:
|
||||
return wl_track
|
||||
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error finding matching wishlist track: {e}")
|
||||
return None
|
||||
|
||||
def get_wishlist_summary(self) -> Dict[str, Any]:
|
||||
"""Get a summary of the wishlist for dashboard display"""
|
||||
try:
|
||||
|
|
|
|||
354
web_server.py
354
web_server.py
|
|
@ -4525,6 +4525,12 @@ def _post_process_matched_download(context_key, context, file_path):
|
|||
|
||||
print(f"✅ Post-processing complete for: {final_path}")
|
||||
|
||||
# WISHLIST REMOVAL: Check if this track should be removed from wishlist after successful download
|
||||
try:
|
||||
_check_and_remove_from_wishlist(context)
|
||||
except Exception as wishlist_error:
|
||||
print(f"⚠️ [Post-Process] Error checking wishlist removal: {wishlist_error}")
|
||||
|
||||
# Call completion callback for missing downloads tasks to start next batch
|
||||
task_id = context.get('task_id')
|
||||
batch_id = context.get('batch_id')
|
||||
|
|
@ -4559,6 +4565,232 @@ def _post_process_matched_download(context_key, context, file_path):
|
|||
# Keep track of processed downloads to avoid re-processing
|
||||
_processed_download_ids = set()
|
||||
|
||||
def _check_and_remove_from_wishlist(context):
|
||||
"""
|
||||
Check if a successfully downloaded track should be removed from wishlist.
|
||||
Extracts Spotify track data from download context and removes from wishlist if found.
|
||||
"""
|
||||
try:
|
||||
from core.wishlist_service import get_wishlist_service
|
||||
wishlist_service = get_wishlist_service()
|
||||
|
||||
# Try to extract Spotify track ID from various sources in the context
|
||||
spotify_track_id = None
|
||||
|
||||
# Method 1: Direct track_info with id
|
||||
track_info = context.get('track_info', {})
|
||||
if track_info.get('id'):
|
||||
spotify_track_id = track_info['id']
|
||||
print(f"📋 [Wishlist] Found Spotify ID from track_info: {spotify_track_id}")
|
||||
|
||||
# Method 2: From original search result
|
||||
elif context.get('original_search_result', {}).get('id'):
|
||||
spotify_track_id = context['original_search_result']['id']
|
||||
print(f"📋 [Wishlist] Found Spotify ID from original_search_result: {spotify_track_id}")
|
||||
|
||||
# Method 3: Check if this is a wishlist download (context has wishlist_id)
|
||||
elif 'wishlist_id' in track_info:
|
||||
wishlist_id = track_info['wishlist_id']
|
||||
print(f"📋 [Wishlist] Found wishlist_id in context: {wishlist_id}")
|
||||
|
||||
# Get the Spotify track ID from the wishlist entry
|
||||
wishlist_tracks = wishlist_service.get_wishlist_tracks_for_download()
|
||||
for wl_track in wishlist_tracks:
|
||||
if wl_track.get('wishlist_id') == wishlist_id:
|
||||
spotify_track_id = wl_track.get('spotify_track_id') or wl_track.get('id')
|
||||
print(f"📋 [Wishlist] Found Spotify ID from wishlist entry: {spotify_track_id}")
|
||||
break
|
||||
|
||||
# Method 4: Try to construct ID from track metadata for fuzzy matching
|
||||
if not spotify_track_id:
|
||||
track_name = track_info.get('name') or context.get('original_search_result', {}).get('title', '')
|
||||
artist_name = _get_track_artist_name(track_info) or _get_track_artist_name(context.get('original_search_result', {}))
|
||||
|
||||
if track_name and artist_name:
|
||||
print(f"📋 [Wishlist] No Spotify ID found, checking for fuzzy match: '{track_name}' by '{artist_name}'")
|
||||
|
||||
# Get all wishlist tracks and find potential matches
|
||||
wishlist_tracks = wishlist_service.get_wishlist_tracks_for_download()
|
||||
for wl_track in wishlist_tracks:
|
||||
wl_name = wl_track.get('name', '').lower()
|
||||
wl_artists = wl_track.get('artists', [])
|
||||
wl_artist_name = ''
|
||||
|
||||
# Extract artist name from wishlist track
|
||||
if wl_artists:
|
||||
if isinstance(wl_artists[0], dict):
|
||||
wl_artist_name = wl_artists[0].get('name', '').lower()
|
||||
else:
|
||||
wl_artist_name = str(wl_artists[0]).lower()
|
||||
|
||||
# Simple fuzzy matching
|
||||
if (wl_name == track_name.lower() and wl_artist_name == artist_name.lower()):
|
||||
spotify_track_id = wl_track.get('spotify_track_id') or wl_track.get('id')
|
||||
print(f"📋 [Wishlist] Found fuzzy match - Spotify ID: {spotify_track_id}")
|
||||
break
|
||||
|
||||
# If we found a Spotify track ID, remove it from wishlist
|
||||
if spotify_track_id:
|
||||
print(f"📋 [Wishlist] Attempting to remove track from wishlist: {spotify_track_id}")
|
||||
removed = wishlist_service.mark_track_download_result(spotify_track_id, success=True)
|
||||
if removed:
|
||||
print(f"✅ [Wishlist] Successfully removed track from wishlist: {spotify_track_id}")
|
||||
else:
|
||||
print(f"ℹ️ [Wishlist] Track not found in wishlist or already removed: {spotify_track_id}")
|
||||
else:
|
||||
print(f"ℹ️ [Wishlist] No Spotify track ID found for wishlist removal check")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ [Wishlist] Error in wishlist removal check: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
def _check_and_remove_track_from_wishlist_by_metadata(track_data):
|
||||
"""
|
||||
Check if a track found during database analysis should be removed from wishlist.
|
||||
Uses track metadata (name, artists, id) to find and remove from wishlist.
|
||||
"""
|
||||
try:
|
||||
from core.wishlist_service import get_wishlist_service
|
||||
wishlist_service = get_wishlist_service()
|
||||
|
||||
# Extract track info
|
||||
track_name = track_data.get('name', '')
|
||||
track_id = track_data.get('id', '')
|
||||
artists = track_data.get('artists', [])
|
||||
|
||||
print(f"📋 [Analysis] Checking if track should be removed from wishlist: '{track_name}' (ID: {track_id})")
|
||||
|
||||
# Method 1: Direct Spotify ID match
|
||||
if track_id:
|
||||
removed = wishlist_service.mark_track_download_result(track_id, success=True)
|
||||
if removed:
|
||||
print(f"✅ [Analysis] Removed track from wishlist via direct ID match: {track_id}")
|
||||
return True
|
||||
|
||||
# Method 2: Fuzzy matching by name and artist if no direct ID match
|
||||
if track_name and artists:
|
||||
# Extract primary artist name
|
||||
primary_artist = ''
|
||||
if isinstance(artists[0], dict) and 'name' in artists[0]:
|
||||
primary_artist = artists[0]['name']
|
||||
elif isinstance(artists[0], str):
|
||||
primary_artist = artists[0]
|
||||
else:
|
||||
primary_artist = str(artists[0])
|
||||
|
||||
print(f"📋 [Analysis] No direct ID match, trying fuzzy match: '{track_name}' by '{primary_artist}'")
|
||||
|
||||
# Get all wishlist tracks and find matches
|
||||
wishlist_tracks = wishlist_service.get_wishlist_tracks_for_download()
|
||||
for wl_track in wishlist_tracks:
|
||||
wl_name = wl_track.get('name', '').lower()
|
||||
wl_artists = wl_track.get('artists', [])
|
||||
wl_artist_name = ''
|
||||
|
||||
# Extract artist name from wishlist track
|
||||
if wl_artists:
|
||||
if isinstance(wl_artists[0], dict):
|
||||
wl_artist_name = wl_artists[0].get('name', '').lower()
|
||||
else:
|
||||
wl_artist_name = str(wl_artists[0]).lower()
|
||||
|
||||
# Fuzzy matching - normalize strings for comparison
|
||||
if (wl_name == track_name.lower() and wl_artist_name == primary_artist.lower()):
|
||||
spotify_track_id = wl_track.get('spotify_track_id') or wl_track.get('id')
|
||||
if spotify_track_id:
|
||||
removed = wishlist_service.mark_track_download_result(spotify_track_id, success=True)
|
||||
if removed:
|
||||
print(f"✅ [Analysis] Removed track from wishlist via fuzzy match: {spotify_track_id}")
|
||||
return True
|
||||
|
||||
print(f"ℹ️ [Analysis] Track not found in wishlist or already removed: '{track_name}'")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ [Analysis] Error checking wishlist removal by metadata: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def _automatic_wishlist_cleanup_after_db_update():
|
||||
"""
|
||||
Automatic wishlist cleanup that runs after database updates.
|
||||
This is a simplified version of the cleanup API endpoint designed for background execution.
|
||||
"""
|
||||
try:
|
||||
from core.wishlist_service import get_wishlist_service
|
||||
from database.music_database import MusicDatabase
|
||||
|
||||
wishlist_service = get_wishlist_service()
|
||||
db = MusicDatabase()
|
||||
active_server = config_manager.get_active_media_server()
|
||||
|
||||
print("📋 [Auto Cleanup] Starting automatic wishlist cleanup after database update...")
|
||||
|
||||
# Get all wishlist tracks
|
||||
wishlist_tracks = wishlist_service.get_wishlist_tracks_for_download()
|
||||
if not wishlist_tracks:
|
||||
print("📋 [Auto Cleanup] No tracks in wishlist to clean up")
|
||||
return
|
||||
|
||||
print(f"📋 [Auto Cleanup] Found {len(wishlist_tracks)} tracks in wishlist")
|
||||
|
||||
removed_count = 0
|
||||
|
||||
for track in wishlist_tracks:
|
||||
track_name = track.get('name', '')
|
||||
artists = track.get('artists', [])
|
||||
spotify_track_id = track.get('spotify_track_id') or track.get('id')
|
||||
|
||||
# Skip if no essential data
|
||||
if not track_name or not artists or not spotify_track_id:
|
||||
continue
|
||||
|
||||
# Check each artist
|
||||
found_in_db = False
|
||||
for artist in artists:
|
||||
# Handle both string format and dict format
|
||||
if isinstance(artist, str):
|
||||
artist_name = artist
|
||||
elif isinstance(artist, dict) and 'name' in artist:
|
||||
artist_name = artist['name']
|
||||
else:
|
||||
artist_name = str(artist)
|
||||
|
||||
try:
|
||||
db_track, confidence = db.check_track_exists(
|
||||
track_name, artist_name,
|
||||
confidence_threshold=0.7,
|
||||
server_source=active_server
|
||||
)
|
||||
|
||||
if db_track and confidence >= 0.7:
|
||||
found_in_db = True
|
||||
print(f"📋 [Auto Cleanup] Track found in database: '{track_name}' by {artist_name} (confidence: {confidence:.2f})")
|
||||
break
|
||||
|
||||
except Exception as db_error:
|
||||
print(f"⚠️ [Auto Cleanup] Error checking database for track '{track_name}': {db_error}")
|
||||
continue
|
||||
|
||||
# If found in database, remove from wishlist
|
||||
if found_in_db:
|
||||
try:
|
||||
removed = wishlist_service.mark_track_download_result(spotify_track_id, success=True)
|
||||
if removed:
|
||||
removed_count += 1
|
||||
print(f"✅ [Auto Cleanup] Removed track from wishlist: '{track_name}' ({spotify_track_id})")
|
||||
except Exception as remove_error:
|
||||
print(f"❌ [Auto Cleanup] Error removing track from wishlist: {remove_error}")
|
||||
|
||||
print(f"📋 [Auto Cleanup] Completed automatic cleanup: {removed_count} tracks removed from wishlist")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ [Auto Cleanup] Error in automatic wishlist cleanup: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
@app.route('/api/version-info', methods=['GET'])
|
||||
def get_version_info():
|
||||
"""
|
||||
|
|
@ -4846,6 +5078,14 @@ def _db_update_finished_callback(total_artists, total_albums, total_tracks, succ
|
|||
with db_update_lock:
|
||||
db_update_state["status"] = "finished"
|
||||
db_update_state["phase"] = f"Completed: {successful} successful, {failed} failed."
|
||||
|
||||
# WISHLIST CLEANUP: Automatically clean up wishlist after database update
|
||||
try:
|
||||
print("📋 [DB Update] Database update completed, starting automatic wishlist cleanup...")
|
||||
# Run cleanup in background to avoid blocking the UI
|
||||
missing_download_executor.submit(_automatic_wishlist_cleanup_after_db_update)
|
||||
except Exception as cleanup_error:
|
||||
print(f"⚠️ [DB Update] Error starting automatic wishlist cleanup: {cleanup_error}")
|
||||
|
||||
def _db_update_error_callback(error_message):
|
||||
with db_update_lock:
|
||||
|
|
@ -5002,6 +5242,95 @@ def clear_wishlist():
|
|||
print(f"Error clearing wishlist: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
@app.route('/api/wishlist/cleanup', methods=['POST'])
|
||||
def cleanup_wishlist():
|
||||
"""Endpoint to remove tracks from wishlist that already exist in the database."""
|
||||
try:
|
||||
from core.wishlist_service import get_wishlist_service
|
||||
from database.music_database import MusicDatabase
|
||||
|
||||
wishlist_service = get_wishlist_service()
|
||||
db = MusicDatabase()
|
||||
active_server = config_manager.get_active_media_server()
|
||||
|
||||
print("📋 [Wishlist Cleanup] Starting wishlist cleanup process...")
|
||||
|
||||
# Get all wishlist tracks
|
||||
wishlist_tracks = wishlist_service.get_wishlist_tracks_for_download()
|
||||
if not wishlist_tracks:
|
||||
return jsonify({"success": True, "message": "No tracks in wishlist to clean up", "removed_count": 0})
|
||||
|
||||
print(f"📋 [Wishlist Cleanup] Found {len(wishlist_tracks)} tracks in wishlist")
|
||||
|
||||
removed_count = 0
|
||||
processed_count = 0
|
||||
|
||||
for track in wishlist_tracks:
|
||||
processed_count += 1
|
||||
track_name = track.get('name', '')
|
||||
artists = track.get('artists', [])
|
||||
spotify_track_id = track.get('spotify_track_id') or track.get('id')
|
||||
|
||||
# Skip if no essential data
|
||||
if not track_name or not artists or not spotify_track_id:
|
||||
continue
|
||||
|
||||
print(f"📋 [Wishlist Cleanup] Checking track {processed_count}/{len(wishlist_tracks)}: '{track_name}'")
|
||||
|
||||
# Check each artist
|
||||
found_in_db = False
|
||||
for artist in artists:
|
||||
# Handle both string format and dict format
|
||||
if isinstance(artist, str):
|
||||
artist_name = artist
|
||||
elif isinstance(artist, dict) and 'name' in artist:
|
||||
artist_name = artist['name']
|
||||
else:
|
||||
artist_name = str(artist)
|
||||
|
||||
try:
|
||||
db_track, confidence = db.check_track_exists(
|
||||
track_name, artist_name,
|
||||
confidence_threshold=0.7,
|
||||
server_source=active_server
|
||||
)
|
||||
|
||||
if db_track and confidence >= 0.7:
|
||||
found_in_db = True
|
||||
print(f"📋 [Wishlist Cleanup] Track found in database: '{track_name}' by {artist_name} (confidence: {confidence:.2f})")
|
||||
break
|
||||
|
||||
except Exception as db_error:
|
||||
print(f"⚠️ [Wishlist Cleanup] Error checking database for track '{track_name}': {db_error}")
|
||||
continue
|
||||
|
||||
# If found in database, remove from wishlist
|
||||
if found_in_db:
|
||||
try:
|
||||
removed = wishlist_service.mark_track_download_result(spotify_track_id, success=True)
|
||||
if removed:
|
||||
removed_count += 1
|
||||
print(f"✅ [Wishlist Cleanup] Removed track from wishlist: '{track_name}' ({spotify_track_id})")
|
||||
else:
|
||||
print(f"⚠️ [Wishlist Cleanup] Failed to remove track from wishlist: '{track_name}' ({spotify_track_id})")
|
||||
except Exception as remove_error:
|
||||
print(f"❌ [Wishlist Cleanup] Error removing track from wishlist: {remove_error}")
|
||||
|
||||
print(f"📋 [Wishlist Cleanup] Completed cleanup: {removed_count} tracks removed from wishlist")
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"message": f"Wishlist cleanup completed: {removed_count} tracks removed",
|
||||
"removed_count": removed_count,
|
||||
"processed_count": processed_count
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error in wishlist cleanup: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
@app.route('/api/database/update', methods=['POST'])
|
||||
def start_database_update():
|
||||
"""Endpoint to start the database update process."""
|
||||
|
|
@ -5510,6 +5839,24 @@ def _on_download_completed(batch_id, task_id, success=True):
|
|||
download_batches[batch_id]['permanently_failed_tracks'].append(track_info)
|
||||
print(f"❌ [Batch Manager] Added failed track to batch tracking: {track_info['track_name']}")
|
||||
|
||||
# WISHLIST REMOVAL: Handle successful downloads for wishlist removal
|
||||
if success and task_id in download_tasks:
|
||||
try:
|
||||
task = download_tasks[task_id]
|
||||
track_info = task.get('track_info', {})
|
||||
print(f"📋 [Batch Manager] Successful download - checking wishlist removal for task {task_id}")
|
||||
|
||||
# Try to remove from wishlist using track info
|
||||
if track_info:
|
||||
# Create a context-like structure for the wishlist removal function
|
||||
context = {
|
||||
'track_info': track_info,
|
||||
'original_search_result': track_info # fallback
|
||||
}
|
||||
_check_and_remove_from_wishlist(context)
|
||||
except Exception as wishlist_error:
|
||||
print(f"⚠️ [Batch Manager] Error checking wishlist removal for successful download: {wishlist_error}")
|
||||
|
||||
# Decrement active count
|
||||
old_active = download_batches[batch_id]['active_count']
|
||||
download_batches[batch_id]['active_count'] -= 1
|
||||
|
|
@ -5628,6 +5975,13 @@ def _run_full_missing_tracks_process(batch_id, playlist_id, tracks_json):
|
|||
analysis_results.append({
|
||||
'track_index': i, 'track': track_data, 'found': found, 'confidence': confidence
|
||||
})
|
||||
|
||||
# WISHLIST REMOVAL: If track is found in database, check if it should be removed from wishlist
|
||||
if found and confidence >= 0.7:
|
||||
try:
|
||||
_check_and_remove_track_from_wishlist_by_metadata(track_data)
|
||||
except Exception as wishlist_error:
|
||||
print(f"⚠️ [Analysis] Error checking wishlist removal for found track: {wishlist_error}")
|
||||
|
||||
with tasks_lock:
|
||||
if batch_id in download_batches:
|
||||
|
|
|
|||
|
|
@ -3405,6 +3405,9 @@ async function openDownloadMissingWishlistModal() {
|
|||
<button class="download-control-btn danger" id="cancel-all-btn-${playlistId}" onclick="cancelAllOperations('${playlistId}')" style="display: none;">
|
||||
Cancel All
|
||||
</button>
|
||||
<button class="download-control-btn secondary" id="cleanup-wishlist-btn-${playlistId}" onclick="cleanupWishlist('${playlistId}')" style="margin-left: 10px;">
|
||||
🧹 Cleanup Wishlist
|
||||
</button>
|
||||
<button class="download-control-btn danger" id="clear-wishlist-btn-${playlistId}" onclick="clearWishlist('${playlistId}')" style="margin-left: 10px;">
|
||||
🗑️ Clear Wishlist
|
||||
</button>
|
||||
|
|
@ -8488,6 +8491,71 @@ async function handleWishlistButtonClick() {
|
|||
}
|
||||
}
|
||||
|
||||
async function cleanupWishlist(playlistId) {
|
||||
try {
|
||||
// Show information dialog
|
||||
const confirmed = confirm(
|
||||
"Cleanup Wishlist\n\n" +
|
||||
"This will check all wishlist tracks against your music library and automatically remove " +
|
||||
"any tracks that already exist in your database.\n\n" +
|
||||
"This is a safe operation that only removes tracks you already have. " +
|
||||
"Continue with cleanup?"
|
||||
);
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable the cleanup button during the operation
|
||||
const cleanupBtn = document.getElementById(`cleanup-wishlist-btn-${playlistId}`);
|
||||
if (cleanupBtn) {
|
||||
cleanupBtn.disabled = true;
|
||||
cleanupBtn.textContent = '🧹 Cleaning...';
|
||||
}
|
||||
|
||||
const response = await fetch('/api/wishlist/cleanup', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
const removedCount = result.removed_count || 0;
|
||||
const processedCount = result.processed_count || 0;
|
||||
|
||||
if (removedCount > 0) {
|
||||
showToast(`Wishlist cleanup completed: ${removedCount} tracks removed (${processedCount} checked)`, 'success');
|
||||
|
||||
// Refresh the modal content to show updated state
|
||||
setTimeout(() => {
|
||||
openDownloadMissingWishlistModal();
|
||||
}, 500);
|
||||
|
||||
// Update the wishlist count in the main dashboard
|
||||
await updateWishlistCount();
|
||||
} else {
|
||||
showToast(`Wishlist cleanup completed: No tracks to remove (${processedCount} checked)`, 'info');
|
||||
}
|
||||
} else {
|
||||
showToast(`Error cleaning wishlist: ${result.error}`, 'error');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error cleaning wishlist:', error);
|
||||
showToast(`Error cleaning wishlist: ${error.message}`, 'error');
|
||||
} finally {
|
||||
// Re-enable the cleanup button
|
||||
const cleanupBtn = document.getElementById(`cleanup-wishlist-btn-${playlistId}`);
|
||||
if (cleanupBtn) {
|
||||
cleanupBtn.disabled = false;
|
||||
cleanupBtn.textContent = '🧹 Cleanup Wishlist';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function clearWishlist(playlistId) {
|
||||
try {
|
||||
// Show confirmation dialog
|
||||
|
|
|
|||
Loading…
Reference in a new issue