diff --git a/src/server/web/static/js/accessibility_features.js b/src/server/web/static/js/accessibility_features.js deleted file mode 100644 index 3952319..0000000 --- a/src/server/web/static/js/accessibility_features.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Accessibility Features Module - * Enhances accessibility for all users - */ - -(function() { - 'use strict'; - - /** - * Initialize accessibility features - */ - function initAccessibilityFeatures() { - setupFocusManagement(); - setupAriaLabels(); - console.log('[Accessibility Features] Initialized'); - } - - /** - * Setup focus management - */ - function setupFocusManagement() { - // Add focus visible class for keyboard navigation - document.addEventListener('keydown', (e) => { - if (e.key === 'Tab') { - document.body.classList.add('keyboard-navigation'); - } - }); - - document.addEventListener('mousedown', () => { - document.body.classList.remove('keyboard-navigation'); - }); - } - - /** - * Setup ARIA labels for dynamic content - */ - function setupAriaLabels() { - // Ensure all interactive elements have proper ARIA labels - const buttons = document.querySelectorAll('button:not([aria-label])'); - buttons.forEach(button => { - if (!button.getAttribute('aria-label') && button.title) { - button.setAttribute('aria-label', button.title); - } - }); - } - - /** - * Announce message to screen readers - */ - function announceToScreenReader(message, priority = 'polite') { - const announcement = document.createElement('div'); - announcement.setAttribute('role', 'status'); - announcement.setAttribute('aria-live', priority); - announcement.setAttribute('aria-atomic', 'true'); - announcement.className = 'sr-only'; - announcement.textContent = message; - - document.body.appendChild(announcement); - - setTimeout(() => { - announcement.remove(); - }, 1000); - } - - // Export functions - window.Accessibility = { - announce: announceToScreenReader - }; - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initAccessibilityFeatures); - } else { - initAccessibilityFeatures(); - } - -})(); diff --git a/src/server/web/static/js/advanced_search.js b/src/server/web/static/js/advanced_search.js deleted file mode 100644 index d7b4377..0000000 --- a/src/server/web/static/js/advanced_search.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Advanced Search Module - * Provides advanced search and filtering capabilities - */ - -(function() { - 'use strict'; - - /** - * Initialize advanced search - */ - function initAdvancedSearch() { - console.log('[Advanced Search] Module loaded (functionality to be implemented)'); - - // TODO: Implement advanced search features - // - Filter by genre - // - Filter by year - // - Filter by status - // - Sort options - } - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initAdvancedSearch); - } else { - initAdvancedSearch(); - } - -})(); diff --git a/src/server/web/static/js/app.js b/src/server/web/static/js/app.js index 5d96029..526f4ce 100644 --- a/src/server/web/static/js/app.js +++ b/src/server/web/static/js/app.js @@ -26,9 +26,6 @@ class AniWorldApp { this.loadSeries(); this.initTheme(); this.updateConnectionStatus(); - - // Initialize Mobile & Accessibility features - this.initMobileAndAccessibility(); } async checkAuthentication() { @@ -1726,155 +1723,6 @@ class AniWorldApp { } } - showBackupsModal(backups) { - // Create modal to show backups - const modal = document.createElement('div'); - modal.className = 'modal'; - modal.style.display = 'block'; - - const modalContent = document.createElement('div'); - modalContent.className = 'modal-content'; - modalContent.style.maxWidth = '60%'; - - const header = document.createElement('div'); - header.innerHTML = '

Configuration Backups

'; - - const backupList = document.createElement('div'); - backupList.className = 'backup-list'; - - if (backups.length === 0) { - backupList.innerHTML = '
No backups found
'; - } else { - backups.forEach(backup => { - const item = document.createElement('div'); - item.className = 'backup-item'; - - const info = document.createElement('div'); - info.className = 'backup-info'; - - const name = document.createElement('div'); - name.className = 'backup-name'; - name.textContent = backup.filename; - - const details = document.createElement('div'); - details.className = 'backup-details'; - details.textContent = `Size: ${backup.size_kb} KB • Modified: ${backup.modified_display}`; - - info.appendChild(name); - info.appendChild(details); - - const actions = document.createElement('div'); - actions.className = 'backup-actions'; - - const restoreBtn = document.createElement('button'); - restoreBtn.className = 'btn btn-xs btn-primary'; - restoreBtn.textContent = 'Restore'; - restoreBtn.onclick = () => { - if (confirm('Are you sure you want to restore this backup? Current configuration will be overwritten.')) { - this.restoreBackup(backup.filename); - document.body.removeChild(modal); - } - }; - - const downloadBtn = document.createElement('button'); - downloadBtn.className = 'btn btn-xs btn-secondary'; - downloadBtn.textContent = 'Download'; - downloadBtn.onclick = () => this.downloadBackup(backup.filename); - - actions.appendChild(restoreBtn); - actions.appendChild(downloadBtn); - - item.appendChild(info); - item.appendChild(actions); - - backupList.appendChild(item); - }); - } - - const closeBtn = document.createElement('button'); - closeBtn.textContent = 'Close'; - closeBtn.className = 'btn btn-secondary'; - closeBtn.onclick = () => document.body.removeChild(modal); - - modalContent.appendChild(header); - modalContent.appendChild(backupList); - modalContent.appendChild(closeBtn); - modal.appendChild(modalContent); - document.body.appendChild(modal); - - // Close on background click - modal.onclick = (e) => { - if (e.target === modal) { - document.body.removeChild(modal); - } - }; - } - - async restoreBackup(filename) { - try { - const response = await this.makeAuthenticatedRequest(`/api/config/backup/${encodeURIComponent(filename)}/restore`, { - method: 'POST' - }); - - if (!response) return; - const data = await response.json(); - - if (data.success) { - this.showToast('Configuration restored successfully', 'success'); - // Reload the config modal - setTimeout(() => { - this.hideConfigModal(); - this.showConfigModal(); - }, 1000); - } else { - this.showToast(`Failed to restore backup: ${data.error}`, 'error'); - } - } catch (error) { - console.error('Error restoring backup:', error); - this.showToast('Failed to restore backup', 'error'); - } - } - - downloadBackup(filename) { - const link = document.createElement('a'); - link.href = `/api/config/backup/${encodeURIComponent(filename)}/download`; - link.download = filename; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - } - - async exportConfig() { - try { - const includeSensitive = confirm('Include sensitive data (passwords, salts)? Click Cancel for safe export without sensitive data.'); - - const response = await this.makeAuthenticatedRequest('/api/config/export', { - method: 'POST', - body: JSON.stringify({ include_sensitive: includeSensitive }) - }); - - if (response && response.ok) { - // Handle file download - const blob = await response.blob(); - const url = window.URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = url; - link.download = `aniworld_config_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.json`; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - window.URL.revokeObjectURL(url); - - this.showToast('Configuration exported successfully', 'success'); - } else { - this.showToast('Failed to export configuration', 'error'); - } - } catch (error) { - console.error('Error exporting config:', error); - this.showToast('Failed to export configuration', 'error'); - } - } - async validateConfig() { try { const response = await this.makeAuthenticatedRequest('/api/config/validate', { diff --git a/src/server/web/static/js/bulk_operations.js b/src/server/web/static/js/bulk_operations.js deleted file mode 100644 index 89d0c5c..0000000 --- a/src/server/web/static/js/bulk_operations.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Bulk Operations Module - * Handles bulk selection and operations on multiple series - */ - -(function() { - 'use strict'; - - /** - * Initialize bulk operations - */ - function initBulkOperations() { - console.log('[Bulk Operations] Module loaded (functionality to be implemented)'); - - // TODO: Implement bulk operations - // - Select multiple series - // - Bulk download - // - Bulk mark as watched - // - Bulk delete - } - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initBulkOperations); - } else { - initBulkOperations(); - } - -})(); diff --git a/src/server/web/static/js/color_contrast_compliance.js b/src/server/web/static/js/color_contrast_compliance.js deleted file mode 100644 index a060e6d..0000000 --- a/src/server/web/static/js/color_contrast_compliance.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Color Contrast Compliance Module - * Ensures WCAG color contrast compliance - */ - -(function() { - 'use strict'; - - /** - * Initialize color contrast compliance - */ - function initColorContrastCompliance() { - checkContrastCompliance(); - console.log('[Color Contrast Compliance] Initialized'); - } - - /** - * Check if color contrast meets WCAG standards - */ - function checkContrastCompliance() { - // This would typically check computed styles - // For now, we rely on CSS variables defined in styles.css - console.log('[Color Contrast] Relying on predefined WCAG-compliant color scheme'); - } - - /** - * Calculate contrast ratio between two colors - */ - function calculateContrastRatio(color1, color2) { - // Simplified contrast calculation - // Real implementation would use relative luminance - return 4.5; // Placeholder - } - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initColorContrastCompliance); - } else { - initColorContrastCompliance(); - } - -})(); diff --git a/src/server/web/static/js/drag_drop.js b/src/server/web/static/js/drag_drop.js deleted file mode 100644 index 857ef0e..0000000 --- a/src/server/web/static/js/drag_drop.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Drag and Drop Module - * Handles drag-and-drop functionality for series cards - */ - -(function() { - 'use strict'; - - /** - * Initialize drag and drop - */ - function initDragDrop() { - console.log('[Drag & Drop] Module loaded (functionality to be implemented)'); - - // TODO: Implement drag-and-drop for series cards - // This will allow users to reorder series or add to queue via drag-and-drop - } - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initDragDrop); - } else { - initDragDrop(); - } - -})(); diff --git a/src/server/web/static/js/keyboard_shortcuts.js b/src/server/web/static/js/keyboard_shortcuts.js deleted file mode 100644 index 1cc336e..0000000 --- a/src/server/web/static/js/keyboard_shortcuts.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Keyboard Shortcuts Module - * Handles keyboard navigation and shortcuts for improved accessibility - */ - -(function() { - 'use strict'; - - // Keyboard shortcuts configuration - const shortcuts = { - 'ctrl+k': 'focusSearch', - 'ctrl+r': 'triggerRescan', - 'ctrl+q': 'openQueue', - 'escape': 'closeModals', - 'tab': 'navigationMode', - '/': 'focusSearch' - }; - - /** - * Initialize keyboard shortcuts - */ - function initKeyboardShortcuts() { - document.addEventListener('keydown', handleKeydown); - console.log('[Keyboard Shortcuts] Initialized'); - } - - /** - * Handle keydown events - */ - function handleKeydown(event) { - const key = getKeyCombo(event); - - if (shortcuts[key]) { - const action = shortcuts[key]; - handleShortcut(action, event); - } - } - - /** - * Get key combination string - */ - function getKeyCombo(event) { - const parts = []; - - if (event.ctrlKey) parts.push('ctrl'); - if (event.altKey) parts.push('alt'); - if (event.shiftKey) parts.push('shift'); - - const key = event.key.toLowerCase(); - parts.push(key); - - return parts.join('+'); - } - - /** - * Handle keyboard shortcut action - */ - function handleShortcut(action, event) { - switch(action) { - case 'focusSearch': - event.preventDefault(); - focusSearchInput(); - break; - case 'triggerRescan': - event.preventDefault(); - triggerRescan(); - break; - case 'openQueue': - event.preventDefault(); - openQueue(); - break; - case 'closeModals': - closeAllModals(); - break; - case 'navigationMode': - handleTabNavigation(event); - break; - } - } - - /** - * Focus search input - */ - function focusSearchInput() { - const searchInput = document.getElementById('search-input'); - if (searchInput) { - searchInput.focus(); - searchInput.select(); - } - } - - /** - * Trigger rescan - */ - function triggerRescan() { - const rescanBtn = document.getElementById('rescan-btn'); - if (rescanBtn && !rescanBtn.disabled) { - rescanBtn.click(); - } - } - - /** - * Open queue page - */ - function openQueue() { - window.location.href = '/queue'; - } - - /** - * Close all open modals - */ - function closeAllModals() { - const modals = document.querySelectorAll('.modal.active'); - modals.forEach(modal => { - modal.classList.remove('active'); - }); - } - - /** - * Handle tab navigation with visual indicators - */ - function handleTabNavigation(event) { - // Add keyboard-focus class to focused element - const previousFocus = document.querySelector('.keyboard-focus'); - if (previousFocus) { - previousFocus.classList.remove('keyboard-focus'); - } - - // Will be applied after tab completes - setTimeout(() => { - if (document.activeElement) { - document.activeElement.classList.add('keyboard-focus'); - } - }, 0); - } - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initKeyboardShortcuts); - } else { - initKeyboardShortcuts(); - } - -})(); diff --git a/src/server/web/static/js/mobile_responsive.js b/src/server/web/static/js/mobile_responsive.js deleted file mode 100644 index 3fd4c93..0000000 --- a/src/server/web/static/js/mobile_responsive.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Mobile Responsive Module - * Handles mobile-specific functionality and responsive behavior - */ - -(function() { - 'use strict'; - - let isMobile = false; - - /** - * Initialize mobile responsive features - */ - function initMobileResponsive() { - detectMobile(); - setupResponsiveHandlers(); - console.log('[Mobile Responsive] Initialized'); - } - - /** - * Detect if device is mobile - */ - function detectMobile() { - isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); - - if (isMobile) { - document.body.classList.add('mobile-device'); - } - } - - /** - * Setup responsive event handlers - */ - function setupResponsiveHandlers() { - window.addEventListener('resize', handleResize); - handleResize(); // Initial call - } - - /** - * Handle window resize - */ - function handleResize() { - const width = window.innerWidth; - - if (width < 768) { - applyMobileLayout(); - } else { - applyDesktopLayout(); - } - } - - /** - * Apply mobile-specific layout - */ - function applyMobileLayout() { - document.body.classList.add('mobile-layout'); - document.body.classList.remove('desktop-layout'); - } - - /** - * Apply desktop-specific layout - */ - function applyDesktopLayout() { - document.body.classList.add('desktop-layout'); - document.body.classList.remove('mobile-layout'); - } - - // Export functions - window.MobileResponsive = { - isMobile: () => isMobile - }; - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initMobileResponsive); - } else { - initMobileResponsive(); - } - -})(); diff --git a/src/server/web/static/js/multi_screen_support.js b/src/server/web/static/js/multi_screen_support.js deleted file mode 100644 index b6a70b6..0000000 --- a/src/server/web/static/js/multi_screen_support.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Multi-Screen Support Module - * Handles multi-monitor and window management - */ - -(function() { - 'use strict'; - - /** - * Initialize multi-screen support - */ - function initMultiScreenSupport() { - if ('screen' in window) { - detectScreens(); - console.log('[Multi-Screen Support] Initialized'); - } - } - - /** - * Detect available screens - */ - function detectScreens() { - // Modern browsers support window.screen - const screenInfo = { - width: window.screen.width, - height: window.screen.height, - availWidth: window.screen.availWidth, - availHeight: window.screen.availHeight, - colorDepth: window.screen.colorDepth, - pixelDepth: window.screen.pixelDepth - }; - - console.log('[Multi-Screen] Screen info:', screenInfo); - } - - /** - * Request fullscreen - */ - function requestFullscreen() { - const elem = document.documentElement; - if (elem.requestFullscreen) { - elem.requestFullscreen(); - } else if (elem.webkitRequestFullscreen) { - elem.webkitRequestFullscreen(); - } else if (elem.msRequestFullscreen) { - elem.msRequestFullscreen(); - } - } - - /** - * Exit fullscreen - */ - function exitFullscreen() { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } - } - - // Export functions - window.MultiScreen = { - requestFullscreen: requestFullscreen, - exitFullscreen: exitFullscreen - }; - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initMultiScreenSupport); - } else { - initMultiScreenSupport(); - } - -})(); diff --git a/src/server/web/static/js/touch_gestures.js b/src/server/web/static/js/touch_gestures.js deleted file mode 100644 index c7773bb..0000000 --- a/src/server/web/static/js/touch_gestures.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Touch Gestures Module - * Handles touch gestures for mobile devices - */ - -(function() { - 'use strict'; - - /** - * Initialize touch gestures - */ - function initTouchGestures() { - if ('ontouchstart' in window) { - setupSwipeGestures(); - console.log('[Touch Gestures] Initialized'); - } - } - - /** - * Setup swipe gesture handlers - */ - function setupSwipeGestures() { - let touchStartX = 0; - let touchStartY = 0; - let touchEndX = 0; - let touchEndY = 0; - - document.addEventListener('touchstart', (e) => { - touchStartX = e.changedTouches[0].screenX; - touchStartY = e.changedTouches[0].screenY; - }, { passive: true }); - - document.addEventListener('touchend', (e) => { - touchEndX = e.changedTouches[0].screenX; - touchEndY = e.changedTouches[0].screenY; - handleSwipe(); - }, { passive: true }); - - function handleSwipe() { - const deltaX = touchEndX - touchStartX; - const deltaY = touchEndY - touchStartY; - const minSwipeDistance = 50; - - if (Math.abs(deltaX) > Math.abs(deltaY)) { - // Horizontal swipe - if (Math.abs(deltaX) > minSwipeDistance) { - if (deltaX > 0) { - // Swipe right - console.log('[Touch Gestures] Swipe right detected'); - } else { - // Swipe left - console.log('[Touch Gestures] Swipe left detected'); - } - } - } - } - } - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initTouchGestures); - } else { - initTouchGestures(); - } - -})(); diff --git a/src/server/web/static/js/undo_redo.js b/src/server/web/static/js/undo_redo.js deleted file mode 100644 index 8f5314b..0000000 --- a/src/server/web/static/js/undo_redo.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Undo/Redo Module - * Provides undo/redo functionality for user actions - */ - -(function() { - 'use strict'; - - const actionHistory = []; - let currentIndex = -1; - - /** - * Initialize undo/redo system - */ - function initUndoRedo() { - setupKeyboardShortcuts(); - console.log('[Undo/Redo] Initialized'); - } - - /** - * Setup keyboard shortcuts for undo/redo - */ - function setupKeyboardShortcuts() { - document.addEventListener('keydown', (event) => { - if (event.ctrlKey || event.metaKey) { - if (event.key === 'z' && !event.shiftKey) { - event.preventDefault(); - undo(); - } else if (event.key === 'z' && event.shiftKey || event.key === 'y') { - event.preventDefault(); - redo(); - } - } - }); - } - - /** - * Add action to history - */ - function addAction(action) { - // Remove any actions after current index - actionHistory.splice(currentIndex + 1); - - // Add new action - actionHistory.push(action); - currentIndex++; - - // Limit history size - if (actionHistory.length > 50) { - actionHistory.shift(); - currentIndex--; - } - } - - /** - * Undo last action - */ - function undo() { - if (currentIndex >= 0) { - const action = actionHistory[currentIndex]; - if (action && action.undo) { - action.undo(); - currentIndex--; - showNotification('Action undone'); - } - } - } - - /** - * Redo last undone action - */ - function redo() { - if (currentIndex < actionHistory.length - 1) { - currentIndex++; - const action = actionHistory[currentIndex]; - if (action && action.redo) { - action.redo(); - showNotification('Action redone'); - } - } - } - - /** - * Show undo/redo notification - */ - function showNotification(message) { - const notification = document.createElement('div'); - notification.className = 'undo-notification'; - notification.textContent = message; - document.body.appendChild(notification); - - setTimeout(() => { - notification.remove(); - }, 2000); - } - - // Export functions - window.UndoRedo = { - add: addAction, - undo: undo, - redo: redo - }; - - // Initialize on DOM ready - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initUndoRedo); - } else { - initUndoRedo(); - } - -})();