Dateien nach "static/js" hochladen

This commit is contained in:
Chaoscat 2025-08-11 06:33:39 +00:00
parent 093951ce5a
commit f82d8e4d19

121
static/js/app.js Normal file
View File

@ -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}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
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');
}
});