diff --git a/web_server.py b/web_server.py
index 833c3080..8c6884c7 100644
--- a/web_server.py
+++ b/web_server.py
@@ -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
diff --git a/webui/static/script.js b/webui/static/script.js
index db86e2cf..56c5d5f5 100644
--- a/webui/static/script.js
+++ b/webui/static/script.js
@@ -13201,12 +13201,18 @@ async function selectWishlistCategory(category) {
tracksList.innerHTML = '
Loading tracks...
';
- 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 = 'No tracks in this category
';
@@ -13333,6 +13339,10 @@ async function selectWishlistCategory(category) {
albumsHTML += '';
tracksList.innerHTML = albumsHTML;
+ if (totalAvailable > tracks.length) {
+ tracksList.insertAdjacentHTML('beforeend',
+ ``);
+ }
_attachWishlistDelegation(tracksList);
} else {
@@ -13393,6 +13403,10 @@ async function selectWishlistCategory(category) {
});
tracksList.innerHTML = tracksHTML;
+ if (totalAvailable > tracks.length) {
+ tracksList.insertAdjacentHTML('beforeend',
+ ``);
+ }
_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) => {
diff --git a/webui/static/style.css b/webui/static/style.css
index c3e6e36d..bda61fca 100644
--- a/webui/static/style.css
+++ b/webui/static/style.css
@@ -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);