diff --git a/backend/main.py b/backend/main.py index 28aac79..6085b5a 100644 --- a/backend/main.py +++ b/backend/main.py @@ -406,7 +406,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "929" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "930" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/routes/dogs.py b/backend/routes/dogs.py index 405856f..7ec90f5 100644 --- a/backend/routes/dogs.py +++ b/backend/routes/dogs.py @@ -844,13 +844,14 @@ async def upload_photo( file: UploadFile = File(...), user=Depends(get_current_user) ): - # Hund gehört dem User? + # Hund gehört dem User? Altes Foto merken für späteres Löschen. with db() as conn: dog = conn.execute( - "SELECT id FROM dogs WHERE id=? AND user_id=?", (dog_id, user["id"]) + "SELECT id, foto_url FROM dogs WHERE id=? AND user_id=?", (dog_id, user["id"]) ).fetchone() if not dog: raise HTTPException(404, "Hund nicht gefunden.") + old_foto_url = dog["foto_url"] # Datei immer als JPEG speichern (HEIC/PNG/WebP → kompatibel für alle Browser) import io @@ -884,6 +885,15 @@ async def upload_photo( with db() as conn: conn.execute("UPDATE dogs SET foto_url=? WHERE id=?", (foto_url, dog_id)) + # Altes Foto von Disk löschen + if old_foto_url: + try: + old_path = safe_media_path(MEDIA_DIR, old_foto_url) + if old_path and os.path.isfile(old_path): + os.remove(old_path) + except Exception: + pass + return {"foto_url": foto_url} diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 22413d4..b950790 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '929'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '930'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/js/pages/dog-profile.js b/backend/static/js/pages/dog-profile.js index 8e18db5..5af569d 100644 --- a/backend/static/js/pages/dog-profile.js +++ b/backend/static/js/pages/dog-profile.js @@ -1380,6 +1380,10 @@ window.Page_dog_profile = (() => { saved.foto_url = result.foto_url; _appState.activeDog = { ...saved }; _appState.dogs = _appState.dogs.map(d => d.id === saved.id ? _appState.activeDog : d); + // Hintergrund-Cache invalidieren damit Welten das neue Foto zeigen + const userId = _appState.user?.id || 'anon'; + const todayKey = `w3_bg3_${userId}_` + new Date().toISOString().slice(0, 10); + localStorage.removeItem(todayKey); } catch { UI.toast.warning('Profil gespeichert, Foto konnte nicht hochgeladen werden.'); } diff --git a/backend/static/sw.js b/backend/static/sw.js index 8895786..c3c3957 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v929'; +const CACHE_VERSION = 'by-v930'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache