Enhance wishlist auto-processing detection and UI feedback
Added backend support for reporting current auto-processing state and cycle in the wishlist stats API. Updated frontend to detect and handle auto-processing start, close modals, and notify users, as well as improved countdown timer updates and conflict handling when starting manual processing.
This commit is contained in:
parent
2ede3ddee7
commit
fb56fbca5f
2 changed files with 70 additions and 21 deletions
|
|
@ -9466,17 +9466,33 @@ def get_wishlist_stats():
|
|||
|
||||
total_count = singles_count + albums_count
|
||||
|
||||
# Calculate time until next auto-processing
|
||||
# Calculate time until next auto-processing and get processing state
|
||||
next_run_in_seconds = 0
|
||||
is_processing = False
|
||||
with wishlist_timer_lock:
|
||||
if wishlist_next_run_time > 0:
|
||||
next_run_in_seconds = max(0, int(wishlist_next_run_time - time.time()))
|
||||
is_processing = wishlist_auto_processing
|
||||
|
||||
# Get current cycle (albums or singles)
|
||||
from database.music_database import MusicDatabase
|
||||
db = MusicDatabase()
|
||||
try:
|
||||
with db._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT value FROM metadata WHERE key = 'wishlist_cycle'")
|
||||
row = cursor.fetchone()
|
||||
current_cycle = row['value'] if row else 'albums'
|
||||
except Exception:
|
||||
current_cycle = 'albums' # Safe fallback
|
||||
|
||||
return jsonify({
|
||||
"singles": singles_count,
|
||||
"albums": albums_count,
|
||||
"total": total_count,
|
||||
"next_run_in_seconds": next_run_in_seconds
|
||||
"next_run_in_seconds": next_run_in_seconds,
|
||||
"is_auto_processing": is_processing,
|
||||
"current_cycle": current_cycle
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -6352,34 +6352,44 @@ function startWishlistCountdownTimer(currentCycle, initialSeconds) {
|
|||
wishlistCountdownInterval = setInterval(async () => {
|
||||
remainingSeconds--;
|
||||
|
||||
if (remainingSeconds <= 0) {
|
||||
// Timer expired, fetch fresh data
|
||||
// Check if auto-processing has started (every 2 seconds to avoid overwhelming backend)
|
||||
if (remainingSeconds % 2 === 0 || remainingSeconds <= 0) {
|
||||
try {
|
||||
const response = await fetch('/api/wishlist/stats');
|
||||
const data = await response.json();
|
||||
remainingSeconds = data.next_run_in_seconds || 0;
|
||||
|
||||
// Also update cycle in case it changed
|
||||
const cycleResponse = await fetch('/api/wishlist/cycle');
|
||||
const cycleData = await cycleResponse.json();
|
||||
const newCycle = cycleData.cycle || 'albums';
|
||||
const newCycleText = newCycle === 'albums' ? 'Albums/EPs' : 'Singles';
|
||||
// AUTO-CLOSE DETECTION: If auto-processing started, close modal and notify user
|
||||
if (data.is_auto_processing) {
|
||||
console.log('🤖 [Wishlist] Auto-processing detected, closing overview modal');
|
||||
closeWishlistOverviewModal();
|
||||
showToast('Wishlist auto-processing started. View progress in Download Manager.', 'info');
|
||||
return; // Exit interval
|
||||
}
|
||||
|
||||
const timerElement = document.getElementById('wishlist-next-auto-timer');
|
||||
if (timerElement) {
|
||||
const countdownText = formatCountdownTime(remainingSeconds);
|
||||
timerElement.textContent = `Next Auto: ${newCycleText}${countdownText ? ' in ' + countdownText : ''}`;
|
||||
// Update remaining seconds if timer expired
|
||||
if (remainingSeconds <= 0) {
|
||||
remainingSeconds = data.next_run_in_seconds || 0;
|
||||
|
||||
// Also update cycle in case it changed
|
||||
const newCycle = data.current_cycle || 'albums';
|
||||
const newCycleText = newCycle === 'albums' ? 'Albums/EPs' : 'Singles';
|
||||
|
||||
const timerElement = document.getElementById('wishlist-next-auto-timer');
|
||||
if (timerElement) {
|
||||
const countdownText = formatCountdownTime(remainingSeconds);
|
||||
timerElement.textContent = `Next Auto: ${newCycleText}${countdownText ? ' in ' + countdownText : ''}`;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.debug('Error updating wishlist countdown:', error);
|
||||
}
|
||||
} else {
|
||||
// Update the display
|
||||
const timerElement = document.getElementById('wishlist-next-auto-timer');
|
||||
if (timerElement) {
|
||||
const countdownText = formatCountdownTime(remainingSeconds);
|
||||
timerElement.textContent = `Next Auto: ${nextCycleText}${countdownText ? ' in ' + countdownText : ''}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Always update the display countdown
|
||||
const timerElement = document.getElementById('wishlist-next-auto-timer');
|
||||
if (timerElement) {
|
||||
const countdownText = formatCountdownTime(remainingSeconds);
|
||||
timerElement.textContent = `Next Auto: ${nextCycleText}${countdownText ? ' in ' + countdownText : ''}`;
|
||||
}
|
||||
}, 1000); // Update every second
|
||||
}
|
||||
|
|
@ -7129,6 +7139,29 @@ async function startWishlistMissingTracksProcess(playlistId) {
|
|||
|
||||
const data = await response.json();
|
||||
if (!data.success) {
|
||||
// Special handling for auto-processing conflict
|
||||
if (response.status === 409) {
|
||||
console.log('🤖 [Wishlist] Auto-processing is running, redirecting to download manager');
|
||||
showToast('Wishlist auto-processing is already running. Opening Download Manager...', 'info');
|
||||
|
||||
// Close wishlist modal and show download manager
|
||||
const wishlistModal = document.getElementById('download-modal-wishlist');
|
||||
if (wishlistModal) {
|
||||
wishlistModal.remove();
|
||||
}
|
||||
delete activeDownloadProcesses[playlistId];
|
||||
|
||||
// Open download manager to show active batch
|
||||
setTimeout(() => {
|
||||
const downloadManager = document.getElementById('download-manager-modal');
|
||||
if (downloadManager) {
|
||||
downloadManager.style.display = 'flex';
|
||||
} else {
|
||||
openDownloadManagerModal();
|
||||
}
|
||||
}, 300);
|
||||
return;
|
||||
}
|
||||
// Special handling for rate limit
|
||||
if (response.status === 429) {
|
||||
throw new Error(`${data.error} Try closing some other download processes first.`);
|
||||
|
|
|
|||
Loading…
Reference in a new issue