App als Download hinzugefügt
This commit is contained in:
@@ -12,4 +12,14 @@ public class PlaylistController {
|
||||
public String index() {
|
||||
return "index";
|
||||
}
|
||||
|
||||
@GetMapping("/impressum")
|
||||
public String impressum() {
|
||||
return "impressum";
|
||||
}
|
||||
|
||||
@GetMapping("/datenschutz")
|
||||
public String datenschutz() {
|
||||
return "datenschutz";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1203,3 +1203,139 @@ body { padding-top: 4rem; }
|
||||
width: 100%;
|
||||
max-width: 260px;
|
||||
}
|
||||
|
||||
/* ── Footer links ── */
|
||||
.footer-links {
|
||||
display: flex;
|
||||
gap: .6rem;
|
||||
align-items: center;
|
||||
font-size: .82rem;
|
||||
color: var(--text-muted);
|
||||
margin-top: .4rem;
|
||||
}
|
||||
.footer-links a {
|
||||
color: var(--text-muted);
|
||||
transition: color .15s;
|
||||
}
|
||||
.footer-links a:hover { color: var(--teal); }
|
||||
|
||||
/* ── Cookie Banner ── */
|
||||
.cookie-banner {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 800;
|
||||
background: var(--surface-2);
|
||||
border-top: 1px solid var(--border);
|
||||
padding: 1rem 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1.25rem;
|
||||
flex-wrap: wrap;
|
||||
box-shadow: 0 -4px 24px rgba(0,0,0,.4);
|
||||
}
|
||||
.cookie-text {
|
||||
font-size: .88rem;
|
||||
color: var(--text-muted);
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
.cookie-text a {
|
||||
color: var(--teal);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
.cookie-btn { white-space: nowrap; flex-shrink: 0; }
|
||||
|
||||
/* ── Legal pages ── */
|
||||
.legal-header {
|
||||
padding: 1rem 0;
|
||||
background: var(--bg-2);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.legal-header .section-inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.25rem;
|
||||
}
|
||||
.legal-back {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .35rem;
|
||||
color: var(--text-muted);
|
||||
font-size: .9rem;
|
||||
transition: color .15s;
|
||||
}
|
||||
.legal-back:hover { color: var(--teal); }
|
||||
.legal-logo {
|
||||
height: 32px;
|
||||
width: auto;
|
||||
margin-left: auto;
|
||||
opacity: .75;
|
||||
}
|
||||
.legal-main {
|
||||
padding: 4rem 0 6rem;
|
||||
min-height: calc(100vh - 200px);
|
||||
}
|
||||
.legal-inner h1 {
|
||||
font-size: clamp(1.8rem, 4vw, 2.6rem);
|
||||
font-weight: 900;
|
||||
letter-spacing: -.5px;
|
||||
margin-bottom: 2.5rem;
|
||||
background: var(--grad);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
.legal-section {
|
||||
margin-bottom: 2.25rem;
|
||||
padding-bottom: 2.25rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.legal-section:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.legal-section h2 {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: var(--teal);
|
||||
margin-bottom: .75rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .05em;
|
||||
font-size: .82rem;
|
||||
}
|
||||
.legal-section p {
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
.legal-section p:last-child { margin-bottom: 0; }
|
||||
.legal-section ul {
|
||||
list-style: none;
|
||||
margin: .5rem 0 .75rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .5rem;
|
||||
}
|
||||
.legal-section ul li {
|
||||
color: var(--text-muted);
|
||||
padding-left: 1.1rem;
|
||||
position: relative;
|
||||
line-height: 1.7;
|
||||
}
|
||||
.legal-section ul li::before {
|
||||
content: '–';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--teal);
|
||||
}
|
||||
.legal-section a {
|
||||
color: var(--teal);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
transition: color .15s;
|
||||
}
|
||||
.legal-section a:hover { color: var(--teal-h); }
|
||||
|
||||
Binary file not shown.
142
src/main/resources/templates/datenschutz.html
Normal file
142
src/main/resources/templates/datenschutz.html
Normal file
@@ -0,0 +1,142 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Datenschutzerklärung – LibreDeck</title>
|
||||
<link rel="icon" type="image/png" th:href="@{/images/favicon.png}">
|
||||
<link rel="stylesheet" th:href="@{/css/style.css}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="legal-header">
|
||||
<div class="section-inner">
|
||||
<a th:href="@{/}" class="legal-back">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round" width="18" height="18" aria-hidden="true">
|
||||
<polyline points="15 18 9 12 15 6"/>
|
||||
</svg>
|
||||
Zurück
|
||||
</a>
|
||||
<img th:src="@{/images/logo.png}" alt="LibreDeck" class="legal-logo">
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="legal-main">
|
||||
<div class="section-inner legal-inner">
|
||||
<h1>Datenschutzerklärung</h1>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>1. Verantwortlicher</h2>
|
||||
<p>
|
||||
Mario Störmer<br>
|
||||
Langheide 14<br>
|
||||
24354 Rieseby<br>
|
||||
E-Mail: <a href="mailto:mario.stoerner@langhei.de">mario.stoerner@langhei.de</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>2. Grundsätze der Datenverarbeitung</h2>
|
||||
<p>
|
||||
LibreDeck verarbeitet keine personenbezogenen Daten dauerhaft. Es werden keine
|
||||
Nutzerkonten angelegt, keine Registrierung verlangt und keine Daten persistent
|
||||
auf dem Server gespeichert. Alle Verarbeitungsschritte finden ausschließlich
|
||||
im Arbeitsspeicher während einer aktiven Sitzung statt.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>3. Zugriffsdaten / Server-Logs</h2>
|
||||
<p>
|
||||
Beim Aufruf der Website werden vom Webserver automatisch allgemeine Zugriffsdaten
|
||||
erfasst (sog. Server-Logs): IP-Adresse, Zeitpunkt des Zugriffs, aufgerufene URL,
|
||||
HTTP-Statuscode, übertragene Datenmenge sowie Referrer und Browser-Kennung.
|
||||
Diese Daten werden ausschließlich zur Sicherstellung des technischen Betriebs
|
||||
verwendet und nach spätestens 7 Tagen gelöscht. Rechtsgrundlage ist
|
||||
Art. 6 Abs. 1 lit. f DSGVO (berechtigtes Interesse am sicheren Betrieb).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>4. Cookies und Sitzungsdaten</h2>
|
||||
<p>
|
||||
LibreDeck setzt ausschließlich technisch notwendige Session-Cookies ein
|
||||
(JSESSIONID). Diese dienen dazu, während einer Browsersitzung den
|
||||
Authentifizierungsstatus gegenüber den verbundenen Streaming-Diensten
|
||||
aufrechtzuerhalten. Das Cookie wird beim Schließen des Browsers automatisch
|
||||
gelöscht. Es findet keine Auswertung für Werbe- oder Trackingzwecke statt.
|
||||
</p>
|
||||
<p>
|
||||
Rechtsgrundlage: Art. 6 Abs. 1 lit. b DSGVO (Vertragserfüllung, da das Cookie
|
||||
für den Betrieb des Dienstes technisch erforderlich ist).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>5. Verbindung mit Streaming-Diensten</h2>
|
||||
<p>
|
||||
Wenn Sie sich über LibreDeck mit einem Streaming-Dienst (Deezer, Spotify, Tidal,
|
||||
Apple Music, YouTube) verbinden, werden Sie zur Anmeldeseite des jeweiligen
|
||||
Anbieters weitergeleitet. LibreDeck erhält anschließend ein zeitlich begrenztes
|
||||
Zugriffstoken, das nur für die Dauer Ihrer Sitzung gespeichert wird. Die
|
||||
eigentliche Authentifizierung und die damit verbundene Datenverarbeitung erfolgt
|
||||
beim jeweiligen Drittanbieter; dessen Datenschutzbestimmungen gelten:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Spotify: <a href="https://www.spotify.com/de/legal/privacy-policy/" target="_blank" rel="noopener">Datenschutzrichtlinie Spotify</a></li>
|
||||
<li>Deezer: <a href="https://www.deezer.com/legal/personal-datas" target="_blank" rel="noopener">Datenschutzrichtlinie Deezer</a></li>
|
||||
<li>Tidal: <a href="https://tidal.com/privacy" target="_blank" rel="noopener">Datenschutzrichtlinie Tidal</a></li>
|
||||
<li>Apple Music: <a href="https://www.apple.com/de/legal/privacy/" target="_blank" rel="noopener">Datenschutzrichtlinie Apple</a></li>
|
||||
<li>YouTube: <a href="https://policies.google.com/privacy" target="_blank" rel="noopener">Datenschutzrichtlinie Google</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>6. MusicBrainz</h2>
|
||||
<p>
|
||||
Zur Ermittlung von Erscheinungsjahren werden Künstlername und Titel einzelner
|
||||
Tracks an die öffentliche API von MusicBrainz (MetaBrainz Foundation, USA)
|
||||
übermittelt. Es handelt sich dabei um keine personenbezogenen Daten.
|
||||
Weitere Informationen: <a href="https://metabrainz.org/privacy" target="_blank" rel="noopener">MetaBrainz Datenschutzrichtlinie</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>7. Ihre Rechte</h2>
|
||||
<p>Nach der DSGVO stehen Ihnen folgende Rechte zu:</p>
|
||||
<ul>
|
||||
<li><strong>Auskunft</strong> (Art. 15 DSGVO): Sie können Auskunft über die zu Ihrer Person gespeicherten Daten verlangen.</li>
|
||||
<li><strong>Berichtigung</strong> (Art. 16 DSGVO): Sie können die Berichtigung unrichtiger Daten verlangen.</li>
|
||||
<li><strong>Löschung</strong> (Art. 17 DSGVO): Sie können die Löschung Ihrer Daten verlangen, soweit keine gesetzliche Aufbewahrungspflicht entgegensteht.</li>
|
||||
<li><strong>Einschränkung</strong> (Art. 18 DSGVO): Sie können die Einschränkung der Verarbeitung Ihrer Daten verlangen.</li>
|
||||
<li><strong>Widerspruch</strong> (Art. 21 DSGVO): Sie können der Verarbeitung Ihrer Daten widersprechen, soweit diese auf Art. 6 Abs. 1 lit. f DSGVO beruht.</li>
|
||||
<li><strong>Beschwerderecht</strong> (Art. 77 DSGVO): Sie haben das Recht, sich bei einer Datenschutzaufsichtsbehörde zu beschweren.</li>
|
||||
</ul>
|
||||
<p>Anfragen richten Sie bitte an: <a href="mailto:mario.stoerner@langhei.de">mario.stoerner@langhei.de</a></p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>8. Änderungen</h2>
|
||||
<p>
|
||||
Wir behalten uns vor, diese Datenschutzerklärung anzupassen, um sie stets den
|
||||
aktuellen rechtlichen Anforderungen oder Änderungen am Dienst anzupassen.
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="section-inner footer-inner">
|
||||
<img th:src="@{/images/logo.png}" alt="LibreDeck" class="footer-logo-img">
|
||||
<p>Keine Datenspeicherung · Kein Account erforderlich</p>
|
||||
<div class="footer-links">
|
||||
<a th:href="@{/impressum}">Impressum</a>
|
||||
<span aria-hidden="true">·</span>
|
||||
<a th:href="@{/datenschutz}">Datenschutz</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
94
src/main/resources/templates/impressum.html
Normal file
94
src/main/resources/templates/impressum.html
Normal file
@@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Impressum – LibreDeck</title>
|
||||
<link rel="icon" type="image/png" th:href="@{/images/favicon.png}">
|
||||
<link rel="stylesheet" th:href="@{/css/style.css}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="legal-header">
|
||||
<div class="section-inner">
|
||||
<a th:href="@{/}" class="legal-back">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round" width="18" height="18" aria-hidden="true">
|
||||
<polyline points="15 18 9 12 15 6"/>
|
||||
</svg>
|
||||
Zurück
|
||||
</a>
|
||||
<img th:src="@{/images/logo.png}" alt="LibreDeck" class="legal-logo">
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="legal-main">
|
||||
<div class="section-inner legal-inner">
|
||||
<h1>Impressum</h1>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Angaben gemäß § 5 TMG</h2>
|
||||
<p>
|
||||
Mario Störmer<br>
|
||||
Langheide 14<br>
|
||||
24354 Rieseby
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Kontakt</h2>
|
||||
<p>E-Mail: <a href="mailto:mario.stoerner@langhei.de">mario.stoerner@langhei.de</a></p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>EU-Streitbeilegung</h2>
|
||||
<p>
|
||||
Die Europäische Kommission stellt eine Plattform zur Online-Streitbeilegung (OS) bereit:
|
||||
<a href="https://ec.europa.eu/consumers/odr/" target="_blank" rel="noopener">
|
||||
https://ec.europa.eu/consumers/odr/
|
||||
</a>.<br>
|
||||
Unsere E-Mail-Adresse finden Sie oben im Impressum.
|
||||
</p>
|
||||
<p>
|
||||
Wir sind nicht bereit oder verpflichtet, an Streitbeilegungsverfahren vor einer
|
||||
Verbraucherschlichtungsstelle teilzunehmen.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Haftung für Inhalte</h2>
|
||||
<p>
|
||||
Als Diensteanbieter sind wir gemäß § 7 Abs. 1 TMG für eigene Inhalte auf diesen Seiten
|
||||
nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als
|
||||
Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde
|
||||
Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige
|
||||
Tätigkeit hinweisen.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-section">
|
||||
<h2>Urheberrecht</h2>
|
||||
<p>
|
||||
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen
|
||||
dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art
|
||||
der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen
|
||||
Zustimmung des jeweiligen Autors bzw. Erstellers.
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="section-inner footer-inner">
|
||||
<img th:src="@{/images/logo.png}" alt="LibreDeck" class="footer-logo-img">
|
||||
<p>Keine Datenspeicherung · Kein Account erforderlich</p>
|
||||
<div class="footer-links">
|
||||
<a th:href="@{/impressum}">Impressum</a>
|
||||
<span aria-hidden="true">·</span>
|
||||
<a th:href="@{/datenschutz}">Datenschutz</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -216,6 +216,28 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Android Download ── -->
|
||||
<section class="download-section" id="androidDownload" style="display:none">
|
||||
<div class="section-inner download-inner">
|
||||
<div class="download-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="5" y="2" width="14" height="20" rx="2"/><line x1="12" y1="18" x2="12" y2="18.01"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="download-text">
|
||||
<h2>Android-App</h2>
|
||||
<p>Scanne deine Karten direkt mit der App – öffnet den richtigen Streaming-Dienst per Tap.</p>
|
||||
<a href="/downloads/libredeck.apk" class="btn btn-lg download-btn" download>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18" aria-hidden="true" style="flex-shrink:0">
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
|
||||
</svg>
|
||||
APK herunterladen
|
||||
</a>
|
||||
<p class="download-hint">Android · Sideload · Einstellungen → Apps → Unbekannte Quellen erlauben</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Card detail ── -->
|
||||
<section class="detail-section">
|
||||
<div class="section-inner detail-inner">
|
||||
@@ -458,36 +480,40 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Android Download ── -->
|
||||
<section class="download-section">
|
||||
<div class="section-inner download-inner">
|
||||
<div class="download-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="5" y="2" width="14" height="20" rx="2"/><line x1="12" y1="18" x2="12" y2="18.01"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="download-text">
|
||||
<h2>Android-App</h2>
|
||||
<p>Scanne deine Karten direkt mit der App – öffnet den richtigen Streaming-Dienst per Tap.</p>
|
||||
<a href="/downloads/libredeck.apk" class="btn btn-lg download-btn" download>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18" aria-hidden="true" style="flex-shrink:0">
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
|
||||
</svg>
|
||||
APK herunterladen
|
||||
</a>
|
||||
<p class="download-hint">Android · Sideload · Einstellungen → Apps → Unbekannte Quellen erlauben</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Footer ── -->
|
||||
<footer class="site-footer">
|
||||
<div class="section-inner footer-inner">
|
||||
<img th:src="@{/images/logo.png}" alt="LibreDeck" class="footer-logo-img">
|
||||
<p>Keine Datenspeicherung · Kein Account erforderlich</p>
|
||||
<div class="footer-links">
|
||||
<a th:href="@{/impressum}">Impressum</a>
|
||||
<span aria-hidden="true">·</span>
|
||||
<a th:href="@{/datenschutz}">Datenschutz</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- ── Cookie Banner ── -->
|
||||
<div id="cookieBanner" class="cookie-banner" role="dialog" aria-label="Cookie-Hinweis" style="display:none">
|
||||
<p class="cookie-text">
|
||||
Diese Website verwendet ausschließlich technisch notwendige Cookies zur Aufrechterhaltung
|
||||
der Sitzung. Es findet kein Tracking statt.
|
||||
<a href="/datenschutz">Datenschutzerklärung</a>
|
||||
</p>
|
||||
<button class="btn btn-sm cookie-btn" onclick="acceptCookies()">Verstanden</button>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
if (!localStorage.getItem('cookieConsent')) {
|
||||
document.getElementById('cookieBanner').style.display = 'flex';
|
||||
}
|
||||
})();
|
||||
function acceptCookies() {
|
||||
localStorage.setItem('cookieConsent', '1');
|
||||
document.getElementById('cookieBanner').style.display = 'none';
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- ── Bulk-check warning dialog ── -->
|
||||
<div id="bulkCheckDialog" style="display:none" role="dialog" aria-modal="true" aria-labelledby="bulkCheckTitle">
|
||||
<div class="dialog-backdrop" onclick="document.getElementById('bulkCheckDialog').style.display='none'"></div>
|
||||
@@ -537,6 +563,11 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// ── Android download banner ──
|
||||
if (/Android/i.test(navigator.userAgent)) {
|
||||
document.getElementById('androidDownload').style.display = '';
|
||||
}
|
||||
|
||||
// ── Unified service state ──
|
||||
const SERVICES = ['Spotify', 'Tidal', 'Deezer', 'Apple Music', 'YouTube'];
|
||||
const GEN_IDS = ['panelSpotify', 'panelTidal', 'panelDeezer', 'panelApple', 'panelYoutube'];
|
||||
|
||||
Reference in New Issue
Block a user