Compare commits

..

34 Commits

Author SHA1 Message Date
b788f54c23 Merge branch 'main' of git.asv.ovh:asvstudiosapps/rpigroupplay 2026-02-14 07:23:58 +01:00
e0cbb2a8f1 inserito ADV WRD 2026-02-14 07:23:34 +01:00
110bc1a1c3 rimosso le versioni precedenti in parentesi 2026-02-10 21:45:19 +01:00
3872a61ad6 vers. 2.4.2 2026-02-10 21:37:59 +01:00
821c353638 corretta la visualizzazione della barra di navigazione dei player 2026-02-07 01:17:17 +01:00
573eeee5f5 corretto la visualizzazione del player 2026-02-07 01:14:12 +01:00
2cdd1cb29b vers. 2.4.1 2026-02-07 01:06:06 +01:00
5b3e05726b vers. 2.4.0 2026-02-07 00:31:18 +01:00
71af2b9407 corretta la visualizzazione della pagina about 2026-02-06 23:51:01 +01:00
a96edaa2b9 Inserito pulsante per i feedback 2026-02-06 23:25:50 +01:00
07864334d4 aggiunta la pagina "about" 2026-02-06 23:08:31 +01:00
ee44bfb7a4 rimosso l'alert per dispositivi ios 2026-02-06 22:19:59 +01:00
2b0b457166 vers. 2.3.0 2026-02-06 22:13:10 +01:00
ae5a4a8153 Inserito alert per iOS 26.2.1 2026-02-05 22:40:41 +01:00
02872cf616 ultima modifica al css 2026-02-04 01:12:28 +01:00
f7ddcda130 # 2026-02-04 01:10:20 +01:00
0982a45307 disattivati le animazioni sui pulsanti 2026-02-04 01:08:58 +01:00
b987bf9062 Update data/changelog.xml
update changelog
2026-02-04 01:02:31 +01:00
c3bac71ad2 Update css/style.css
correzione css
2026-02-04 01:02:11 +01:00
0d76cd4794 FIX: la navbar e il footer venivano oscurati dal loader 2026-02-04 00:57:11 +01:00
3619ababf2 FIX: correzione visualizzazione del caricamento 2026-02-04 00:52:23 +01:00
f562f5bfde vers. 2.2.0 2026-02-04 00:50:09 +01:00
91ebc5c883 vers. 2.1.4 2026-01-30 00:08:08 +01:00
ff9c5896f0 Fix player HLS v2 2026-01-28 23:21:18 +01:00
ea36956669 vers. 2.1.3 2026-01-28 23:14:52 +01:00
3c350b17ae aggiunto player hls v.2 2026-01-28 23:13:46 +01:00
008df364fe spero ultimo bugfix hls mobile 2026-01-28 23:08:43 +01:00
6f68bf123d secondo bugfix hls mobile 2026-01-28 23:03:48 +01:00
891feaed5d bugfix hls mobile 2026-01-28 22:59:59 +01:00
bb8d88f60a ver. 2.1.2 2026-01-28 22:45:13 +01:00
d7e098140c Aggiornamento index.php 2026-01-28 20:24:10 +01:00
4d9c7fd328 modifica gitignore 2026-01-28 19:40:11 +01:00
0b6a3ffea4 modifica Readme.md 2026-01-28 19:31:16 +01:00
52e40799d6 vers. 2.1.1 2026-01-28 19:05:44 +01:00
37 changed files with 14482 additions and 13358 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
*:Zone.Identifier
*Zone.Identifier
*.old
/api/*
.htaccess

View File

@@ -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';

View File

@@ -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";

View File

@@ -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);

View File

@@ -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");

View File

@@ -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; return null;
} }
if (!isset($xml->station)) {
error_log("Nessuna stazione trovata nel file XML");
return null;
}
foreach ($xml->station as $station) { foreach ($xml->station as $station) {
if ((int)$station->id === $id) { if ((int)$station->id === (int)$id) {
return $station; return $station;
} }
} }
error_log("Stazione radio non trovata con ID: $id");
return null; return null;
} }
// Funzione per caricare il file XML delle TV /**
* 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; return null;
} }
if (!isset($xml->station)) {
error_log("Nessuna stazione TV trovata nel file XML");
return null;
}
foreach ($xml->station as $station) { foreach ($xml->station as $station) {
if ((int)$station->id === $id) { if ((int)$station->id === (int)$id) {
return $station; return $station;
} }
} }
error_log("Stazione TV non trovata con ID: $id");
return null; return null;
} }
$changelog = simplexml_load_file("./data/changelog.xml") or die("Errore: Impossibile accedere al file CHANGELOG"); /**
$version_app = $changelog->version->number[0]; * 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");
}

View File

@@ -3,8 +3,76 @@
======================================== */ ======================================== */
/* ========================================
LOADING OVERLAY
======================================== */
/* Overlay di caricamento a schermo intero */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(16, 25, 75, 0.95);
backdrop-filter: blur(8px);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
/* Quando l'overlay è attivo */
.loading-overlay.active {
opacity: 1;
visibility: visible;
}
/* Contenuto dell'overlay */
.loading-content {
text-align: center;
color: white;
}
/* Spinner grande per il loading overlay */
.spinner-large {
width: 60px;
height: 60px;
border: 5px solid rgba(255, 255, 255, 0.2);
border-top-color: #f7b835;
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin: 0 auto 20px;
}
/* Testo di caricamento */
.loading-text {
font-size: 1.1rem;
font-weight: 500;
color: white;
margin: 0;
animation: pulse 1.5s ease-in-out infinite;
}
/* Animazione pulse per il testo */
@keyframes pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
/* Transizione per i link di navigazione */ /* Transizione per i link di navigazione */
.navLink, /* .navLink,
.nav-link, .nav-link,
.station-link, .station-link,
.linkBox { .linkBox {
@@ -13,7 +81,7 @@
} }
/* Effetto hover sui link */ /* Effetto hover sui link */
.navLink:hover, /* .navLink:hover,
.nav-link:hover, .nav-link:hover,
.station-link:hover, .station-link:hover,
.linkBox:hover { .linkBox:hover {
@@ -25,10 +93,13 @@
@keyframes pulseActive { @keyframes pulseActive {
0%, 100% {
0%,
100% {
opacity: 1; opacity: 1;
transform: translateX(-50%) scale(1); transform: translateX(-50%) scale(1);
} }
50% { 50% {
opacity: 0.6; opacity: 0.6;
transform: translateX(-50%) scale(1.2); transform: translateX(-50%) scale(1.2);
@@ -36,7 +107,7 @@
} }
/* Effetto click/tap */ /* Effetto click/tap */
.navLink:active, /* .navLink:active,
.nav-link:active, .nav-link:active,
.station-link:active, .station-link:active,
.linkBox:active { .linkBox:active {
@@ -45,7 +116,7 @@
} }
/* Transizione per le card delle stazioni */ /* Transizione per le card delle stazioni */
.station-card { /*.station-card {
transition: transform 0.3s ease, box-shadow 0.3s ease; transition: transform 0.3s ease, box-shadow 0.3s ease;
} }
@@ -55,7 +126,7 @@
} }
/* Transizione per i clickBox della home */ /* Transizione per i clickBox della home */
.clickBox { /* .clickBox {
transition: all 0.3s ease; transition: all 0.3s ease;
} }
@@ -100,7 +171,7 @@
} }
/* Transizione per elementi che appaiono */ /* Transizione per elementi che appaiono */
.content-page, /*.content-page,
.station-list, .station-list,
.player-container { .player-container {
animation: fadeInContent 0.5s ease-out; animation: fadeInContent 0.5s ease-out;
@@ -116,7 +187,7 @@
} }
/* Transizione per le immagini */ /* Transizione per le immagini */
.station-logo, /* .station-logo,
.station-logo-large { .station-logo-large {
transition: transform 0.3s ease, filter 0.3s ease; transition: transform 0.3s ease, filter 0.3s ease;
} }
@@ -128,7 +199,7 @@
} }
/* Transizione per i pulsanti */ /* Transizione per i pulsanti */
button, /* button,
.submit-btn, .submit-btn,
.play-pause-btn { .play-pause-btn {
transition: all 0.3s ease; transition: all 0.3s ease;
@@ -148,7 +219,7 @@ button:active,
} }
/* Transizione smooth per tutti gli elementi interattivi */ /* Transizione smooth per tutti gli elementi interattivi */
a, button, input, textarea, select { /* a, button, input, textarea, select {
transition: all 0.2s ease; transition: all 0.2s ease;
} }
@@ -156,7 +227,7 @@ a, button, input, textarea, select {
/* Non ci sono più after pseudo-elementi per le underline */ /* Non ci sono più after pseudo-elementi per le underline */
/* Transizione per il back-link */ /* Transizione per il back-link */
.back-link a { /* .back-link a {
transition: all 0.3s ease; transition: all 0.3s ease;
display: inline-block; display: inline-block;
} }
@@ -167,7 +238,7 @@ a, button, input, textarea, select {
} }
/* Animazione per le liste */ /* Animazione per le liste */
.stations-container { /* .stations-container {
display: grid; display: grid;
gap: 1rem; gap: 1rem;
} }
@@ -194,7 +265,7 @@ a, button, input, textarea, select {
} }
/* Transizione per i form */ /* Transizione per i form */
.form-group input, /* .form-group input,
.form-group textarea, .form-group textarea,
.form-group select { .form-group select {
transition: border-color 0.3s ease, box-shadow 0.3s ease; transition: border-color 0.3s ease, box-shadow 0.3s ease;
@@ -208,7 +279,7 @@ a, button, input, textarea, select {
} }
/* Animazione per i messaggi di risposta */ /* Animazione per i messaggi di risposta */
.form-response { /* .form-response {
animation: slideInDown 0.4s ease-out; animation: slideInDown 0.4s ease-out;
} }
@@ -224,7 +295,7 @@ a, button, input, textarea, select {
} }
/* Transizione per video e iframe */ /* Transizione per video e iframe */
video, /* video,
iframe { iframe {
transition: opacity 0.3s ease; transition: opacity 0.3s ease;
} }
@@ -235,17 +306,17 @@ iframe:hover {
} }
/* Performance optimization */ /* Performance optimization */
* { /** {
-webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent;
} }
/* Smooth scrolling */ /* Smooth scrolling */
html { /* html {
scroll-behavior: smooth; scroll-behavior: smooth;
} }
/* Riduzione movimento per chi ha impostato preferenze di accessibilità */ /* Riduzione movimento per chi ha impostato preferenze di accessibilità */
@media (prefers-reduced-motion: reduce) { /*@media (prefers-reduced-motion: reduce) {
*, *,
*::before, *::before,
*::after { *::after {

View File

@@ -112,7 +112,7 @@ div.dbox_mobile {
div.dbox_mobile { div.dbox_mobile {
width: 90%; width: 90%;
max-width: 450px; max-width: 750px;
color: white; color: white;
border-radius: 10px; border-radius: 10px;
max-height: 475px; max-height: 475px;
@@ -163,7 +163,7 @@ div.dfooter {
.appBody { .appBody {
background-color: #10194b; background-color: #10194b;
max-width: 450px; max-width: 750px;
min-width: 330px; min-width: 330px;
margin: auto; margin: auto;
display: flex; display: flex;
@@ -258,7 +258,7 @@ main {
.tec, .tec,
.stationList { .stationList {
padding: 0 13px; padding: 0 13px;
margin: 0 0 7px; margin: 0 0 10px;
text-align: justify; text-align: justify;
hyphens: auto; hyphens: auto;
} }
@@ -289,12 +289,12 @@ main {
margin: 0; margin: 0;
} */ } */
.stationCard.isthematic{ .stationCard.isthematic {
text-align: right; text-align: right;
margin-top: -24px; margin-top: -24px;
} }
.stationCard.isthematic:before{ .stationCard.isthematic:before {
content: "Tematica"; content: "Tematica";
position: relative; position: relative;
background: #f7b835; background: #f7b835;
@@ -308,42 +308,38 @@ main {
margin: 0; margin: 0;
} }
iframe.contentplayer{ iframe.contentplayer {
position: absolute; height: calc(100vh - 393px);
left: 50%;
height: calc(100vh - 312px);
width: 100%; width: 100%;
max-width: 450px; max-width: 750px;
transform: translateX(-50%);
} }
.footer_player{ .footer_player {
background: #f7b835; background: #f7b835;
color: #2a377d; color: #2a377d;
position: fixed;
z-index: 90; z-index: 90;
bottom: 70px;
left: 50%;
transform: translateX(-50%);
width: 100%; width: 100%;
max-width: 450px; max-width: 750px;
height: 100px; height: 100px;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
padding: 20px; padding: 20px;
border-top: 1px solid #eee;
flex: 1;
align-content: end;
} }
.footer_player > .row > .col-2 > img{ .footer_player>.row>.col-2>img {
border-radius: 5px; border-radius: 5px;
} }
button#playPauseBtn{ button#playPauseBtn,
button#formatToggleBtn {
background: none; background: none;
border: none; border: none;
} }
.footer{ .footer,
z-index: 1; .header {
z-index: 10000;
} }
.footer>.menu-section { .footer>.menu-section {
@@ -398,3 +394,28 @@ button#playPauseBtn{
} }
/* Forza orientamento portrait - nasconde contenuto in landscape */
@media screen and (orientation: landscape) and (max-height: 450px) {
body.appBody::after {
content: "Ruota il dispositivo in verticale";
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #2a377e;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
font-weight: 600;
z-index: 9999;
text-align: center;
padding: 20px;
}
body.appBody>* {
display: none !important;
}
}

View File

@@ -1,6 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<changelog> <changelog>
<version>
<number>2.4.2</number>
<logs>
<log>Aggiornata la grandezza della finestra dell'applicazione da desktop.</log>
<log>Inserito il link della repository su ASV Git all'interno della pagina del changelog.</log>
<log>Correzione e bugfix di problematiche varie.</log>
</logs>
</version>
<version>
<number>2.4.1</number>
<logs>
<log>Aggiornata la pagiana del player audio, per renderla più coerente con le altre pagine dell'applicazione.</log>
<log>Aggiunta la visualizzazione dell'artista e del brano in riproduzione.</log>
<log>Correzione e bugfix di problematiche varie.</log>
</logs>
</version>
<version>
<number>2.4.0</number>
<logs>
<log>Implementato il player video dedicato per la riproduzione dei canali visivi.</log>
<log>Correzione e bugfix di problematiche varie.</log>
</logs>
</version>
<version>
<number>2.3.0</number>
<logs>
<log>Ottimizzata la risoluzione dell'applicazione su dispositivi larghi (tablet, iPad e computer).</log>
<log>Implementato lo switch tra il player audio in HLS e il player audio in MP3/AAC.</log>
<log>Rimosso l'avviso per i dispositivi iOS.</log>
<log>Correzione e bugfix di problematiche varie.</log>
</logs>
</version>
<version>
<number>2.2.0</number>
<logs>
<log>E' stato reintrodotto la schermata di caricamento ad ogni selezione di ogni pagina dell'applicazione.</log>
<log>Correzione e bugfix di problematiche varie.</log>
</logs>
</version>
<version>
<number>2.1.4</number>
<logs>
<log>Corretto la visione verticale sui dispositivi mobili.</log>
<log>Correzione e bugfix di problematiche varie.</log>
</logs>
</version>
<version>
<number>2.1.3</number>
<logs>
<log>Implementato il nuovo player audio per la riproduzione dei flussi audio in HLS per il bitrate adattivo.</log>
<log>Correzione e bugfix di problematiche varie.</log>
</logs>
</version>
<version>
<number>2.1.2</number>
<logs>
<log>Implementazione del sistema di qualità adattiva (ABR) per il player audio.</log>
<log>Correzione e bugfix di problematiche varie.</log>
</logs>
</version>
<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>
@@ -13,8 +97,8 @@
<version> <version>
<number>2.0.3</number> <number>2.0.3</number>
<logs> <logs>
<log>Corretta la visualizzazione dei contenuti forniti dalle emittenti all'interno del player</log> <log>Corretta la visualizzazione dei contenuti forniti dalle emittenti all'interno del player.</log>
<log>Corretta la visualizzazione del player audio</log> <log>Corretta la visualizzazione del player audio.</log>
<log>Correzione e bugfix di problematiche varie.</log> <log>Correzione e bugfix di problematiche varie.</log>
</logs> </logs>
</version> </version>
@@ -22,7 +106,7 @@
<version> <version>
<number>2.0.2</number> <number>2.0.2</number>
<logs> <logs>
<log>Inserita la pagina statica per le emittenti tematiche</log> <log>Inserita la pagina statica per le emittenti tematiche.</log>
<log>Correzione e bugfix di problematiche varie.</log> <log>Correzione e bugfix di problematiche varie.</log>
</logs> </logs>
</version> </version>
@@ -30,7 +114,7 @@
<version> <version>
<number>2.0.1</number> <number>2.0.1</number>
<logs> <logs>
<log>Aggiunta la Visual Radio dell'emittente "Radio Città 105</log> <log>Aggiunta la Visual Radio dell'emittente "Radio Città 105".</log>
<log>Correzione e bugfix di problematiche varie.</log> <log>Correzione e bugfix di problematiche varie.</log>
</logs> </logs>
</version> </version>
@@ -38,7 +122,7 @@
<version> <version>
<number>2.0.0</number> <number>2.0.0</number>
<logs> <logs>
<log>Nuova UI/UX: RPIGroup aggiorna la veste grafica della sua applicazione, rendendola più "fumettosa" e "giocattolosa". Un'estetica completamente diversa da tutte le altre varie app radiofoniche</log> <log>Nuova UI/UX: RPIGroup aggiorna la veste grafica della sua applicazione, rendendola più "fumettosa" e "giocattolosa". Un'estetica completamente diversa da tutte le altre varie app radiofoniche.</log>
<log>Nuova Engine: Nuovo motore e struttura dell'applicazione. Lato backend è cambiato completamente rispetto alla versione 1.</log> <log>Nuova Engine: Nuovo motore e struttura dell'applicazione. Lato backend è cambiato completamente rispetto alla versione 1.</log>
<log>Nuovo Player Audio/Video: Player più semplice, ma conserva le caratteristiche della precedente versione.</log> <log>Nuovo Player Audio/Video: Player più semplice, ma conserva le caratteristiche della precedente versione.</log>
<log>Termini e Condizioni: inserimento per obblighi di legge dei corrispettivi "Termini e Condizioni"</log> <log>Termini e Condizioni: inserimento per obblighi di legge dei corrispettivi "Termini e Condizioni"</log>
@@ -59,7 +143,7 @@
<version> <version>
<number>1.2.0 Stable</number> <number>1.2.0 Stable</number>
<logs> <logs>
<log>Implementato il "Media Sessions" che permette di visualizzare la radio in riproduzione nel centro notifiche su iOS e Android</log> <log>Implementato il "Media Sessions" che permette di visualizzare la radio in riproduzione nel centro notifiche su iOS e Android.</log>
<log>Preparazione dell'ottimizzazione del software in occasione della terza versione dell'app.</log> <log>Preparazione dell'ottimizzazione del software in occasione della terza versione dell'app.</log>
<log>Correzione e bugfix di problematiche varie.</log> <log>Correzione e bugfix di problematiche varie.</log>
</logs> </logs>
@@ -77,9 +161,9 @@
<version> <version>
<number>1.1.0 Stable</number> <number>1.1.0 Stable</number>
<logs> <logs>
<log>Aggiunta la nuova stazione radio tematica "RDL Revival 70-80-90"</log> <log>Aggiunta la nuova stazione radio tematica "RDL Revival 70-80-90".</log>
<log>Migliorata la visualizzazione del selettore radio della pagina home</log> <log>Migliorata la visualizzazione del selettore radio della pagina home.</log>
<log>Implementato nel player la visualizzazione della pagina statica per le radio tematiche</log> <log>Implementato nel player la visualizzazione della pagina statica per le radio tematiche.</log>
<log>Correzione e bugfix di problematiche varie causate dall'ultima versione "Beta".</log> <log>Correzione e bugfix di problematiche varie causate dall'ultima versione "Beta".</log>
</logs> </logs>
</version> </version>
@@ -87,10 +171,10 @@
<version> <version>
<number>1.0.0 Stable</number> <number>1.0.0 Stable</number>
<logs> <logs>
<log>Passaggio alla versione "Stable" dell'applicazione</log> <log>Passaggio alla versione "Stable" dell'applicazione.</log>
<log>Verifica di ulteriori correzioni dal passaggio della versione stabile</log> <log>Verifica di ulteriori correzioni dal passaggio della versione stabile.</log>
<log>Leggerimento dell'applicazione a livello backend</log> <log>Leggerimento dell'applicazione a livello backend.</log>
<log>Ulteriori analisi di stabilità dal momento del passaggio alla versione stabile</log> <log>Ulteriori analisi di stabilità dal momento del passaggio alla versione stabile.</log>
<log>Correzione e bugfix di problematiche varie causate dall'ultima versione "Beta".</log> <log>Correzione e bugfix di problematiche varie causate dall'ultima versione "Beta".</log>
</logs> </logs>
</version> </version>
@@ -127,7 +211,7 @@
<version> <version>
<number>0.23.1 Beta</number> <number>0.23.1 Beta</number>
<logs> <logs>
<log>Rimozione del logo al caricamento di ogni singola pagina (tranne all'avvio dell'app)</log> <log>Rimozione del logo al caricamento di ogni singola pagina (tranne all'avvio dell'app).</log>
<log>Correzione e bugfix di problematiche varie.</log> <log>Correzione e bugfix di problematiche varie.</log>
</logs> </logs>
</version> </version>
@@ -135,8 +219,8 @@
<version> <version>
<number>0.23.0 Beta</number> <number>0.23.0 Beta</number>
<logs> <logs>
<log>Rilasciato il nuovo player video</log> <log>Rilasciato il nuovo player video.</log>
<log>Inserimento dell'emittente RC105TV nella lista delle WebTV</log> <log>Inserimento dell'emittente RC105TV nella lista delle WebTV.</log>
<log>Correzione e bugfix di problematiche varie.</log> <log>Correzione e bugfix di problematiche varie.</log>
</logs> </logs>
</version> </version>
@@ -144,9 +228,9 @@
<version> <version>
<number>0.22.4 Beta</number> <number>0.22.4 Beta</number>
<logs> <logs>
<log>Correzione errori minimi nel sistema</log> <log>Correzione errori minimi nel sistema.</log>
<log>Aggiunta indicatore della versione app nella schermata desktop</log> <log>Aggiunta indicatore della versione app nella schermata desktop.</log>
<log>Preparazione player video - Correzioni minimi player e aggiunta di pagine mancanti</log> <log>Preparazione player video - Correzioni minimi player e aggiunta di pagine mancanti.</log>
<log>Correzione e bugfix di problematiche varie.</log> <log>Correzione e bugfix di problematiche varie.</log>
</logs> </logs>
</version> </version>
@@ -154,8 +238,8 @@
<version> <version>
<number>0.22.3 Beta</number> <number>0.22.3 Beta</number>
<logs> <logs>
<log>Migliorati i tempi di caricamento dei player</log> <log>Migliorati i tempi di caricamento dei player.</log>
<log>Aggiunta nuovi file di Configurazione</log> <log>Aggiunta nuovi file di Configurazione.</log>
<log>Correzione e bugfix di problematiche varie.</log> <log>Correzione e bugfix di problematiche varie.</log>
</logs> </logs>
</version> </version>
@@ -173,8 +257,8 @@
<version> <version>
<number>0.22.1 Beta</number> <number>0.22.1 Beta</number>
<logs> <logs>
<log>Corretto il bug del logo all'interno dell'homepage</log> <log>Corretto il bug del logo all'interno dell'homepage.</log>
<log>Corretto la riproduzione audio dell'emittente Radio Città 105</log> <log>Corretto la riproduzione audio dell'emittente Radio Città 105.</log>
<log>Correzione e bugfix di problematiche varie.</log> <log>Correzione e bugfix di problematiche varie.</log>
</logs> </logs>
</version> </version>

View File

@@ -8,9 +8,10 @@
<slogan>O Sei Fuori, O Sei Dei Nostri</slogan> <slogan>O Sei Fuori, O Sei Dei Nostri</slogan>
<thematic>false</thematic> <thematic>false</thematic>
<logo>https://i0.wp.com/www.radiodiffusionelibera.com/wp-content/uploads/2017/01/RDL-Facebook.png</logo> <logo>https://i0.wp.com/www.radiodiffusionelibera.com/wp-content/uploads/2017/01/RDL-Facebook.png</logo>
<stream>https://asvradiostream.asvstudios.it/radio/8000/radio.mp3</stream> <stream>https://asvradiostream.asvstudios.it/radio/8000/radio.aac</stream>
<streamhls>https://srvone.radio.asvhosting.com/hls/rdlradio/live.m3u8</streamhls> <streamhls>https://srvone.radio.asvhosting.com/hls/rdlradio/live.m3u8</streamhls>
<contentplayer>https://www.radiodiffusionelibera.com/contentrpigplay</contentplayer> <contentplayer>https://www.radiodiffusionelibera.com/contentrpigplay</contentplayer>
<apiradio>https://srvone.radio.asvhosting.com/api/nowplaying/2</apiradio>
</station> </station>
<station> <station>
@@ -22,9 +23,10 @@
<stream>https://asvradiostream.asvstudios.it/radio/8020/auto.aac</stream> <stream>https://asvradiostream.asvstudios.it/radio/8020/auto.aac</stream>
<streamhls>https://srvone.radio.asvhosting.com/hls/radiocitta105/live.m3u8</streamhls> <streamhls>https://srvone.radio.asvhosting.com/hls/radiocitta105/live.m3u8</streamhls>
<contentplayer>https://www.radiocitta105.it/contentrpigplay</contentplayer> <contentplayer>https://www.radiocitta105.it/contentrpigplay</contentplayer>
<apiradio>https://srvone.radio.asvhosting.com/api/nowplaying/1</apiradio>
</station> </station>
<station> <!-- <station>
<id>3</id> <id>3</id>
<name>RadioAI</name> <name>RadioAI</name>
<slogan>Solo musica AI - Powered by RDL </slogan> <slogan>Solo musica AI - Powered by RDL </slogan>
@@ -33,9 +35,9 @@
<stream>https://srvone.radio.asvhosting.com/listen/radioai/radio.mp3</stream> <stream>https://srvone.radio.asvhosting.com/listen/radioai/radio.mp3</stream>
<streamhls>https://srvone.radio.asvhosting.com/hls/radioai/live.m3u8</streamhls> <streamhls>https://srvone.radio.asvhosting.com/hls/radioai/live.m3u8</streamhls>
<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,9 +46,9 @@
<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>
<name>Radio People Italy</name> <name>Radio People Italy</name>
<slogan>La radio della Gente</slogan> <slogan>La radio della Gente</slogan>
@@ -55,6 +57,6 @@
<stream></stream> <stream></stream>
<streamhls></streamhls> <streamhls></streamhls>
<contentplayer>https://www.rpigroup.it/radiopeopleitaly_contentrpigroup/</contentplayer> <contentplayer>https://www.rpigroup.it/radiopeopleitaly_contentrpigroup/</contentplayer>
</station> </station> -->
</radio> </radio>

View File

@@ -14,8 +14,8 @@
<id>1</id> <id>1</id>
<name>Rc105 TV</name> <name>Rc105 TV</name>
<logo>https://www.radiocitta105.it/wp-content/uploads/2020/06/26168468_1590103344416186_7025872599153073152_n-1.png</logo> <logo>https://www.radiocitta105.it/wp-content/uploads/2020/06/26168468_1590103344416186_7025872599153073152_n-1.png</logo>
<stream>https://webtv.rpigroup.it/e1e55a4b-abec-4043-8f08-e2105b48b59b.m3u8</stream> <stream>https://tv.rpigroup.net/memfs/a9699134-efb3-4932-b8db-5a49ae214031.m3u8</stream>
<poster>https://webtv.rpigroup.it/memfs/e1e55a4b-abec-4043-8f08-e2105b48b59b.jpg</poster> <poster>https://tv.rpigroup.net/memfs/a9699134-efb3-4932-b8db-5a49ae214031.jpg</poster>
</station> </station>
</tv> </tv>

View File

@@ -5,12 +5,17 @@
# --------------------------------------------------------------- # ---------------------------------------------------------------
# Author: A.S.V. Studios APPS # Author: A.S.V. Studios APPS
# Website: https://app.rpigroup.net # Website: https://app.rpigroup.net
# Copyright (c) 2025-202 A.S.V. Studios APPS
# ---------------------------------------------------------------
# Questa app è disponibile all'interno della repository pubblica di RPIGroup Play.
# --------------------------------------------------------------- # ---------------------------------------------------------------
# All Rights is reserved by A.S.V. Studios APPS. # All Rights is reserved by A.S.V. Studios APPS.
# #
# 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';

990
js/app.js

File diff suppressed because it is too large Load Diff

7
js/bootstrap.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -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>

View File

@@ -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">
@@ -10,7 +15,7 @@
</div> </div>
</div> </div>
<main class="container" id="content"> <main class="container-fluid" id="content">
<?php <?php
// Carica il contenuto iniziale in base all'URL // Carica il contenuto iniziale in base all'URL
switch ($page) { switch ($page) {
@@ -88,11 +93,19 @@
?> ?>
</main> </main>
<!-- Loading Overlay -->
<div id="loadingOverlay" class="loading-overlay">
<div class="loading-content">
<div class="spinner-large"></div>
<p class="loading-text">Caricamento...</p>
</div>
</div>
<div class="footer"> <div class="footer">
<div class="menu-section"> <div class="menu-section">
<a href="<?php echo $base_path; ?>/page/termini-condizioni" data-page="page/termini-condizioni" class="navLink">Termini e Condizioni</a> • <a href="<?php echo $base_path; ?>/page/termini-condizioni" data-page="page/termini-condizioni" class="navLink">Termini e Condizioni</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/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;" <? } ?>>&copy; 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>

View File

@@ -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>

View File

@@ -1,9 +1,33 @@
<?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>
<div class="tec"> <div class="tec">
<p>La pagina è in fase di realizzazione... Attendi il prossimo aggiornamento per leggere le nostre istruzioni d'uso!</p> <p>RPIGroup Play è l'applicazione che permette di ascoltare le radio e le webtv preferite in un unico luogo.</p>
<p>Per utilizzare l'applicazione, basta semplicemente entrare nell'applicazione dal link app.rpigroup.it, selezionare la sezione Radio o TV e scegliere la radio o la webtv che desideri ascoltare.</p>
<br>
<p>
<b>Come installare l'app?</b></br>
Per installare l'applicazione, basta semplicemente entrare nell'applicazione dal link app.rpigroup.it e cliccare sull'icona "Aggiungi all'Home". Oppure, per gli utenti iOS, entrando da safari dal link app.rpigroup.it, cliccare sull'icona "Convididi", scendere alla voce "Aggiungi all'Home" e cliccare su "Aggiungi all'Home".
</p>
<br>
<br><br>
<h2 class="text-center titlePage">F.A.Q.</h2>
<hr>
<p>
<b>Posso scaricarla da Google Play Store e Apple App Store?</b></br>
Non è possibile al momento scaricare l'applicazione da Google Play Store e Apple App Store.
</p>
<p>
<b>Posso utilizzare l'applicazione su un computer?</b></br>
Sì, dal tuo browser preferito, visita la pagina app.rpigroup.it. L'applicazione è anche installabile, cliccando sulla icona dedicata all'installazione della PWA.
</p>
<p>
<b>Posso aggiungere la mia stazione radio preferita?</b></br>
Sì, cliccando sul pulsante "Aggiungi Radio" nella sezione Radio, potrai aggiungere la tua stazione radio preferita compilando il form dedicato.
</p>
</div> </div>
<a href="<?php echo $base_path; ?>/home" data-page="home" class="linkBox mt-3"> <a href="<?php echo $base_path; ?>/home" data-page="home" class="linkBox mt-3">

View File

@@ -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>

View File

@@ -1,13 +1,32 @@
<?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>
<p class="text-center mb-4" style="font-size: 0.9rem; font-weight: 300;">Codice dell'app visionabile su <a href="https://git.asv.ovh/asvstudiosapps/rpigroupplay" target="_blank" style="font-weight: 500;">ASV Git</a></p>
<?php <?php
foreach($changelog->version as $version){ // Verifica che $changelog sia stato caricato correttamente in getStation.inc.php
echo "<hr>"; if (isset($changelog) && $changelog !== false && isset($changelog->version)) {
echo "<p class=\"changelogTitle\">Versione ".$version->number."</p>"; // Itera attraverso le versioni
foreach($version->logs->log as $log_print){ foreach($changelog->version as $version) {
echo "<p class=\"changelogList\">• ".$log_print."</p>"; echo "<hr>";
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) {
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>";
} }
?> ?>

View File

@@ -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">

View File

@@ -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>

View File

@@ -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>
@@ -20,6 +22,38 @@
</div> </div>
</div> </div>
<style>
.content-adv{
text-align: center;
background: #3849a8;
padding: 20px;
border-radius: 20px;
}
.content-adv:before{
content: "ADV";
position: relative;
background: #f7b835;
padding: 3px 10px;
font-size: 0.8rem;
border-radius: 27px;
font-style: italic;
font-weight: 600;
top: -10px;
margin: 0;
}
.content-adv img{
max-width: 100%;
border-radius: 10px;
margin-top: -20px;
}
</style>
<div class="content-adv mb-4">
<a href="https://www.worldradioday.it" target="_blank" class="">
<img src="https://www.radiodiffusionelibera.com/wp-content/uploads/2026/01/banner300x250.jpg" alt="adv">
</a>
</div>
<div class="row g-2 mb-4"> <div class="row g-2 mb-4">
<div class="col-12"> <div class="col-12">
<a href="https://www.co-municare.it" target="_blank" class=""> <a href="https://www.co-municare.it" target="_blank" class="">
@@ -38,7 +72,7 @@
<div class="col-4"> <div class="col-4">
<a href="<?php echo $base_path; ?>/page/about" data-page="page/about" class="linkBox"> <a href="<?php echo $base_path; ?>/page/about" data-page="page/about" class="linkBox">
<div class="clickBox"> <div class="clickBox">
Come funziona? Come<br>funziona?
</div> </div>
</a> </a>
</div> </div>
@@ -57,3 +91,13 @@
</a> </a>
</div> </div>
</div> </div>
<div class="row g-2 mb-4">
<div class="col-12">
<a href="https://drive.asv.ovh/apps/forms/s/Zfk8cJk3oCz2Y2dHyWdEcgL7" target="_blank" class="linkBox">
<div class="clickBox p-2">
Lascia un feedback
</div>
</a>
</div>
</div>

View File

@@ -1,62 +1,102 @@
<?php <?php
if($station->contentplayer == ""){
?> $station_id = (string)$station->id;
<style> $station_name = (string)$station->name;
.staticpage{ $station_slogan = (string)$station->slogan;
background: linear-gradient(45deg, #3849a8, #f7b835); $station_logo = (string)$station->logo;
padding: 22px 35px 10px 35px; $station_stream = (string)$station->stream;
display: block; $station_streamhls = (string)$station->streamhls;
z-index: 1; $station_contentplayer = (string)$station->contentplayer;
position: absolute; $station_apiradio = (string)$station->apiradio;
height: calc(100vh - 312px);
color: white;
text-align: center;
width: 100%;
max-width: 450px;
left: 50%;
transform: translateX(-50%);
}
.staticpage > .logo{
width: 200px;
border-radius: 15px;
margin-bottom: 20px;
}
.staticpage > p{
margin: 0;
}
.staticpage > p.titleRadio{
font-weight: 600;
}
</style>
<div class="staticpage">
<img src="<?php echo $station->logo; ?>" class="logo" alt="logo radio">
<p class="titleRadio"><?php echo $station->name; ?></p>
<p class="subtitleRadio"><?php echo $station->slogan; ?></p>
</div>
<?php
}else{
?>
<iframe src="<?php echo $station->contentplayer; ?>" class="contentplayer" frameborder="0"></iframe>
<?php
}
?> ?>
<div class="footer_player" <?php if($is_mobile){ ?> style="bottom: 84px;" <? } ?>> <div class="radio-player-container" style="background-color: #ffffff;height: calc(100% - <?php if($is_mobile){ echo "232px"; }else{ echo "217px"; } ?>);position: absolute;left: calc(50%);display: flex;flex-direction: column;max-width: 750px;transform: translateX(-50%);width: 100%;">
<div class="row align-items-center">
<div class="col-2" style="width: 70px;"> <div class="radio-header" style="padding: 20px; border-bottom: 1px solid #eee; display: flex; align-items: center; justify-content: space-between;">
<img src="<?php echo $station->logo; ?>" alt="<?php echo $station->name; ?>" style="width: 60px;"> <div class="left-controls" style="display: flex; align-items: center;">
<a href="<?php echo $base_path; ?>/radio" data-page="radio" class="linkBox" style="color: #333; display: flex; align-items: center; text-decoration: none;">
<span class="material-icons" style="font-size: 28px;">arrow_back</span>
</a>
<span style="font-size: 18px; font-weight: 600; color: #333; margin-left: 15px;"><?php echo $station_name; ?></span>
</div> </div>
<div class="col">
<div id="artist" style="font-weight: 700; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;"><?php echo $station->name; ?></div> <?php if(!empty($station_logo)): ?>
<div id="playerStatus" style="text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical ;overflow: hidden;"><?php echo $station->slogan; ?></div> <div class="right-controls">
<img src="<?php echo $station_logo; ?>" alt="Logo" style="height: 30px; width: auto;">
</div> </div>
<div class="col-2" style="text-align: center; margin-top: 1px; margin-right: 5px; width: 67px;"> <?php endif; ?>
<button id="playPauseBtn" data-stream-hls="<?php echo $station->streamhls; ?>" data-stream-fallback="<?php echo $station->stream; ?>" data-station-name="<?php echo htmlspecialchars($station->name); ?>" data-station-logo="<?php echo $station->logo; ?>" data-station-slogan="<?php echo htmlspecialchars($station->slogan); ?>"> </div>
<i class="material-icons play-icon" id="play-pause" style="font-size: 35px; border-radius: 10px; border: 2px solid #ffffff; padding: 4px 5px 4px 4px; margin-top: -2px; background: #f7b835; color: #2a377e;">play_arrow</i>
<i class="material-icons pause-icon" id="play-pause" style="display:none; font-size: 35px; border-radius: 10px; border: 2px solid #ffffff; padding: 4px 5px 4px 4px; margin-top: -2px; background: #f7b835; color: #2a377e;">pause</i> <?php
</button> if($station->contentplayer == ""){
?>
<style>
.staticpage{
background: linear-gradient(45deg, #3849a8, #f7b835);
padding: 22px 35px 10px 35px;
display: block;
z-index: 1;
height: calc(100vh - 393px);
color: white;
text-align: center;
width: 100%;
max-width: 750px;
}
.staticpage > .logo{
width: 200px;
border-radius: 15px;
margin-bottom: 20px;
}
.staticpage > p{
margin: 0;
}
.staticpage > p.titleRadio{
font-weight: 600;
}
</style>
<div class="staticpage">
<img src="<?php echo $station->logo; ?>" class="logo" alt="logo radio">
<p class="titleRadio"><?php echo $station->name; ?></p>
<p class="subtitleRadio"><?php echo $station->slogan; ?></p>
</div>
<?php
}else{
?>
<iframe src="<?=$station_contentplayer?>" class="contentplayer" frameborder="0"></iframe>
<?php
}
?>
<div class="footer_player">
<div class="row align-items-center">
<div class="col-2" style="width: 70px;">
<img id="albumsong" src="<?php echo $station->logo; ?>" alt="<?php echo $station->name; ?>" style="width: 60px;height: 60px;">
</div>
<div class="col">
<div id="songs" style="font-weight: 700; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;"><?php echo $station->name; ?></div>
<div id="artist" style="text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical ;overflow: hidden;"><?php echo $station->slogan; ?></div>
</div>
<div class="col-auto" style="text-align: center; margin-top: 1px; padding-right: 0;">
<button id="formatToggleBtn" title="Cambia formato audio">
<span id="formatLabel" style="font-size: 12px;font-weight: 600;border-radius: 6px;border: 2px solid #ffffff;padding: 4px 6px;background: rgba(247, 184, 53, 0.3);color: #2a377e;">HLS</span>
</button>
</div>
<div class="col-2" style="text-align: center; margin-top: 1px; margin-right: 5px; width: 67px;">
<button id="playPauseBtn"
data-stream-hls="<?php echo $station->streamhls; ?>"
data-stream-fallback="<?php echo $station->stream; ?>"
data-station-name="<?php echo htmlspecialchars($station->name); ?>"
data-station-logo="<?php echo $station->logo; ?>"
data-station-slogan="<?php echo htmlspecialchars($station->slogan); ?>"
data-api-url="<?php echo $station_apiradio; ?>">
<i class="material-icons play-icon" id="play-pause" style="font-size: 35px; border-radius: 10px; border: 2px solid #ffffff; padding: 4px 5px 4px 4px; margin-top: -2px; background: #f7b835; color: #2a377e;">play_arrow</i>
<i class="material-icons pause-icon" id="play-pause" style="display:none; font-size: 35px; border-radius: 10px; border: 2px solid #ffffff; padding: 4px 5px 4px 4px; margin-top: -2px; background: #f7b835; color: #2a377e;">pause</i>
</button>
</div>
</div> </div>
</div> </div>
</div> </div>
<audio id="hlsAudioPlayer" preload="none"></audio> <audio id="hlsAudioPlayer" preload="none"></audio>

View File

@@ -0,0 +1,50 @@
<?php
// Assicurati che $station sia definito (dovrebbe essere passato da mobile.php)
if (!isset($station) || empty($station)) {
echo '<div class="alert alert-danger">Errore: Stazione TV non trovata.</div>';
return;
}
$station_id = (string)$station->id;
$station_name = (string)$station->name;
$station_logo = (string)$station->logo;
$station_stream = (string)$station->stream;
$station_poster = isset($station->poster) ? (string)$station->poster : '';
?>
<!-- Container player con sfondo bianco -->
<div class="tv-player-container" style="background-color: #ffffff;height: calc(100% - <?php if($is_mobile){ echo "232px"; }else{ echo "217px"; } ?>);position: absolute;left: calc(50%);display: flex;flex-direction: column;max-width: 750px;transform: translateX(-50%);width: 100%;">
<!-- Header semplice con pulsante indietro e nome -->
<div class="tv-header" style="padding: 20px; border-bottom: 1px solid #eee; display: flex; align-items: center; justify-content: space-between;">
<div class="left-controls" style="display: flex; align-items: center;">
<a href="<?php echo $base_path; ?>/tv" data-page="tv" class="linkBox" style="color: #333; display: flex; align-items: center; text-decoration: none;">
<span class="material-icons" style="font-size: 28px;">arrow_back</span>
</a>
<span style="font-size: 18px; font-weight: 600; color: #333; margin-left: 15px;"><?php echo $station_name; ?></span>
</div>
<?php if(!empty($station_logo)): ?>
<div class="right-controls">
<img src="<?php echo $station_logo; ?>" alt="Logo" style="height: 30px; width: auto;">
</div>
<?php endif; ?>
</div>
<!-- Area Video -->
<div class="video-wrapper" style="flex: 1; display: flex; align-items: center; justify-content: center; background-color: #000;">
<video id="tvVideoPlayer"
class="video-js"
controls
playsinline
data-src="<?php echo $station_stream; ?>"
poster="<?php echo $station_poster; ?>"
style="width: 100%; max-width: 100%; max-height: 100vh; aspect-ratio: 16/9;">
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
</div>
</div>

View File

@@ -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>

View File

@@ -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();

View File

@@ -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>

View File

@@ -1,10 +1,27 @@
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
<?php
// views/home.php - Vista della pagina principale
$stations = loadTvStations();
?>
<h1 class="titlePage">TV</h1> <h1 class="titlePage">TV</h1>
<p class="subtitlePage">Guarda in streaming <b>RC105 TV</b></p> <p class="subtitlePage">Seleziona la webtv che vuoi guardare</p>
<hr> <hr>
<div class="tec"> <div class="stationList">
<iframe src="https://tv.rpigroup.net/a9699134-efb3-4932-b8db-5a49ae214031.html" style="width:100%; height: 225px;" frameborder="no" scrolling="no" allowfullscreen="true"></iframe> <div class="row g-2">
<?php foreach ($stations as $station): ?>
<div class="col-6">
<div class="stationCard <?php if((string)$station->thematic === 'true'){echo "isthematic";} ?>" data-id="<?php echo $station->id; ?>">
<a href="<?php echo $base_path; ?>/playtv/<?php echo $station->id; ?>" data-page="playtv/<?php echo $station->id; ?>" class="nav-link stationLink">
<img src="<?php echo $station->logo; ?>" alt="<?php echo $station->name; ?>" class="stationLogo">
</a>
</div>
</div>
<?php endforeach; ?>
</div>
</div> </div>
<a href="<?php echo $base_path; ?>/home" data-page="home" class="linkBox mt-3"> <a href="<?php echo $base_path; ?>/home" data-page="home" class="linkBox mt-3">

6
readme.md Normal file
View File

@@ -0,0 +1,6 @@
# RPIGroup Play
Il player ufficiale del gruppo RPIGroup
---
Questa repository è connessa al dominio APP.RPIGROUP.IT, ed è modificabile solo dagli utenti autorizzati

View File

@@ -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>

View File

@@ -1,3 +1,14 @@
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
<?php
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: SAMEORIGIN');
header('X-XSS-Protection: 1; mode=block');
header('Referrer-Policy: strict-origin-when-cross-origin');
?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="it"> <html lang="it">
<head> <head>
@@ -21,17 +32,40 @@
<meta name="screen-orientation" content="portrait"> <meta name="screen-orientation" content="portrait">
<meta name="x5-orientation" content="portrait"> <meta name="x5-orientation" content="portrait">
<meta name="x5-fullscreen" content="true"> <meta name="x5-fullscreen" content="true">
<meta name="apple-mobile-web-app-orientations" content="portrait">
<meta name="browsermode" content="application"> <meta name="browsermode" content="application">
<link rel="manifest" href="<?=$base_path?>/manifest.json?v=<?=$version_app?>"> <link rel="manifest" href="<?=$base_path?>/manifest.json?v=<?=$version_app?>">
<link rel="stylesheet" href="<?=$base_path?>/css/bootstrap.css"> <link rel="stylesheet" href="<?=$base_path?>/css/bootstrap.css">
<link rel="stylesheet" href="<?=$base_path?>/css/style.css?v=<?=$version_app?>"> <link rel="stylesheet" href="<?=$base_path?>/css/style.css?v=<?=$version_app?>">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- <link rel="stylesheet" href="<?=$base_path?>/css/animation.css?v=<?=$version_app?>"> <link rel="stylesheet" href="<?=$base_path?>/css/animation.css?v=<?=$version_app?>">
<script src="https://code.jquery.com/jquery-2.2.4.js"></script> <script src="https://code.jquery.com/jquery-2.2.4.js?v=<?=$version_app?>"></script>
<script src="<?=$base_path?>/js/bootstrap.js"></script> --> <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script src="<?=$base_path?>/js/bootstrap.js?v=<?=$version_app?>"></script>
<script> <script>
// Passa il percorso base a JavaScript // Passa il percorso base a JavaScript
var BASE_PATH = "<?=$base_path?>"; var BASE_PATH = "<?=$base_path?>";
// Forza l'orientamento portrait
if (window.screen && window.screen.orientation) {
// Tenta di bloccare l'orientamento in portrait
window.addEventListener('load', function() {
if (screen.orientation && screen.orientation.lock) {
screen.orientation.lock('portrait').catch(function(error) {
console.log('Orientation lock not supported or failed:', error);
});
}
});
}
// Fallback per dispositivi che non supportano l'API
// Mostra un avviso se l'utente ruota il dispositivo
window.addEventListener('orientationchange', function() {
if (window.orientation !== 0 && window.orientation !== 180) {
// Il dispositivo è in landscape, ma non possiamo forzarlo
console.log('Si prega di tenere il dispositivo in posizione verticale');
}
});
</script> </script>
</head> </head>
<body class="<?php echo $show_app ? 'appBody' : 'desktopBody'; ?>"> <body class="<?php echo $show_app ? 'appBody' : 'desktopBody'; ?>">