Commit graph

10 commits

Author SHA1 Message Date
d807db57a2 1.1: Home-Screen-Widget + Siri-Kurzbefehl „Gassi gehen"
App Group group.app.banyaro.ios verbindet App und Widget-Extension
(Entitlements in beiden Targets, CODE_SIGN_ENTITLEMENTS fürs Widget).

Home-Screen-Widget (D):
- BanYaroHomeWidget (klein + mittel): Tagesfoto, Hundename, nächster Termin.
- App schreibt beim Heim-Laden einen Snapshot (HomeWidgetData) in die App
  Group und triggert WidgetCenter-Reload; Snapshot wird bei Logout/401 geleert.

Siri-/Kurzbefehl (E):
- StartWalkIntent „Gassi gehen" + AppShortcutsProvider (öffnet die App).
- WalkLauncher überbrückt Intent → UI: Flag in der App Group, beim Aktivwerden
  eingelöst → Aufnehmen-Tab + Aufnahme-Start (TrackingView.startFresh).
- MainTabView mit Tab-Auswahl (Tags), BanYaroGoApp liest scenePhase.
2026-06-02 20:01:16 +02:00
a2646a18ef 1.1: Offline-Cache + Outbox für Touren/Tagebuch, WeatherKit-Fix, Aufräumen
App-Review-Fix (Guideline 2.1 WeatherKit):
- OneShotLocation: deterministisches async resolve() mit 10s-Timeout statt
  onChange-Lauschen; WetterView lädt bei fehlendem Standort einen Berlin-Fallback
  → kein ewiges Hängen bei "Hole Standort…", WeatherKit ist immer sichtbar.

Offline-Lesen (SwiftData):
- CachedRoute/CachedDiaryEntry/CachedImage + CachedAsyncImage: Touren, Tagebuch
  und Fotos werden cache-first geladen und sind offline verfügbar.
- Cache wird bei Logout/401 geleert (RootView), kein Durchschimmern fremder User.

Offline-Speichern (Outbox):
- PendingRoute/PendingRoutePhoto: Tour inkl. unterwegs hinzugefügter Fotos wird
  offline lokal gesichert und automatisch hochgeladen (Touren-Tab + App-Start).
- Touren-Liste zeigt offline gesicherte Touren mit "wird hochgeladen"-Badge.

FinishWalkSheet:
- Dismiss-Schutz: Speichern-Dialog lässt sich nicht mehr wegwischen — eine
  aufgezeichnete Tour geht nicht mehr durch Runterwischen verloren.

Wetter:
- Ortslabel (Reverse-Geocoding; Fallback "Berlin · Näherung").
- Saubere Offline-Meldung statt rohem networkError.

Aufräumen:
- Doppeltes "Gassi-Treffen" im Mehr-Tab entfernt.
- Veraltete Phase-1/2-Texte neu getextet.
- Tote DogsListView gelöscht (Hund-Wechsel läuft über den Heim-Picker).
2026-06-02 19:37:30 +02:00
546386dcbd Hunde-Cache leeren bei Logout/401 — kein Durchschimmern auf neuen User
Bug: ActiveDogStore cached dogs + activeDogId (UserDefaults). Beim
Login mit einem neuen Account waren die Hunde des vorigen Users
weiter zu sehen, weil HeimView nur loadDogs() ruft wenn dogs.isEmpty.

Fix:
- ActiveDogStore hat jetzt reset() (dogs=[], activeDogId=0,
  UserDefaults gelöscht).
- ActiveDogStore hört auf .userDidLogout und auf .apiUnauthorized,
  beides löst reset() aus.
- AuthSession.logout() postet jetzt .userDidLogout.
- Nach Login holt HeimView's .task automatisch die neuen Hunde
  (dogs.isEmpty → loadDogs).
2026-05-30 18:25:23 +02:00
7848817cbe GPX-Import via Teilen-Menü und 'Öffnen mit'
Andere Apps können jetzt GPX-Tracks zu Ban Yaro Go schicken (Komoot,
Outdooractive, GPSies, AllTrails, Files-App, Mail-Anhänge, AirDrop).

- Info.plist:
  - UTImportedTypeDeclarations: com.topografix.gpx (conforms to
    public.xml/data/content, ext gpx, MIME application/gpx+xml)
  - CFBundleDocumentTypes registriert die UTI als Viewer (LSHandlerRank
    Alternate, damit wir nicht die Default-App werden)
  - LSSupportsOpeningDocumentsInPlace=true
- Support/GPXParser.swift: schlanker XMLParser/SAX-Reader für
  <trkpt>/<wpt>/<rtept>, Track-Name aus <trk><name>, ele + ISO8601 time
- Views/GPXImportSheet.swift: Sheet mit Map(MapPolyline)+Start/Ziel-Pins,
  Distanz/Punkte/Dauer-Karte, zwei Aktionen:
    1. 'Als Tour übernehmen' — Name editierbar, Hunde-Picker (FlowDogs),
       öffentlich-Toggle → POST /api/routes
    2. 'Nur ansehen' — Startpunkt in Apple Maps
- BanYaroGoApp.swift: .onOpenURL prüft .gpx, security-scoped resource,
  parst und triggert das Sheet via TrackBox-Wrapper
2026-05-30 14:34:40 +02:00
08069d6ea4 Wetter: deutsche Conditions + Asphalt-Label entrümpelt
- WeatherCondition deutsch: 'Mostly Clear' → 'Überwiegend klar' etc.
- AsphaltLevel.label nur noch ein Wort (Heiß/Warm/Gefährlich),
  die safety-Info wandert in den advice-Text → Title bleibt einzeilig
2026-05-30 13:30:01 +02:00
357c57e880 Gassi-Wetter mit WeatherKit + banyaro-Logik
WeatherKit als Datenquelle (statt OpenMeteo-Proxy via banyaro-Backend):
- BanYaroGo.entitlements: com.apple.developer.weatherkit
- WetterView komplett neu mit WeatherService.shared.weather(for:)
- DayWeather.symbolName als SF-Symbol direkt, kein WMO-Mapping nötig

GassiWetter-Logik (1:1-Port aus banyaro PWA wetter.js):
- gassiScore(...) 1-10 mit Temp/Regen/Wind/Asphalt/Gewitter
- asphaltTemp(airMax, uvMax) — gleiche Formel mit t_factor und UV-Bonus
- asphaltLevel safe/warm/hot/danger mit Advice-Texten
- schnueffelIndex aus Feuchte (precipProb-derived) und Temperatur
- tickRisk March-Oktober, Schwellen 7/12/20°C
- pawColdProtection bei tempMin <= 0

UI:
- Horizontaler Tag-Picker (Heute/Morgen + EEE) mit Mini-Stats
- Großer Gassi-Score-Badge in Empfehlungs-Farbe (grün/amber/rot)
- Stats-Grid 2x2: Niederschlag, Wind, UV, Asphalt
- Hunde-Hinweise als farbige Boxen (Asphalt, Pfoten, Gewitter, Zecken)
- Schnüffel-Index als kompakte Karte mit Emoji

Color(hex:)-Extension für die HEX-Werte aus dem PWA übernommen.
2026-05-30 13:16:48 +02:00
f054b2a07f Tagebuch + Heim-Tab mit täglichem Background
Tagebuch (Diary):
- DiaryEntry + DiaryMedia + DiaryCreateBody DTOs
- TagebuchView: Liste der Einträge für aktiven Hund mit Titel, Text,
  Ortsname, Meilenstein-Stern, Foto-Strip
- AddDiaryEntrySheet: Titel/Text/Datum/Meilenstein/Ort/Tags +
  PhotosPicker, nach POST /api/dogs/{id}/diary werden Fotos einzeln
  via POST /api/dogs/{id}/diary/{entry_id}/media hochgeladen (mit
  ImageResize.resizedJPEG)

Heim-Tab als neuer 1. Tab:
- DashboardSnapshot DTO für /api/dogs/{id}/welcome-dashboard
- ActiveDogStore (@Observable + UserDefaults("activeDogId")): hält
  den aktiven Hund app-weit
- HeimView: tägliches Hintergrundfoto aus random_photo.url (rotiert
  pro Tag, vom Backend gewählt), Gradient zur Lesbarkeit, Tagezeit-
  Begrüßung mit User-Namen, Hund-Picker (Menu), Info-Karten für
  letzten Eintrag/nächsten Termin/Gewicht/Eintragszahl,
  Quick-Action-Buttons (Tagebuch, Wetter, Erste Hilfe)

Reorganisation:
- 5 Tabs: Heim, Touren, Aufnehmen, Statistik, Mehr
- Hunde-Liste wandert in Mehr → "Hund & Alltag"
- Tagebuch in Mehr → "Hund & Alltag" + erreichbar von Heim
2026-05-30 12:22:51 +02:00
68b084be97 Sechs Offline-Features: Erste Hilfe, Ausgaben, Wetter, Gassi-Zeiten, Giftköder, Verlorene
Pitch-Karte erweitert um die neuen Features (sowie Hundesitting, Züchter).

Neue DTOs in DTOs.swift:
- Expense + ExpenseCreateBody
- GassiZeit + GassiZeitCreateBody (mit wochentage [String], radius_m)
- PoisonAlert + PoisonCreateBody
- LostDog + LostDogCreateBody
- WeatherForecast + WeatherDay (mit asphalt_temp, zecken, pollen-Felder)

Neue Views:
- ErsteHilfeView + Detail: sechs Notfall-Topics (Vergiftung, Hitzschlag,
  Wunden, Atemnot, Krampfanfall, Magendrehung) — komplett offline, kein API
- AusgabenView: Liste mit Total, AddExpenseSheet mit Kategorie/Betrag/
  Datum/Hund-Picker
- WetterView: One-Shot Location + /api/weather/forecast, 7-Tage-Vorhersage
  mit Hunde-Tipps (Hitze ab 25°/30°, Frost, Asphalt ≥50°, Zecken, Regen)
- GassiZeitenView: eigene Zeiten + Add-Sheet (Wochentag-Picker, Hund-
  Auswahl), automatische lokale UNCalendarNotifications via Scheduler
- GiftkoederView: Map mit Pins + Liste in 5km Umkreis, Report-Sheet mit
  Typ-Auswahl
- VerloreneHundeView: Liste mit Foto/Distanz, Detail mit Karte

Support:
- OneShotLocation: kleiner CLLocationManager-Wrapper für einmalige
  Positionsabfrage (Wetter, Giftköder)
- GassiZeitenScheduler: UNCalendarNotificationTrigger pro Wochentag,
  Identifier-Schema "gz-{id}-{weekday}"

Navigation: Section "Hund & Alltag" im Mehr-Tab mit NavigationLinks zu
allen sechs neuen Ansichten.
2026-05-30 12:03:24 +02:00
c01e3d6be7 Phase 3.6: B+C+D komplett + HealthKit Sync
D.10 401-Handling: APIError.unauthorized, NotificationCenter-Bridge,
  AuthSession.logout() bei 401 → User landet wieder im Login

D.12 PWA-Deep-Links: Settings-Section mit Forum/Hunde/Walks/Settings
  öffnet Safari per https://banyaro.app/#fragment

B.4 Auto-Pause: 2-min-Inaktivität → isAutoPaused, automatischer Resume bei
  nächstem GPS-Update. Settings-Toggle, im UI eigenes Badge "Auto-Pause"
  (grau vs. Pause orange).

C.7 Edit/Delete: RouteUpdateBody + APIClient.patch + APIClient.delete,
  EditRouteSheet (Name/Beschreibung/Public), Menu in Toolbar (nur eigene
  Touren), Alert für Delete.

C.9 Statistik-Tab: neuer Tab "Statistik" zwischen Hunde und Mehr. Filtert
  /api/routes auf meine Touren, rechnet Woche/Monat/Allzeit (Distanz, Dauer,
  Touren), Längste Tour, aktuelle Streak (Tage in Folge).

B.5 Walk-Review: Map-Header an die Spitze des FinishWalkSheet-Forms.

B.6 Geo-Fotos: CapturedPhoto (Data + GPSPoint?), PhotoLocation @Model in
  SwiftData. Kamera während Walk taggt mit tracker.points.last. Nach Upload:
  foto_url aus Response → PhotoLocation persistiert. MiniRouteMap rendert
  Annotations mit Tap-Callback, PhotoViewerSheet zeigt Foto fullscreen.

C.8 Share PNG+GPX: RouteShareImage (MKMapSnapshotter + Polyline overlay +
  SwiftUI ShareCard via ImageRenderer), GPXExporter (Tempfile mit XML),
  ShareSheet (UIActivityViewController-Wrapper), Menu in Route-Toolbar.

D.11 Icon-Varianten: AppIcon-Dark (0.45 Brightness), AppIcon-Tinted
  (Grayscale + Kontrastverstärkung), Contents.json mit appearance entries.

A.2 HealthKit: BanYaroGo.entitlements (com.apple.developer.healthkit),
  NSHealthShare/UpdateUsageDescription. WalkHealthSync.shared mit
  HKWorkoutBuilder (.walking) + HKWorkoutRouteBuilder, Timestamps gleichmäßig
  über Walk-Dauer verteilt. Settings-Toggle mit Permission-Request.
2026-05-30 11:19:53 +02:00
e27fa39620 Phase 3: Foto-Upload + Mindeststrecken-Warnung
- APIClient.uploadFile: multipart POST mit Bearer-Token, generischer
  field/filename/mime
- ImageResize: längste Kante max 2048px, JPEG q=0.8 — iPhone-Fotos sonst
  5-10MB pro Stück
- FinishWalkSheet:
  - PhotosPicker (iOS 16+, kein NSPhotoLibraryUsageDescription nötig)
  - Thumbnail-Strip der gewählten Fotos
  - Sequentieller Upload nach POST /api/routes, Toolbar zeigt "N/M"
  - Bei < 50m: orangene Warnung "Sehr kurze Tour — du kannst trotzdem speichern"
  - Save-Button blockt korrekt während Upload, Verwerfen auch
2026-05-30 10:18:08 +02:00