diff --git a/data/aniworld.db-shm b/data/aniworld.db-shm index 6ad606e..22a2e95 100644 Binary files a/data/aniworld.db-shm and b/data/aniworld.db-shm differ diff --git a/data/aniworld.db-wal b/data/aniworld.db-wal index 1999346..8da8378 100644 Binary files a/data/aniworld.db-wal and b/data/aniworld.db-wal differ diff --git a/data/config.json b/data/config.json index b2e684e..c18efb5 100644 --- a/data/config.json +++ b/data/config.json @@ -17,7 +17,7 @@ "keep_days": 30 }, "other": { - "master_password_hash": "$pbkdf2-sha256$29000$1TrHeM8Z45yTsjZG6B1DKA$w4AoTXhgcGh90quXesvoRqVkH720fYXEu8LI2L4nUFM", + "master_password_hash": "$pbkdf2-sha256$29000$vrf2npNSKqVU6r137t27tw$XkJLRylHf84bQFQtXUKVSY7QsaMV1Z1Wgh41H3girGc", "anime_directory": "/mnt/server/serien/Serien/" }, "version": "1.0.0" diff --git a/data/config_backups/config_backup_20251224_210928.json b/data/config_backups/config_backup_20251224_210928.json deleted file mode 100644 index 5f8ab65..0000000 --- a/data/config_backups/config_backup_20251224_210928.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "Aniworld", - "data_dir": "data", - "scheduler": { - "enabled": true, - "interval_minutes": 60 - }, - "logging": { - "level": "INFO", - "file": null, - "max_bytes": null, - "backup_count": 3 - }, - "backup": { - "enabled": false, - "path": "data/backups", - "keep_days": 30 - }, - "other": { - "master_password_hash": "$pbkdf2-sha256$29000$tTYmJCSEUArhnLN2TmktpQ$mhMKshEetPJfjRqYYUUvOGNRxcnIMNIto73IRKw4hPM", - "anime_directory": "/mnt/server/serien/Serien/" - }, - "version": "1.0.0" -} \ No newline at end of file diff --git a/data/config_backups/config_backup_20251224_210530.json b/data/config_backups/config_backup_20251224_212619.json similarity index 77% rename from data/config_backups/config_backup_20251224_210530.json rename to data/config_backups/config_backup_20251224_212619.json index f3ca4aa..584ba1e 100644 --- a/data/config_backups/config_backup_20251224_210530.json +++ b/data/config_backups/config_backup_20251224_212619.json @@ -17,7 +17,7 @@ "keep_days": 30 }, "other": { - "master_password_hash": "$pbkdf2-sha256$29000$GKP0fo.RspaScm5trRWiFA$cEeWdNCea5O7PAF21LyHVK.Xxj8sw3/9bbEdapRbCrw", + "master_password_hash": "$pbkdf2-sha256$29000$tpaSEqI0BmCMsbb2HgOA0A$zF52br5qvqyA2ciQlDt7.Cdny2d2qaq1BPqNEntoMeY", "anime_directory": "/mnt/server/serien/Serien/" }, "version": "1.0.0" diff --git a/src/server/web/static/css/styles.css b/src/server/web/static/css/styles.css index b0b32d5..a6e6812 100644 --- a/src/server/web/static/css/styles.css +++ b/src/server/web/static/css/styles.css @@ -1500,6 +1500,10 @@ body { } /* Rescan icon specific styling */ +#rescan-status { + cursor: pointer; +} + #rescan-status i { color: var(--color-text-disabled); /* Gray when idle */ @@ -1511,6 +1515,10 @@ body { animation: iconPulse 2s infinite; } +#rescan-status.running { + cursor: pointer; +} + /* Status text removed - using tooltips only */ .status-dot { diff --git a/src/server/web/static/js/app.js b/src/server/web/static/js/app.js index 1486870..f3748c5 100644 --- a/src/server/web/static/js/app.js +++ b/src/server/web/static/js/app.js @@ -417,6 +417,11 @@ class AniWorldApp { this.rescanSeries(); }); + // Click on rescan status indicator to reopen scan overlay + document.getElementById('rescan-status').addEventListener('click', () => { + this.reopenScanOverlay(); + }); + // Configuration modal document.getElementById('config-btn').addEventListener('click', () => { this.showConfigModal(); @@ -1016,33 +1021,39 @@ class AniWorldApp { async rescanSeries() { try { - this.showToast('Scanning directory...', 'info'); + // Show the overlay immediately before making the API call + this.showScanProgressOverlay({ + directory: 'Starting scan...', + total_items: 0 + }); + this.updateProcessStatus('rescan', true); const response = await this.makeAuthenticatedRequest('/api/anime/rescan', { method: 'POST' }); - if (!response) return; + if (!response) { + this.removeScanProgressOverlay(); + this.updateProcessStatus('rescan', false); + return; + } const data = await response.json(); // Debug logging console.log('Rescan response:', data); console.log('Success value:', data.success, 'Type:', typeof data.success); - if (data.success === true) { - const seriesCount = data.series_count || 0; - this.showToast( - `Rescan complete! Found ${seriesCount} series with missing episodes.`, - 'success' - ); - - // Reload the series list to show the updated data - await this.loadSeries(); - } else { + // Note: The scan progress will be updated via WebSocket events + // The overlay will be closed when scan_completed is received + if (data.success !== true) { + this.removeScanProgressOverlay(); + this.updateProcessStatus('rescan', false); this.showToast(`Rescan error: ${data.message}`, 'error'); } } catch (error) { console.error('Rescan error:', error); + this.removeScanProgressOverlay(); + this.updateProcessStatus('rescan', false); this.showToast('Failed to start rescan', 'error'); } } @@ -1090,6 +1101,9 @@ class AniWorldApp { // Store total items for progress calculation this.scanTotalItems = data?.total_items || 0; + + // Store last scan data for reopening + this._lastScanData = data; // Create overlay element const overlay = document.createElement('div'); @@ -1136,6 +1150,14 @@ class AniWorldApp { document.body.appendChild(overlay); + // Add click-outside-to-close handler + overlay.addEventListener('click', (e) => { + // Only close if clicking the overlay background, not the container + if (e.target === overlay) { + this.removeScanProgressOverlay(); + } + }); + // Trigger animation by adding visible class after a brief delay requestAnimationFrame(() => { overlay.classList.add('visible'); @@ -1281,6 +1303,49 @@ class AniWorldApp { } } + /** + * Reopen the scan progress overlay if a scan is in progress + * Called when user clicks on the rescan status indicator + */ + async reopenScanOverlay() { + // Check if overlay already exists + const existingOverlay = document.getElementById('scan-progress-overlay'); + if (existingOverlay) { + // Overlay is already open, do nothing + return; + } + + // Check if scan is running via API + try { + const response = await this.makeAuthenticatedRequest('/api/anime/scan/status'); + if (!response || !response.ok) { + console.log('Could not fetch scan status'); + return; + } + + const data = await response.json(); + console.log('Scan status for reopen:', data); + + if (data.is_scanning) { + // A scan is in progress, show the overlay + this.showScanProgressOverlay({ + directory: data.directory, + total_items: data.total_items + }); + + // Update with current progress + this.updateScanProgressOverlay({ + directories_scanned: data.directories_scanned, + files_found: data.directories_scanned, + current_directory: data.current_directory, + total_items: data.total_items + }); + } + } catch (error) { + console.error('Error checking scan status for reopen:', error); + } + } + /** * Check if a scan is currently in progress (useful after page reload) * and show the progress overlay if so