chore: update watchlist features and fixes

This commit is contained in:
root
2026-02-28 09:22:57 +00:00
parent 4c96d0c1c5
commit 20bcc75b9b
64 changed files with 5193 additions and 77 deletions
+10
View File
@@ -242,6 +242,16 @@ function switchTab(tabName) {
loadHomeContent();
}
}
// Load watchlist content when switching to watchlist tab
if (tabName === 'watchlist') {
if (typeof loadSchedulerStatus === 'function') {
loadSchedulerStatus();
}
if (typeof displayWatchlist === 'function') {
displayWatchlist();
}
}
}
+38 -16
View File
@@ -2,6 +2,16 @@
* Watchlist UI functions
*/
/**
* Escape HTML to prevent XSS
*/
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
/**
* Display watchlist items
*/
@@ -21,8 +31,6 @@ async function displayWatchlist(status = null) {
<div style="text-align: center; padding: 60px 20px;">
<svg style="width:80px;height:80px;margin:0 auto 20px;opacity:0.3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
</svg>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M15 17h5l-1.405-1.405A2.032 2.032 0 018.138 7.702 10.78 1.478 1.482-1.478-10.78-1.478 1.478-8.138 1.478-1.478 1.478-1.478-8.138 1.478-1.478 1.478-8.138 1.478z"></path>
</svg>
<h3 style="color: #666; margin-bottom: 10px;">Aucun anime dans votre watchlist</h3>
<p style="color: #999;">Ajoutez des animes depuis la recherche pour commencer le suivi automatique</p>
@@ -103,7 +111,7 @@ async function displayWatchlist(status = null) {
</button>
` : ''}
<button class="btn-secondary btn-small" onclick="handleCheckItem('${item.id}')" style="padding: 6px 12px; font-size: 12px;" title="Vérifier maintenant">
<button class="btn-secondary btn-small" onclick="handleCheckItem.call(this, '${item.id}')" style="padding: 6px 12px; font-size: 12px;" title="Vérifier maintenant">
🔍 Vérifier
</button>
@@ -166,8 +174,16 @@ function getStatusBadge(status) {
*/
async function handleAddToWatchlist(animeUrl, providerId) {
try {
// Decode URL if it's encoded - always work with decoded URL
let decodedUrl = animeUrl;
try {
decodedUrl = decodeURIComponent(animeUrl);
} catch (e) {
// URL might already be decoded
}
// Get anime details from the DOM or API
const response = await fetch(`${API_BASE}/anime/metadata?url=${encodeURIComponent(animeUrl)}`);
const response = await fetch(`${API_BASE}/anime/metadata?url=${encodeURIComponent(decodedUrl)}`);
if (!response.ok) {
throw new Error('Failed to fetch anime details');
@@ -179,12 +195,6 @@ async function handleAddToWatchlist(animeUrl, providerId) {
// Extract anime title from URL if not in metadata
let animeTitle = metadata.title || 'Unknown Anime';
if (animeTitle === 'Unknown Anime' || !animeTitle) {
// Decode URL first if it's encoded
let decodedUrl = animeUrl;
try {
decodedUrl = decodeURIComponent(animeUrl);
} catch (e) {}
// Try to extract title from URL
try {
const urlParts = decodedUrl.split('/');
@@ -204,10 +214,16 @@ async function handleAddToWatchlist(animeUrl, providerId) {
}
}
// Normalize provider_id to use dash format (anime-sama not animesama)
let normalizedProviderId = providerId;
if (providerId === 'animesama') {
normalizedProviderId = 'anime-sama';
}
const itemData = {
anime_title: animeTitle,
anime_url: animeUrl,
provider_id: providerId,
anime_url: decodedUrl, // Always use decoded URL
provider_id: normalizedProviderId,
lang: 'vostfr',
auto_download: true,
quality_preference: 'auto',
@@ -255,8 +271,14 @@ async function handleAddToWatchlist(animeUrl, providerId) {
* Update add button state
*/
function updateAddButton(animeUrl, isInWatchlist) {
// Find all buttons for this anime
const buttons = document.querySelectorAll(`[data-watchlist-url="${encodeURIComponent(animeUrl)}"]`);
// Decode URL for matching
let decodedUrl = animeUrl;
try {
decodedUrl = decodeURIComponent(animeUrl);
} catch (e) {}
// Find all buttons for this anime (try both encoded and decoded)
const buttons = document.querySelectorAll(`[data-watchlist-url="${encodeURIComponent(decodedUrl)}"], [data-watchlist-url="${decodedUrl}"]`);
buttons.forEach(button => {
if (isInWatchlist) {
@@ -303,7 +325,7 @@ async function handleResumeWatchlist(itemId) {
* Check specific item
*/
async function handleCheckItem(itemId) {
const button = event.target;
const button = this;
const originalText = button.innerHTML;
try {
@@ -351,7 +373,7 @@ async function handleDeleteWatchlist(itemId) {
* Check all items
*/
async function handleCheckAll() {
const button = event.target;
const button = this;
const originalText = button.innerHTML;
try {
+15 -5
View File
@@ -425,19 +425,29 @@ function updateSchedulerUI(status) {
const stopBtn = document.getElementById('stopSchedulerBtn');
const nextRunInfo = document.getElementById('nextRunInfo');
if (!startBtn || !stopBtn || !nextRunInfo) return;
// nextRunInfo is required, but buttons are optional
if (!nextRunInfo) {
console.warn('nextRunInfo element not found');
return;
}
if (status.running) {
startBtn.style.display = 'none';
stopBtn.style.display = 'inline-block';
// Update buttons if they exist
if (startBtn) startBtn.style.display = 'none';
if (stopBtn) stopBtn.style.display = 'inline-block';
if (status.next_run) {
const nextRun = new Date(status.next_run);
nextRunInfo.innerHTML = `✓ En cours<br>Prochaine vérification: ${nextRun.toLocaleString('fr-FR')}`;
} else {
// Scheduler running but no next_run yet (just started)
const interval = status.settings?.check_interval_hours || 6;
nextRunInfo.innerHTML = `✓ En cours<br>Vérification toutes les ${interval}h`;
}
} else {
startBtn.style.display = 'inline-block';
stopBtn.style.display = 'none';
// Update buttons if they exist
if (startBtn) startBtn.style.display = 'inline-block';
if (stopBtn) stopBtn.style.display = 'none';
nextRunInfo.innerHTML = '⏸️ Arrêté';
}
}