Improve scan overlay UX
- Show overlay immediately when rescan is clicked (before API response) - Add click-outside-to-close on overlay background - Add click on rescan-status indicator to reopen overlay - Add cursor pointer to rescan-status for clickability feedback - All 1024 tests passing
This commit is contained in:
parent
b6d44ca7d8
commit
458ca1d776
Binary file not shown.
Binary file not shown.
@ -17,7 +17,7 @@
|
|||||||
"keep_days": 30
|
"keep_days": 30
|
||||||
},
|
},
|
||||||
"other": {
|
"other": {
|
||||||
"master_password_hash": "$pbkdf2-sha256$29000$1TrHeM8Z45yTsjZG6B1DKA$w4AoTXhgcGh90quXesvoRqVkH720fYXEu8LI2L4nUFM",
|
"master_password_hash": "$pbkdf2-sha256$29000$vrf2npNSKqVU6r137t27tw$XkJLRylHf84bQFQtXUKVSY7QsaMV1Z1Wgh41H3girGc",
|
||||||
"anime_directory": "/mnt/server/serien/Serien/"
|
"anime_directory": "/mnt/server/serien/Serien/"
|
||||||
},
|
},
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
|
|||||||
@ -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"
|
|
||||||
}
|
|
||||||
@ -17,7 +17,7 @@
|
|||||||
"keep_days": 30
|
"keep_days": 30
|
||||||
},
|
},
|
||||||
"other": {
|
"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/"
|
"anime_directory": "/mnt/server/serien/Serien/"
|
||||||
},
|
},
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
@ -1500,6 +1500,10 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rescan icon specific styling */
|
/* Rescan icon specific styling */
|
||||||
|
#rescan-status {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
#rescan-status i {
|
#rescan-status i {
|
||||||
color: var(--color-text-disabled);
|
color: var(--color-text-disabled);
|
||||||
/* Gray when idle */
|
/* Gray when idle */
|
||||||
@ -1511,6 +1515,10 @@ body {
|
|||||||
animation: iconPulse 2s infinite;
|
animation: iconPulse 2s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#rescan-status.running {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
/* Status text removed - using tooltips only */
|
/* Status text removed - using tooltips only */
|
||||||
|
|
||||||
.status-dot {
|
.status-dot {
|
||||||
|
|||||||
@ -417,6 +417,11 @@ class AniWorldApp {
|
|||||||
this.rescanSeries();
|
this.rescanSeries();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Click on rescan status indicator to reopen scan overlay
|
||||||
|
document.getElementById('rescan-status').addEventListener('click', () => {
|
||||||
|
this.reopenScanOverlay();
|
||||||
|
});
|
||||||
|
|
||||||
// Configuration modal
|
// Configuration modal
|
||||||
document.getElementById('config-btn').addEventListener('click', () => {
|
document.getElementById('config-btn').addEventListener('click', () => {
|
||||||
this.showConfigModal();
|
this.showConfigModal();
|
||||||
@ -1016,33 +1021,39 @@ class AniWorldApp {
|
|||||||
|
|
||||||
async rescanSeries() {
|
async rescanSeries() {
|
||||||
try {
|
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', {
|
const response = await this.makeAuthenticatedRequest('/api/anime/rescan', {
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response) return;
|
if (!response) {
|
||||||
|
this.removeScanProgressOverlay();
|
||||||
|
this.updateProcessStatus('rescan', false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
// Debug logging
|
// Debug logging
|
||||||
console.log('Rescan response:', data);
|
console.log('Rescan response:', data);
|
||||||
console.log('Success value:', data.success, 'Type:', typeof data.success);
|
console.log('Success value:', data.success, 'Type:', typeof data.success);
|
||||||
|
|
||||||
if (data.success === true) {
|
// Note: The scan progress will be updated via WebSocket events
|
||||||
const seriesCount = data.series_count || 0;
|
// The overlay will be closed when scan_completed is received
|
||||||
this.showToast(
|
if (data.success !== true) {
|
||||||
`Rescan complete! Found ${seriesCount} series with missing episodes.`,
|
this.removeScanProgressOverlay();
|
||||||
'success'
|
this.updateProcessStatus('rescan', false);
|
||||||
);
|
|
||||||
|
|
||||||
// Reload the series list to show the updated data
|
|
||||||
await this.loadSeries();
|
|
||||||
} else {
|
|
||||||
this.showToast(`Rescan error: ${data.message}`, 'error');
|
this.showToast(`Rescan error: ${data.message}`, 'error');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Rescan error:', error);
|
console.error('Rescan error:', error);
|
||||||
|
this.removeScanProgressOverlay();
|
||||||
|
this.updateProcessStatus('rescan', false);
|
||||||
this.showToast('Failed to start rescan', 'error');
|
this.showToast('Failed to start rescan', 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1090,6 +1101,9 @@ class AniWorldApp {
|
|||||||
|
|
||||||
// Store total items for progress calculation
|
// Store total items for progress calculation
|
||||||
this.scanTotalItems = data?.total_items || 0;
|
this.scanTotalItems = data?.total_items || 0;
|
||||||
|
|
||||||
|
// Store last scan data for reopening
|
||||||
|
this._lastScanData = data;
|
||||||
|
|
||||||
// Create overlay element
|
// Create overlay element
|
||||||
const overlay = document.createElement('div');
|
const overlay = document.createElement('div');
|
||||||
@ -1136,6 +1150,14 @@ class AniWorldApp {
|
|||||||
|
|
||||||
document.body.appendChild(overlay);
|
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
|
// Trigger animation by adding visible class after a brief delay
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
overlay.classList.add('visible');
|
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)
|
* Check if a scan is currently in progress (useful after page reload)
|
||||||
* and show the progress overlay if so
|
* and show the progress overlay if so
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user