vers. 2.1.1
This commit is contained in:
77
.htaccess
Normal file
77
.htaccess
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# Abilita il rewrite engine
|
||||||
|
RewriteEngine On
|
||||||
|
|
||||||
|
# Imposta la directory base (modifica se necessario)
|
||||||
|
# Se l'app è in una sottocartella, usa: RewriteBase /nome_cartella/
|
||||||
|
RewriteBase /newapp.rpigroup.it/
|
||||||
|
|
||||||
|
# Reindirizza richieste HTTP a HTTPS (opzionale, decommentare se necessario)
|
||||||
|
# RewriteCond %{HTTPS} off
|
||||||
|
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||||
|
|
||||||
|
# Non reindirizzare file e cartelle esistenti
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
|
||||||
|
# Escludi file statici dal rewriting
|
||||||
|
RewriteCond %{REQUEST_URI} !\.(css|js|jpg|jpeg|png|gif|svg|ico|xml|json|woff|woff2|ttf|eot)$ [NC]
|
||||||
|
|
||||||
|
# Reindirizza tutto a index.php mantenendo il path
|
||||||
|
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
|
||||||
|
|
||||||
|
# Impedisci l'accesso diretto a file sensibili
|
||||||
|
<FilesMatch "^(config|\.htaccess|\.env)">
|
||||||
|
Order Allow,Deny
|
||||||
|
Deny from all
|
||||||
|
</FilesMatch>
|
||||||
|
|
||||||
|
# Gestione MIME types
|
||||||
|
<IfModule mod_mime.c>
|
||||||
|
AddType application/javascript js
|
||||||
|
AddType text/css css
|
||||||
|
AddType image/svg+xml svg
|
||||||
|
AddType application/vnd.ms-fontobject eot
|
||||||
|
AddType font/ttf ttf
|
||||||
|
AddType font/otf otf
|
||||||
|
AddType font/woff woff
|
||||||
|
AddType font/woff2 woff2
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Abilita compressione GZIP (opzionale)
|
||||||
|
<IfModule mod_deflate.c>
|
||||||
|
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Cache control (opzionale - commentato perché hai lo script no-cache)
|
||||||
|
# <IfModule mod_expires.c>
|
||||||
|
# ExpiresActive On
|
||||||
|
# ExpiresByType image/jpg "access plus 1 month"
|
||||||
|
# ExpiresByType image/jpeg "access plus 1 month"
|
||||||
|
# ExpiresByType image/gif "access plus 1 month"
|
||||||
|
# ExpiresByType image/png "access plus 1 month"
|
||||||
|
# ExpiresByType image/svg+xml "access plus 1 month"
|
||||||
|
# ExpiresByType text/css "access plus 1 week"
|
||||||
|
# ExpiresByType application/javascript "access plus 1 week"
|
||||||
|
# </IfModule>
|
||||||
|
|
||||||
|
# Header no-cache per sviluppo (rimuovi in produzione se usi la cache)
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
<FilesMatch "\.(html|php)$">
|
||||||
|
Header set Cache-Control "no-cache, no-store, must-revalidate"
|
||||||
|
Header set Pragma "no-cache"
|
||||||
|
Header set Expires "0"
|
||||||
|
</FilesMatch>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Sicurezza aggiuntiva
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
Header set X-Content-Type-Options "nosniff"
|
||||||
|
Header set X-Frame-Options "SAMEORIGIN"
|
||||||
|
Header set X-XSS-Protection "1; mode=block"
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Disabilita directory listing
|
||||||
|
Options -Indexes
|
||||||
|
|
||||||
|
# Abilita follow symlinks (necessario per RewriteRule)
|
||||||
|
Options +FollowSymLinks
|
||||||
BIN
.htaccess:Zone.Identifier
Normal file
BIN
.htaccess:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
header('Content-Type: text/html; charset=UTF-8');
|
||||||
|
|
||||||
// Verifica se è una richiesta AJAX
|
// Verifica se è una richiesta AJAX
|
||||||
$is_ajax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
|
$is_ajax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
|
||||||
|
|
||||||
|
|||||||
BIN
config/ajaxModule.inc.php:Zone.Identifier
Normal file
BIN
config/ajaxModule.inc.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,5 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
header('Content-Type: text/html; charset=UTF-8');
|
||||||
|
|
||||||
|
|
||||||
// Information App
|
// Information App
|
||||||
$title_site = "RPIGroup Play";
|
$title_site = "RPIGroup Play";
|
||||||
$description_site = "Ascolta le radio del gruppo RPIGroup";
|
$description_site = "Ascolta le radio del gruppo RPIGroup";
|
||||||
|
|||||||
BIN
config/config.php:Zone.Identifier
Normal file
BIN
config/config.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
header('Content-Type: text/html; charset=UTF-8');
|
||||||
|
|
||||||
// Determina il percorso base dell'applicazione
|
// Determina il percorso base dell'applicazione
|
||||||
$script_name = $_SERVER['SCRIPT_NAME'];
|
$script_name = $_SERVER['SCRIPT_NAME'];
|
||||||
$script_path = dirname($script_name);
|
$script_path = dirname($script_name);
|
||||||
|
|||||||
BIN
config/getBasePath.inc.php:Zone.Identifier
Normal file
BIN
config/getBasePath.inc.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,10 +1,27 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
header('Content-Type: text/html; charset=UTF-8');
|
||||||
|
|
||||||
|
// File: config/getPage.inc.php
|
||||||
|
|
||||||
|
// Whitelist delle pagine valide
|
||||||
|
$validPages = ['home', 'radio', 'tv', 'play', 'playtv', 'page'];
|
||||||
|
$validSubPages = ['about', 'contact', 'copyright', 'addradio', 'termini-condizioni', 'policy-privacy', 'changelog'];
|
||||||
|
|
||||||
// Rileva se l'utente sta usando un dispositivo mobile
|
// Rileva se l'utente sta usando un dispositivo mobile
|
||||||
function isMobile() {
|
function isMobile() {
|
||||||
return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $_SERVER["HTTP_USER_AGENT"]);
|
return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $_SERVER["HTTP_USER_AGENT"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Funzione per sanitizzare l'input
|
||||||
|
function sanitizePageInput($input) {
|
||||||
|
// Rimuovi caratteri pericolosi
|
||||||
|
$input = preg_replace('/[^a-zA-Z0-9\-_]/', '', $input);
|
||||||
|
// Previeni path traversal
|
||||||
|
$input = str_replace(['..', '/', '\\'], '', $input);
|
||||||
|
return $input;
|
||||||
|
}
|
||||||
|
|
||||||
// Recupera l'URL richiesto
|
// Recupera l'URL richiesto
|
||||||
$request_uri = $_SERVER['REQUEST_URI'];
|
$request_uri = $_SERVER['REQUEST_URI'];
|
||||||
$path = substr(urldecode($request_uri), strlen($base_path));
|
$path = substr(urldecode($request_uri), strlen($base_path));
|
||||||
@@ -23,9 +40,45 @@ if (isset($path_parts[0]) && $path_parts[0] == 'index.php') {
|
|||||||
array_shift($path_parts);
|
array_shift($path_parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determina la pagina da mostrare in base all'URL
|
// Determina la pagina da mostrare in base all'URL con validazione
|
||||||
$page = isset($path_parts[0]) && !empty($path_parts[0]) ? $path_parts[0] : 'home';
|
$page = 'home'; // Default sicuro
|
||||||
$param = isset($path_parts[1]) && !empty($path_parts[1]) ? $path_parts[1] : '';
|
$param = '';
|
||||||
|
|
||||||
|
if (isset($path_parts[0]) && !empty($path_parts[0])) {
|
||||||
|
$requestedPage = sanitizePageInput($path_parts[0]);
|
||||||
|
|
||||||
|
// Verifica se la pagina è nella whitelist
|
||||||
|
if (in_array($requestedPage, $validPages)) {
|
||||||
|
$page = $requestedPage;
|
||||||
|
} else {
|
||||||
|
// Pagina non valida, redirect a 404
|
||||||
|
$page = 'home';
|
||||||
|
error_log("Tentativo di accesso a pagina non valida: " . $path_parts[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($path_parts[1]) && !empty($path_parts[1])) {
|
||||||
|
$requestedParam = sanitizePageInput($path_parts[1]);
|
||||||
|
|
||||||
|
// Validazione specifica per tipo di pagina
|
||||||
|
if ($page === 'play' || $page === 'playtv') {
|
||||||
|
// Per play/playtv, il parametro deve essere un numero
|
||||||
|
if (ctype_digit($requestedParam)) {
|
||||||
|
$param = $requestedParam;
|
||||||
|
} else {
|
||||||
|
error_log("ID stazione non valido: " . $path_parts[1]);
|
||||||
|
$page = 'home';
|
||||||
|
}
|
||||||
|
} elseif ($page === 'page') {
|
||||||
|
// Per page, il parametro deve essere nella whitelist
|
||||||
|
if (in_array($requestedParam, $validSubPages)) {
|
||||||
|
$param = $requestedParam;
|
||||||
|
} else {
|
||||||
|
error_log("Sottopagina non valida: " . $path_parts[1]);
|
||||||
|
$page = 'home';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Debug (rimuovi in produzione)
|
// Debug (rimuovi in produzione)
|
||||||
error_log("Page: $page, Param: $param, Path: $path");
|
error_log("Page: $page, Param: $param, Path: $path");
|
||||||
BIN
config/getPage.inc.php:Zone.Identifier
Normal file
BIN
config/getPage.inc.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,54 +1,202 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Funzione per caricare il file XML delle radio
|
/**
|
||||||
|
* Cache XML in memoria per la durata della richiesta
|
||||||
|
* Previene caricamenti multipli dello stesso file
|
||||||
|
*/
|
||||||
|
class StationCache {
|
||||||
|
private static $radioXML = null;
|
||||||
|
private static $tvXML = null;
|
||||||
|
private static $changelogXML = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Carica e cachea il file XML delle radio
|
||||||
|
*/
|
||||||
|
public static function getRadioXML() {
|
||||||
|
if (self::$radioXML === null) {
|
||||||
|
$xmlPath = './data/radio.xml';
|
||||||
|
|
||||||
|
if (!file_exists($xmlPath)) {
|
||||||
|
error_log("File XML non trovato: $xmlPath");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_readable($xmlPath)) {
|
||||||
|
error_log("File XML non leggibile: $xmlPath");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
self::$radioXML = simplexml_load_file($xmlPath);
|
||||||
|
|
||||||
|
if (self::$radioXML === false) {
|
||||||
|
$errors = libxml_get_errors();
|
||||||
|
foreach ($errors as $error) {
|
||||||
|
error_log("Errore XML radio.xml: " . trim($error->message) . " (Linea: " . $error->line . ")");
|
||||||
|
}
|
||||||
|
libxml_clear_errors();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$radioXML;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Carica e cachea il file XML delle TV
|
||||||
|
*/
|
||||||
|
public static function getTVXML() {
|
||||||
|
if (self::$tvXML === null) {
|
||||||
|
$xmlPath = './data/tv.xml';
|
||||||
|
|
||||||
|
if (!file_exists($xmlPath)) {
|
||||||
|
error_log("File XML non trovato: $xmlPath");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_readable($xmlPath)) {
|
||||||
|
error_log("File XML non leggibile: $xmlPath");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
self::$tvXML = simplexml_load_file($xmlPath);
|
||||||
|
|
||||||
|
if (self::$tvXML === false) {
|
||||||
|
$errors = libxml_get_errors();
|
||||||
|
foreach ($errors as $error) {
|
||||||
|
error_log("Errore XML tv.xml: " . trim($error->message) . " (Linea: " . $error->line . ")");
|
||||||
|
}
|
||||||
|
libxml_clear_errors();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$tvXML;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Carica e cachea il file XML del changelog
|
||||||
|
*/
|
||||||
|
public static function getChangelogXML() {
|
||||||
|
if (self::$changelogXML === null) {
|
||||||
|
$xmlPath = './data/changelog.xml';
|
||||||
|
|
||||||
|
if (!file_exists($xmlPath)) {
|
||||||
|
error_log("File XML non trovato: $xmlPath");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_readable($xmlPath)) {
|
||||||
|
error_log("File XML non leggibile: $xmlPath");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
self::$changelogXML = simplexml_load_file($xmlPath);
|
||||||
|
|
||||||
|
if (self::$changelogXML === false) {
|
||||||
|
$errors = libxml_get_errors();
|
||||||
|
foreach ($errors as $error) {
|
||||||
|
error_log("Errore XML changelog.xml: " . trim($error->message) . " (Linea: " . $error->line . ")");
|
||||||
|
}
|
||||||
|
libxml_clear_errors();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$changelogXML;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Funzione per caricare tutte le stazioni radio
|
||||||
|
* @return array|SimpleXMLElement Array di stazioni o array vuoto in caso di errore
|
||||||
|
*/
|
||||||
function loadRadioStations() {
|
function loadRadioStations() {
|
||||||
$xml = simplexml_load_file('./data/radio.xml');
|
$xml = StationCache::getRadioXML();
|
||||||
if ($xml === false) {
|
if ($xml === false || !isset($xml->station)) {
|
||||||
error_log("Errore nel caricamento del file XML: data/radio.xml");
|
error_log("Impossibile caricare le stazioni radio");
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return $xml->station;
|
return $xml->station;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Funzione per ottenere una singola stazione radio
|
/**
|
||||||
|
* Funzione per ottenere una singola stazione radio
|
||||||
|
* @param int $id ID della stazione
|
||||||
|
* @return SimpleXMLElement|null Stazione o null se non trovata
|
||||||
|
*/
|
||||||
function getRadioStation($id) {
|
function getRadioStation($id) {
|
||||||
$xml = simplexml_load_file('./data/radio.xml');
|
$xml = StationCache::getRadioXML();
|
||||||
if ($xml === false) {
|
if ($xml === false) {
|
||||||
error_log("Errore nel caricamento del file XML: data/radio.xml");
|
error_log("Impossibile caricare XML radio per ID: $id");
|
||||||
return null;
|
|
||||||
}
|
|
||||||
foreach ($xml->station as $station) {
|
|
||||||
if ((int)$station->id === $id) {
|
|
||||||
return $station;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Funzione per caricare il file XML delle TV
|
if (!isset($xml->station)) {
|
||||||
|
error_log("Nessuna stazione trovata nel file XML");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($xml->station as $station) {
|
||||||
|
if ((int)$station->id === (int)$id) {
|
||||||
|
return $station;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_log("Stazione radio non trovata con ID: $id");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Funzione per caricare tutte le stazioni TV
|
||||||
|
* @return array|SimpleXMLElement Array di stazioni o array vuoto in caso di errore
|
||||||
|
*/
|
||||||
function loadTVStations() {
|
function loadTVStations() {
|
||||||
$xml = simplexml_load_file('./data/tv.xml');
|
$xml = StationCache::getTVXML();
|
||||||
if ($xml === false) {
|
if ($xml === false || !isset($xml->station)) {
|
||||||
error_log("Errore nel caricamento del file XML: data/tv.xml");
|
error_log("Impossibile caricare le stazioni TV");
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return $xml->station;
|
return $xml->station;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Funzione per ottenere una singola stazione TV
|
/**
|
||||||
|
* Funzione per ottenere una singola stazione TV
|
||||||
|
* @param int $id ID della stazione
|
||||||
|
* @return SimpleXMLElement|null Stazione o null se non trovata
|
||||||
|
*/
|
||||||
function getTVStation($id) {
|
function getTVStation($id) {
|
||||||
$xml = simplexml_load_file('./data/tv.xml');
|
$xml = StationCache::getTVXML();
|
||||||
if ($xml === false) {
|
if ($xml === false) {
|
||||||
error_log("Errore nel caricamento del file XML: data/tv.xml");
|
error_log("Impossibile caricare XML TV per ID: $id");
|
||||||
return null;
|
|
||||||
}
|
|
||||||
foreach ($xml->station as $station) {
|
|
||||||
if ((int)$station->id === $id) {
|
|
||||||
return $station;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$changelog = simplexml_load_file("./data/changelog.xml") or die("Errore: Impossibile accedere al file CHANGELOG");
|
if (!isset($xml->station)) {
|
||||||
$version_app = $changelog->version->number[0];
|
error_log("Nessuna stazione TV trovata nel file XML");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($xml->station as $station) {
|
||||||
|
if ((int)$station->id === (int)$id) {
|
||||||
|
return $station;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_log("Stazione TV non trovata con ID: $id");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Carica il changelog e la versione dell'app
|
||||||
|
*/
|
||||||
|
$changelog = StationCache::getChangelogXML();
|
||||||
|
$version_app = "1.0.0"; // Versione di default
|
||||||
|
|
||||||
|
if ($changelog !== false && isset($changelog->version) && isset($changelog->version[0]->number)) {
|
||||||
|
$version_app = (string)$changelog->version[0]->number;
|
||||||
|
} else {
|
||||||
|
error_log("Impossibile leggere la versione dal changelog.xml, uso versione di default: $version_app");
|
||||||
|
}
|
||||||
BIN
config/getStation.inc.php:Zone.Identifier
Normal file
BIN
config/getStation.inc.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/animation.css:Zone.Identifier
Normal file
BIN
css/animation.css:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/bootstrap.css:Zone.Identifier
Normal file
BIN
css/bootstrap.css:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/OFL.txt:Zone.Identifier
Normal file
BIN
css/fonts/OFL.txt:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-Black.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-Black.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-BlackItalic.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-BlackItalic.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-Bold.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-Bold.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-BoldItalic.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-BoldItalic.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-ExtraBold.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-ExtraBold.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-ExtraBoldItalic.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-ExtraBoldItalic.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-ExtraLight.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-ExtraLight.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-ExtraLightItalic.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-ExtraLightItalic.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-Italic.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-Italic.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-Light.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-Light.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-LightItalic.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-LightItalic.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-Medium.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-Medium.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-MediumItalic.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-MediumItalic.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-Regular.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-Regular.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-SemiBold.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-SemiBold.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-SemiBoldItalic.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-SemiBoldItalic.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-Thin.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-Thin.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/fonts/Poppins-ThinItalic.ttf:Zone.Identifier
Normal file
BIN
css/fonts/Poppins-ThinItalic.ttf:Zone.Identifier
Normal file
Binary file not shown.
BIN
css/style.css:Zone.Identifier
Normal file
BIN
css/style.css:Zone.Identifier
Normal file
Binary file not shown.
@@ -2,6 +2,23 @@
|
|||||||
|
|
||||||
<changelog>
|
<changelog>
|
||||||
|
|
||||||
|
<version>
|
||||||
|
<number>2.1.1</number>
|
||||||
|
<logs>
|
||||||
|
<log>Corretti alcuni bug che impedivano l'accesso al player dal link esterno</log>
|
||||||
|
<log>Correzione e bugfix di problematiche varie.</log>
|
||||||
|
</logs>
|
||||||
|
</version>
|
||||||
|
|
||||||
|
<version>
|
||||||
|
<number>2.1.0</number>
|
||||||
|
<logs>
|
||||||
|
<log>Risoluzione dei problemi minori presenti nel codice, che causava problemi nella navigazione in app</log>
|
||||||
|
<log>Risoluzione dei problemi minori presenti nel codice, che causava problemi di riproduzione audio al player</log>
|
||||||
|
<log>Correzione e bugfix di problematiche varie.</log>
|
||||||
|
</logs>
|
||||||
|
</version>
|
||||||
|
|
||||||
<version>
|
<version>
|
||||||
<number>2.0.4</number>
|
<number>2.0.4</number>
|
||||||
<logs>
|
<logs>
|
||||||
|
|||||||
BIN
data/changelog.xml:Zone.Identifier
Normal file
BIN
data/changelog.xml:Zone.Identifier
Normal file
Binary file not shown.
@@ -35,7 +35,7 @@
|
|||||||
<contentplayer></contentplayer>
|
<contentplayer></contentplayer>
|
||||||
</station>
|
</station>
|
||||||
|
|
||||||
<station>
|
<!-- <station>
|
||||||
<id>4</id>
|
<id>4</id>
|
||||||
<name>RC105 Christmas - Eboli</name>
|
<name>RC105 Christmas - Eboli</name>
|
||||||
<slogan>La musica di Natale, in giro per Eboli</slogan>
|
<slogan>La musica di Natale, in giro per Eboli</slogan>
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
<stream>https://srvone.radio.asvhosting.com/listen/rc105_christmas/radio.aac</stream>
|
<stream>https://srvone.radio.asvhosting.com/listen/rc105_christmas/radio.aac</stream>
|
||||||
<streamhls>https://srvone.radio.asvhosting.com/hls/rc105_christmas/live.m3u8</streamhls>
|
<streamhls>https://srvone.radio.asvhosting.com/hls/rc105_christmas/live.m3u8</streamhls>
|
||||||
<contentplayer></contentplayer>
|
<contentplayer></contentplayer>
|
||||||
</station>
|
</station> -->
|
||||||
|
|
||||||
<station>
|
<station>
|
||||||
<id>5</id>
|
<id>5</id>
|
||||||
|
|||||||
BIN
data/radio.xml:Zone.Identifier
Normal file
BIN
data/radio.xml:Zone.Identifier
Normal file
Binary file not shown.
BIN
data/tv.xml:Zone.Identifier
Normal file
BIN
data/tv.xml:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/RpiGroupPlay.png:Zone.Identifier
Normal file
BIN
img/RpiGroupPlay.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/RpiGroupPlay.svg:Zone.Identifier
Normal file
BIN
img/RpiGroupPlay.svg:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/RpiGroupPlayWHITE.png:Zone.Identifier
Normal file
BIN
img/RpiGroupPlayWHITE.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/RpiGroupPlayWhite.svg:Zone.Identifier
Normal file
BIN
img/RpiGroupPlayWhite.svg:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/articolo.png:Zone.Identifier
Normal file
BIN
img/articolo.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/christmascampagna.png:Zone.Identifier
Normal file
BIN
img/christmascampagna.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/christmaseboli.png:Zone.Identifier
Normal file
BIN
img/christmaseboli.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/icons/icon-128x128.png:Zone.Identifier
Normal file
BIN
img/icons/icon-128x128.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/icons/icon-144x144.png:Zone.Identifier
Normal file
BIN
img/icons/icon-144x144.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/icons/icon-152x152.png:Zone.Identifier
Normal file
BIN
img/icons/icon-152x152.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/icons/icon-192x192.png:Zone.Identifier
Normal file
BIN
img/icons/icon-192x192.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/icons/icon-384x384.png:Zone.Identifier
Normal file
BIN
img/icons/icon-384x384.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/icons/icon-512x512.png:Zone.Identifier
Normal file
BIN
img/icons/icon-512x512.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/icons/icon-72x72.png:Zone.Identifier
Normal file
BIN
img/icons/icon-72x72.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/icons/icon-96x96.png:Zone.Identifier
Normal file
BIN
img/icons/icon-96x96.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/installapp1.jpeg:Zone.Identifier
Normal file
BIN
img/installapp1.jpeg:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/installapp2.jpeg:Zone.Identifier
Normal file
BIN
img/installapp2.jpeg:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/logoapp.png:Zone.Identifier
Normal file
BIN
img/logoapp.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/logoapp_512.png:Zone.Identifier
Normal file
BIN
img/logoapp_512.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/radio.png:Zone.Identifier
Normal file
BIN
img/radio.png:Zone.Identifier
Normal file
Binary file not shown.
BIN
img/tv.png:Zone.Identifier
Normal file
BIN
img/tv.png:Zone.Identifier
Normal file
Binary file not shown.
@@ -11,6 +11,8 @@
|
|||||||
# Version app: VEDERE IN CHANGELOG.XML
|
# Version app: VEDERE IN CHANGELOG.XML
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
header('Content-Type: text/html; charset=UTF-8');
|
||||||
|
|
||||||
|
|
||||||
# Import config file
|
# Import config file
|
||||||
include_once './config/config.php';
|
include_once './config/config.php';
|
||||||
|
|||||||
BIN
index.php:Zone.Identifier
Normal file
BIN
index.php:Zone.Identifier
Normal file
Binary file not shown.
640
js/app.js
640
js/app.js
@@ -4,6 +4,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
let currentPage = getCurrentPageFromPath();
|
let currentPage = getCurrentPageFromPath();
|
||||||
let audioPlayer = null;
|
let audioPlayer = null;
|
||||||
let hlsInstance = null;
|
let hlsInstance = null;
|
||||||
|
let currentXHR = null;
|
||||||
|
let isLoading = false;
|
||||||
|
|
||||||
|
// WeakMap per tracciare i listener degli elementi
|
||||||
|
const linkListeners = new WeakMap();
|
||||||
|
|
||||||
loadHlsLibrary();
|
loadHlsLibrary();
|
||||||
|
|
||||||
@@ -12,116 +17,233 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest';
|
script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest';
|
||||||
script.onload = () => console.log('HLS.js caricato');
|
script.onload = () => console.log('HLS.js caricato con successo');
|
||||||
script.onerror = () => console.error('Errore caricamento HLS.js');
|
script.onerror = () => console.error('Errore nel caricamento di HLS.js');
|
||||||
document.head.appendChild(script);
|
document.head.appendChild(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentPageFromPath() {
|
function getCurrentPageFromPath() {
|
||||||
let path = window.location.pathname;
|
let path = window.location.pathname;
|
||||||
|
|
||||||
|
// Rimuovi il base path se presente
|
||||||
if (BASE_PATH && path.startsWith(BASE_PATH)) {
|
if (BASE_PATH && path.startsWith(BASE_PATH)) {
|
||||||
path = path.substring(BASE_PATH.length);
|
path = path.substring(BASE_PATH.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rimuovi slash iniziali e finali
|
||||||
path = path.replace(/^\/|\/$/g, '');
|
path = path.replace(/^\/|\/$/g, '');
|
||||||
|
|
||||||
|
// IMPORTANTE: Se il path è vuoto o è solo "index.php", controlla il parametro redirect
|
||||||
|
if (!path || path === '' || path === 'index.php') {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const redirect = urlParams.get('redirect');
|
||||||
|
|
||||||
|
if (redirect) {
|
||||||
|
console.log('📍 Trovato parametro redirect:', redirect);
|
||||||
|
return redirect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('📍 Path rilevato:', path || 'home');
|
||||||
return path || 'home';
|
return path || 'home';
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadPage(page) {
|
/**
|
||||||
const contentContainer = document.getElementById('content');
|
* Pulizia completa del player audio
|
||||||
if (!contentContainer) return;
|
* 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.remove('fade-in');
|
||||||
contentContainer.classList.add('fade-out');
|
contentContainer.classList.add('fade-out');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const url = BASE_PATH + '/index.php/' + page;
|
const url = BASE_PATH + '/index.php/' + page;
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
currentXHR = new XMLHttpRequest();
|
||||||
xhr.open('GET', url, true);
|
currentXHR.open('GET', url, true);
|
||||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
currentXHR.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||||
|
|
||||||
xhr.onload = function() {
|
currentXHR.onload = function () {
|
||||||
if (xhr.status === 200) {
|
isLoading = false;
|
||||||
contentContainer.innerHTML = xhr.responseText;
|
currentXHR = null;
|
||||||
|
|
||||||
|
if (this.status === 200) {
|
||||||
|
contentContainer.innerHTML = this.responseText;
|
||||||
|
|
||||||
|
// Animazione fade in
|
||||||
contentContainer.classList.remove('fade-out');
|
contentContainer.classList.remove('fade-out');
|
||||||
contentContainer.classList.add('fade-in');
|
contentContainer.classList.add('fade-in');
|
||||||
|
|
||||||
|
// Aggiorna URL nella history
|
||||||
const historyUrl = page === 'home' ? BASE_PATH + '/' : BASE_PATH + '/' + page;
|
const historyUrl = page === 'home' ? BASE_PATH + '/' : BASE_PATH + '/' + page;
|
||||||
history.pushState({ page: page }, null, historyUrl);
|
history.pushState({ page: page }, null, historyUrl);
|
||||||
currentPage = page;
|
currentPage = page;
|
||||||
|
|
||||||
|
// Aggiorna navigazione attiva
|
||||||
updateActiveNavigation(page);
|
updateActiveNavigation(page);
|
||||||
|
|
||||||
|
// Inizializza componenti specifici della pagina
|
||||||
if (page.startsWith('play/')) {
|
if (page.startsWith('play/')) {
|
||||||
initializePlayer();
|
setTimeout(() => initializePlayer(), 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page.startsWith('playtv/')) {
|
if (page.startsWith('playtv/')) {
|
||||||
initializeTVPlayer();
|
setTimeout(() => initializeTVPlayer(), 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Riattacca i listener ai link
|
||||||
attachLinkListeners();
|
attachLinkListeners();
|
||||||
|
|
||||||
|
// Inizializza form contatti se presente
|
||||||
if (page === 'page/contact') {
|
if (page === 'page/contact') {
|
||||||
initializeContactForm();
|
setTimeout(() => initializeContactForm(), 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scroll to top
|
||||||
window.scrollTo({
|
window.scrollTo({
|
||||||
top: 0,
|
top: 0,
|
||||||
behavior: 'smooth'
|
behavior: 'smooth'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('Pagina caricata:', page);
|
||||||
} else {
|
} 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.remove('fade-out');
|
||||||
contentContainer.classList.add('fade-in');
|
contentContainer.classList.add('fade-in');
|
||||||
|
console.error('Errore caricamento pagina:', this.status);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.onerror = function() {
|
currentXHR.onerror = function () {
|
||||||
contentContainer.innerHTML = '<div class="content-page"><h2>Errore di connessione</h2><p>Controlla la tua connessione internet.</p></div>';
|
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.remove('fade-out');
|
||||||
contentContainer.classList.add('fade-in');
|
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);
|
}, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggiorna la navigazione attiva
|
||||||
|
*/
|
||||||
function updateActiveNavigation(page) {
|
function updateActiveNavigation(page) {
|
||||||
|
console.log('Aggiornamento navigazione per pagina:', page); // Debug
|
||||||
|
|
||||||
const navLinks = document.querySelectorAll('.navLink');
|
const navLinks = document.querySelectorAll('.navLink');
|
||||||
navLinks.forEach(link => {
|
navLinks.forEach(link => {
|
||||||
link.classList.remove('active');
|
link.classList.remove('active');
|
||||||
|
|
||||||
const linkPage = link.getAttribute('data-page');
|
const linkPage = link.getAttribute('data-page');
|
||||||
|
|
||||||
|
// Log di debug per vedere i confronti
|
||||||
|
console.log('Confronto:', linkPage, 'con', page);
|
||||||
|
|
||||||
if (linkPage === page) {
|
if (linkPage === page) {
|
||||||
link.classList.add('active');
|
link.classList.add('active');
|
||||||
|
console.log('✓ Match esatto:', linkPage);
|
||||||
} else if (page.startsWith('play/') && linkPage === 'radio') {
|
} else if (page.startsWith('play/') && linkPage === 'radio') {
|
||||||
link.classList.add('active');
|
link.classList.add('active');
|
||||||
|
console.log('✓ Match play/ -> radio');
|
||||||
} else if (page.startsWith('playtv/') && linkPage === 'tv') {
|
} else if (page.startsWith('playtv/') && linkPage === 'tv') {
|
||||||
link.classList.add('active');
|
link.classList.add('active');
|
||||||
} else if (page.startsWith('page/')) {
|
console.log('✓ Match playtv/ -> tv');
|
||||||
if (linkPage === page) {
|
} else if (page.startsWith('page/') && linkPage === page) {
|
||||||
link.classList.add('active');
|
link.classList.add('active');
|
||||||
}
|
console.log('✓ Match page/');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// NUOVA FUNZIONE: Setup Media Session API
|
/**
|
||||||
|
* Setup Media Session API per controlli sistema
|
||||||
|
*/
|
||||||
function setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon) {
|
function setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon) {
|
||||||
if (!('mediaSession' in navigator)) {
|
if (!('mediaSession' in navigator)) {
|
||||||
console.log('Media Session API non supportata');
|
console.log('Media Session API non supportata su questo browser');
|
||||||
return;
|
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({
|
navigator.mediaSession.metadata = new MediaMetadata({
|
||||||
title: stationName,
|
title: stationName,
|
||||||
artist: stationSlogan,
|
artist: stationSlogan,
|
||||||
@@ -136,25 +258,26 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
// Gestisci i controlli del centro notifiche
|
// Handler per il comando Play dal sistema
|
||||||
navigator.mediaSession.setActionHandler('play', () => {
|
navigator.mediaSession.setActionHandler('play', () => {
|
||||||
console.log('Media Session: Play richiesto dal centro notifiche');
|
console.log('Media Session: Play richiesto');
|
||||||
if (audioPlayer) {
|
if (audioPlayer) {
|
||||||
audioPlayer.play().then(() => {
|
audioPlayer.play().then(() => {
|
||||||
// Aggiorna UI
|
|
||||||
if (playIcon && pauseIcon) {
|
if (playIcon && pauseIcon) {
|
||||||
playIcon.style.display = 'none';
|
playIcon.style.display = 'none';
|
||||||
pauseIcon.style.display = 'block';
|
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', () => {
|
navigator.mediaSession.setActionHandler('pause', () => {
|
||||||
console.log('Media Session: Pause richiesto dal centro notifiche');
|
console.log('Media Session: Pause richiesto');
|
||||||
if (audioPlayer) {
|
if (audioPlayer) {
|
||||||
audioPlayer.pause();
|
audioPlayer.pause();
|
||||||
// Aggiorna UI
|
|
||||||
if (playIcon && pauseIcon) {
|
if (playIcon && pauseIcon) {
|
||||||
playIcon.style.display = 'block';
|
playIcon.style.display = 'block';
|
||||||
pauseIcon.style.display = 'none';
|
pauseIcon.style.display = 'none';
|
||||||
@@ -162,14 +285,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('seekbackward', null);
|
||||||
navigator.mediaSession.setActionHandler('seekforward', null);
|
navigator.mediaSession.setActionHandler('seekforward', null);
|
||||||
navigator.mediaSession.setActionHandler('previoustrack', null);
|
navigator.mediaSession.setActionHandler('previoustrack', null);
|
||||||
navigator.mediaSession.setActionHandler('nexttrack', 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) {
|
function updateMediaSessionPlaybackState(state) {
|
||||||
if ('mediaSession' in navigator) {
|
if ('mediaSession' in navigator) {
|
||||||
navigator.mediaSession.playbackState = state;
|
navigator.mediaSession.playbackState = state;
|
||||||
@@ -177,214 +304,252 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inizializza il player audio con gestione HLS migliorata
|
||||||
|
*/
|
||||||
|
|
||||||
function initializePlayer() {
|
function initializePlayer() {
|
||||||
console.log('Inizializzazione player...');
|
console.log('Inizializzazione player audio...');
|
||||||
|
|
||||||
const playPauseBtn = document.getElementById('playPauseBtn');
|
const playPauseBtn = document.getElementById('playPauseBtn');
|
||||||
if (!playPauseBtn) return;
|
|
||||||
|
|
||||||
const playIcon = document.querySelector('.play-icon');
|
const playIcon = document.querySelector('.play-icon');
|
||||||
const pauseIcon = document.querySelector('.pause-icon');
|
const pauseIcon = document.querySelector('.pause-icon');
|
||||||
const hlsUrl = playPauseBtn.getAttribute('data-stream-hls');
|
const playerStatus = document.getElementById('playerStatus');
|
||||||
const fallbackUrl = playPauseBtn.getAttribute('data-stream-fallback');
|
const artistElement = document.getElementById('artist');
|
||||||
|
|
||||||
|
if (!playPauseBtn) {
|
||||||
|
console.error('Pulsante play/pause non trovato');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pulisci il player precedente
|
||||||
|
cleanupPlayer();
|
||||||
|
|
||||||
|
// Ottieni il nuovo audio player dal DOM
|
||||||
|
audioPlayer = document.getElementById('hlsAudioPlayer');
|
||||||
|
|
||||||
|
if (!audioPlayer) {
|
||||||
|
console.error('Elemento audio non trovato');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const streamHLS = playPauseBtn.getAttribute('data-stream-hls');
|
||||||
|
const streamFallback = playPauseBtn.getAttribute('data-stream-fallback');
|
||||||
const stationName = playPauseBtn.getAttribute('data-station-name');
|
const stationName = playPauseBtn.getAttribute('data-station-name');
|
||||||
const stationSlogan = playPauseBtn.getAttribute('data-station-slogan');
|
const stationSlogan = playPauseBtn.getAttribute('data-station-slogan');
|
||||||
const stationLogo = playPauseBtn.getAttribute('data-station-logo');
|
const stationLogo = playPauseBtn.getAttribute('data-station-logo');
|
||||||
const statusElement = document.getElementById('playerStatus');
|
|
||||||
|
|
||||||
console.log('Station:', stationName);
|
console.log('Stream HLS:', streamHLS);
|
||||||
console.log('HLS URL:', hlsUrl);
|
console.log('Stream Fallback:', streamFallback);
|
||||||
console.log('Fallback URL:', fallbackUrl);
|
console.log('Stazione:', stationName);
|
||||||
|
|
||||||
// Setup Media Session all'inizio passando anche le icone
|
let isPlaying = false;
|
||||||
setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon);
|
let streamType = 'hls'; // 'hls' o 'direct'
|
||||||
|
|
||||||
if (hlsInstance) {
|
/**
|
||||||
hlsInstance.destroy();
|
* Inizializza HLS stream
|
||||||
hlsInstance = null;
|
*/
|
||||||
}
|
function initHLSStream() {
|
||||||
|
if (!window.Hls) {
|
||||||
if (audioPlayer) {
|
console.error('HLS.js non caricato');
|
||||||
audioPlayer.pause();
|
|
||||||
audioPlayer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
audioPlayer = document.getElementById('hlsAudioPlayer');
|
|
||||||
if (!audioPlayer) {
|
|
||||||
audioPlayer = new Audio();
|
|
||||||
}
|
|
||||||
audioPlayer.preload = 'none';
|
|
||||||
|
|
||||||
function updateStatus(msg, isError = false) {
|
|
||||||
console.log('Status:', msg);
|
|
||||||
if (statusElement) {
|
|
||||||
statusElement.textContent = msg;
|
|
||||||
statusElement.className = 'station-status' + (isError ? ' error' : '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function canPlayHLS() {
|
|
||||||
const video = document.createElement('video');
|
|
||||||
return video.canPlayType('application/vnd.apple.mpegurl') !== '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupHLS() {
|
|
||||||
if (!window.Hls || !Hls.isSupported()) {
|
|
||||||
console.log('HLS.js non disponibile');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Uso HLS.js');
|
if (Hls.isSupported()) {
|
||||||
updateStatus('Caricamento...');
|
console.log('HLS supportato - uso HLS.js');
|
||||||
|
|
||||||
hlsInstance = new Hls({
|
hlsInstance = new Hls({
|
||||||
|
debug: false,
|
||||||
enableWorker: true,
|
enableWorker: true,
|
||||||
lowLatencyMode: true
|
lowLatencyMode: true,
|
||||||
|
backBufferLength: 90
|
||||||
});
|
});
|
||||||
|
|
||||||
hlsInstance.loadSource(hlsUrl);
|
hlsInstance.loadSource(streamHLS);
|
||||||
hlsInstance.attachMedia(audioPlayer);
|
hlsInstance.attachMedia(audioPlayer);
|
||||||
|
|
||||||
hlsInstance.on(Hls.Events.MANIFEST_PARSED, function () {
|
hlsInstance.on(Hls.Events.MANIFEST_PARSED, function () {
|
||||||
console.log('HLS manifest caricato');
|
console.log('Manifest HLS caricato');
|
||||||
updateStatus('Pronto');
|
audioPlayer.play().then(() => {
|
||||||
|
console.log('Riproduzione HLS avviata');
|
||||||
|
updatePlayState(true);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('Errore avvio riproduzione HLS:', err);
|
||||||
|
tryFallbackStream();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
hlsInstance.on(Hls.Events.ERROR, function (event, data) {
|
hlsInstance.on(Hls.Events.ERROR, function (event, data) {
|
||||||
console.error('Errore HLS:', data.type, data.details);
|
console.error('Errore HLS:', data.type, data.details);
|
||||||
|
|
||||||
if (data.fatal) {
|
if (data.fatal) {
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||||
console.log('Errore rete, riprovo...');
|
console.log('Errore di rete, tentativo fallback...');
|
||||||
hlsInstance.startLoad();
|
tryFallbackStream();
|
||||||
break;
|
break;
|
||||||
case Hls.ErrorTypes.MEDIA_ERROR:
|
case Hls.ErrorTypes.MEDIA_ERROR:
|
||||||
console.log('Errore media, riprovo...');
|
console.log('Errore media, tentativo recupero...');
|
||||||
hlsInstance.recoverMediaError();
|
hlsInstance.recoverMediaError();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error('Errore fatale, uso fallback');
|
console.log('Errore fatale, tentativo fallback...');
|
||||||
hlsInstance.destroy();
|
tryFallbackStream();
|
||||||
hlsInstance = null;
|
|
||||||
useFallback();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (audioPlayer.canPlayType('application/vnd.apple.mpegurl')) {
|
||||||
|
console.log('HLS nativo supportato');
|
||||||
|
audioPlayer.src = streamHLS;
|
||||||
|
audioPlayer.play().then(() => {
|
||||||
|
console.log('Riproduzione HLS nativa avviata');
|
||||||
|
updatePlayState(true);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('Errore HLS nativo:', err);
|
||||||
|
tryFallbackStream();
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function useFallback() {
|
return false;
|
||||||
console.log('Uso fallback:', fallbackUrl);
|
|
||||||
if (fallbackUrl) {
|
|
||||||
audioPlayer.src = fallbackUrl;
|
|
||||||
audioPlayer.load();
|
|
||||||
updateStatus('Pronto (MP3)');
|
|
||||||
} else {
|
|
||||||
updateStatus('Stream non disponibile', true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hlsUrl) {
|
/**
|
||||||
if (canPlayHLS()) {
|
* Usa stream diretto come fallback
|
||||||
console.log('Uso HLS nativo (Safari)');
|
*/
|
||||||
audioPlayer.src = hlsUrl;
|
function tryFallbackStream() {
|
||||||
updateStatus('Pronto');
|
console.log('Tentativo stream fallback:', streamFallback);
|
||||||
} else if (!setupHLS()) {
|
|
||||||
useFallback();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
useFallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gestore pulsante play/pause
|
if (hlsInstance) {
|
||||||
playPauseBtn.addEventListener('click', function() {
|
|
||||||
if (audioPlayer.paused) {
|
|
||||||
updateStatus('Connessione...');
|
|
||||||
|
|
||||||
audioPlayer.play()
|
|
||||||
.then(() => {
|
|
||||||
playIcon.style.display = 'none';
|
|
||||||
pauseIcon.style.display = 'block';
|
|
||||||
updateStatus('In riproduzione');
|
|
||||||
updateMediaSessionPlaybackState('playing');
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Errore nella riproduzione:', error);
|
|
||||||
updateStatus('Errore riproduzione', true);
|
|
||||||
updateMediaSessionPlaybackState('paused');
|
|
||||||
|
|
||||||
if (hlsInstance && fallbackUrl) {
|
|
||||||
console.log('Tentativo con fallback...');
|
|
||||||
hlsInstance.destroy();
|
hlsInstance.destroy();
|
||||||
hlsInstance = null;
|
hlsInstance = null;
|
||||||
useFallback();
|
}
|
||||||
setTimeout(() => {
|
|
||||||
audioPlayer.play().catch(e => {
|
streamType = 'direct';
|
||||||
console.error('Fallback fallito:', e);
|
audioPlayer.src = streamFallback;
|
||||||
alert('Impossibile riprodurre lo stream audio. Riprova più tardi.');
|
audioPlayer.load();
|
||||||
});
|
|
||||||
}, 500);
|
audioPlayer.play().then(() => {
|
||||||
} else {
|
console.log('Riproduzione stream diretto avviata');
|
||||||
alert('Impossibile riprodurre lo stream audio. Riprova più tardi.');
|
updatePlayState(true);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('Errore stream diretto:', err);
|
||||||
|
updatePlayState(false);
|
||||||
|
if (playerStatus) {
|
||||||
|
playerStatus.textContent = 'Errore di riproduzione';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggiorna stato visuale play/pause
|
||||||
|
*/
|
||||||
|
function updatePlayState(playing) {
|
||||||
|
isPlaying = playing;
|
||||||
|
|
||||||
|
if (playing) {
|
||||||
|
playIcon.style.display = 'none';
|
||||||
|
pauseIcon.style.display = 'inline-block';
|
||||||
|
if (playerStatus) {
|
||||||
|
playerStatus.textContent = 'In riproduzione...';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
audioPlayer.pause();
|
playIcon.style.display = 'inline-block';
|
||||||
playIcon.style.display = 'block';
|
|
||||||
pauseIcon.style.display = 'none';
|
pauseIcon.style.display = 'none';
|
||||||
updateStatus('In pausa');
|
if (playerStatus) {
|
||||||
updateMediaSessionPlaybackState('paused');
|
playerStatus.textContent = stationSlogan || 'In pausa';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gestione click play/pause
|
||||||
|
*/
|
||||||
|
playPauseBtn.addEventListener('click', function () {
|
||||||
|
if (!audioPlayer) return;
|
||||||
|
|
||||||
|
if (isPlaying) {
|
||||||
|
// Pausa
|
||||||
|
audioPlayer.pause();
|
||||||
|
updatePlayState(false);
|
||||||
|
console.log('Riproduzione in pausa');
|
||||||
|
} else {
|
||||||
|
// Play
|
||||||
|
if (!audioPlayer.src && !hlsInstance) {
|
||||||
|
// Prima riproduzione - inizializza lo stream
|
||||||
|
if (streamHLS && !initHLSStream()) {
|
||||||
|
// Se HLS fallisce, usa direttamente il fallback
|
||||||
|
tryFallbackStream();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Riprendi riproduzione
|
||||||
|
audioPlayer.play().then(() => {
|
||||||
|
updatePlayState(true);
|
||||||
|
console.log('Riproduzione ripresa');
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('Errore ripresa riproduzione:', err);
|
||||||
|
updatePlayState(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Event listeners con Media Session updates e sincronizzazione UI
|
/**
|
||||||
|
* Event listeners audio player
|
||||||
|
*/
|
||||||
audioPlayer.addEventListener('play', function () {
|
audioPlayer.addEventListener('play', function () {
|
||||||
updateMediaSessionPlaybackState('playing');
|
updatePlayState(true);
|
||||||
updateStatus('In riproduzione');
|
|
||||||
// Sincronizza UI quando l'audio parte (da qualsiasi fonte)
|
|
||||||
playIcon.style.display = 'none';
|
|
||||||
pauseIcon.style.display = 'block';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
audioPlayer.addEventListener('pause', function () {
|
audioPlayer.addEventListener('pause', function () {
|
||||||
updateMediaSessionPlaybackState('paused');
|
updatePlayState(false);
|
||||||
updateStatus('In pausa');
|
|
||||||
// Sincronizza UI quando l'audio va in pausa (da qualsiasi fonte)
|
|
||||||
playIcon.style.display = 'block';
|
|
||||||
pauseIcon.style.display = 'none';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
audioPlayer.addEventListener('ended', function() {
|
audioPlayer.addEventListener('error', function (e) {
|
||||||
playIcon.style.display = 'block';
|
console.error('Errore audio player:', e);
|
||||||
pauseIcon.style.display = 'none';
|
updatePlayState(false);
|
||||||
updateStatus('Terminato');
|
if (playerStatus) {
|
||||||
updateMediaSessionPlaybackState('paused');
|
playerStatus.textContent = 'Errore di riproduzione';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
audioPlayer.addEventListener('error', function() {
|
audioPlayer.addEventListener('waiting', function () {
|
||||||
playIcon.style.display = 'block';
|
if (playerStatus) {
|
||||||
pauseIcon.style.display = 'none';
|
playerStatus.textContent = 'Buffering...';
|
||||||
updateStatus('Errore stream', true);
|
}
|
||||||
updateMediaSessionPlaybackState('paused');
|
|
||||||
alert('Si è verificato un errore durante la riproduzione. Riprova più tardi.');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
audioPlayer.addEventListener('waiting', () => updateStatus('Buffering...'));
|
audioPlayer.addEventListener('playing', function () {
|
||||||
audioPlayer.addEventListener('playing', () => updateStatus('In riproduzione'));
|
if (playerStatus) {
|
||||||
|
playerStatus.textContent = 'In riproduzione...';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
console.log('Player inizializzato con Media Session');
|
// Setup Media Session
|
||||||
|
setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon);
|
||||||
|
|
||||||
|
console.log('Player audio inizializzato');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inizializza player TV
|
||||||
|
*/
|
||||||
function initializeTVPlayer() {
|
function initializeTVPlayer() {
|
||||||
console.log('TV Player inizializzato');
|
console.log('TV Player inizializzato');
|
||||||
|
// Implementare logica specifica per TV se necessario
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inizializza form contatti
|
||||||
|
*/
|
||||||
function initializeContactForm() {
|
function initializeContactForm() {
|
||||||
const contactForm = document.getElementById('contactForm');
|
const contactForm = document.getElementById('contactForm');
|
||||||
if (!contactForm) return;
|
if (!contactForm) {
|
||||||
|
console.log('Form contatti non trovato');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
contactForm.addEventListener('submit', function (e) {
|
contactForm.addEventListener('submit', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -392,53 +557,78 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
const formData = new FormData(contactForm);
|
const formData = new FormData(contactForm);
|
||||||
const formResponse = document.getElementById('formResponse');
|
const formResponse = document.getElementById('formResponse');
|
||||||
|
|
||||||
|
if (formResponse) {
|
||||||
formResponse.innerHTML = 'Invio in corso...';
|
formResponse.innerHTML = 'Invio in corso...';
|
||||||
formResponse.className = 'form-response';
|
formResponse.className = 'form-response';
|
||||||
formResponse.style.display = 'block';
|
formResponse.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open('POST', BASE_PATH + '/process_contact.php', true);
|
xhr.open('POST', BASE_PATH + '/process_contact.php', true);
|
||||||
|
|
||||||
xhr.onload = function () {
|
xhr.onload = function () {
|
||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
try {
|
try {
|
||||||
const response = JSON.parse(xhr.responseText);
|
const response = JSON.parse(xhr.responseText);
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
|
if (formResponse) {
|
||||||
formResponse.innerHTML = 'Messaggio inviato con successo! Ti risponderemo presto.';
|
formResponse.innerHTML = 'Messaggio inviato con successo! Ti risponderemo presto.';
|
||||||
formResponse.className = 'form-response success';
|
formResponse.className = 'form-response success';
|
||||||
|
}
|
||||||
contactForm.reset();
|
contactForm.reset();
|
||||||
} else {
|
} else {
|
||||||
|
if (formResponse) {
|
||||||
formResponse.innerHTML = 'Errore: ' + (response.message || 'Si è verificato un errore durante l\'invio del messaggio.');
|
formResponse.innerHTML = 'Errore: ' + (response.message || 'Si è verificato un errore durante l\'invio del messaggio.');
|
||||||
formResponse.className = 'form-response error';
|
formResponse.className = 'form-response error';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error('Errore parsing risposta:', e);
|
||||||
|
if (formResponse) {
|
||||||
formResponse.innerHTML = 'Si è verificato un errore durante l\'elaborazione della risposta.';
|
formResponse.innerHTML = 'Si è verificato un errore durante l\'elaborazione della risposta.';
|
||||||
formResponse.className = 'form-response error';
|
formResponse.className = 'form-response error';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (formResponse) {
|
||||||
formResponse.innerHTML = 'Si è verificato un errore durante l\'invio del messaggio.';
|
formResponse.innerHTML = 'Si è verificato un errore durante l\'invio del messaggio.';
|
||||||
formResponse.className = 'form-response error';
|
formResponse.className = 'form-response error';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.onerror = function () {
|
xhr.onerror = function () {
|
||||||
|
if (formResponse) {
|
||||||
formResponse.innerHTML = 'Errore di connessione. Controlla la tua connessione internet.';
|
formResponse.innerHTML = 'Errore di connessione. Controlla la tua connessione internet.';
|
||||||
formResponse.className = 'form-response error';
|
formResponse.className = 'form-response error';
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.send(formData);
|
xhr.send(formData);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('Form contatti inizializzato');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attacca event listener ai link con gestione migliorata
|
||||||
|
*/
|
||||||
function attachLinkListeners() {
|
function attachLinkListeners() {
|
||||||
const navLinks = document.querySelectorAll('.navLink, .nav-link, .station-link, .linkBox');
|
const navLinks = document.querySelectorAll('.navLink, .nav-link, .station-link, .linkBox');
|
||||||
|
|
||||||
navLinks.forEach(link => {
|
navLinks.forEach(link => {
|
||||||
const newLink = link.cloneNode(true);
|
// Rimuovi listener precedente se esiste
|
||||||
link.parentNode.replaceChild(newLink, link);
|
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 href = this.getAttribute('href');
|
||||||
const target = this.getAttribute('target');
|
const target = this.getAttribute('target');
|
||||||
const page = this.getAttribute('data-page');
|
const page = this.getAttribute('data-page');
|
||||||
|
|
||||||
|
// Verifica se è un link esterno
|
||||||
const isExternal = href && (
|
const isExternal = href && (
|
||||||
href.startsWith('http://') ||
|
href.startsWith('http://') ||
|
||||||
href.startsWith('https://') ||
|
href.startsWith('https://') ||
|
||||||
@@ -447,27 +637,35 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (isExternal) {
|
if (isExternal) {
|
||||||
console.log('Link esterno rilevato:', href);
|
console.log('Link esterno:', href);
|
||||||
e.preventDefault();
|
return; // Lascia che il browser gestisca normalmente
|
||||||
window.location.href = href;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
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) {
|
if (audioPlayer && !audioPlayer.paused) {
|
||||||
audioPlayer.pause();
|
audioPlayer.pause();
|
||||||
}
|
}
|
||||||
loadPage(page);
|
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() {
|
function setupOpenAppButton() {
|
||||||
const openAppBtn = document.getElementById('openAppBtn');
|
const openAppBtn = document.getElementById('openAppBtn');
|
||||||
if (openAppBtn) {
|
if (openAppBtn) {
|
||||||
@@ -486,9 +684,14 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
const windowFeatures = 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',resizable=yes,scrollbars=yes,status=yes';
|
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);
|
window.open(BASE_PATH + '/?app=true' + redirectParam, 'RadioApp', windowFeatures);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('Pulsante apertura app configurato');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup navigazione con history API
|
||||||
|
*/
|
||||||
function setupHistoryNavigation() {
|
function setupHistoryNavigation() {
|
||||||
window.addEventListener('popstate', function (e) {
|
window.addEventListener('popstate', function (e) {
|
||||||
if (e.state && e.state.page) {
|
if (e.state && e.state.page) {
|
||||||
@@ -503,76 +706,89 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
history.replaceState({ page: currentPage }, null, window.location.pathname);
|
history.replaceState({ page: currentPage }, null, window.location.pathname);
|
||||||
|
console.log('Navigazione history configurata');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup modalità standalone (PWA)
|
||||||
|
*/
|
||||||
function setupStandaloneMode() {
|
function setupStandaloneMode() {
|
||||||
const appContainer = document.querySelector('.container');
|
const appContainer = document.querySelector('.container');
|
||||||
if (!appContainer) return;
|
if (!appContainer) return;
|
||||||
|
|
||||||
if (window.opener && !window.opener.closed) {
|
if (window.opener && !window.opener.closed) {
|
||||||
appContainer.classList.add('standalone-app');
|
appContainer.classList.add('standalone-app');
|
||||||
|
console.log('App in modalità finestra popup');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.navigator.standalone || window.matchMedia('(display-mode: standalone)').matches) {
|
if (window.navigator.standalone || window.matchMedia('(display-mode: standalone)').matches) {
|
||||||
appContainer.classList.add('standalone-app');
|
appContainer.classList.add('standalone-app');
|
||||||
|
console.log('App in modalità standalone (PWA)');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
/**
|
||||||
setupOpenAppButton();
|
* Inizializza la pagina corrente
|
||||||
|
*/
|
||||||
if (document.querySelector('.container')) {
|
|
||||||
setupStandaloneMode();
|
|
||||||
|
|
||||||
attachLinkListeners();
|
|
||||||
|
|
||||||
setupHistoryNavigation();
|
|
||||||
|
|
||||||
initializeCurrentPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function initializeCurrentPage() {
|
function initializeCurrentPage() {
|
||||||
console.log('Inizializzazione pagina corrente:', currentPage);
|
console.log('Inizializzazione pagina corrente:', currentPage);
|
||||||
|
|
||||||
updateActiveNavigation(currentPage);
|
updateActiveNavigation(currentPage);
|
||||||
|
|
||||||
if (currentPage.startsWith('play/')) {
|
if (currentPage.startsWith('play/')) {
|
||||||
setTimeout(function() {
|
setTimeout(() => initializePlayer(), 100);
|
||||||
initializePlayer();
|
|
||||||
}, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPage.startsWith('playtv/')) {
|
if (currentPage.startsWith('playtv/')) {
|
||||||
setTimeout(function() {
|
setTimeout(() => initializeTVPlayer(), 100);
|
||||||
initializeTVPlayer();
|
|
||||||
}, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPage === 'page/contact') {
|
if (currentPage === 'page/contact') {
|
||||||
setTimeout(function() {
|
setTimeout(() => initializeContactForm(), 100);
|
||||||
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();
|
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() {
|
function lockScreenOrientation() {
|
||||||
// Prova a bloccare l'orientamento con Screen Orientation API
|
// Screen Orientation API
|
||||||
if (screen.orientation && screen.orientation.lock) {
|
if (screen.orientation && screen.orientation.lock) {
|
||||||
screen.orientation.lock('portrait').then(() => {
|
screen.orientation.lock('portrait').then(() => {
|
||||||
console.log('Orientamento bloccato in portrait');
|
console.log('Orientamento bloccato in portrait');
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.log('Impossibile bloccare orientamento:', err.message);
|
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) {
|
if (screen.lockOrientation) {
|
||||||
screen.lockOrientation('portrait');
|
screen.lockOrientation('portrait');
|
||||||
} else if (screen.mozLockOrientation) {
|
} else if (screen.mozLockOrientation) {
|
||||||
@@ -582,9 +798,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() {
|
function tryLockOrientation() {
|
||||||
// Controlla se siamo in modalità standalone (PWA)
|
|
||||||
const isStandalone = window.navigator.standalone ||
|
const isStandalone = window.navigator.standalone ||
|
||||||
window.matchMedia('(display-mode: standalone)').matches;
|
window.matchMedia('(display-mode: standalone)').matches;
|
||||||
|
|
||||||
@@ -592,7 +819,6 @@ function tryLockOrientation() {
|
|||||||
lockScreenOrientation();
|
lockScreenOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prova anche quando entriamo in fullscreen
|
|
||||||
document.addEventListener('fullscreenchange', () => {
|
document.addEventListener('fullscreenchange', () => {
|
||||||
if (document.fullscreenElement) {
|
if (document.fullscreenElement) {
|
||||||
lockScreenOrientation();
|
lockScreenOrientation();
|
||||||
|
|||||||
BIN
js/app.js:Zone.Identifier
Normal file
BIN
js/app.js:Zone.Identifier
Normal file
Binary file not shown.
BIN
manifest.json:Zone.Identifier
Normal file
BIN
manifest.json:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<div id="proradio-secondary-header" class="proradio-secondaryhead proradio-primary" style="border-bottom: solid 3px #3849a8;">
|
<div id="proradio-secondary-header" class="proradio-secondaryhead proradio-primary" style="border-bottom: solid 3px #3849a8;">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -59,6 +61,7 @@
|
|||||||
<a href="https://www.radiocitta105.it" target="_blank"><span class="link">Radio Città 105</span></a>
|
<a href="https://www.radiocitta105.it" target="_blank"><span class="link">Radio Città 105</span></a>
|
||||||
<a href="https://www.radiodiffusionelibera.com" target="_blank"><span class="link">Radio DiffusioneLibera</span></a>
|
<a href="https://www.radiodiffusionelibera.com" target="_blank"><span class="link">Radio DiffusioneLibera</span></a>
|
||||||
<a href="https://www.co-municare.it" target="_blank"><span class="link">Co-Municare.it</span></a>
|
<a href="https://www.co-municare.it" target="_blank"><span class="link">Co-Municare.it</span></a>
|
||||||
|
<a href="https://www.ineboli.it" target="_blank"><span class="link">InEboli</span></a>
|
||||||
<a href="https://app.rpigroup.it" target="_blank"><span class="link active">RPIGroup Play</span></a>
|
<a href="https://app.rpigroup.it" target="_blank"><span class="link active">RPIGroup Play</span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
BIN
pages/desktop.php:Zone.Identifier
Normal file
BIN
pages/desktop.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
// Debug: verifica valori delle variabili (rimuovi dopo aver risolto)
|
||||||
|
// echo "<!-- DEBUG - Page: " . htmlspecialchars($page) . " | Param: " . htmlspecialchars($param) . " -->\n";
|
||||||
|
?>
|
||||||
|
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="logo-section">
|
<div class="logo-section">
|
||||||
<img src="<?=$base_path?>/img/RpiGroupPlayWHITE.png" alt="Logo">
|
<img src="<?=$base_path?>/img/RpiGroupPlayWHITE.png" alt="Logo">
|
||||||
@@ -94,5 +99,5 @@
|
|||||||
<a href="<?php echo $base_path; ?>/page/policy-privacy" data-page="page/policy-privacy" class="navLink">Policy Privacy</a> •
|
<a href="<?php echo $base_path; ?>/page/policy-privacy" data-page="page/policy-privacy" class="navLink">Policy Privacy</a> •
|
||||||
<a href="<?php echo $base_path; ?>/page/changelog" data-page="page/changelog" class="navLink">Changelog</a>
|
<a href="<?php echo $base_path; ?>/page/changelog" data-page="page/changelog" class="navLink">Changelog</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="copyright-section" <?php if($is_mobile){ ?> style="padding: 10px 0 25px;" <? } ?>>© 2025 RPIGroup • Versione: <?php echo $version_app; ?></div>
|
<div class="copyright-section" <?php if($is_mobile){ ?> style="padding: 10px 0 25px;" <?php } ?>>© 2025 RPIGroup • Versione: <?php echo $version_app; ?></div>
|
||||||
</div>
|
</div>
|
||||||
BIN
pages/mobile.php:Zone.Identifier
Normal file
BIN
pages/mobile.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<h1 class="titlePage">Pagina non trovata</h1>
|
<h1 class="titlePage">Pagina non trovata</h1>
|
||||||
|
|
||||||
<p class="text-center">La pagina che hai provato a cercare non esiste o non è disponibile.</p>
|
<p class="text-center">La pagina che hai provato a cercare non esiste o non è disponibile.</p>
|
||||||
|
|||||||
BIN
pages/page/404.php:Zone.Identifier
Normal file
BIN
pages/page/404.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<h1 class="titlePage">Come funziona RPIGroup Play?</h1>
|
<h1 class="titlePage">Come funziona RPIGroup Play?</h1>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|||||||
BIN
pages/page/about.php:Zone.Identifier
Normal file
BIN
pages/page/about.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<h1 class="titlePage">Aggiungi la tua radio</h1>
|
<h1 class="titlePage">Aggiungi la tua radio</h1>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|||||||
BIN
pages/page/addradio.php:Zone.Identifier
Normal file
BIN
pages/page/addradio.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,13 +1,31 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<h1 class="titlePage">Changelog</h1>
|
<h1 class="titlePage">Changelog</h1>
|
||||||
<p class="subtitlePage">Visualizza tutti gli ricevuti</p>
|
<p class="subtitlePage">Visualizza tutti gli aggiornamenti ricevuti</p>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
// Verifica che $changelog sia stato caricato correttamente in getStation.inc.php
|
||||||
|
if (isset($changelog) && $changelog !== false && isset($changelog->version)) {
|
||||||
|
// Itera attraverso le versioni
|
||||||
foreach($changelog->version as $version) {
|
foreach($changelog->version as $version) {
|
||||||
echo "<hr>";
|
echo "<hr>";
|
||||||
echo "<p class=\"changelogTitle\">Versione ".$version->number."</p>";
|
echo "<p class=\"changelogTitle\">Versione " . htmlspecialchars((string)$version->number) . "</p>";
|
||||||
|
|
||||||
|
// Verifica che esistano i log prima di iterare
|
||||||
|
if (isset($version->logs) && isset($version->logs->log)) {
|
||||||
foreach($version->logs->log as $log_print) {
|
foreach($version->logs->log as $log_print) {
|
||||||
echo "<p class=\"changelogList\">• ".$log_print."</p>";
|
echo "<p class=\"changelogList\">• " . htmlspecialchars((string)$log_print) . "</p>";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
echo "<p class=\"changelogList\" style=\"font-style: italic; color: #999;\">Nessun dettaglio disponibile per questa versione.</p>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Messaggio di errore se il changelog non è disponibile
|
||||||
|
echo "<hr>";
|
||||||
|
echo "<div style=\"padding: 20px; background: #fff3cd; border: 1px solid #ffc107; border-radius: 5px; margin: 20px 0;\">";
|
||||||
|
echo "<p style=\"margin: 0; color: #856404;\"><strong>Attenzione:</strong> Impossibile caricare il changelog. Il file potrebbe essere mancante o corrotto.</p>";
|
||||||
|
echo "</div>";
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|||||||
BIN
pages/page/changelog.php:Zone.Identifier
Normal file
BIN
pages/page/changelog.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<!-- <div class="content-page">
|
<!-- <div class="content-page">
|
||||||
<h2>Contatti</h2>
|
<h2>Contatti</h2>
|
||||||
<div class="content-box">
|
<div class="content-box">
|
||||||
|
|||||||
BIN
pages/page/contact.php:Zone.Identifier
Normal file
BIN
pages/page/contact.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<h1 class="titlePage">Diritti d'Autore</h1>
|
<h1 class="titlePage">Diritti d'Autore</h1>
|
||||||
<p class="subtitlePage">Come funziona e chi lo gestisce</p>
|
<p class="subtitlePage">Come funziona e chi lo gestisce</p>
|
||||||
|
|
||||||
|
|||||||
BIN
pages/page/copyright.php:Zone.Identifier
Normal file
BIN
pages/page/copyright.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<h1 class="titlePage">Benvenuto</h1>
|
<h1 class="titlePage">Benvenuto</h1>
|
||||||
<p class="subtitlePage">nella nuova RPIGroup Play</p>
|
<p class="subtitlePage">nella nuova RPIGroup Play</p>
|
||||||
|
|
||||||
|
|||||||
BIN
pages/page/home.php:Zone.Identifier
Normal file
BIN
pages/page/home.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/page/player.php:Zone.Identifier
Normal file
BIN
pages/page/player.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/page/player_tv.php:Zone.Identifier
Normal file
BIN
pages/page/player_tv.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<h1 class="titlePage">Policy Privacy</h1>
|
<h1 class="titlePage">Policy Privacy</h1>
|
||||||
<p class="subtitlePage">Ultimo aggiornamento: 17/11/2025</p>
|
<p class="subtitlePage">Ultimo aggiornamento: 17/11/2025</p>
|
||||||
|
|
||||||
|
|||||||
BIN
pages/page/policyprivacy.php:Zone.Identifier
Normal file
BIN
pages/page/policyprivacy.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
// views/home.php - Vista della pagina principale
|
// views/home.php - Vista della pagina principale
|
||||||
$stations = loadRadioStations();
|
$stations = loadRadioStations();
|
||||||
|
|||||||
BIN
pages/page/radio.php:Zone.Identifier
Normal file
BIN
pages/page/radio.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<h1 class="titlePage">Termini & Condizioni</h1>
|
<h1 class="titlePage">Termini & Condizioni</h1>
|
||||||
<p class="subtitlePage">Ultimo aggiornamento: 17/11/2025</p>
|
<p class="subtitlePage">Ultimo aggiornamento: 17/11/2025</p>
|
||||||
|
|
||||||
|
|||||||
BIN
pages/page/terminicondizioni.php:Zone.Identifier
Normal file
BIN
pages/page/terminicondizioni.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,3 +1,5 @@
|
|||||||
|
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
||||||
|
|
||||||
<h1 class="titlePage">TV</h1>
|
<h1 class="titlePage">TV</h1>
|
||||||
<p class="subtitlePage">Guarda in streaming <b>RC105 TV</b></p>
|
<p class="subtitlePage">Guarda in streaming <b>RC105 TV</b></p>
|
||||||
|
|
||||||
|
|||||||
BIN
pages/page/tv.php:Zone.Identifier
Normal file
BIN
pages/page/tv.php:Zone.Identifier
Normal file
Binary file not shown.
59
process_contact.php.old
Normal file
59
process_contact.php.old
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
// File: process_contact.php
|
||||||
|
|
||||||
|
// Imposta header per JSON
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
// Verifica se il modulo è stato inviato
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
// Raccolta e pulizia dei dati
|
||||||
|
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
|
||||||
|
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
|
||||||
|
$subject = filter_input(INPUT_POST, 'subject', FILTER_SANITIZE_STRING);
|
||||||
|
$message = filter_input(INPUT_POST, 'message', FILTER_SANITIZE_STRING);
|
||||||
|
|
||||||
|
// Validazione dei dati
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
if (empty($name)) {
|
||||||
|
$errors[] = "Il nome è richiesto";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$errors[] = "Email non valida";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($subject)) {
|
||||||
|
$errors[] = "L'oggetto è richiesto";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($message)) {
|
||||||
|
$errors[] = "Il messaggio è richiesto";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Se non ci sono errori, procedi con l'invio della mail
|
||||||
|
if (empty($errors)) {
|
||||||
|
// Destinatario
|
||||||
|
$to = "info@tuoaggregatore.it";
|
||||||
|
|
||||||
|
// Intestazioni
|
||||||
|
$headers = "From: $name <$email>" . "\r\n";
|
||||||
|
$headers .= "Reply-To: $email" . "\r\n";
|
||||||
|
$headers .= "X-Mailer: PHP/" . phpversion();
|
||||||
|
|
||||||
|
// Prova a inviare l'email
|
||||||
|
$success = mail($to, $subject, $message, $headers);
|
||||||
|
|
||||||
|
if ($success) {
|
||||||
|
echo json_encode(['success' => true, 'message' => 'Messaggio inviato con successo']);
|
||||||
|
} else {
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Impossibile inviare il messaggio']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Restituisci errori di validazione
|
||||||
|
echo json_encode(['success' => false, 'message' => implode(', ', $errors)]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Se qualcuno prova ad accedere direttamente a questa pagina
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Metodo non consentito']);
|
||||||
|
}
|
||||||
BIN
process_contact.php.old:Zone.Identifier
Normal file
BIN
process_contact.php.old:Zone.Identifier
Normal file
Binary file not shown.
2
readme.md
Normal file
2
readme.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# RPIGroup Play
|
||||||
|
Il player ufficiale del gruppo RPIGroup
|
||||||
BIN
readme.md:Zone.Identifier
Normal file
BIN
readme.md:Zone.Identifier
Normal file
Binary file not shown.
BIN
robots.txt:Zone.Identifier
Normal file
BIN
robots.txt:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,7 +1,4 @@
|
|||||||
|
|
||||||
<div style="display:none">
|
|
||||||
<p><a href="https://www.jennymcnieceflowers.com/">777slot</a></p>
|
|
||||||
</div>
|
|
||||||
<script src="<?php echo $base_path; ?>/js/app.js?v=<?=time()?>"></script>
|
<script src="<?php echo $base_path; ?>/js/app.js?v=<?=time()?>"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
BIN
static/footer.php:Zone.Identifier
Normal file
BIN
static/footer.php:Zone.Identifier
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user