Compare commits
2 Commits
main
...
db91775a5d
| Author | SHA1 | Date | |
|---|---|---|---|
| db91775a5d | |||
| 6b15afb9da |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,5 +1 @@
|
|||||||
*:Zone.Identifier
|
*:Zone.Identifier
|
||||||
*Zone.Identifier
|
|
||||||
*.old
|
|
||||||
/api/*
|
|
||||||
.htaccess
|
|
||||||
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.
BIN
config/ajaxModule.inc.php:Zone.Identifier
Normal file
BIN
config/ajaxModule.inc.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
config/config.php:Zone.Identifier
Normal file
BIN
config/config.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
config/getBasePath.inc.php:Zone.Identifier
Normal file
BIN
config/getBasePath.inc.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
config/getPage.inc.php:Zone.Identifier
Normal file
BIN
config/getPage.inc.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
config/getStation.inc.php:Zone.Identifier
Normal file
BIN
config/getStation.inc.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -3,76 +3,8 @@
|
|||||||
======================================== */
|
======================================== */
|
||||||
|
|
||||||
|
|
||||||
/* ========================================
|
|
||||||
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 {
|
||||||
@@ -81,7 +13,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 {
|
||||||
@@ -93,13 +25,10 @@
|
|||||||
|
|
||||||
|
|
||||||
@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);
|
||||||
@@ -107,7 +36,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 {
|
||||||
@@ -116,7 +45,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +55,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +100,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;
|
||||||
@@ -187,7 +116,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;
|
||||||
}
|
}
|
||||||
@@ -199,7 +128,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;
|
||||||
@@ -219,7 +148,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +156,7 @@ button:active,
|
|||||||
/* 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;
|
||||||
}
|
}
|
||||||
@@ -238,7 +167,7 @@ button:active,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Animazione per le liste */
|
/* Animazione per le liste */
|
||||||
/* .stations-container {
|
.stations-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
@@ -265,7 +194,7 @@ button:active,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
||||||
@@ -279,7 +208,7 @@ button:active,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +224,7 @@ button:active,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Transizione per video e iframe */
|
/* Transizione per video e iframe */
|
||||||
/* video,
|
video,
|
||||||
iframe {
|
iframe {
|
||||||
transition: opacity 0.3s ease;
|
transition: opacity 0.3s ease;
|
||||||
}
|
}
|
||||||
@@ -306,17 +235,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 {
|
||||||
|
|||||||
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.
@@ -112,7 +112,7 @@ div.dbox_mobile {
|
|||||||
|
|
||||||
div.dbox_mobile {
|
div.dbox_mobile {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
max-width: 750px;
|
max-width: 450px;
|
||||||
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: 750px;
|
max-width: 450px;
|
||||||
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 10px;
|
margin: 0 0 7px;
|
||||||
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,38 +308,42 @@ main {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
iframe.contentplayer {
|
iframe.contentplayer{
|
||||||
height: calc(100vh - 393px);
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
height: calc(100vh - 312px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 750px;
|
max-width: 450px;
|
||||||
|
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: 750px;
|
max-width: 450px;
|
||||||
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{
|
||||||
.header {
|
z-index: 1;
|
||||||
z-index: 10000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer>.menu-section {
|
.footer>.menu-section {
|
||||||
@@ -394,28 +398,3 @@ button#formatToggleBtn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
css/style.css:Zone.Identifier
Normal file
BIN
css/style.css:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,78 +1,11 @@
|
|||||||
<?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>
|
<version>
|
||||||
<number>2.1.1</number>
|
<number>2.1.1</number>
|
||||||
<logs>
|
<logs>
|
||||||
<log>Corretti alcuni bug che impedivano l'accesso al player dal link esterno.</log>
|
<log>Corretti alcuni bug che impedivano l'accesso al player dal link esterno</log>
|
||||||
<log>Correzione e bugfix di problematiche varie.</log>
|
<log>Correzione e bugfix di problematiche varie.</log>
|
||||||
</logs>
|
</logs>
|
||||||
</version>
|
</version>
|
||||||
@@ -80,8 +13,8 @@
|
|||||||
<version>
|
<version>
|
||||||
<number>2.1.0</number>
|
<number>2.1.0</number>
|
||||||
<logs>
|
<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 nella navigazione in app</log>
|
||||||
<log>Risoluzione dei problemi minori presenti nel codice, che causava problemi di riproduzione audio al player.</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>
|
<log>Correzione e bugfix di problematiche varie.</log>
|
||||||
</logs>
|
</logs>
|
||||||
</version>
|
</version>
|
||||||
@@ -97,8 +30,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>
|
||||||
@@ -106,7 +39,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>
|
||||||
@@ -114,7 +47,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>
|
||||||
@@ -122,7 +55,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>
|
||||||
@@ -143,7 +76,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>
|
||||||
@@ -161,9 +94,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>
|
||||||
@@ -171,10 +104,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>
|
||||||
@@ -211,7 +144,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>
|
||||||
@@ -219,8 +152,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>
|
||||||
@@ -228,9 +161,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>
|
||||||
@@ -238,8 +171,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>
|
||||||
@@ -257,8 +190,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>
|
||||||
|
|||||||
BIN
data/changelog.xml:Zone.Identifier
Normal file
BIN
data/changelog.xml:Zone.Identifier
Normal file
Binary file not shown.
@@ -8,10 +8,9 @@
|
|||||||
<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.aac</stream>
|
<stream>https://asvradiostream.asvstudios.it/radio/8000/radio.mp3</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>
|
||||||
@@ -23,10 +22,9 @@
|
|||||||
<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>
|
||||||
@@ -35,7 +33,7 @@
|
|||||||
<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>
|
||||||
@@ -48,7 +46,7 @@
|
|||||||
<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>
|
||||||
@@ -57,6 +55,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>
|
||||||
BIN
data/radio.xml:Zone.Identifier
Normal file
BIN
data/radio.xml:Zone.Identifier
Normal file
Binary file not shown.
@@ -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://tv.rpigroup.net/memfs/a9699134-efb3-4932-b8db-5a49ae214031.m3u8</stream>
|
<stream>https://webtv.rpigroup.it/e1e55a4b-abec-4043-8f08-e2105b48b59b.m3u8</stream>
|
||||||
<poster>https://tv.rpigroup.net/memfs/a9699134-efb3-4932-b8db-5a49ae214031.jpg</poster>
|
<poster>https://webtv.rpigroup.it/memfs/e1e55a4b-abec-4043-8f08-e2105b48b59b.jpg</poster>
|
||||||
</station>
|
</station>
|
||||||
|
|
||||||
</tv>
|
</tv>
|
||||||
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.
@@ -5,9 +5,6 @@
|
|||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# 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.
|
||||||
#
|
#
|
||||||
|
|||||||
BIN
index.php:Zone.Identifier
Normal file
BIN
index.php:Zone.Identifier
Normal file
Binary file not shown.
554
js/app.js
554
js/app.js
@@ -6,8 +6,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
let hlsInstance = null;
|
let hlsInstance = null;
|
||||||
let currentXHR = null;
|
let currentXHR = null;
|
||||||
let isLoading = false;
|
let isLoading = false;
|
||||||
let loadingOverlay = null;
|
|
||||||
let metadataInterval = null;
|
|
||||||
|
|
||||||
// WeakMap per tracciare i listener degli elementi
|
// WeakMap per tracciare i listener degli elementi
|
||||||
const linkListeners = new WeakMap();
|
const linkListeners = new WeakMap();
|
||||||
@@ -57,12 +55,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
function cleanupPlayer() {
|
function cleanupPlayer() {
|
||||||
console.log('Pulizia player audio...');
|
console.log('Pulizia player audio...');
|
||||||
|
|
||||||
// Stop metadata updates
|
|
||||||
if (metadataInterval) {
|
|
||||||
clearInterval(metadataInterval);
|
|
||||||
metadataInterval = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Distruggi istanza HLS
|
// Distruggi istanza HLS
|
||||||
if (hlsInstance) {
|
if (hlsInstance) {
|
||||||
try {
|
try {
|
||||||
@@ -102,27 +94,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Mostra l'overlay di caricamento
|
|
||||||
*/
|
|
||||||
function showLoadingOverlay() {
|
|
||||||
if (!loadingOverlay) {
|
|
||||||
loadingOverlay = document.getElementById('loadingOverlay');
|
|
||||||
}
|
|
||||||
if (loadingOverlay) {
|
|
||||||
loadingOverlay.classList.add('active');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Nasconde l'overlay di caricamento
|
|
||||||
*/
|
|
||||||
function hideLoadingOverlay() {
|
|
||||||
if (loadingOverlay) {
|
|
||||||
loadingOverlay.classList.remove('active');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caricamento pagina con protezione da race condition
|
* Caricamento pagina con protezione da race condition
|
||||||
*/
|
*/
|
||||||
@@ -149,9 +120,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mostra l'overlay di caricamento
|
|
||||||
showLoadingOverlay();
|
|
||||||
|
|
||||||
// Animazione fade out
|
// Animazione fade out
|
||||||
contentContainer.classList.remove('fade-in');
|
contentContainer.classList.remove('fade-in');
|
||||||
contentContainer.classList.add('fade-out');
|
contentContainer.classList.add('fade-out');
|
||||||
@@ -170,9 +138,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
if (this.status === 200) {
|
if (this.status === 200) {
|
||||||
contentContainer.innerHTML = this.responseText;
|
contentContainer.innerHTML = this.responseText;
|
||||||
|
|
||||||
// Nascondi overlay di caricamento
|
|
||||||
hideLoadingOverlay();
|
|
||||||
|
|
||||||
// Animazione fade in
|
// Animazione fade in
|
||||||
contentContainer.classList.remove('fade-out');
|
contentContainer.classList.remove('fade-out');
|
||||||
contentContainer.classList.add('fade-in');
|
contentContainer.classList.add('fade-in');
|
||||||
@@ -210,7 +175,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
|
|
||||||
console.log('Pagina caricata:', page);
|
console.log('Pagina caricata:', page);
|
||||||
} else {
|
} else {
|
||||||
hideLoadingOverlay();
|
|
||||||
contentContainer.innerHTML = '<div class="content-page"><h2>Errore</h2><p>Impossibile caricare la pagina. Codice errore: ' + this.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');
|
||||||
@@ -221,7 +185,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
currentXHR.onerror = function () {
|
currentXHR.onerror = function () {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
currentXHR = null;
|
currentXHR = null;
|
||||||
hideLoadingOverlay();
|
|
||||||
contentContainer.innerHTML = '<div class="content-page"><h2>Errore di connessione</h2><p>Controlla la tua connessione internet e riprova.</p></div>';
|
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');
|
||||||
@@ -231,7 +194,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
currentXHR.onabort = function () {
|
currentXHR.onabort = function () {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
currentXHR = null;
|
currentXHR = null;
|
||||||
hideLoadingOverlay();
|
|
||||||
console.log('Richiesta XHR annullata');
|
console.log('Richiesta XHR annullata');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -347,304 +309,228 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function initializePlayer() {
|
function initializePlayer() {
|
||||||
console.log('Inizializzazione player audio (v2.1 - Format Toggle)...');
|
console.log('Inizializzazione player audio...');
|
||||||
|
|
||||||
const playPauseBtn = document.getElementById('playPauseBtn');
|
const playPauseBtn = document.getElementById('playPauseBtn');
|
||||||
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 playerStatus = document.getElementById('playerStatus');
|
const playerStatus = document.getElementById('playerStatus');
|
||||||
const formatToggleBtn = document.getElementById('formatToggleBtn');
|
const artistElement = document.getElementById('artist');
|
||||||
const formatLabel = document.getElementById('formatLabel');
|
|
||||||
|
|
||||||
if (!playPauseBtn) return;
|
if (!playPauseBtn) {
|
||||||
|
console.error('Pulsante play/pause non trovato');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Cleanup Preventivo
|
// Pulisci il player precedente
|
||||||
cleanupPlayer();
|
cleanupPlayer();
|
||||||
|
|
||||||
// 2. Setup Elementi
|
// Ottieni il nuovo audio player dal DOM
|
||||||
audioPlayer = document.getElementById('hlsAudioPlayer');
|
audioPlayer = document.getElementById('hlsAudioPlayer');
|
||||||
if (!audioPlayer) return;
|
|
||||||
|
if (!audioPlayer) {
|
||||||
|
console.error('Elemento audio non trovato');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const streamHLS = playPauseBtn.getAttribute('data-stream-hls');
|
const streamHLS = playPauseBtn.getAttribute('data-stream-hls');
|
||||||
const streamFallback = playPauseBtn.getAttribute('data-stream-fallback');
|
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 stationLogo = playPauseBtn.getAttribute('data-station-logo');
|
||||||
|
|
||||||
|
console.log('Stream HLS:', streamHLS);
|
||||||
|
console.log('Stream Fallback:', streamFallback);
|
||||||
|
console.log('Stazione:', stationName);
|
||||||
|
|
||||||
// Stato formato audio (preferenza salvata in localStorage)
|
|
||||||
const storageKey = 'audioFormat_' + stationName;
|
|
||||||
let currentFormat = localStorage.getItem(storageKey) || 'hls'; // 'hls' o 'direct'
|
|
||||||
let isPlaying = false;
|
let isPlaying = false;
|
||||||
|
let streamType = 'hls'; // 'hls' o 'direct'
|
||||||
// Aggiorna label del formato
|
|
||||||
function updateFormatLabel() {
|
|
||||||
if (formatLabel) {
|
|
||||||
formatLabel.textContent = currentFormat === 'hls' ? 'HLS' : 'MP3';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateFormatLabel();
|
|
||||||
|
|
||||||
// Configurazione HLS.js Ottimizzata per Qualità
|
|
||||||
const hlsConfig = {
|
|
||||||
debug: false,
|
|
||||||
enableWorker: true,
|
|
||||||
lowLatencyMode: false, // Disabilitato per stabilità e buffer migliore
|
|
||||||
backBufferLength: 90,
|
|
||||||
maxBufferLength: 30, // Aumentato buffer (default 30s)
|
|
||||||
startLevel: -1, // Auto start
|
|
||||||
xhrSetup: function (xhr, url) {
|
|
||||||
xhr.withCredentials = false; // Fix CORS issues sometimes
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logica di Selezione Player
|
* Inizializza HLS stream
|
||||||
* Priorità: HLS.js (PC/Android) > Nativo (iOS) > Fallback (Direct Stream)
|
|
||||||
*/
|
*/
|
||||||
function initStream(forceFormat = null) {
|
function initHLSStream() {
|
||||||
const preferredFormat = forceFormat || currentFormat;
|
if (!window.Hls) {
|
||||||
|
console.error('HLS.js non caricato');
|
||||||
// Se l'utente ha scelto formato diretto, usa subito MP3/AAC
|
return false;
|
||||||
if (preferredFormat === 'direct') {
|
|
||||||
console.log('User preference: Direct stream (MP3/AAC)');
|
|
||||||
useDirectStream();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// STRATEGIA 1: HLS.js (Preferita per PC e Android)
|
|
||||||
if (Hls.isSupported()) {
|
if (Hls.isSupported()) {
|
||||||
console.log('Strategy: HLS.js (High Quality Control)');
|
console.log('HLS supportato - uso HLS.js');
|
||||||
|
|
||||||
|
hlsInstance = new Hls({
|
||||||
|
debug: false,
|
||||||
|
enableWorker: true,
|
||||||
|
lowLatencyMode: true,
|
||||||
|
backBufferLength: 90
|
||||||
|
});
|
||||||
|
|
||||||
hlsInstance = new Hls(hlsConfig);
|
|
||||||
hlsInstance.loadSource(streamHLS);
|
hlsInstance.loadSource(streamHLS);
|
||||||
hlsInstance.attachMedia(audioPlayer);
|
hlsInstance.attachMedia(audioPlayer);
|
||||||
|
|
||||||
hlsInstance.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
|
hlsInstance.on(Hls.Events.MANIFEST_PARSED, function () {
|
||||||
console.log(`HLS Manifest Loaded. Levels: ${data.levels.length}`);
|
console.log('Manifest HLS caricato');
|
||||||
|
audioPlayer.play().then(() => {
|
||||||
// Log dettagliato di tutti i livelli disponibili per debug
|
console.log('Riproduzione HLS avviata');
|
||||||
data.levels.forEach((level, index) => {
|
updatePlayState(true);
|
||||||
console.log(`Level ${index}: ${level.bitrate} bps (${(level.bitrate / 1000).toFixed(0)} kbps)`);
|
}).catch(err => {
|
||||||
|
console.error('Errore avvio riproduzione HLS:', err);
|
||||||
|
tryFallbackStream();
|
||||||
});
|
});
|
||||||
|
|
||||||
// CRITICAL: Forza partenza dal livello massimo per garantire qualità alta
|
|
||||||
if (data.levels.length > 1) {
|
|
||||||
const maxLevel = data.levels.length - 1;
|
|
||||||
hlsInstance.startLevel = maxLevel;
|
|
||||||
console.log(`✓ Forced START level to MAX: ${maxLevel} (${(data.levels[maxLevel].bitrate / 1000).toFixed(0)} kbps)`);
|
|
||||||
}
|
|
||||||
|
|
||||||
attemptPlay();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Track quality switches per debug
|
|
||||||
hlsInstance.on(Hls.Events.LEVEL_SWITCHING, function (event, data) {
|
|
||||||
console.log(`→ Switching to level ${data.level}...`);
|
|
||||||
});
|
|
||||||
|
|
||||||
hlsInstance.on(Hls.Events.LEVEL_SWITCHED, function (event, data) {
|
|
||||||
const currentLevel = hlsInstance.levels[data.level];
|
|
||||||
console.log(`✓ Switched to level ${data.level}: ${(currentLevel.bitrate / 1000).toFixed(0)} kbps`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
hlsInstance.on(Hls.Events.ERROR, function (event, data) {
|
hlsInstance.on(Hls.Events.ERROR, function (event, data) {
|
||||||
|
console.error('Errore HLS:', data.type, data.details);
|
||||||
if (data.fatal) {
|
if (data.fatal) {
|
||||||
console.warn('HLS Fatal Error:', data.type);
|
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||||
hlsInstance.startLoad();
|
console.log('Errore di rete, tentativo fallback...');
|
||||||
|
tryFallbackStream();
|
||||||
break;
|
break;
|
||||||
case Hls.ErrorTypes.MEDIA_ERROR:
|
case Hls.ErrorTypes.MEDIA_ERROR:
|
||||||
|
console.log('Errore media, tentativo recupero...');
|
||||||
hlsInstance.recoverMediaError();
|
hlsInstance.recoverMediaError();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
useDirectStream();
|
console.log('Errore fatale, tentativo fallback...');
|
||||||
|
tryFallbackStream();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return true;
|
||||||
}
|
} else if (audioPlayer.canPlayType('application/vnd.apple.mpegurl')) {
|
||||||
|
console.log('HLS nativo supportato');
|
||||||
// STRATEGIA 2: Nativo (Obbligatorio per iOS)
|
|
||||||
if (audioPlayer.canPlayType('application/vnd.apple.mpegurl')) {
|
|
||||||
console.log('Strategy: Native HLS (iOS/Safari)');
|
|
||||||
audioPlayer.src = streamHLS;
|
audioPlayer.src = streamHLS;
|
||||||
audioPlayer.preload = 'auto'; // Suggerisce al browser di caricare dati
|
audioPlayer.play().then(() => {
|
||||||
|
console.log('Riproduzione HLS nativa avviata');
|
||||||
// Hack per iOS: Alcune volte serve un tocco utente, gestito dal click play
|
updatePlayState(true);
|
||||||
attemptPlay();
|
}).catch(err => {
|
||||||
return;
|
console.error('Errore HLS nativo:', err);
|
||||||
|
tryFallbackStream();
|
||||||
|
});
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STRATEGIA 3: Fallback (Stream MP3 diretto)
|
return false;
|
||||||
console.log('Strategy: Direct Fallback');
|
|
||||||
useDirectStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function useDirectStream() {
|
/**
|
||||||
|
* Usa stream diretto come fallback
|
||||||
|
*/
|
||||||
|
function tryFallbackStream() {
|
||||||
|
console.log('Tentativo stream fallback:', streamFallback);
|
||||||
|
|
||||||
if (hlsInstance) {
|
if (hlsInstance) {
|
||||||
hlsInstance.destroy();
|
hlsInstance.destroy();
|
||||||
hlsInstance = null;
|
hlsInstance = null;
|
||||||
}
|
}
|
||||||
console.log('Using direct stream:', streamFallback);
|
|
||||||
|
streamType = 'direct';
|
||||||
audioPlayer.src = streamFallback;
|
audioPlayer.src = streamFallback;
|
||||||
attemptPlay();
|
audioPlayer.load();
|
||||||
}
|
|
||||||
|
|
||||||
// Funzione per cambiare formato
|
audioPlayer.play().then(() => {
|
||||||
function toggleFormat() {
|
console.log('Riproduzione stream diretto avviata');
|
||||||
const wasPlaying = !audioPlayer.paused;
|
updatePlayState(true);
|
||||||
|
}).catch(err => {
|
||||||
// Cambia formato
|
console.error('Errore stream diretto:', err);
|
||||||
currentFormat = currentFormat === 'hls' ? 'direct' : 'hls';
|
updatePlayState(false);
|
||||||
localStorage.setItem(storageKey, currentFormat);
|
if (playerStatus) {
|
||||||
console.log('Switching to format:', currentFormat);
|
playerStatus.textContent = 'Errore di riproduzione';
|
||||||
|
|
||||||
// Aggiorna label
|
|
||||||
updateFormatLabel();
|
|
||||||
|
|
||||||
// Ferma riproduzione corrente
|
|
||||||
if (audioPlayer) {
|
|
||||||
audioPlayer.pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pulisci player precedente
|
|
||||||
if (hlsInstance) {
|
|
||||||
hlsInstance.destroy();
|
|
||||||
hlsInstance = null;
|
|
||||||
}
|
|
||||||
audioPlayer.src = '';
|
|
||||||
|
|
||||||
// Reinizializza con nuovo formato
|
|
||||||
initStream(currentFormat);
|
|
||||||
|
|
||||||
// Riprendi riproduzione se era in corso
|
|
||||||
if (wasPlaying) {
|
|
||||||
setTimeout(() => {
|
|
||||||
togglePlay();
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function attemptPlay() {
|
|
||||||
// Nota: chiamare .play() senza interazione utente fallirà.
|
|
||||||
// Questa funzione prepara lo stato. Il vero play avviene al click.
|
|
||||||
if (playerStatus) playerStatus.textContent = 'Pronto alla riproduzione';
|
|
||||||
}
|
|
||||||
|
|
||||||
function togglePlay() {
|
|
||||||
if (audioPlayer.paused) {
|
|
||||||
const playPromise = audioPlayer.play();
|
|
||||||
if (playPromise !== undefined) {
|
|
||||||
playPromise.then(() => {
|
|
||||||
updateUI(true);
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('Play prevented:', error);
|
|
||||||
// Se HLS fallisce al play (es. stale manifest), prova fallback
|
|
||||||
if (!audioPlayer.src.includes(streamFallback) && !hlsInstance) {
|
|
||||||
fallbackToDirectStream();
|
|
||||||
audioPlayer.play().catch(e => console.error('Fallback failed:', e));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
audioPlayer.pause();
|
|
||||||
updateUI(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateUI(playing) {
|
/**
|
||||||
|
* Aggiorna stato visuale play/pause
|
||||||
|
*/
|
||||||
|
function updatePlayState(playing) {
|
||||||
isPlaying = playing;
|
isPlaying = playing;
|
||||||
playIcon.style.display = playing ? 'none' : 'block';
|
|
||||||
pauseIcon.style.display = playing ? 'block' : 'none';
|
if (playing) {
|
||||||
|
playIcon.style.display = 'none';
|
||||||
|
pauseIcon.style.display = 'inline-block';
|
||||||
if (playerStatus) {
|
if (playerStatus) {
|
||||||
playerStatus.textContent = playing ? 'In riproduzione' : 'In pausa';
|
playerStatus.textContent = 'In riproduzione...';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Listeners
|
|
||||||
playPauseBtn.onclick = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
// Se non inizializzato (primo click), avvia stream
|
|
||||||
if (!audioPlayer.src && !hlsInstance) {
|
|
||||||
initStream();
|
|
||||||
// Piccolo timeout per dare tempo al setup prima del play effettivo
|
|
||||||
setTimeout(togglePlay, 50);
|
|
||||||
} else {
|
} else {
|
||||||
togglePlay();
|
playIcon.style.display = 'inline-block';
|
||||||
|
pauseIcon.style.display = 'none';
|
||||||
|
if (playerStatus) {
|
||||||
|
playerStatus.textContent = stationSlogan || 'In pausa';
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
audioPlayer.onplay = () => updateUI(true);
|
|
||||||
audioPlayer.onpause = () => updateUI(false);
|
|
||||||
|
|
||||||
audioPlayer.onerror = (e) => {
|
|
||||||
console.error('Audio Error:', audioPlayer.error);
|
|
||||||
if (playerStatus) playerStatus.textContent = 'Errore riproduzione';
|
|
||||||
updateUI(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Format toggle button listener
|
|
||||||
if (formatToggleBtn) {
|
|
||||||
formatToggleBtn.onclick = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
toggleFormat();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 audio player
|
||||||
|
*/
|
||||||
|
audioPlayer.addEventListener('play', function () {
|
||||||
|
updatePlayState(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
audioPlayer.addEventListener('pause', function () {
|
||||||
|
updatePlayState(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
audioPlayer.addEventListener('error', function (e) {
|
||||||
|
console.error('Errore audio player:', e);
|
||||||
|
updatePlayState(false);
|
||||||
|
if (playerStatus) {
|
||||||
|
playerStatus.textContent = 'Errore di riproduzione';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
audioPlayer.addEventListener('waiting', function () {
|
||||||
|
if (playerStatus) {
|
||||||
|
playerStatus.textContent = 'Buffering...';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
audioPlayer.addEventListener('playing', function () {
|
||||||
|
if (playerStatus) {
|
||||||
|
playerStatus.textContent = 'In riproduzione...';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Setup Media Session
|
// Setup Media Session
|
||||||
setupMediaSession(stationName, playPauseBtn.getAttribute('data-station-slogan'), playPauseBtn.getAttribute('data-station-logo'), playIcon, pauseIcon);
|
setupMediaSession(stationName, stationSlogan, stationLogo, playIcon, pauseIcon);
|
||||||
|
|
||||||
// --- GESTIONE METADATI (Now Playing) ---
|
console.log('Player audio inizializzato');
|
||||||
const apiUrl = playPauseBtn.getAttribute('data-api-url');
|
|
||||||
if (apiUrl) {
|
|
||||||
console.log('Starting metadata polling for:', apiUrl);
|
|
||||||
|
|
||||||
function updateMetadata() {
|
|
||||||
fetch(apiUrl)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.now_playing && data.now_playing.song) {
|
|
||||||
const song = data.now_playing.song;
|
|
||||||
|
|
||||||
// Aggiorna DOM
|
|
||||||
const songsEl = document.getElementById('songs');
|
|
||||||
const artistEl = document.getElementById('artist');
|
|
||||||
const albumArtEl = document.getElementById('albumsong');
|
|
||||||
|
|
||||||
if (songsEl) songsEl.textContent = song.title;
|
|
||||||
if (artistEl) artistEl.textContent = song.artist;
|
|
||||||
if (albumArtEl && song.art) {
|
|
||||||
// Evita refresh se l'immagine è la stessa
|
|
||||||
if (albumArtEl.src !== song.art) {
|
|
||||||
albumArtEl.src = song.art;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aggiorna Media Session
|
|
||||||
if ('mediaSession' in navigator) {
|
|
||||||
navigator.mediaSession.metadata = new MediaMetadata({
|
|
||||||
title: song.title,
|
|
||||||
artist: song.artist,
|
|
||||||
album: stationName,
|
|
||||||
artwork: [
|
|
||||||
{ src: song.art || playPauseBtn.getAttribute('data-station-logo'), sizes: '512x512', type: 'image/png' }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => console.error('Error fetching metadata:', err));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chiamata immediata
|
|
||||||
updateMetadata();
|
|
||||||
|
|
||||||
// Polling ogni 10 secondi
|
|
||||||
metadataInterval = setInterval(updateMetadata, 10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Player System Ready with format toggle.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -652,127 +538,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
*/
|
*/
|
||||||
function initializeTVPlayer() {
|
function initializeTVPlayer() {
|
||||||
console.log('TV Player inizializzato');
|
console.log('TV Player inizializzato');
|
||||||
|
// Implementare logica specifica per TV se necessario
|
||||||
const video = document.getElementById('tvVideoPlayer');
|
|
||||||
if (!video) {
|
|
||||||
console.log('Elemento video TV non trovato');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup istanza precedente se esiste
|
|
||||||
if (video.hlsInstance) {
|
|
||||||
video.hlsInstance.destroy();
|
|
||||||
delete video.hlsInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
const videoSrc = video.getAttribute('data-src');
|
|
||||||
console.log('Video Source:', videoSrc);
|
|
||||||
|
|
||||||
if (!videoSrc) {
|
|
||||||
console.error('Nessuna sorgente video specificata in data-src');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creazione elemento per errori se non esiste già
|
|
||||||
let errorDisplay = video.parentNode.querySelector('.tv-error-display');
|
|
||||||
if (!errorDisplay) {
|
|
||||||
errorDisplay = document.createElement('div');
|
|
||||||
errorDisplay.className = 'tv-error-display';
|
|
||||||
errorDisplay.style.display = 'none';
|
|
||||||
errorDisplay.style.position = 'absolute';
|
|
||||||
errorDisplay.style.top = '50%';
|
|
||||||
errorDisplay.style.left = '50%';
|
|
||||||
errorDisplay.style.transform = 'translate(-50%, -50%)';
|
|
||||||
errorDisplay.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
|
|
||||||
errorDisplay.style.color = '#fff';
|
|
||||||
errorDisplay.style.padding = '20px';
|
|
||||||
errorDisplay.style.borderRadius = '8px';
|
|
||||||
errorDisplay.style.textAlign = 'center';
|
|
||||||
errorDisplay.style.zIndex = '2000';
|
|
||||||
errorDisplay.style.maxWidth = '90%';
|
|
||||||
if (video.parentNode) {
|
|
||||||
video.parentNode.appendChild(errorDisplay);
|
|
||||||
// Assicurati che il parent sia relative per il posizionamento absolute
|
|
||||||
if (getComputedStyle(video.parentNode).position === 'static') {
|
|
||||||
video.parentNode.style.position = 'relative';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showError(msg, details) {
|
|
||||||
console.error(msg, details);
|
|
||||||
errorDisplay.innerHTML = '<strong>Errore:</strong><br>' + msg + (details ? '<br><small>' + details + '</small>' : '');
|
|
||||||
errorDisplay.style.display = 'block';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Controllo libreria HLS
|
|
||||||
if (typeof Hls === 'undefined') {
|
|
||||||
// Riprova tra poco se magari sta ancora caricando
|
|
||||||
setTimeout(() => {
|
|
||||||
if (typeof Hls === 'undefined') {
|
|
||||||
showError('Libreria HLS non caricata correttamente.');
|
|
||||||
} else {
|
|
||||||
initializeTVPlayer(); // Riprova inizializzazione
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Hls.isSupported()) {
|
|
||||||
console.log('HLS Supported - Loading stream');
|
|
||||||
var hls = new Hls({
|
|
||||||
debug: false,
|
|
||||||
enableWorker: true
|
|
||||||
});
|
|
||||||
|
|
||||||
hls.loadSource(videoSrc);
|
|
||||||
hls.attachMedia(video);
|
|
||||||
|
|
||||||
hls.on(Hls.Events.MANIFEST_PARSED, function () {
|
|
||||||
console.log('TV Manifest Parsed - Ready to play');
|
|
||||||
var playPromise = video.play();
|
|
||||||
if (playPromise !== undefined) {
|
|
||||||
playPromise.catch(error => {
|
|
||||||
console.log('Autoplay blocked or failed:', error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Gestione errori estesa
|
|
||||||
hls.on(Hls.Events.ERROR, function (event, data) {
|
|
||||||
console.warn('HLS Error:', data);
|
|
||||||
if (data.fatal) {
|
|
||||||
switch (data.type) {
|
|
||||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
|
||||||
console.log('Network error, recovering...');
|
|
||||||
hls.startLoad();
|
|
||||||
break;
|
|
||||||
case Hls.ErrorTypes.MEDIA_ERROR:
|
|
||||||
console.log('Media error, recovering...');
|
|
||||||
hls.recoverMediaError();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
showError('Errore fatale riproduzione.', data.type);
|
|
||||||
hls.destroy();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
video.hlsInstance = hls;
|
|
||||||
|
|
||||||
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
|
||||||
console.log('Native HLS Supported (Safari/iOS)');
|
|
||||||
video.src = videoSrc;
|
|
||||||
video.addEventListener('loadedmetadata', function () {
|
|
||||||
video.play().catch(e => console.log("Autoplay iOS prevented"));
|
|
||||||
});
|
|
||||||
video.addEventListener('error', function (e) {
|
|
||||||
showError('Errore riproduzione nativa.', e.message);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
showError('Il tuo browser non supporta HLS.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -910,8 +676,8 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
const pathWithoutBase = currentPath.replace(BASE_PATH, '').replace(/^\//, '');
|
const pathWithoutBase = currentPath.replace(BASE_PATH, '').replace(/^\//, '');
|
||||||
const redirectParam = pathWithoutBase ? '&redirect=' + encodeURIComponent(pathWithoutBase) : '';
|
const redirectParam = pathWithoutBase ? '&redirect=' + encodeURIComponent(pathWithoutBase) : '';
|
||||||
|
|
||||||
const width = 400;
|
const width = 375;
|
||||||
const height = 840;
|
const height = 667;
|
||||||
const left = (window.screen.width / 2) - (width / 2);
|
const left = (window.screen.width / 2) - (width / 2);
|
||||||
const top = (window.screen.height / 2) - (height / 2);
|
const top = (window.screen.height / 2) - (height / 2);
|
||||||
|
|
||||||
@@ -947,7 +713,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
* Setup modalità standalone (PWA)
|
* Setup modalità standalone (PWA)
|
||||||
*/
|
*/
|
||||||
function setupStandaloneMode() {
|
function setupStandaloneMode() {
|
||||||
const appContainer = document.querySelector('.container') || document.querySelector('.container-fluid');
|
const appContainer = document.querySelector('.container');
|
||||||
if (!appContainer) return;
|
if (!appContainer) return;
|
||||||
|
|
||||||
if (window.opener && !window.opener.closed) {
|
if (window.opener && !window.opener.closed) {
|
||||||
@@ -990,7 +756,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
|
|
||||||
setupOpenAppButton();
|
setupOpenAppButton();
|
||||||
|
|
||||||
if (document.querySelector('.container') || document.querySelector('.container-fluid')) {
|
if (document.querySelector('.container')) {
|
||||||
setupStandaloneMode();
|
setupStandaloneMode();
|
||||||
attachLinkListeners();
|
attachLinkListeners();
|
||||||
setupHistoryNavigation();
|
setupHistoryNavigation();
|
||||||
|
|||||||
BIN
js/app.js:Zone.Identifier
Normal file
BIN
js/app.js:Zone.Identifier
Normal file
Binary file not shown.
7
js/bootstrap.js
vendored
7
js/bootstrap.js
vendored
File diff suppressed because one or more lines are too long
BIN
manifest.json:Zone.Identifier
Normal file
BIN
manifest.json:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/desktop.php:Zone.Identifier
Normal file
BIN
pages/desktop.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -15,7 +15,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main class="container-fluid" id="content">
|
<main class="container" id="content">
|
||||||
<?php
|
<?php
|
||||||
// Carica il contenuto iniziale in base all'URL
|
// Carica il contenuto iniziale in base all'URL
|
||||||
switch ($page) {
|
switch ($page) {
|
||||||
@@ -93,14 +93,6 @@
|
|||||||
?>
|
?>
|
||||||
</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> •
|
||||||
|
|||||||
BIN
pages/mobile.php:Zone.Identifier
Normal file
BIN
pages/mobile.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/page/404.php:Zone.Identifier
Normal file
BIN
pages/page/404.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -5,29 +5,7 @@
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="tec">
|
<div class="tec">
|
||||||
<p>RPIGroup Play è l'applicazione che permette di ascoltare le radio e le webtv preferite in un unico luogo.</p>
|
<p>La pagina è in fase di realizzazione... Attendi il prossimo aggiornamento per leggere le nostre istruzioni d'uso!</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">
|
||||||
|
|||||||
BIN
pages/page/about.php:Zone.Identifier
Normal file
BIN
pages/page/about.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/page/addradio.php:Zone.Identifier
Normal file
BIN
pages/page/addradio.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
<h1 class="titlePage">Changelog</h1>
|
<h1 class="titlePage">Changelog</h1>
|
||||||
<p class="subtitlePage">Visualizza tutti gli aggiornamenti 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
|
||||||
// Verifica che $changelog sia stato caricato correttamente in getStation.inc.php
|
// Verifica che $changelog sia stato caricato correttamente in getStation.inc.php
|
||||||
|
|||||||
BIN
pages/page/changelog.php:Zone.Identifier
Normal file
BIN
pages/page/changelog.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/page/contact.php:Zone.Identifier
Normal file
BIN
pages/page/contact.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/page/copyright.php:Zone.Identifier
Normal file
BIN
pages/page/copyright.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -22,38 +22,6 @@
|
|||||||
</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="">
|
||||||
@@ -72,7 +40,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<br>funziona?
|
Come funziona?
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -91,13 +59,3 @@
|
|||||||
</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>
|
|
||||||
BIN
pages/page/home.php:Zone.Identifier
Normal file
BIN
pages/page/home.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,34 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
$station_id = (string)$station->id;
|
|
||||||
$station_name = (string)$station->name;
|
|
||||||
$station_slogan = (string)$station->slogan;
|
|
||||||
$station_logo = (string)$station->logo;
|
|
||||||
$station_stream = (string)$station->stream;
|
|
||||||
$station_streamhls = (string)$station->streamhls;
|
|
||||||
$station_contentplayer = (string)$station->contentplayer;
|
|
||||||
$station_apiradio = (string)$station->apiradio;
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
<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="radio-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; ?>/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>
|
|
||||||
|
|
||||||
<?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>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
if($station->contentplayer == ""){
|
if($station->contentplayer == ""){
|
||||||
?>
|
?>
|
||||||
<style>
|
<style>
|
||||||
@@ -37,11 +7,14 @@
|
|||||||
padding: 22px 35px 10px 35px;
|
padding: 22px 35px 10px 35px;
|
||||||
display: block;
|
display: block;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
height: calc(100vh - 393px);
|
position: absolute;
|
||||||
|
height: calc(100vh - 312px);
|
||||||
color: white;
|
color: white;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 750px;
|
max-width: 450px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
.staticpage > .logo{
|
.staticpage > .logo{
|
||||||
width: 200px;
|
width: 200px;
|
||||||
@@ -63,40 +36,27 @@
|
|||||||
<?php
|
<?php
|
||||||
}else{
|
}else{
|
||||||
?>
|
?>
|
||||||
<iframe src="<?=$station_contentplayer?>" class="contentplayer" frameborder="0"></iframe>
|
<iframe src="<?php echo $station->contentplayer; ?>" class="contentplayer" frameborder="0"></iframe>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="footer_player">
|
<div class="footer_player" <?php if($is_mobile){ ?> style="bottom: 84px;" <? } ?>>
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-2" style="width: 70px;">
|
<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;">
|
<img src="<?php echo $station->logo; ?>" alt="<?php echo $station->name; ?>" style="width: 60px;">
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<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="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 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>
|
|
||||||
<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>
|
||||||
<div class="col-2" style="text-align: center; margin-top: 1px; margin-right: 5px; width: 67px;">
|
<div class="col-2" style="text-align: center; margin-top: 1px; margin-right: 5px; width: 67px;">
|
||||||
<button id="playPauseBtn"
|
<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-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 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>
|
<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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<audio id="hlsAudioPlayer" preload="none"></audio>
|
<audio id="hlsAudioPlayer" preload="none"></audio>
|
||||||
BIN
pages/page/player.php:Zone.Identifier
Normal file
BIN
pages/page/player.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,50 +0,0 @@
|
|||||||
<?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>
|
|
||||||
|
|||||||
BIN
pages/page/player_tv.php:Zone.Identifier
Normal file
BIN
pages/page/player_tv.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/page/policyprivacy.php:Zone.Identifier
Normal file
BIN
pages/page/policyprivacy.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/page/radio.php:Zone.Identifier
Normal file
BIN
pages/page/radio.php:Zone.Identifier
Normal file
Binary file not shown.
BIN
pages/page/terminicondizioni.php:Zone.Identifier
Normal file
BIN
pages/page/terminicondizioni.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -1,27 +1,12 @@
|
|||||||
<?php header('Content-Type: text/html; charset=UTF-8'); ?>
|
<?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">Seleziona la webtv che vuoi guardare</p>
|
<p class="subtitlePage">Guarda in streaming <b>RC105 TV</b></p>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class="stationList">
|
<div class="tec">
|
||||||
<div class="row g-2">
|
<iframe src="https://tv.rpigroup.net/a9699134-efb3-4932-b8db-5a49ae214031.html" style="width:100%; height: 225px;" frameborder="no" scrolling="no" allowfullscreen="true"></iframe>
|
||||||
<?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">
|
||||||
|
|||||||
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.
@@ -1,6 +1,2 @@
|
|||||||
# RPIGroup Play
|
# RPIGroup Play
|
||||||
Il player ufficiale del gruppo RPIGroup
|
Il player ufficiale del gruppo RPIGroup
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Questa repository è connessa al dominio APP.RPIGROUP.IT, ed è modificabile solo dagli utenti autorizzati
|
|
||||||
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.
BIN
static/footer.php:Zone.Identifier
Normal file
BIN
static/footer.php:Zone.Identifier
Normal file
Binary file not shown.
@@ -32,40 +32,17 @@ header('Referrer-Policy: strict-origin-when-cross-origin');
|
|||||||
<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?v=<?=$version_app?>"></script>
|
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
|
<script src="<?=$base_path?>/js/bootstrap.js"></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'; ?>">
|
||||||
BIN
static/head.php:Zone.Identifier
Normal file
BIN
static/head.php:Zone.Identifier
Normal file
Binary file not shown.
Reference in New Issue
Block a user