Commit vers. 2.1.0
This commit is contained in:
531
js/app.js
531
js/app.js
@@ -4,6 +4,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
let currentPage = getCurrentPageFromPath();
|
||||
let audioPlayer = null;
|
||||
let hlsInstance = null;
|
||||
let currentXHR = null;
|
||||
let isLoading = false;
|
||||
|
||||
// WeakMap per tracciare i listener degli elementi
|
||||
const linkListeners = new WeakMap();
|
||||
|
||||
loadHlsLibrary();
|
||||
|
||||
@@ -12,8 +17,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest';
|
||||
script.onload = () => console.log('HLS.js caricato');
|
||||
script.onerror = () => console.error('Errore caricamento HLS.js');
|
||||
script.onload = () => console.log('HLS.js caricato con successo');
|
||||
script.onerror = () => console.error('Errore nel caricamento di HLS.js');
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
@@ -29,68 +34,162 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
return path || 'home';
|
||||
}
|
||||
|
||||
function loadPage(page) {
|
||||
const contentContainer = document.getElementById('content');
|
||||
if (!contentContainer) return;
|
||||
/**
|
||||
* Pulizia completa del player audio
|
||||
* Previene memory leak rimuovendo istanze HLS e player audio
|
||||
*/
|
||||
function cleanupPlayer() {
|
||||
console.log('Pulizia player audio...');
|
||||
|
||||
// Distruggi istanza HLS
|
||||
if (hlsInstance) {
|
||||
try {
|
||||
hlsInstance.destroy();
|
||||
console.log('HLS instance distrutta');
|
||||
} catch (e) {
|
||||
console.error('Errore nella distruzione di HLS:', e);
|
||||
}
|
||||
hlsInstance = null;
|
||||
}
|
||||
|
||||
// Pulisci audio player
|
||||
if (audioPlayer) {
|
||||
try {
|
||||
audioPlayer.pause();
|
||||
audioPlayer.src = '';
|
||||
audioPlayer.load(); // Libera risorse
|
||||
|
||||
// Rimuovi tutti gli event listeners clonando il nodo
|
||||
const parent = audioPlayer.parentNode;
|
||||
if (parent) {
|
||||
const newPlayer = audioPlayer.cloneNode(true);
|
||||
parent.replaceChild(newPlayer, audioPlayer);
|
||||
}
|
||||
|
||||
console.log('Audio player pulito');
|
||||
} catch (e) {
|
||||
console.error('Errore nella pulizia del player audio:', e);
|
||||
}
|
||||
audioPlayer = null;
|
||||
}
|
||||
|
||||
// Reset Media Session
|
||||
if ('mediaSession' in navigator) {
|
||||
navigator.mediaSession.metadata = null;
|
||||
navigator.mediaSession.playbackState = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Caricamento pagina con protezione da race condition
|
||||
*/
|
||||
function loadPage(page) {
|
||||
// Previeni richieste multiple simultanee
|
||||
if (isLoading) {
|
||||
console.log('Caricamento già in corso, richiesta ignorata');
|
||||
return;
|
||||
}
|
||||
|
||||
// Annulla richiesta XHR precedente se presente
|
||||
if (currentXHR) {
|
||||
console.log('Annullamento richiesta precedente');
|
||||
currentXHR.abort();
|
||||
currentXHR = null;
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
const contentContainer = document.getElementById('content');
|
||||
|
||||
if (!contentContainer) {
|
||||
console.error('Container contenuto non trovato');
|
||||
isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Animazione fade out
|
||||
contentContainer.classList.remove('fade-in');
|
||||
contentContainer.classList.add('fade-out');
|
||||
|
||||
setTimeout(() => {
|
||||
const url = BASE_PATH + '/index.php/' + page;
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
currentXHR = new XMLHttpRequest();
|
||||
currentXHR.open('GET', url, true);
|
||||
currentXHR.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
contentContainer.innerHTML = xhr.responseText;
|
||||
currentXHR.onload = function() {
|
||||
isLoading = false;
|
||||
currentXHR = null;
|
||||
|
||||
if (this.status === 200) {
|
||||
contentContainer.innerHTML = this.responseText;
|
||||
|
||||
// Animazione fade in
|
||||
contentContainer.classList.remove('fade-out');
|
||||
contentContainer.classList.add('fade-in');
|
||||
|
||||
// Aggiorna URL nella history
|
||||
const historyUrl = page === 'home' ? BASE_PATH + '/' : BASE_PATH + '/' + page;
|
||||
history.pushState({page: page}, null, historyUrl);
|
||||
currentPage = page;
|
||||
|
||||
// Aggiorna navigazione attiva
|
||||
updateActiveNavigation(page);
|
||||
|
||||
// Inizializza componenti specifici della pagina
|
||||
if (page.startsWith('play/')) {
|
||||
initializePlayer();
|
||||
setTimeout(() => initializePlayer(), 100);
|
||||
}
|
||||
|
||||
if (page.startsWith('playtv/')) {
|
||||
initializeTVPlayer();
|
||||
setTimeout(() => initializeTVPlayer(), 100);
|
||||
}
|
||||
|
||||
// Riattacca i listener ai link
|
||||
attachLinkListeners();
|
||||
|
||||
// Inizializza form contatti se presente
|
||||
if (page === 'page/contact') {
|
||||
initializeContactForm();
|
||||
setTimeout(() => initializeContactForm(), 100);
|
||||
}
|
||||
|
||||
// Scroll to top
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
|
||||
console.log('Pagina caricata:', page);
|
||||
} else {
|
||||
contentContainer.innerHTML = '<div class="content-page"><h2>Errore</h2><p>Impossibile caricare la pagina. Codice errore: ' + xhr.status + '</p></div>';
|
||||
contentContainer.innerHTML = '<div class="content-page"><h2>Errore</h2><p>Impossibile caricare la pagina. Codice errore: ' + this.status + '</p></div>';
|
||||
contentContainer.classList.remove('fade-out');
|
||||
contentContainer.classList.add('fade-in');
|
||||
console.error('Errore caricamento pagina:', this.status);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function() {
|
||||
contentContainer.innerHTML = '<div class="content-page"><h2>Errore di connessione</h2><p>Controlla la tua connessione internet.</p></div>';
|
||||
currentXHR.onerror = function() {
|
||||
isLoading = false;
|
||||
currentXHR = null;
|
||||
contentContainer.innerHTML = '<div class="content-page"><h2>Errore di connessione</h2><p>Controlla la tua connessione internet e riprova.</p></div>';
|
||||
contentContainer.classList.remove('fade-out');
|
||||
contentContainer.classList.add('fade-in');
|
||||
console.error('Errore di rete durante il caricamento della pagina');
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
currentXHR.onabort = function() {
|
||||
isLoading = false;
|
||||
currentXHR = null;
|
||||
console.log('Richiesta XHR annullata');
|
||||
};
|
||||
|
||||
currentXHR.send();
|
||||
}, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggiorna la navigazione attiva
|
||||
*/
|
||||
function updateActiveNavigation(page) {
|
||||
const navLinks = document.querySelectorAll('.navLink');
|
||||
navLinks.forEach(link => {
|
||||
@@ -104,24 +203,24 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
link.classList.add('active');
|
||||
} else if (page.startsWith('playtv/') && linkPage === 'tv') {
|
||||
link.classList.add('active');
|
||||
} else if (page.startsWith('page/')) {
|
||||
if (linkPage === page) {
|
||||
link.classList.add('active');
|
||||
}
|
||||
} else if (page.startsWith('page/') && linkPage === page) {
|
||||
link.classList.add('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// NUOVA FUNZIONE: Setup Media Session API
|
||||
/**
|
||||
* Setup Media Session API per controlli sistema
|
||||
*/
|
||||
function setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon) {
|
||||
if (!('mediaSession' in navigator)) {
|
||||
console.log('Media Session API non supportata');
|
||||
console.log('Media Session API non supportata su questo browser');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Setup Media Session:', stationName, stationSlogan);
|
||||
console.log('Configurazione Media Session:', stationName);
|
||||
|
||||
// Imposta i metadati
|
||||
// Imposta i metadati della riproduzione
|
||||
navigator.mediaSession.metadata = new MediaMetadata({
|
||||
title: stationName,
|
||||
artist: stationSlogan,
|
||||
@@ -136,25 +235,26 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
]
|
||||
});
|
||||
|
||||
// Gestisci i controlli del centro notifiche
|
||||
// Handler per il comando Play dal sistema
|
||||
navigator.mediaSession.setActionHandler('play', () => {
|
||||
console.log('Media Session: Play richiesto dal centro notifiche');
|
||||
console.log('Media Session: Play richiesto');
|
||||
if (audioPlayer) {
|
||||
audioPlayer.play().then(() => {
|
||||
// Aggiorna UI
|
||||
if (playIcon && pauseIcon) {
|
||||
playIcon.style.display = 'none';
|
||||
pauseIcon.style.display = 'block';
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('Errore play da Media Session:', err);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handler per il comando Pause dal sistema
|
||||
navigator.mediaSession.setActionHandler('pause', () => {
|
||||
console.log('Media Session: Pause richiesto dal centro notifiche');
|
||||
console.log('Media Session: Pause richiesto');
|
||||
if (audioPlayer) {
|
||||
audioPlayer.pause();
|
||||
// Aggiorna UI
|
||||
if (playIcon && pauseIcon) {
|
||||
playIcon.style.display = 'block';
|
||||
pauseIcon.style.display = 'none';
|
||||
@@ -162,14 +262,18 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
|
||||
// Opzionale: gestisci skip (per radio potrebbe non servire)
|
||||
// Disabilita i controlli non utilizzati per radio streaming
|
||||
navigator.mediaSession.setActionHandler('seekbackward', null);
|
||||
navigator.mediaSession.setActionHandler('seekforward', null);
|
||||
navigator.mediaSession.setActionHandler('previoustrack', null);
|
||||
navigator.mediaSession.setActionHandler('nexttrack', null);
|
||||
|
||||
console.log('Media Session configurata correttamente');
|
||||
}
|
||||
|
||||
// NUOVA FUNZIONE: Aggiorna playback state
|
||||
/**
|
||||
* Aggiorna lo stato di riproduzione nella Media Session
|
||||
*/
|
||||
function updateMediaSessionPlaybackState(state) {
|
||||
if ('mediaSession' in navigator) {
|
||||
navigator.mediaSession.playbackState = state;
|
||||
@@ -177,11 +281,20 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inizializza il player audio con gestione HLS migliorata
|
||||
*/
|
||||
function initializePlayer() {
|
||||
console.log('Inizializzazione player...');
|
||||
console.log('Inizializzazione player audio...');
|
||||
|
||||
// Pulisci eventuali istanze precedenti
|
||||
cleanupPlayer();
|
||||
|
||||
const playPauseBtn = document.getElementById('playPauseBtn');
|
||||
if (!playPauseBtn) return;
|
||||
if (!playPauseBtn) {
|
||||
console.error('Pulsante play/pause non trovato');
|
||||
return;
|
||||
}
|
||||
|
||||
const playIcon = document.querySelector('.play-icon');
|
||||
const pauseIcon = document.querySelector('.pause-icon');
|
||||
@@ -192,29 +305,24 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const stationLogo = playPauseBtn.getAttribute('data-station-logo');
|
||||
const statusElement = document.getElementById('playerStatus');
|
||||
|
||||
console.log('Station:', stationName);
|
||||
console.log('HLS URL:', hlsUrl);
|
||||
console.log('Fallback URL:', fallbackUrl);
|
||||
console.log('Stazione:', stationName);
|
||||
console.log('URL HLS:', hlsUrl);
|
||||
console.log('URL Fallback:', fallbackUrl);
|
||||
|
||||
// Setup Media Session all'inizio passando anche le icone
|
||||
// Setup Media Session
|
||||
setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon);
|
||||
|
||||
if (hlsInstance) {
|
||||
hlsInstance.destroy();
|
||||
hlsInstance = null;
|
||||
}
|
||||
|
||||
if (audioPlayer) {
|
||||
audioPlayer.pause();
|
||||
audioPlayer = null;
|
||||
}
|
||||
|
||||
// Ottieni riferimento al player audio
|
||||
audioPlayer = document.getElementById('hlsAudioPlayer');
|
||||
if (!audioPlayer) {
|
||||
audioPlayer = new Audio();
|
||||
console.error('Elemento audio player non trovato nel DOM');
|
||||
return;
|
||||
}
|
||||
audioPlayer.preload = 'none';
|
||||
|
||||
/**
|
||||
* Aggiorna lo stato visualizzato
|
||||
*/
|
||||
function updateStatus(msg, isError = false) {
|
||||
console.log('Status:', msg);
|
||||
if (statusElement) {
|
||||
@@ -223,31 +331,56 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica supporto HLS nativo (Safari)
|
||||
*/
|
||||
function canPlayHLS() {
|
||||
const video = document.createElement('video');
|
||||
return video.canPlayType('application/vnd.apple.mpegurl') !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup HLS.js con gestione errori robusta
|
||||
*/
|
||||
function setupHLS() {
|
||||
if (!window.Hls || !Hls.isSupported()) {
|
||||
console.log('HLS.js non disponibile');
|
||||
console.log('HLS.js non disponibile o non supportato');
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('Uso HLS.js');
|
||||
updateStatus('Caricamento...');
|
||||
console.log('Utilizzo HLS.js per lo streaming');
|
||||
updateStatus('Caricamento stream...');
|
||||
|
||||
hlsInstance = new Hls({
|
||||
const hlsConfig = {
|
||||
enableWorker: true,
|
||||
lowLatencyMode: true
|
||||
});
|
||||
lowLatencyMode: true,
|
||||
maxBufferLength: 30,
|
||||
maxMaxBufferLength: 60,
|
||||
maxBufferSize: 60 * 1000 * 1000,
|
||||
manifestLoadingTimeOut: 10000,
|
||||
manifestLoadingMaxRetry: 3,
|
||||
manifestLoadingRetryDelay: 500,
|
||||
levelLoadingTimeOut: 10000,
|
||||
levelLoadingMaxRetry: 4,
|
||||
fragLoadingTimeOut: 20000,
|
||||
fragLoadingMaxRetry: 6
|
||||
};
|
||||
|
||||
hlsInstance = new Hls(hlsConfig);
|
||||
|
||||
let networkErrorCount = 0;
|
||||
let mediaErrorCount = 0;
|
||||
const MAX_NETWORK_ERRORS = 3;
|
||||
const MAX_MEDIA_ERRORS = 2;
|
||||
|
||||
hlsInstance.loadSource(hlsUrl);
|
||||
hlsInstance.attachMedia(audioPlayer);
|
||||
|
||||
hlsInstance.on(Hls.Events.MANIFEST_PARSED, function() {
|
||||
console.log('HLS manifest caricato');
|
||||
updateStatus('Pronto');
|
||||
console.log('Manifest HLS caricato con successo');
|
||||
updateStatus('Pronto per la riproduzione');
|
||||
networkErrorCount = 0;
|
||||
mediaErrorCount = 0;
|
||||
});
|
||||
|
||||
hlsInstance.on(Hls.Events.ERROR, function(event, data) {
|
||||
@@ -256,40 +389,82 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
if (data.fatal) {
|
||||
switch(data.type) {
|
||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||
console.log('Errore rete, riprovo...');
|
||||
hlsInstance.startLoad();
|
||||
networkErrorCount++;
|
||||
console.log(`Errore di rete ${networkErrorCount}/${MAX_NETWORK_ERRORS}`);
|
||||
|
||||
if (networkErrorCount < MAX_NETWORK_ERRORS) {
|
||||
updateStatus('Riconnessione in corso...');
|
||||
// Backoff esponenziale
|
||||
setTimeout(() => {
|
||||
console.log('Tentativo di riconnessione...');
|
||||
hlsInstance.startLoad();
|
||||
}, 1000 * networkErrorCount);
|
||||
} else {
|
||||
console.error('Troppi errori di rete, utilizzo stream fallback');
|
||||
updateStatus('Utilizzo stream alternativo...', true);
|
||||
hlsInstance.destroy();
|
||||
hlsInstance = null;
|
||||
useFallback();
|
||||
}
|
||||
break;
|
||||
|
||||
case Hls.ErrorTypes.MEDIA_ERROR:
|
||||
console.log('Errore media, riprovo...');
|
||||
hlsInstance.recoverMediaError();
|
||||
mediaErrorCount++;
|
||||
console.log(`Errore media ${mediaErrorCount}/${MAX_MEDIA_ERRORS}`);
|
||||
|
||||
if (mediaErrorCount < MAX_MEDIA_ERRORS) {
|
||||
updateStatus('Recupero errore media...');
|
||||
hlsInstance.recoverMediaError();
|
||||
} else {
|
||||
console.error('Troppi errori media, utilizzo stream fallback');
|
||||
updateStatus('Utilizzo stream alternativo...', true);
|
||||
hlsInstance.destroy();
|
||||
hlsInstance = null;
|
||||
useFallback();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error('Errore fatale, uso fallback');
|
||||
console.error('Errore fatale non recuperabile:', data.details);
|
||||
updateStatus('Stream non disponibile', true);
|
||||
hlsInstance.destroy();
|
||||
hlsInstance = null;
|
||||
useFallback();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Errori non fatali
|
||||
console.warn('Errore HLS non fatale:', data.details);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utilizza stream fallback MP3
|
||||
*/
|
||||
function useFallback() {
|
||||
console.log('Uso fallback:', fallbackUrl);
|
||||
console.log('Utilizzo stream fallback MP3:', fallbackUrl);
|
||||
if (fallbackUrl) {
|
||||
audioPlayer.src = fallbackUrl;
|
||||
audioPlayer.load();
|
||||
updateStatus('Pronto (MP3)');
|
||||
try {
|
||||
audioPlayer.src = fallbackUrl;
|
||||
audioPlayer.load();
|
||||
updateStatus('Pronto (MP3)');
|
||||
} catch (e) {
|
||||
console.error('Errore nel caricamento del fallback:', e);
|
||||
updateStatus('Stream non disponibile', true);
|
||||
}
|
||||
} else {
|
||||
console.error('Nessuno stream fallback disponibile');
|
||||
updateStatus('Stream non disponibile', true);
|
||||
}
|
||||
}
|
||||
|
||||
// Inizializza lo streaming
|
||||
if (hlsUrl) {
|
||||
if (canPlayHLS()) {
|
||||
console.log('Uso HLS nativo (Safari)');
|
||||
console.log('Utilizzo supporto HLS nativo (Safari)');
|
||||
audioPlayer.src = hlsUrl;
|
||||
updateStatus('Pronto');
|
||||
} else if (!setupHLS()) {
|
||||
@@ -299,10 +474,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
useFallback();
|
||||
}
|
||||
|
||||
// Gestore pulsante play/pause
|
||||
// Event handler per il pulsante play/pause
|
||||
playPauseBtn.addEventListener('click', function() {
|
||||
if (audioPlayer.paused) {
|
||||
updateStatus('Connessione...');
|
||||
updateStatus('Connessione allo stream...');
|
||||
|
||||
audioPlayer.play()
|
||||
.then(() => {
|
||||
@@ -310,25 +485,28 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
pauseIcon.style.display = 'block';
|
||||
updateStatus('In riproduzione');
|
||||
updateMediaSessionPlaybackState('playing');
|
||||
console.log('Riproduzione avviata');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Errore nella riproduzione:', error);
|
||||
updateStatus('Errore riproduzione', true);
|
||||
updateMediaSessionPlaybackState('paused');
|
||||
|
||||
// Tentativo con fallback se HLS fallisce
|
||||
if (hlsInstance && fallbackUrl) {
|
||||
console.log('Tentativo con fallback...');
|
||||
console.log('Tentativo con stream fallback...');
|
||||
hlsInstance.destroy();
|
||||
hlsInstance = null;
|
||||
useFallback();
|
||||
|
||||
setTimeout(() => {
|
||||
audioPlayer.play().catch(e => {
|
||||
console.error('Fallback fallito:', e);
|
||||
alert('Impossibile riprodurre lo stream audio. Riprova più tardi.');
|
||||
console.error('Anche il fallback è fallito:', e);
|
||||
alert('Impossibile riprodurre lo stream audio. Verifica la tua connessione e riprova.');
|
||||
});
|
||||
}, 500);
|
||||
} else {
|
||||
alert('Impossibile riprodurre lo stream audio. Riprova più tardi.');
|
||||
alert('Impossibile riprodurre lo stream audio. Verifica la tua connessione e riprova.');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -337,14 +515,14 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
pauseIcon.style.display = 'none';
|
||||
updateStatus('In pausa');
|
||||
updateMediaSessionPlaybackState('paused');
|
||||
console.log('Riproduzione in pausa');
|
||||
}
|
||||
});
|
||||
|
||||
// Event listeners con Media Session updates e sincronizzazione UI
|
||||
// Event listeners per sincronizzazione UI e Media Session
|
||||
audioPlayer.addEventListener('play', function() {
|
||||
updateMediaSessionPlaybackState('playing');
|
||||
updateStatus('In riproduzione');
|
||||
// Sincronizza UI quando l'audio parte (da qualsiasi fonte)
|
||||
playIcon.style.display = 'none';
|
||||
pauseIcon.style.display = 'block';
|
||||
});
|
||||
@@ -352,7 +530,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
audioPlayer.addEventListener('pause', function() {
|
||||
updateMediaSessionPlaybackState('paused');
|
||||
updateStatus('In pausa');
|
||||
// Sincronizza UI quando l'audio va in pausa (da qualsiasi fonte)
|
||||
playIcon.style.display = 'block';
|
||||
pauseIcon.style.display = 'none';
|
||||
});
|
||||
@@ -364,27 +541,48 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
updateMediaSessionPlaybackState('paused');
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('error', function() {
|
||||
audioPlayer.addEventListener('error', function(e) {
|
||||
playIcon.style.display = 'block';
|
||||
pauseIcon.style.display = 'none';
|
||||
updateStatus('Errore stream', true);
|
||||
updateMediaSessionPlaybackState('paused');
|
||||
console.error('Errore audio player:', e);
|
||||
alert('Si è verificato un errore durante la riproduzione. Riprova più tardi.');
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('waiting', () => updateStatus('Buffering...'));
|
||||
audioPlayer.addEventListener('playing', () => updateStatus('In riproduzione'));
|
||||
audioPlayer.addEventListener('waiting', () => {
|
||||
updateStatus('Buffering...');
|
||||
});
|
||||
|
||||
console.log('Player inizializzato con Media Session');
|
||||
audioPlayer.addEventListener('playing', () => {
|
||||
updateStatus('In riproduzione');
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('stalled', () => {
|
||||
console.warn('Stream stalled');
|
||||
updateStatus('Connessione lenta...');
|
||||
});
|
||||
|
||||
console.log('Player audio inizializzato correttamente');
|
||||
}
|
||||
|
||||
/**
|
||||
* Inizializza player TV
|
||||
*/
|
||||
function initializeTVPlayer() {
|
||||
console.log('TV Player inizializzato');
|
||||
// Implementare logica specifica per TV se necessario
|
||||
}
|
||||
|
||||
/**
|
||||
* Inizializza form contatti
|
||||
*/
|
||||
function initializeContactForm() {
|
||||
const contactForm = document.getElementById('contactForm');
|
||||
if (!contactForm) return;
|
||||
if (!contactForm) {
|
||||
console.log('Form contatti non trovato');
|
||||
return;
|
||||
}
|
||||
|
||||
contactForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
@@ -392,53 +590,78 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const formData = new FormData(contactForm);
|
||||
const formResponse = document.getElementById('formResponse');
|
||||
|
||||
formResponse.innerHTML = 'Invio in corso...';
|
||||
formResponse.className = 'form-response';
|
||||
formResponse.style.display = 'block';
|
||||
if (formResponse) {
|
||||
formResponse.innerHTML = 'Invio in corso...';
|
||||
formResponse.className = 'form-response';
|
||||
formResponse.style.display = 'block';
|
||||
}
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', BASE_PATH + '/process_contact.php', true);
|
||||
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
try {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
if (response.success) {
|
||||
formResponse.innerHTML = 'Messaggio inviato con successo! Ti risponderemo presto.';
|
||||
formResponse.className = 'form-response success';
|
||||
if (formResponse) {
|
||||
formResponse.innerHTML = 'Messaggio inviato con successo! Ti risponderemo presto.';
|
||||
formResponse.className = 'form-response success';
|
||||
}
|
||||
contactForm.reset();
|
||||
} else {
|
||||
formResponse.innerHTML = 'Errore: ' + (response.message || 'Si è verificato un errore durante l\'invio del messaggio.');
|
||||
formResponse.className = 'form-response error';
|
||||
if (formResponse) {
|
||||
formResponse.innerHTML = 'Errore: ' + (response.message || 'Si è verificato un errore durante l\'invio del messaggio.');
|
||||
formResponse.className = 'form-response error';
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
formResponse.innerHTML = 'Si è verificato un errore durante l\'elaborazione della risposta.';
|
||||
formResponse.className = 'form-response error';
|
||||
console.error('Errore parsing risposta:', e);
|
||||
if (formResponse) {
|
||||
formResponse.innerHTML = 'Si è verificato un errore durante l\'elaborazione della risposta.';
|
||||
formResponse.className = 'form-response error';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
formResponse.innerHTML = 'Si è verificato un errore durante l\'invio del messaggio.';
|
||||
if (formResponse) {
|
||||
formResponse.innerHTML = 'Si è verificato un errore durante l\'invio del messaggio.';
|
||||
formResponse.className = 'form-response error';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function() {
|
||||
if (formResponse) {
|
||||
formResponse.innerHTML = 'Errore di connessione. Controlla la tua connessione internet.';
|
||||
formResponse.className = 'form-response error';
|
||||
}
|
||||
};
|
||||
xhr.onerror = function() {
|
||||
formResponse.innerHTML = 'Errore di connessione. Controlla la tua connessione internet.';
|
||||
formResponse.className = 'form-response error';
|
||||
};
|
||||
|
||||
xhr.send(formData);
|
||||
});
|
||||
|
||||
console.log('Form contatti inizializzato');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attacca event listener ai link con gestione migliorata
|
||||
*/
|
||||
function attachLinkListeners() {
|
||||
const navLinks = document.querySelectorAll('.navLink, .nav-link, .station-link, .linkBox');
|
||||
|
||||
navLinks.forEach(link => {
|
||||
const newLink = link.cloneNode(true);
|
||||
link.parentNode.replaceChild(newLink, link);
|
||||
// Rimuovi listener precedente se esiste
|
||||
const oldListener = linkListeners.get(link);
|
||||
if (oldListener) {
|
||||
link.removeEventListener('click', oldListener);
|
||||
}
|
||||
|
||||
newLink.addEventListener('click', function(e) {
|
||||
const clickHandler = function(e) {
|
||||
const href = this.getAttribute('href');
|
||||
const target = this.getAttribute('target');
|
||||
const page = this.getAttribute('data-page');
|
||||
|
||||
// Verifica se è un link esterno
|
||||
const isExternal = href && (
|
||||
href.startsWith('http://') ||
|
||||
href.startsWith('https://') ||
|
||||
@@ -447,27 +670,35 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
);
|
||||
|
||||
if (isExternal) {
|
||||
console.log('Link esterno rilevato:', href);
|
||||
e.preventDefault();
|
||||
window.location.href = href;
|
||||
return;
|
||||
console.log('Link esterno:', href);
|
||||
return; // Lascia che il browser gestisca normalmente
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
console.log('Link cliccato, pagina:', page, 'currentPage:', currentPage);
|
||||
console.log('Navigazione a:', page);
|
||||
|
||||
if (page && page !== currentPage) {
|
||||
// Naviga solo se la pagina è diversa e non stiamo già caricando
|
||||
if (page && page !== currentPage && !isLoading) {
|
||||
// Metti in pausa l'audio se in riproduzione
|
||||
if (audioPlayer && !audioPlayer.paused) {
|
||||
audioPlayer.pause();
|
||||
}
|
||||
loadPage(page);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
link.addEventListener('click', clickHandler);
|
||||
linkListeners.set(link, clickHandler);
|
||||
});
|
||||
|
||||
console.log('Event listener attaccati a', navLinks.length, 'link');
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup pulsante apertura app (desktop)
|
||||
*/
|
||||
function setupOpenAppButton() {
|
||||
const openAppBtn = document.getElementById('openAppBtn');
|
||||
if (openAppBtn) {
|
||||
@@ -486,9 +717,14 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const windowFeatures = 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',resizable=yes,scrollbars=yes,status=yes';
|
||||
window.open(BASE_PATH + '/?app=true' + redirectParam, 'RadioApp', windowFeatures);
|
||||
});
|
||||
|
||||
console.log('Pulsante apertura app configurato');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup navigazione con history API
|
||||
*/
|
||||
function setupHistoryNavigation() {
|
||||
window.addEventListener('popstate', function(e) {
|
||||
if (e.state && e.state.page) {
|
||||
@@ -503,76 +739,89 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
|
||||
history.replaceState({page: currentPage}, null, window.location.pathname);
|
||||
console.log('Navigazione history configurata');
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup modalità standalone (PWA)
|
||||
*/
|
||||
function setupStandaloneMode() {
|
||||
const appContainer = document.querySelector('.container');
|
||||
if (!appContainer) return;
|
||||
|
||||
if (window.opener && !window.opener.closed) {
|
||||
appContainer.classList.add('standalone-app');
|
||||
console.log('App in modalità finestra popup');
|
||||
}
|
||||
|
||||
if (window.navigator.standalone || window.matchMedia('(display-mode: standalone)').matches) {
|
||||
appContainer.classList.add('standalone-app');
|
||||
console.log('App in modalità standalone (PWA)');
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
setupOpenAppButton();
|
||||
|
||||
if (document.querySelector('.container')) {
|
||||
setupStandaloneMode();
|
||||
|
||||
attachLinkListeners();
|
||||
|
||||
setupHistoryNavigation();
|
||||
|
||||
initializeCurrentPage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inizializza la pagina corrente
|
||||
*/
|
||||
function initializeCurrentPage() {
|
||||
console.log('Inizializzazione pagina corrente:', currentPage);
|
||||
|
||||
updateActiveNavigation(currentPage);
|
||||
|
||||
if (currentPage.startsWith('play/')) {
|
||||
setTimeout(function() {
|
||||
initializePlayer();
|
||||
}, 100);
|
||||
setTimeout(() => initializePlayer(), 100);
|
||||
}
|
||||
|
||||
if (currentPage.startsWith('playtv/')) {
|
||||
setTimeout(function() {
|
||||
initializeTVPlayer();
|
||||
}, 100);
|
||||
setTimeout(() => initializeTVPlayer(), 100);
|
||||
}
|
||||
|
||||
if (currentPage === 'page/contact') {
|
||||
setTimeout(function() {
|
||||
initializeContactForm();
|
||||
}, 100);
|
||||
setTimeout(() => initializeContactForm(), 100);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inizializzazione principale
|
||||
*/
|
||||
function init() {
|
||||
console.log('Inizializzazione app...');
|
||||
|
||||
setupOpenAppButton();
|
||||
|
||||
if (document.querySelector('.container')) {
|
||||
setupStandaloneMode();
|
||||
attachLinkListeners();
|
||||
setupHistoryNavigation();
|
||||
initializeCurrentPage();
|
||||
}
|
||||
|
||||
console.log('App inizializzata correttamente');
|
||||
}
|
||||
|
||||
// Avvia l'inizializzazione
|
||||
init();
|
||||
});
|
||||
|
||||
|
||||
// Funzione per bloccare l'orientamento (funziona solo in PWA/fullscreen)
|
||||
/**
|
||||
* GESTIONE ORIENTAMENTO SCHERMO
|
||||
*/
|
||||
|
||||
/**
|
||||
* Blocca l'orientamento in portrait (funziona solo in PWA/fullscreen)
|
||||
*/
|
||||
function lockScreenOrientation() {
|
||||
// Prova a bloccare l'orientamento con Screen Orientation API
|
||||
// Screen Orientation API
|
||||
if (screen.orientation && screen.orientation.lock) {
|
||||
screen.orientation.lock('portrait').then(() => {
|
||||
console.log('Orientamento bloccato in portrait');
|
||||
}).catch((err) => {
|
||||
console.log('Impossibile bloccare orientamento:', err.message);
|
||||
// Non è un errore grave, il CSS gestirà la situazione
|
||||
});
|
||||
}
|
||||
|
||||
// Alternativa per browser più vecchi
|
||||
// Fallback per browser più vecchi
|
||||
if (screen.lockOrientation) {
|
||||
screen.lockOrientation('portrait');
|
||||
} else if (screen.mozLockOrientation) {
|
||||
@@ -582,9 +831,20 @@ function lockScreenOrientation() {
|
||||
}
|
||||
}
|
||||
|
||||
// Prova a bloccare quando l'app è in fullscreen/standalone
|
||||
/**
|
||||
* Gestisce il cambio di orientamento
|
||||
*/
|
||||
function handleOrientationChange() {
|
||||
const orientation = window.orientation || (screen.orientation && screen.orientation.angle) || 0;
|
||||
console.log('Orientamento schermo:', orientation);
|
||||
|
||||
// Puoi aggiungere logica specifica qui se necessario
|
||||
}
|
||||
|
||||
/**
|
||||
* Tenta di bloccare l'orientamento quando appropriato
|
||||
*/
|
||||
function tryLockOrientation() {
|
||||
// Controlla se siamo in modalità standalone (PWA)
|
||||
const isStandalone = window.navigator.standalone ||
|
||||
window.matchMedia('(display-mode: standalone)').matches;
|
||||
|
||||
@@ -592,7 +852,6 @@ function tryLockOrientation() {
|
||||
lockScreenOrientation();
|
||||
}
|
||||
|
||||
// Prova anche quando entriamo in fullscreen
|
||||
document.addEventListener('fullscreenchange', () => {
|
||||
if (document.fullscreenElement) {
|
||||
lockScreenOrientation();
|
||||
|
||||
Reference in New Issue
Block a user