From f82d8e4d19bf2c653948cce878e9ad5913baf6ba Mon Sep 17 00:00:00 2001 From: Chaoscat Date: Mon, 11 Aug 2025 06:33:39 +0000 Subject: [PATCH] Dateien nach "static/js" hochladen --- static/js/app.js | 121 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 static/js/app.js diff --git a/static/js/app.js b/static/js/app.js new file mode 100644 index 0000000..251cdf0 --- /dev/null +++ b/static/js/app.js @@ -0,0 +1,121 @@ +/** + * AniWorld Downloader Web Interface + * Main JavaScript file + */ + +// Format timestamps +function formatDateTime(dateString) { + const date = new Date(dateString); + return date.toLocaleString('de-DE', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); +} + +// Helper to capitalize first letter +function capitalizeFirst(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +// Helper to truncate text with ellipsis +function truncateText(text, maxLength) { + return text.length > maxLength ? text.substring(0, maxLength) + '...' : text; +} + +// Parse URL parameters +function getUrlParams() { + const params = {}; + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + + for (const [key, value] of urlParams) { + params[key] = value; + } + + return params; +} + +// Show notification +function showNotification(message, type = 'info') { + // Check if notification container exists + let container = document.getElementById('notification-container'); + + if (!container) { + container = document.createElement('div'); + container.id = 'notification-container'; + container.style.position = 'fixed'; + container.style.top = '20px'; + container.style.right = '20px'; + container.style.zIndex = '9999'; + document.body.appendChild(container); + } + + // Create notification + const notification = document.createElement('div'); + notification.className = `alert alert-${type} alert-dismissible fade show`; + notification.innerHTML = ` + ${message} + + `; + + container.appendChild(notification); + + // Auto-close after 5 seconds + setTimeout(() => { + notification.classList.remove('show'); + setTimeout(() => { + notification.remove(); + }, 150); + }, 5000); +} + +// Extract title from URL +function extractTitleFromUrl(url) { + try { + if (url.includes('bs.to')) { + const match = url.match(/\/serie\/([^\/]+)/); + return match ? match[1].replace(/-/g, ' ') : 'Unknown Title'; + } else { + const match = url.match(/\/stream\/([^\/]+)/); + return match ? match[1].replace(/-/g, ' ') : 'Unknown Title'; + } + } catch (e) { + return 'Unknown Title'; + } +} + +// Check if URL is valid +function isValidUrl(url) { + const pattern = /^(https?:\/\/)?(www\.)?(aniworld\.to|s\.to|bs\.to)\/.*$/; + return pattern.test(url); +} + +// Initialize page-specific scripts when DOM is loaded +document.addEventListener('DOMContentLoaded', function() { + // Check for link parameter and populate the input + const urlParams = getUrlParams(); + if (urlParams.link && document.getElementById('animeLink')) { + document.getElementById('animeLink').value = urlParams.link; + + // Auto-analyze if requested + if (urlParams.analyze === 'true') { + document.getElementById('analyzeButton').click(); + } + } + + // Apply theme preference + const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; + if (prefersDarkMode) { + document.body.classList.add('dark-mode'); + } +}); + +// Handle AJAX errors globally +window.addEventListener('error', function(e) { + if (e.message.includes('NetworkError') || e.message.includes('Failed to fetch')) { + showNotification('Netzwerkfehler. Bitte überprüfe deine Verbindung.', 'danger'); + } +}); \ No newline at end of file