TODO: - [x] Fehler: Explore ohne Filterfunktion - [x] Benachrichtigung - Button klein Alles Gelesen markieren. - [x] Head-Bereich verdeckt Handy-Infos nicht lesbarer Bereich Uhrzeit, WIFI Battery - Bitte GoogleRichtlinen beachten - [x] Dark-Mode ? wo ? TODO Neu: - [x] Explore Filter ist jetzt vorhanden, der Rassen-Dropdown, schiebt die Vorhanden elemente nach unten statt darüber zu lappen. - [x] Explore Seite ist nur Halb im Darkmode - [x] Benachrichtiungsseite nicht wirklich im Darkmode TODO Neu2: - [ ] Sprache ist Standard Englisch auch schon im Login-Screen, hier wäre bei der ersten Einwahl in die App, eine Prüfung der Systemsprache wichtig damit direkt Englisch oder Deutsch ausgewählt wird. → Ursache: expo-localization (Geräte-Spracherkennung) ist als natives Modul noch nicht in den Dev-Client eingebunden, daher greift aktuell immer der Englisch-Fallback. Löst sich mit dem geplanten nativen Rebuild von selbst. - [x] Im Feed habe ich als Nutzer keine Möglich einen Beitrag zu Reporten! Das wäre wichtig. Report-Funktion ist in der Webansicht vollfunktionsfähig und wird im Admin-Bereich getrackt. → Melden-Button (⋮) auf jedem Beitrag, 5 Report-Gründe, live getestet (Übermittlung + Speicherung bestätigt). - [x] Bilder lassen sich nicht Vergrößern mit 2 Fingern. → Pinch-to-Zoom im Bild-Viewer ergänzt (ohne neue native Abhängigkeit). Über adb nicht als echte Zwei-Finger-Geste simulierbar, daher nur Code+Typecheck geprüft, nicht live. - [x] Innerhal des Tierprofils + Gesundheitskarte ist der DarkMode nicht umgesetzt → Tierprofil, Profil bearbeiten, Follower/Folgt sowie die komplette Gesundheitsseite (inkl. Einwilligungs-Screen) sind jetzt dark-mode-fähig, live bestätigt. - [x] Gesundheitsdaten werden nicht gespeichert, sowie kein Zurückbutton sobald man fertig ist mit der bearbeitung der daten. → Zurück-Pfeil war nur unsichtbar (schwarz auf schwarzem Header im Dark Mode), jetzt auf allen Unterseiten sichtbar. Speicherproblem lag am Datumsformat (nächster Punkt) plus fehlender Fehlermeldung bei ungültiger Eingabe — beides behoben, End-to-End getestet. - [x] Datum wird Korrekt dargestellt, die eingabe ist aber, aktuelle ansicht JJJJ-MM-DD // korrekt wäre DD-MM-JJJJ → Eingabefelder akzeptieren jetzt TT-MM-JJJJ, werden intern korrekt umgewandelt; ungültige Eingaben zeigen eine Fehlermeldung. - [x] Gewichtsdaten werden nicht als Diagramm angezeigt (feature) → Echtes Feature, kein Bug — noch offen, Rückmeldung ob/wann gewünscht. → **Umgesetzt (04.10.):** Neues `WeightChart` (`src/components/health/WeightChart.tsx`, Port des Web-Diagramms mit `react-native-svg`) erscheint ab 2 Einträgen über der Gewichtsliste. Die x-Achse ist zeitproportional (unregelmäßige Wiegetermine werden nicht verzerrt), die y-Achse hat runde Werte, Datumslabels überlappen nicht (bei über einem Jahr „Feb. 25“). Antippen wählt die nächste Messung, Wert + Datum stehen im Kopf; rechts die Veränderung seit der ersten Messung. Linienfarbe als neues Token `chartLine` (#ea580c), mit dem Dataviz-Validator gegen helle und dunkle Flächen geprüft (Kontrast ≥ 3:1). Geometrie in `src/lib/weight-chart.ts` mit 11 Tests; die Darstellung habe ich als Vorschau mit der echten Geometrie in Hell + Dunkel gerendert und geprüft. Commit `e60abba`, OTA Runtime 1.0.6: Android `16d95168-caf2-4c0d-a0c7-730acd1bfb96`, iOS `d8e82f19-2a66-4f21-9558-b16296a7ba3f`. Nicht auf einem Gerät getestet. - [x] Technische Frage, was wird beim Feed abgerufen? Zum vergleich in der Web umgebung wird mein feed(followerbezogen) und der trend (könnte dir auch gefallen) seperat eingeblendet, wird in der App eine kombination daraus gemacht ? falls ja super. → Nein: Mobile Feed zeigt ausschließlich den chronologischen Follower-Feed (feed.getFeed, mode "chrono"). Web's separater "Trending"-Tab (explore.getTrending, "könnte dir auch gefallen") ist in der App noch gar nicht gebaut — bekannte Lücke, bereits in der README dokumentiert. - [x] unter meine Tiere, bitte Impressum datenschutz und agbs als link einbinden. sowie eine Versionsnummer der App → Links + "Version 1.0.0" unterhalb der Sprachauswahl ergänzt, live getestet (Impressum öffnet im Browser). - [x] Symbole für Deutsch Englisch und Automatisch im Meine tiere menü ändern. auf flaggen z.b. → 🇩🇪 / 🇬🇧 / 🌐 statt Icon, live bestätigt. - [x] Benachrichtigungen trennen zwischen den einzelnen Benachrichtigungen für mehr optik → Sichtbare Trennlinie zwischen den Einträgen ergänzt, live bestätigt. - [x] Benachrichtigungen sind nicht anklickbar, sollten aber zu dem jeweiligen Post / Pet gehen. → Tap markiert als gelesen und navigiert zum Ziel (Post-Kommentare bzw. Tierprofil je nach Typ), live bestätigt. - [x] Drei Punkte, menü im Feed, falls es der eigene Beitrag ist, lösch funktion hinzufügen, statt Report. → Bei eigenem Beitrag öffnet "⋮" jetzt einen Lösch-Bestätigungsdialog statt der Report-Ansicht, bei fremden Beiträgen bleibt Report wie gewohnt; beides live bestätigt. - [x] im Feed fehlt ein Indikator wenn in einem Post mehrere Bilder hinterlegt sind. das wischen funktioniert, aber nur wenn man weiß das dort mehrere bilder hinterlegt sind. unwissende würde nur ein bild sehen können. → Zähler-Badge oben rechts ("1 / 3") plus Punkte-Indikator unter dem Bild ergänzt (analog zur Web-Version), live bestätigt. - [x] Kommentar Fenster ist nicht im Darkmode - [x] Tier Anlegen ist nicht im Darkmode + Rassen werden als Dropdown angezeigt lassen sich aber nicht scrollen. → Darkmode: PetCreateForm.tsx + onboarding/pet.tsx nutzten noch die statischen (Hell-only) `colors`/`typography` statt `useTheme()` — umgestellt auf das gleiche Muster wie sign-up.tsx/OptionPicker.tsx. Scroll-Bug: onboarding/pet.tsx nutzte als äußeren Container ein normales `ScrollView`, darin verschachtelt der Rassen-Dropdown (OptionPicker) sein eigenes `ScrollView` — zwei gleichachsige ScrollViews ineinander verschlucken auf Android die Scroll-Geste des inneren, auch mit `nestedScrollEnabled`. Fix: äußeren Container auf `FlatList` (leere Liste + `ListHeaderComponent`) umgestellt, exakt das bereits funktionierende Muster aus explore.tsx für dieselbe OptionPicker-Komponente. Typecheck + Lint sauber, i18n-Parität unverändert (243/243) — nicht live auf Android getestet (kein Emulator in dieser Session), nur strukturell gegen den bekannten Explore-Fix abgeglichen. - [x] Nach dem Speichern des ersten Tiers, und dem Hochladen des Profilfotos, wird man wieder zurück geworfen auf Tier erstellen. erst ein neustart der app lässt einen auf den feed zugreifen. (BUG) → Ursache: `pets.create`-Mutation in PetCreateForm.tsx hat die `trpc.pets.list`-Query (ActivePetContext) nie invalidiert. Nach dem Avatar-Schritt landet man in `(app)`, aber `OnboardingRedirect` (app/_layout.tsx) sah dort weiterhin den alten, leeren Pets-Stand aus dem Cache und schickte sofort wieder zurück nach `/onboarding/pet` — nur ein Neustart hat die Liste frisch geladen. Fix: `queryClient.invalidateQueries` auf `trpc.pets.list` direkt im `onSuccess` der Create-Mutation. Typecheck sauber. TODO Neu3: - [x] Videos die angeklickt werden, laufen in Endlosschleife weiter obwohl man im Feed weiter scrollt. → expo-video hat kein eingebautes "bin ich noch sichtbar"-Bewusstsein; der Player lief nach dem Wegscrollen einfach weiter (mit `loop = true`). Neuer Hook `useVisiblePostIds` (FlatList-`viewabilityConfigCallbackPairs`) trackt sichtbare Post-IDs, `isVisible`-Prop läuft durch PostCard → VideoPlayer, der beim Verschwinden `player.pause()` aufruft. In Feed UND Tierprofil-Postliste verdrahtet (beide nutzen VideoPlayer). Typecheck + Lint sauber, nicht live auf Android getestet (kein Emulator in dieser Session). - [x] Profilbilder sind nicht vergrößerbar → Das Tierprofilbild (Tierprofil-Kopfbereich, size="lg") war reines, nicht antippbares ``. Öffnet jetzt bei Vorhandensein eines Avatars den bereits vorhandenen `/image-viewer` (denselben Viewer inkl. Pinch-to-Zoom, den Beitragsbilder schon nutzen) mit dem vollen Avatar-Bild. Ohne hinterlegtes Foto (Initialen-Fallback) bleibt es unangetippt, da nichts zu vergrößern ist. Typecheck + Lint sauber. Nicht live getestet (kein Emulator in dieser Session). - [x] Profilbearbeiten, lässt sich die Rasse nicht mehr ändern; wäre wichtig wenn man bei der Erstellung Fehler gemacht hat. - [x] Sowie kann man beim Tier kein Geburtstag hinterlegen oder Adoptionstag wie es im Web vorhanden ist. → Beides war nur eine Mobile-UI-Lücke, das Backend (`pets.update`) unterstützt `breedId`/`birthday`/`adoptedAt` bereits (Web nutzt es längst). Rassen-Dropdown aus PetCreateForm.tsx in eine geteilte `BreedPicker`-Komponente ausgelagert (DRY) und in edit.tsx eingebaut (Tierart selbst bleibt fix, nur die Rasse ist neu wählbar). Geburtstag/Adoptionstag als TT-MM-JJJJ-Textfelder ergänzt, gleiches Validierungs-/Konvertierungsmuster wie bei den Health-Formularen (`date-format.ts`). Da BreedPicker wie zuvor ein eigenes ScrollView verschachtelt, wurde edit.tsx aus demselben Grund wie onboarding/pet.tsx von `ScrollView` auf `FlatList` umgestellt. Typecheck + Lint sauber (ein vorbestehender, nicht selbst verursachter `set-state-in-effect`-Lint-Hinweis in der bereits vorhandenen Effect besteht unverändert fort), i18n-Parität 247/247. Nicht live getestet (kein Emulator in dieser Session). - [x] Meilensteine sind nicht im Darkmode verfügbar → milestones.tsx (Liste) und milestone-new.tsx (neuer Meilenstein) nutzten noch die statischen (Hell-only) `colors`/`typography` statt `useTheme()` — auf das etablierte `makeStyles(colors)`-Muster umgestellt. Typecheck sauber, Lint zeigt nur vorbestehende, nicht selbst verursachte Warnungen (fehlendes `t`-Dep, fehlendes `alt`). Nicht live getestet (kein Emulator in dieser Session). TODO Neu4 (Tester-Feedback aus der Google Group, Closed Testing): - [x] Im Darkmode hatte ein User nach dem Login "alles in Schwarz" gesehen (kein Gerät bekannt). → Zwei konkrete Lücken gefunden und behoben: (1) Der `LoadingScreen` in `app/_layout.tsx` (Anzeige während Fonts/Clerk-Auth laden, u.a. direkt nach dem Login) war fest auf helle Farben verdrahtet, da er *vor* dem ThemeProvider rendert und `useTheme()` dort nicht zur Verfügung steht — jetzt löst `resolveInitialColors()` (neu in ThemeContext.tsx) dieselbe Preference-oder-System-Vermutung auf, die der ThemeProvider selbst für seinen ersten Frame nutzt. (2) Der Splash-Screen (`app.json`) hatte nur eine helle `backgroundColor`, keine Dark-Variante — im expo-splash-screen-Plugin per Source-Code verifiziert: ohne `dark.backgroundColor` bleibt der Splash in jedem System-Modus hell (kein automatisches Schwarz, aber eben auch kein Dark-Modus) — jetzt mit `dark.backgroundColor: "#111111"` (identisch zu `darkColors.porchWhite`) ergänzt, gleiches Icon (verifiziert: transparenter Alpha-Kanal, funktioniert auf beiden Hintergründen). Speculativ, da ohne Repro/Gerätedaten nicht 100% zu verifizieren — sollte den wahrscheinlichsten Kandidaten (helle Screens/Splash im dunklen Kontext) aber abdecken. Nicht live getestet (kein Emulator in dieser Session). - [x] Tablet-Login-Screenshot: komplette App sieht "sehr großgezogen" aus. → Ursache (ohne den Screenshot selbst gesehen zu haben, aber strukturell bestätigt): sign-in.tsx/sign-up.tsx hatten keine Breitenbegrenzung — das äußere `View` war `flex:1` ohne `maxWidth`, wodurch Inputs/Button per Default-`alignItems:"stretch"` auf die volle Bildschirmbreite gezogen wurden. Auf einem Phone (~350dp) unauffällig, auf einem Tablet (~800-1200dp) wirkt das wie randlos aufgeblasene Formularfelder. Fix: Inhalt in einen zentrierten `form`-Container mit `maxWidth: 420` gepackt (beide Screens). Scope bewusst auf die gemeldeten Auth-Screens begrenzt — falls der Effekt laut nächstem Feedback app-weit auftritt, braucht es einen gemeinsamen Screen-Wrapper statt Einzelfixes. Nicht live auf einem Tablet getestet (kein Emulator/Tablet in dieser Session). - [x] Ein User wünscht sich SSO mit Google. → Umgesetzt und live getestet (funktioniert). `expo-auth-session`+`expo-web-browser` installiert (native Module, kein OTA-Update möglich), neuer `GoogleSignInButton` (eigenes SVG-„G"-Icon) auf sign-in.tsx + sign-up.tsx, `useSSO()` aus `@clerk/expo` (stable, nicht `/experimental` — konsistent mit dem Rest der App), `WebBrowser.maybeCompleteAuthSession()` im Root-Layout + `useWarmUpBrowser`-Hook. Zwei echte Blocker unterwegs gefunden und gelöst: (1) Google-Connection war im Clerk-Dashboard zunächst nicht aktiviert (per öffentlichem `/v1/environment`-Endpoint live verifiziert) — vom User nachgeholt. (2) `pawfeed://sso-callback` war nicht als erlaubte Redirect-URL in Clerk eingetragen → Clerk fiel auf einen `home_url`+`/sign-in`-Fallback zurück, der auf dieser App nicht existiert (404, da die Web-Route `/log-in` heißt) — vom User im Dashboard eingetragen, jetzt behoben. Zusätzlich behandelt: Diese Clerk-Instanz verlangt `legal_consent_enabled: true`, aber Clerks SSO-Transfer-Flow übergibt kein Consent-Feld — hätte sonst bei neuen Google-Konten im selben `missing_requirements`-Hänger geendet wie früher der Passwort-Flow. Fix: sign-up.tsx sperrt den Google-Button bis die bestehende Checkbox angehakt ist und ruft danach `signUp.update({ legalAccepted: true })` nach; sign-in.tsx hat keine Consent-UI und zeigt bei einem noch nicht existierenden Account stattdessen eine Fehlermeldung, die auf „Registrieren" verweist, statt still ein Konto ohne Zustimmung anzulegen. Vorab noch ein reines EAS Update (Runtime 1.0.2, Branch `production`, Update-Gruppe `f1f3a381`) mit nur den Dark-Mode-/Tablet-Fixes an die bestehenden Nutzer ausgeliefert, bevor der SSO-Code dazukam — die SSO-Verdrahtung ruft `expo-web-browser` beim App-Start auf (natives Modul, im installierten 1.0.2-Build nicht vorhanden); ein OTA-Update mit dieser Verdrahtung hätte den bestehenden Build zum Absturz gebracht. Dafür wurde `app.json`/`app/_layout.tsx`/sign-in.tsx/sign-up.tsx temporär auf den Stand ohne SSO zurückgesetzt, das Update veröffentlicht, danach alles 1:1 wiederhergestellt (Typecheck+Lint nach beiden Schritten sauber). TODO Neu5 (weiteres Tester-Feedback): - [x] Erster Content-Load fühlt sich für Nutzer zu langsam an — Frage nach CDN-loser Beschleunigung. → Query-Cache (MMKV-persistiert, 24h gcTime), DB-Indizes und die Redis-gestützte Feed-Rangliste waren schon solide, das war nicht die Ursache. Eigentlicher Flaschenhals: Uploads liefen nur mit JPEG-Kompression (`quality: 0.8`), aber ohne Auflösungs-Downscale — ein Kamerafoto blieb bei 3000-4000px, und jeder Feed-Betrachter lud dieses Vollbild nur um es auf Kartenbreite zu skalieren. User hat parallel geprüft: Supabase Image Transform API (serverseitiges Resize) ist nur im Pro-Plan verfügbar, den wir nicht haben — daher Fix am Schreib- statt Lesezeitpunkt. Neue `resizeForUpload()`-Utility (`src/lib/resize-image.ts`, nutzt `expo-image-manipulator`s aktuelle `ImageManipulator.manipulate(uri).resize().renderAsync()`-Chain-API, nicht das deprecated `manipulateAsync`) — skaliert auf max. 1600px lange Kante (nur falls nötig, kein Hochskalieren) und re-encoded immer auf JPEG @ 0.8 Kompression, unabhängig vom Ursprungsformat. In allen 4 Upload-Stellen eingebaut: AvatarStep.tsx, post-new.tsx, story-new.tsx, milestone-new.tsx. `expo-image-manipulator` installiert (natives Modul, kein OTA-Update möglich — wird zusammen mit dem SSO-Build 1.0.3 ausgeliefert). Typecheck + Lint sauber (nur vorbestehende `t`-Dep-Warnungen). Nicht live getestet (kein Emulator in dieser Session) — insbesondere `File(uri).size` ist in den TS-Typdefs des installierten expo-file-system nicht direkt sichtbar, aber im nativen iOS-Quellcode (`Property("size")`) bestätigt. - [x] Auf einem Android 17 - Pixel 10 Pro XL: App erneut gestartet (zweiter Tag) und dauerhafter Ladescreen. Frage nach Log-Einsicht. → Kein Log-Zugriff möglich: Mobile hatte bislang kein Crash-/Error-Tracking, kein Gerät/Emulator in dieser Session verfügbar. Verdacht: `app/_layout.tsx`s allererster Ladescreen wartet auf Clerks `isLoaded` — beim Wiederöffnen nach längerer Pause ist der gespeicherte Session-Token abgelaufen, Clerk muss dann still über Netzwerk erneuern; hängt dieser Refresh (schlechte Verbindung o.ä.), blieb `isLoaded` für immer `false` und der Spinner drehte endlos, ohne Fehleranzeige oder Retry-Möglichkeit. Zwei Fixes: (1) **Sentry/GlitchTip für Mobile eingerichtet** (`@sentry/react-native`, self-hosted GlitchTip-Instanz wie bei Web, eigener DSN über `EXPO_PUBLIC_SENTRY_DSN`). `Sentry.init()` nur wenn DSN gesetzt (No-op sonst), `Sentry.wrap(RootLayout)` als Error Boundary für sonst unbemerkte Render-Fehler. Bewusst ohne Sourcemap-Upload aus dem JS-Code heraus verdrahtet (schlägt bei dieser GlitchTip-Instanz für Web schon mit CSRF 403 fehl, siehe CLAUDE.md) — trotzdem versuchte der native Android-Build automatisch, Sourcemaps hochzuladen (Sentrys Expo-Config-Plugin hängt das standardmäßig als Gradle-Task ein), was den ersten 1.0.4-Build mit `error: An organization ID or slug is required (provide with --org)` hat scheitern lassen. Fix: `SENTRY_DISABLE_AUTO_UPLOAD: "true"` in `eas.json` (preview/production `env`) ergänzt — das ist die von `@sentry/react-native`s `sentry.gradle` selbst geprüfte Umgebungsvariable, um den Upload-Task zu überspringen. (2) **10-Sekunden-Timeout für die Auth-Ladephase**: neuer `useTimedOut()`-Hook + `AuthTimeoutScreen` — zeigt nach 10s Wartezeit auf `isLoaded` statt des endlosen Spinners einen Hinweistext + Retry-Button (`Updates.reloadAsync()`, nutzt das schon vorhandene EAS-Update-Runtime). Sentry-Warnmeldung wird sowohl beim Erscheinen des Timeout-Screens als auch beim Retry-Tap abgesetzt, damit ein künftiger Vorfall diesmal nachvollziehbar ist. `expo-updates`/`expo-web-browser` bereits vorhanden, `@sentry/react-native` ist ein neues natives Modul (Config-Plugin automatisch in app.json ergänzt) — kein OTA-Update möglich, geht mit dem 1.0.4-Build raus. Typecheck + Lint sauber, i18n-Parität 252/252. Nicht live getestet (kein Emulator in dieser Session). - [x] Bitte prüfen, ob das Rassen-Dropdown-Scroll-Problem bei "Tier erstellen" theoretisch erneut auftreten kann — ein Nutzer hat das bemängelt. → Struktur-Vergleich: onboarding/pet.tsx, edit.tsx und explore.tsx nutzen alle exakt dasselbe Muster (äußeres FlatList + OptionPickers inneres ScrollView mit `nestedScrollEnabled`) — keine Inkonsistenz, kein Regressions-Bug zwischen den dreien. Das eigentliche Problem: `nestedScrollEnabled` ist auf Android seit Jahren bekanntermaßen unzuverlässig bei verschachtelten gleichachsigen Scrollbereichen (FlatList/VirtualizedList + ScrollView) — kann je nach Android-Version/Listenlänge/Touch-Timing mal funktionieren, mal nicht (der Tester war auf Android 17, einer brandneuen Version). Strukturelle statt kosmetische Lösung: `OptionPicker.tsx` auf `Modal` umgebaut — das Dropdown rendert jetzt in einer eigenen nativen Ebene komplett außerhalb der äußeren Scroll-Hierarchie, damit ist die ganze Klasse von Nested-Scroll-Bugs eliminiert statt nur umschifft. Button-Position wird per `measureInWindow()` gemessen, damit das Dropdown weiterhin optisch wie ein Inline-Dropdown direkt unter dem Button erscheint (nicht als Vollbild-Sheet). Wirkt automatisch für alle 3 Verbraucher (Explore, Tier erstellen, Profil bearbeiten), keine Änderung an deren Props nötig. Aufräumen als Folge: explore.tsx's `headerWrapper`-zIndex-Hack (war nur für das alte absolut-positionierte Overlay nötig) entfernt; veraltete Kommentare in onboarding/pet.tsx + edit.tsx aktualisiert (FlatList bleibt dort bestehen, ist aber nicht mehr zwingend aus diesem Grund nötig). Kein neues natives Modul (Modal ist RN-Core) — theoretisch auch per OTA an 1.0.2-Nutzer ausliefbar, geht aber ohnehin mit dem 1.0.3-Build raus. Typecheck + Lint sauber. Nicht live getestet (kein Emulator/Gerät in dieser Session) — größtes Restrisiko: die Positions-Messung (`measureInWindow`) könnte auf einem echten Gerät leicht daneben liegen (z.B. bei Statusbar-Offsets), bitte beim nächsten Test gezielt prüfen. TODO Neu6: - [x] Ein User hat ein Redirect-Problem beim Google-Login gemeldet, nicht reproduzierbar. Wann wurde die Redirect-Fix-Änderung gemacht? → Die `pawfeed://sso-callback`-Whitelist wurde im Clerk-Dashboard noch vor dem 1.0.3-Build eingetragen (reine Backend-Config, kein App-Code) — wirkt serverseitig sofort für jede App-Version mit SSO-Code (1.0.3+), nicht an eine Build-Nummer gebunden. Ein Redirect-Problem danach wäre also entweder ein Tester auf einer Version vor 1.0.3 (kein SSO-Code, "Redirect-Problem" eher ein Missverständnis) oder ein bisher unbekannter Android-/Browser-Edge-Case. Echter Fund dabei: `GoogleSignInButton.tsx`s catch-Block meldete Fehler bisher nur lokal (Bildschirmtext), nicht an Sentry — nachgerüstet (`Sentry.captureException(err)`), damit ein künftiger Fall tatsächlich Logs hinterlässt. Per EAS Update (Runtime 1.0.4, Branch `production`, Update-Gruppe `eea1524b`) ausgeliefert — kein neuer Build nötig, reiner JS-Fix auf bereits vorhandenem `@sentry/react-native`. - [x] Im Explorer gibt es beim Breed-Dropdown jetzt auch das Scroll-Problem. → War NICHT nur ein Altlast-Feedback von vor 1.0.4 — User hat nach dem ersten Fix-Versuch (EAS Update, s.o.) bestätigt: immer noch nicht scrollbar. Erster Fix-Versuch (Pressable→View bei der Dropdown-Karte) war unvollständig: die Karte steckte immer noch als Kind-Element im vollflächigen Backdrop-`Pressable`, und ein `Pressable` IRGENDWO oberhalb einer `ScrollView` im Baum ist immer noch ein konkurrierender Responder-Kandidat für die Scroll-Geste. Nach erneuter Bestätigung durch den User ("neu gestartet, weiterhin defekt") das eigentliche Problem gefunden: Backdrop und Dropdown-Liste müssen **Geschwister** sein, nicht Eltern-Kind — jetzt so umgebaut, dass ein Tap innerhalb der Liste direkt in deren eigenen Teilbaum trifft und den Backdrop-Pressable darunter nie erreicht. Zweimal per EAS Update (Runtime 1.0.4) ausgeliefert, kein neuer Build nötig. Wichtige Erkenntnis für künftige Vorfälle: **nach einem OTA-Update muss die App komplett geschlossen und neu geöffnet werden** (nicht nur in den Hintergrund) — `expo-updates` wendet ein heruntergeladenes Update erst beim übernächsten Start an, der erste Start nach Download läuft noch mit dem alten Bundle. Typecheck + Lint sauber. Nicht live getestet (kein Emulator in dieser Session) — bitte diesmal wirklich explizit bestätigen lassen. - [x] Kein Logout-Button in der App vorhanden — Neu-Anmeldung mit anderem Konto nicht möglich. → Echte Funktionslücke, nicht vorher gebaut. Neue `LogoutSection` unter „Meine Tiere" (ganz unten, nach den rechtlichen Links), mit Bestätigungsdialog (analog zum bestehenden "Tier löschen"-Muster in edit.tsx). Ruft Clerks `signOut()` (`useAuth()` aus `@clerk/expo`) plus `clearActivePetId()` auf, damit nach einem Konto-Wechsel keine alte Pet-ID aus dem vorherigen Konto hängen bleibt — die Weiterleitung zum Login übernimmt automatisch `useProtectedRoute()` in app/_layout.tsx, sobald `isSignedIn` auf `false` kippt. Kein neues natives Modul, per EAS Update (Runtime 1.0.4) ausgeliefert. Typecheck + Lint sauber, i18n-Parität 255/255. Nicht live getestet (kein Emulator in dieser Session). **Wichtiger Kontext im Nachhinein (User-Hinweis):** Der 1.0.4-Build wurde zwar erstellt, aber **nie in die Play Console hochgeladen** — die Tester/Neuinstallationen liefen die ganze Zeit noch auf der vorherigen Version (vermutlich 1.0.2, ohne SSO-Code). Das erklärt rückwirkend, warum der Google-Redirect-Fehler und der Dropdown-Bug auch nach mehreren EAS Updates (die alle auf Runtime 1.0.4 zielten) und einer Neuinstallation weiter auftraten — die Updates konnten ein Gerät, das nie 1.0.4 installiert hatte, gar nicht erreichen. Die Analysen/Fixes selbst bleiben gültig, waren aber bis zum echten 1.0.4-Rollout nicht wirklich verifizierbar. User lädt 1.0.4 jetzt nach — sobald das live ist, sollten alle drei EAS-Update-Runden (Sentry-Fix, erster Dropdown-Versuch, finaler Sibling-Fix + Logout) automatisch beim übernächsten App-Start greifen, ohne weiteren Build. **Fortsetzung — echtes 1.0.4 live, EAS Updates kommen trotzdem nie an:** Nachdem 1.0.4 wirklich in der Play Console lag, blieb der Logout-Button trotzdem unsichtbar. Diagnose-Werkzeug gebaut (`UpdateDiagnosticsSection` + `FooterErrorBoundary` in pets.tsx, temporär, per EAS Update ausgeliefert) — aber selbst DAS kam nie an, auch nach 20 Neustarts und 2 kompletten Neuinstallationen auf zwei komplett unterschiedlichen Geräten (Pixel 10 Pro XL extern, Xiaomi 13 Pro beim User selbst). Netzwerk-Check ausgeschlossen: `https://u.expo.dev/` ist vom Testgerät aus erreichbar (erwartete Header-Fehlermeldung, kein Timeout/Blockade). Build-Metadaten (`eas build:view`) bestätigten Channel/Runtime-Version korrekt eingebettet — kein Konfigurationsfehler bei den Publishes selbst. **Ursache gefunden:** `app.json`s Plugin-Liste enthielt `expo-dev-client` — und zwar ungefiltert für **alle** Build-Profile inkl. `production`. Dieses Paket ist laut eigener Doku nur für Debug-/Development-Builds gedacht und bringt eine eigene Update-/Branch-Auswahl-Logik mit, die den normalen automatischen `expo-updates`-Check verdrängen kann — passt exakt zum Symptom (Updates kommen strukturell nie an, geräteunabhängig). Der lokale Dev-Client war laut früheren Sessions ohnehin schon kaputt, kein Verlust durchs Entfernen. Fix: `expo-dev-client` aus der gemeinsamen `plugins`-Liste entfernt (Paket bleibt in package.json, `eas.json`s `development`-Profil hat sein eigenes `developmentClient: true`, unabhängig von dieser Liste). **Braucht einen neuen nativen Build** (Plugin-Änderungen sind nicht OTA-fähig) — 1.0.5/versionCode 6 angestoßen. Falls das die Ursache war, sollte ab diesem Build der normale automatische Update-Check endlich greifen. **Notiz für einen künftigen Build (nicht dringend, rein vorsorglich):** Beim 1.0.5-Build meldete EAS Patch-Versions-Abweichungen bei etlichen Expo-Paketen (`expo`, `expo-router`, `expo-updates`, `expo-image`, u.v.m. — installiert liegt jeweils einen Patch hinter dem für SDK 57 aktuell erwarteten Stand). Nur Patch-Ebene, kein Build-Blocker, aber beim nächsten ohnehin anstehenden Build sollte vorher `npx expo install --fix` laufen, um das aufzuräumen. **Bestätigt und abgeschlossen:** 1.0.5 freigegeben und getestet — Logout-Button UND das Diagnose-Tool waren sichtbar, `expo-dev-client` war also tatsächlich die Ursache. EAS Update funktioniert damit ab 1.0.5 wieder normal. Feedback: Logout-Button sah "wie ein Dev-Button" aus — lag am direkt danebenstehenden, absichtlich roh gehaltenen Diagnose-Block ("Update-Diagnose (temporär)" + Monospace-Dump + Debug-Button). Diagnose-Tool war ohnehin nur zur Fehlersuche gedacht und jetzt entfernt (`UpdateDiagnosticsSection` + zugehörige Styles raus aus pets.tsx); `FooterErrorBoundary` um `LogoutSection` bleibt als dauerhaftes, günstiges Sicherheitsnetz bestehen. Per EAS Update (Runtime 1.0.5, Gruppe `105f39e3`) ausgeliefert, kein neuer Build nötig. Typecheck + Lint sauber. **Kleiner Nachklapp:** Das Cleanup-Update (`105f39e3`) wurde von `checkForUpdateAsync()` als `updatePreviouslyFailed` gemeldet — vermutlich wurde der Download/Start bei einem der vielen Testneustarts unterbrochen, bevor die App sich als erfolgreich gestartet melden konnte; `expo-updates` blockiert eine einmal fehlgeschlagene Update-ID danach dauerhaft, unabhängig davon ob der Code eigentlich intakt ist (war er hier: Typecheck sauber, keine verwaisten Referenzen). Per `eas update:republish` mit frischer Update-ID (`fdba4e10`) umgangen — sollte jetzt ohne die Blockade ankommen. **Doch kein Interrupt-Artefakt — echter Absturz bestätigt:** Der Republish (`fdba4e10`) zeigte im Expo-Dashboard ebenfalls "known launches: 1, known crashes: 1", identisch zum Original. Das widerlegt die Interrupt-Theorie (eine frische Update-ID hätte keinen alten Absturz "erben" können) — der Absturz ist real und reproduzierbar. GlitchTip zeigte dazu **nichts** (nur 2 alte, unabhängige Meldungen) — d.h. der Crash passiert unterhalb der JS-Ebene, bevor `Sentry.wrap()` überhaupt greifen kann, exakt beim Umschalten auf das heruntergeladene Bundle. Das eingebettete Bundle (im APK selbst) läuft dagegen einwandfrei — jedes bisher unter Runtime 1.0.5 versuchte OTA-Update war das allererste OTA-Update überhaupt auf diesem (Dev-Client-befreiten) nativen Build, und es scheiterte konsistent. **Verdacht:** `expo-updates` lag laut `expo install --check`-Warnung beim 1.0.5-Build einen Patch hinter (`57.0.21` statt erwartet `~57.0.22`) — genau solche Patches beheben oft subtile Update-Apply-Bugs. Mit `npx expo install --fix` alle Expo-Pakete auf den erwarteten Stand gebracht (u.a. `expo-updates` → `57.0.22`, `expo` → `57.0.22`, `expo-router` → `57.0.21`). Typecheck + volles Lint danach unverändert sauber (identische 39 vorbestehende Probleme wie zu Sessionbeginn, nichts Neues). **Neuer nativer Build 1.0.6/versionCode 7 nötig** (Dependency-Update wirkt nur bei einem frischen nativen Build) — bewusst neue Runtime-Version (nicht 1.0.5 wiederverwendet), um jede Verwechslung mit dem bekannt kaputten 1.0.5-Runtime-Zustand auszuschließen. Falls das die Ursache war, sollte OTA ab 1.0.6 tatsächlich funktionieren — sonst brauchen wir echte native Logs vom Gerät (Sentry kann diesen Absturz nicht sehen). **1.0.6 installiert, Diagnose-Text weg, Logout-Button da — aber "DEV-Optik".** Nachfrage ergab: zu schlicht/unfertig (dünner Rahmen, kein Füllhintergrund), Farbe/Kontrast falsch, UND Icon/Schrift passen nicht — alle drei zugleich. Ursache: der Button war komplett handgestylt (kopiert von edit.tsx's Delete-Pet-Muster: roter Rahmen, `LogOut`-Icon, eigene Styles) statt die etablierte, überall sonst genutzte `Button`-Komponente zu verwenden. Logout ist zudem nicht destruktiv/irreversibel wie Löschen — die neutrale `outline`-Variante (heller Hintergrund, Ink-Text, Hairline-Rahmen) passt semantisch besser als Alarmrot. Fix: `LogoutSection` nutzt jetzt `