Sprint 14: Map-Fixes, City-Prewarm, Dog-Animation, Scan-Flash

Karte:
- Frankfurt-Fallback (Zoom 10→14 flyTo) mit _frankfurtTimer-Cancel
  wenn echter Standort eintrifft
- OSM-Tile-Fetch parallelisiert (asyncio.Semaphore(3))
- Bounds-Fix: invalidateSize() + pad(0.15) vor getBounds()
- map-pin-slash Icon für gesperrten Standort
- Scan-Done-Flash: Statusbar-Pill grün bei 100%
- Schnüffelhund: outer div (by-wander X) + inner SVG (by-sniff Y)
  für natürlichere zweiachsige Bewegung

Backend:
- City-Prewarm-Job: ~70 deutsche Großstädte beim Start (+90s) und
  wöchentlich (So 01:00), Fortschritts-Mails alle 5h an ADMIN_EMAIL
- ADMIN_EMAIL Env-Var in .env.example dokumentiert

Bugfixes:
- Profil-Edit: /api/profile → /profile (doppelter Prefix)
- Friends: Mobile-Portrait-Layout (flex-wrap, overflow-x:hidden)
- Trainingspläne: Pills text-wrap (flex + white-space:normal)
This commit is contained in:
rene 2026-04-17 14:06:10 +02:00
parent cd3f118113
commit 6fcf841594
10 changed files with 340 additions and 32 deletions

View file

@ -4,6 +4,7 @@ Cacht OSM-Daten lokal, erlaubt Nutzern eigene Marker und Meldungen.
"""
import math
import asyncio
import httpx
import logging
from typing import Optional
@ -142,8 +143,11 @@ async def get_pois(
stale = _stale_tiles(type, tiles)
if stale and not fast:
for (x, y) in stale:
await _fetch_and_store_tile(type, x, y)
sem = asyncio.Semaphore(3)
async def _limited(x, y):
async with sem:
await _fetch_and_store_tile(type, x, y)
await asyncio.gather(*[_limited(x, y) for (x, y) in stale])
fetched_fresh = True
with db() as conn:
@ -309,9 +313,16 @@ async def analyze_region(
tiles = _covering_tiles(south, west, north, east, CACHE_ZOOM)
async def _warmup():
for poi_type in OSM_QUERIES:
for (x, y) in _stale_tiles(poi_type, tiles):
sem = asyncio.Semaphore(3)
async def _limited(poi_type, x, y):
async with sem:
await _fetch_and_store_tile(poi_type, x, y)
tasks = [
_limited(pt, x, y)
for pt in OSM_QUERIES
for (x, y) in _stale_tiles(pt, tiles)
]
await asyncio.gather(*tasks)
background_tasks.add_task(_warmup)
return {'status': 'gestartet', 'tiles': len(tiles), 'types': list(OSM_QUERIES.keys())}