Paginate wishlist modal to prevent browser crash on large wishlists (5K+)
Initial load fetches 200 tracks instead of all. "Load More" button at bottom shows (200 of 5,000) and loads next batch on click. Backend now returns total count alongside limited results for both album and singles categories. Rendering logic unchanged — just operates on smaller sets.
This commit is contained in:
parent
5cecb46788
commit
8ba1585646
3 changed files with 56 additions and 4 deletions
|
|
@ -23189,12 +23189,16 @@ def get_wishlist_tracks():
|
|||
if limit and len(filtered_tracks) >= limit:
|
||||
break
|
||||
|
||||
print(f"📊 Wishlist filter: {len(filtered_tracks)}/{len(sanitized_tracks)} tracks in '{category}' category (limit: {limit or 'none'})")
|
||||
return jsonify({"tracks": filtered_tracks, "category": category})
|
||||
# Count total in category (quick scan — no heavy processing, just classification)
|
||||
total_in_category = sum(1 for t in sanitized_tracks if _classify_wishlist_track(t) == category)
|
||||
|
||||
print(f"📊 Wishlist filter: {len(filtered_tracks)}/{total_in_category} tracks in '{category}' category (limit: {limit or 'none'})")
|
||||
return jsonify({"tracks": filtered_tracks, "category": category, "total": total_in_category})
|
||||
|
||||
# Apply limit to non-filtered results
|
||||
total_count = len(sanitized_tracks)
|
||||
result_tracks = sanitized_tracks[:limit] if limit else sanitized_tracks
|
||||
return jsonify({"tracks": result_tracks})
|
||||
return jsonify({"tracks": result_tracks, "total": total_count})
|
||||
except Exception as e:
|
||||
print(f"Error getting wishlist tracks: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
|
|
|||
|
|
@ -13201,12 +13201,18 @@ async function selectWishlistCategory(category) {
|
|||
|
||||
tracksList.innerHTML = '<div class="loading-indicator">Loading tracks...</div>';
|
||||
|
||||
const response = await fetch(`/api/wishlist/tracks?category=${category}`);
|
||||
const _wlPageSize = window._wlNextLimit || 200;
|
||||
window._wlNextLimit = null;
|
||||
const response = await fetch(`/api/wishlist/tracks?category=${category}&limit=${_wlPageSize}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) throw new Error(data.error || 'Failed to fetch tracks');
|
||||
|
||||
const tracks = data.tracks || [];
|
||||
const totalAvailable = data.total || tracks.length;
|
||||
window._wlCategory = category;
|
||||
window._wlOffset = tracks.length;
|
||||
window._wlTotal = totalAvailable;
|
||||
|
||||
if (tracks.length === 0) {
|
||||
tracksList.innerHTML = '<div class="empty-state">No tracks in this category</div>';
|
||||
|
|
@ -13333,6 +13339,10 @@ async function selectWishlistCategory(category) {
|
|||
albumsHTML += '</div>';
|
||||
|
||||
tracksList.innerHTML = albumsHTML;
|
||||
if (totalAvailable > tracks.length) {
|
||||
tracksList.insertAdjacentHTML('beforeend',
|
||||
`<button class="wishlist-load-more-btn" onclick="loadMoreWishlistTracks()">Load More (${tracks.length} of ${totalAvailable})</button>`);
|
||||
}
|
||||
_attachWishlistDelegation(tracksList);
|
||||
|
||||
} else {
|
||||
|
|
@ -13393,6 +13403,10 @@ async function selectWishlistCategory(category) {
|
|||
});
|
||||
|
||||
tracksList.innerHTML = tracksHTML;
|
||||
if (totalAvailable > tracks.length) {
|
||||
tracksList.insertAdjacentHTML('beforeend',
|
||||
`<button class="wishlist-load-more-btn" onclick="loadMoreWishlistTracks()">Load More (${tracks.length} of ${totalAvailable})</button>`);
|
||||
}
|
||||
_attachWishlistDelegation(tracksList);
|
||||
}
|
||||
|
||||
|
|
@ -13402,6 +13416,16 @@ async function selectWishlistCategory(category) {
|
|||
}
|
||||
}
|
||||
|
||||
async function loadMoreWishlistTracks() {
|
||||
const btn = document.querySelector('.wishlist-load-more-btn');
|
||||
if (btn) { btn.textContent = 'Loading...'; btn.disabled = true; }
|
||||
// Increase page size and reload
|
||||
window._wlOffset = (window._wlOffset || 200) + 200;
|
||||
// Override the page size for this reload
|
||||
window._wlNextLimit = window._wlOffset;
|
||||
selectWishlistCategory(window._wlCategory);
|
||||
}
|
||||
|
||||
function _attachWishlistDelegation(container) {
|
||||
// Single click handler for all wishlist album/track interactions
|
||||
container.addEventListener('click', (e) => {
|
||||
|
|
|
|||
|
|
@ -16298,6 +16298,30 @@ body.helper-mode-active #dashboard-activity-feed:hover {
|
|||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.wishlist-load-more-btn {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
margin-top: 12px;
|
||||
background: rgba(138, 43, 226, 0.1);
|
||||
border: 1px solid rgba(138, 43, 226, 0.3);
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.wishlist-load-more-btn:hover {
|
||||
background: rgba(138, 43, 226, 0.2);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.wishlist-load-more-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.wishlist-album-card {
|
||||
background: linear-gradient(135deg, rgba(26, 26, 26, 0.95) 0%, rgba(18, 18, 18, 0.98) 100%);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
|
|
|
|||
Loading…
Reference in a new issue