Feature: Welten-Onboarding, Wetter-Motivation, UX-Fixes (SW by-v715)

Welten (worlds.js):
- Swipe-Hints beim ersten Öffnen (JETZT ← → WELT animiert, einmalig)
- Kein-Hund-Onboarding: Feature-Preview-Grid statt leerer Karte
- Hintergrund-Foto-Hint: Kamera-Karte wenn noch kein Tagebuchfoto
- worlds-back: navigiert zu Welcome wenn kein User eingeloggt
- Nach Logout: worlds-back Button sofort ausgeblendet

Wetter (wetter.js):
- Standort-Fehlerseite zu Motivations-Seite umgebaut
- Feature-Preview: Gassi-Score, 7-Tage, Regenradar, Rekorde
- CTA: Standort freigeben + Registrieren (nur für Gäste)

Settings (settings.js):
- Logo in Auth-Form: display:block + margin:0 auto zentriert
- Header bleibt sichtbar (FAB/Zurück-Navigation funktioniert)

Jobs (jobs.js):
- 2-Spalten-Grid auf Mobile: auto-fit statt festes 1fr 1fr
- Kein doppeltes Padding im Wrapper

Backend:
- weather.py, achievements.py: diary JOIN fix (d.user_id → dogs JOIN)
- Neue Wetter-Badges: wetter_tapfer, jahreszeiten, schnee
- Ernährungs-, Reise-, Ausgaben-Seite: diverse UX-Verbesserungen
- Presse-Seite erweitert
- Ban Yaro Foto-Assets (WebP + HIRES JPG)
This commit is contained in:
rene 2026-05-05 17:32:03 +02:00
parent aa4849d947
commit 55069d246b
28 changed files with 719 additions and 198 deletions

View file

@ -178,6 +178,17 @@ def generate_preview(data: bytes, ext: str) -> bytes | None:
return None
def get_image_size(data: bytes) -> tuple[int, int] | None:
"""Gibt (width, height) eines Bildes zurück, oder None bei Fehler."""
try:
from PIL import Image, ImageOps
img = Image.open(io.BytesIO(data))
img = ImageOps.exif_transpose(img)
return img.size # (width, height)
except Exception:
return None
def preview_url_from(url: str | None) -> str | None:
"""Leitet die Preview-URL aus der Original-URL ab (fügt _preview vor Extension ein).
Gibt None für Videos, PDFs, bereits generierte Previews und leere URLs zurück."""