From d0a76e1b54f1e5290ae9e15a85937138cfb73204 Mon Sep 17 00:00:00 2001 From: rene Date: Sun, 14 Jun 2026 21:33:23 +0200 Subject: [PATCH] =?UTF-8?q?Ban=20Yaro=20Blues=20=E2=80=94=20Hymne=20in=20d?= =?UTF-8?q?er=20WELT-Welt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eigener Song (KI-Demo via Suno) als Marken-Hymne. Dezente Player-Karte unter dem Tageszitat; preload=none → 6 MB MP3 lädt erst bei Play, der SW cacht sie danach für offline. Der Banner ist einmalige Einladung und verschwindet nach erstem Hören (durchgehört oder >30s + Pause); danach dezenter runder Play-Button unten links als Gegenspieler zum FAB, nur in WELT. Audio-Element zentral in index.html → übersteht Welt-Wechsel & Re-Renders. „Gehört" wird hybrid gemerkt: localStorage (sofort/offline) + DB-Flag anthem_heard am User (neue Spalte, über /auth/me, gesetzt via POST /api/profile/anthem-heard) — geräte- und deploy-übergreifend, damit der Banner nicht erneut nervt. --- VERSION | 2 +- backend/database.py | 1 + backend/routes/auth.py | 2 +- backend/routes/profile.py | 10 +++ backend/static/css/components.css | 23 ++++++ backend/static/index.html | 30 ++++---- backend/static/js/app.js | 2 +- backend/static/js/worlds.js | 93 +++++++++++++++++++++++ backend/static/landing.html | 2 +- backend/static/sounds/ban-yaro-blues.mp3 | Bin 0 -> 6280918 bytes backend/static/sw.js | 2 +- 11 files changed, 149 insertions(+), 18 deletions(-) create mode 100644 backend/static/sounds/ban-yaro-blues.mp3 diff --git a/VERSION b/VERSION index 364aacb..1f5e025 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1292 \ No newline at end of file +1295 \ No newline at end of file diff --git a/backend/database.py b/backend/database.py index 4f3ce10..a26bd07 100644 --- a/backend/database.py +++ b/backend/database.py @@ -605,6 +605,7 @@ def _migrate(conn_factory): ("notes", "location_name", "TEXT"), ("notes", "parent_label", "TEXT"), ("users", "notes_ki_enabled", "INTEGER NOT NULL DEFAULT 1"), + ("users", "anthem_heard", "INTEGER NOT NULL DEFAULT 0"), # Züchter-Rolle ("users", "breeder_status", "TEXT"), # Würfe: Verknüpfung mit Zuchtkartei-Hunden + Welfare diff --git a/backend/routes/auth.py b/backend/routes/auth.py index 403eae8..771f735 100644 --- a/backend/routes/auth.py +++ b/backend/routes/auth.py @@ -398,7 +398,7 @@ async def me(user=Depends(get_current_user)): bio, wohnort, erfahrung, social_link, profil_sichtbarkeit, avatar_url, created_at, is_founder, is_partner, founder_number, is_founder_pending, - notes_ki_enabled, gassi_stunde_push, + notes_ki_enabled, gassi_stunde_push, anthem_heard, preferred_theme, subscription_tier, subscription_expires_at, subscription_cancelled_at, needs_dog_selection, billing_address, geburtstag diff --git a/backend/routes/profile.py b/backend/routes/profile.py index bf16ce0..17cc159 100644 --- a/backend/routes/profile.py +++ b/backend/routes/profile.py @@ -50,6 +50,16 @@ def _load_user(user_id: int) -> dict: return data +@router.post("/anthem-heard", status_code=204) +async def mark_anthem_heard(user=Depends(get_current_user)): + """Merkt server-seitig, dass die Hymne gehört wurde — geräteübergreifend und + übersteht Cache-Clear bzw. die iOS-Trennung von PWA- und Safari-localStorage, + damit der Banner nach einem Deploy nicht erneut auftaucht.""" + with db() as conn: + conn.execute("UPDATE users SET anthem_heard=1 WHERE id=?", (user["id"],)) + return None + + @router.patch("") async def update_profile(data: ProfileUpdate, user=Depends(get_current_user)): fields = data.model_dump(exclude_none=True) diff --git a/backend/static/css/components.css b/backend/static/css/components.css index a96b2ab..cad9fcd 100644 --- a/backend/static/css/components.css +++ b/backend/static/css/components.css @@ -8267,6 +8267,29 @@ svg.empty-state-icon { } #worlds-fab:active { transform: scale(0.92); box-shadow: 0 2px 10px rgba(196,132,58,0.3); } +/* Hymne-Button — Gegenspieler zum FAB, unten links, nur WELT + nach erstem Hören */ +#worlds-anthem { + position: fixed; + bottom: calc(env(safe-area-inset-bottom, 16px) + 16px); + left: 20px; + width: 54px; height: 54px; + border-radius: 50%; + background: rgba(22,26,30,0.66); + -webkit-backdrop-filter: blur(8px); + backdrop-filter: blur(8px); + color: #fff; + border: 1px solid rgba(255,255,255,0.20); + cursor: pointer; + z-index: 60; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 18px rgba(0,0,0,0.40); + transition: transform 0.12s, background 0.2s; +} +#worlds-anthem:active { transform: scale(0.92); } +#worlds-anthem.playing { background: var(--c-primary); border-color: transparent; } + /* Header + Bottom-Nav: vollständig entfernt — Welten übernehmen Navigation */ #app-header { display: none !important; } #bottom-nav { display: none !important; } diff --git a/backend/static/index.html b/backend/static/index.html index 830ff54..58232ad 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -86,14 +86,14 @@ Ban Yaro - + - - - - - + + + + + @@ -596,6 +596,10 @@
+ +