69e14afedf
- Fixed navigation blockage by moving Alpine state to body scope - Resolved CSS display conflicts between legacy .active class and x-show - Synchronized legacy auth logic with Alpine global state - Redirected legacy switchTab calls to Alpine events - Removed obsolete tabs.js and updated home section initialization - Added E2E navigation test placeholder
222 lines
7.5 KiB
JavaScript
222 lines
7.5 KiB
JavaScript
/**
|
|
* Main initialization and event handlers
|
|
*/
|
|
|
|
// Initialize on DOM load
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
initializeForms();
|
|
loadProviders();
|
|
loadDownloads();
|
|
setInterval(loadDownloads, 1000);
|
|
|
|
// Load home content (recommendations & releases)
|
|
loadHomeContent();
|
|
});
|
|
|
|
/**
|
|
* Initialize form event listeners
|
|
*/
|
|
function initializeForms() {
|
|
// Anime search form
|
|
const animeSearchInput = document.getElementById('animeSearchInput');
|
|
if (animeSearchInput) {
|
|
animeSearchInput.addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter') {
|
|
handleAnimeSearch();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Series search form
|
|
const seriesSearchInput = document.getElementById('seriesSearchInput');
|
|
if (seriesSearchInput) {
|
|
seriesSearchInput.addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter') {
|
|
handleSeriesSearch();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Direct download form
|
|
const downloadForm = document.getElementById('downloadForm');
|
|
if (downloadForm) {
|
|
downloadForm.addEventListener('submit', handleDirectDownload);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load providers dynamically (legacy support)
|
|
* Note: This is kept for compatibility but the new interface uses static tabs
|
|
*/
|
|
async function loadProviders() {
|
|
try {
|
|
const data = await getProvidersInfo();
|
|
|
|
// Update supported hosts badges (if element exists)
|
|
const hostsContainer = document.querySelector('.supported-hosts');
|
|
if (hostsContainer) {
|
|
hostsContainer.innerHTML = '';
|
|
|
|
Object.values(data.file_hosts).forEach(host => {
|
|
const badge = document.createElement('span');
|
|
badge.className = 'host-badge';
|
|
badge.textContent = `${host.icon} ${host.name}`;
|
|
hostsContainer.appendChild(badge);
|
|
});
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Error loading providers:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create anime provider tab content
|
|
*/
|
|
function createAnimeTabContent(providerId, provider) {
|
|
return `
|
|
<div class="url-form">
|
|
<div class="anime-input-group">
|
|
<input
|
|
type="text"
|
|
id="${providerId}UrlInput"
|
|
placeholder="URL de l'anime (ex: ${provider.url_pattern})"
|
|
>
|
|
<button type="button" class="btn-primary" onclick="handleLoadProviderEpisodes('${providerId}')">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
|
</svg>
|
|
Charger
|
|
</button>
|
|
</div>
|
|
|
|
<div id="${providerId}EpisodeSelector" class="anime-select-group" style="display:none;">
|
|
<select id="${providerId}EpisodeSelect">
|
|
<option value="">Sélectionner un épisode</option>
|
|
</select>
|
|
<button type="button" class="btn-primary" onclick="handleDownloadProviderEpisode('${providerId}')">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path>
|
|
</svg>
|
|
Télécharger
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* Create series provider tab content
|
|
*/
|
|
function createSeriesTabContent(providerId, provider) {
|
|
return `
|
|
<div class="url-form">
|
|
<div class="anime-input-group">
|
|
<input
|
|
type="text"
|
|
id="${providerId}UrlInput"
|
|
placeholder="URL de la série (ex: ${provider.url_pattern})"
|
|
>
|
|
<button type="button" class="btn-primary" onclick="handleLoadProviderEpisodes('${providerId}')">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
|
</svg>
|
|
Charger
|
|
</button>
|
|
</div>
|
|
|
|
<div id="${providerId}EpisodeSelector" class="anime-select-group" style="display:none;">
|
|
<select id="${providerId}EpisodeSelect">
|
|
<option value="">Sélectionner un épisode</option>
|
|
</select>
|
|
<button type="button" class="btn-primary" onclick="handleDownloadProviderEpisode('${providerId}')">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path>
|
|
</svg>
|
|
Télécharger
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* Handle load provider episodes
|
|
*/
|
|
async function handleLoadProviderEpisodes(providerId) {
|
|
const animeUrl = document.getElementById(`${providerId}UrlInput`).value;
|
|
if (!animeUrl) {
|
|
alert('Veuillez entrer une URL d\'anime');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const data = await loadEpisodes(animeUrl, null);
|
|
|
|
if (data.episodes && data.episodes.length > 0) {
|
|
const select = document.getElementById(`${providerId}EpisodeSelect`);
|
|
select.innerHTML = '<option value="">Sélectionner un épisode</option>';
|
|
|
|
data.episodes.forEach(ep => {
|
|
const option = document.createElement('option');
|
|
option.value = ep.url;
|
|
option.textContent = `Épisode ${ep.episode}`;
|
|
select.appendChild(option);
|
|
});
|
|
|
|
document.getElementById(`${providerId}EpisodeSelector`).style.display = 'flex';
|
|
} else {
|
|
alert('Aucun épisode trouvé');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading episodes:', error);
|
|
alert('Erreur lors du chargement des épisodes');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle download provider episode
|
|
*/
|
|
async function handleDownloadProviderEpisode(providerId) {
|
|
const episodeUrl = document.getElementById(`${providerId}EpisodeSelect`).value;
|
|
if (!episodeUrl) {
|
|
alert('Veuillez sélectionner un épisode');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await downloadEpisode(episodeUrl);
|
|
document.getElementById(`${providerId}EpisodeSelect`).value = '';
|
|
loadDownloads();
|
|
} catch (error) {
|
|
console.error('Download error:', error);
|
|
alert('Erreur lors du téléchargement');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Switch between tabs (Modernized to Alpine.js)
|
|
*/
|
|
function switchTab(tabName) {
|
|
console.log('Switching tab to:', tabName);
|
|
window.dispatchEvent(new CustomEvent('set-tab', { detail: { tab: tabName } }));
|
|
}
|
|
|
|
|
|
// Handle URL hash on page load
|
|
if (window.location.hash) {
|
|
const hash = window.location.hash.substring(1);
|
|
if (hash === 'watchlist' || hash === 'anime' || hash === 'series' || hash === 'providers') {
|
|
switchTab(hash);
|
|
}
|
|
}
|
|
|
|
// Listen for hash changes
|
|
window.addEventListener('hashchange', function() {
|
|
if (window.location.hash) {
|
|
const hash = window.location.hash.substring(1);
|
|
if (hash === 'watchlist' || hash === 'anime' || hash === 'series' || hash === 'providers') {
|
|
switchTab(hash);
|
|
}
|
|
}
|
|
}); |