- Add MoviesScreen and corresponding navigation - Implement movie data aggregation in ViewingDao and repository - Enhance NetflixParser to support multiple JSON payload shapes - Apply custom app theme and update launcher icons - Add back navigation handling to ProviderSyncScreen
4.9 KiB
Plan: Filme-Tab + Web-Sync-Reparatur + Navigations-Bug
Drei unabhängige Fixes, alle ohne Datenbank-Migration (Room fallbackToDestructiveMigration ist aktiv, Schema bleibt v1, nur neue Queries).
Fix 1: Filme als eigener Tab in der Bottom-Navi
Aktuell ist das Dashboard "Filme"-Zählen kaputt (itemCount - topShows.episodeCount mit LIMIT 20) und Filme tauchen im Serien-Ranking auf.
1a. Neue DAO-Queries (ViewingDao.kt) — Room speichert contentType als TEXT ('MOVIE'/'SERIES'), daher String-Filter:
getTopMovies(limit)→SELECT ... WHERE contentType = 'MOVIE' GROUP BY showTitle ORDER BY totalMinutes DESCgetTopShows(limit)→ ergänzeWHERE contentType != 'MOVIE'damit Filme aus dem Serien-Ranking verschwindengetMoviesCount()→SELECT COUNT(*) ... WHERE contentType = 'MOVIE'getSeriesEpisodesCount()→SELECT COUNT(*) ... WHERE contentType != 'MOVIE'
1b. WatchStats korrekt befüllen (StatsRepository.kt) — combine von 7 Flows (Vararg-Variante wie bereits vorhanden), echte Counts statt Heuristik. moviesCount und seriesEpisodesCount direkt aus der DB.
1c. Neue Datenmodelle (WatchStats.kt) — MovieSummary (analog ShowSummary) + topMovies: List<MovieSummary>-Feld in WatchStats.
1d. Neuer Screen MoviesScreen.kt — Clone von SeriesStatsScreen.kt mit MovieRankItem (zeigt Dauer statt Folgenanzahl, Movie-Icon statt "X Folgen"). Wiederverwendet ProviderBadge.
1e. Bottom-Navi erweitern (MainActivity.kt) — Neuer Screen.Movies("movies", "Filme", Icons.Default.Movie) zwischen Series und Analytics. NavHost erhält die neue Route.
Fix 2: Web-Sync JS-Extraktion reparieren
Root Cause: Der Button nimmt die komplette HTML-Seite (document.documentElement.outerHTML) und füttert sie dem CSV-Parser → 1 Müll-Eintrag mit <meta>-Tag-Text.
Recherche zeigt: DOM-Klassen sind bei Netflix gehasht (brittel). Der robuste Weg ist die Netflix Shakti-API aus dem WebView heraus, da die Session-Cookies (NetflixId) automatisch vorliegen.
2a. Provider-spezifische JS-Extraktion (ProviderSyncScreen.kt → WebViewSyncSection):
- Netflix: Injiziere JS, das
window.netflix.reactContext.models.serverDefs.data.BUILD_IDENTIFIER+authURLliest, dannfetch('/api/shakti/'+buildId+'/viewingactivity?pg='+n)paginiert (Schleife bisvhSizeerreicht) und ein sauberes JSON-Array von{title, seriesTitle, episodeTitle, date, duration}zurückgibt. - Prime Video: Parse inline-JSON aus
script[type="text/template"](props→widgets→content.content.titles[]), fallback auf[data-automation-id^="wh-date"]. - Andere (Disney+/Apple): Greaceful-Degradation-Meldung "Web-Sync noch nicht unterstützt, bitte CSV verwenden".
2b. Toast-Feedback statt HTML-String: Der Button zeigt Fortschritt ("Lade Seite N…"). Die extrahierten JSON-Daten gehen an viewModel.importScrapedWebHistory(json, provider) — bereits vorhanden, leitet an NetflixParser.parseJsonApiPayload weiter.
2c. parseJsonApiPayload robuster machen (NetflixParser.kt): Akzeptiert jetzt sowohl das Netflix-viewedItems-Array als auch ein flaches Array (für den Prime-Fall). Field-Reading defensiv (seriesTitle für Episoden, title für Filme → korrekter contentType). Dauer aus dem duration-Feld (ms → Minuten) falls vorhanden, sonst Default.
Fix 3: Navigations-Bug (hängt nach "Verlauf Auslesen" fest)
Symptom: Nach dem Sync-Screen kommt man nicht mehr aufs Dashboard. Ursachen: WebView wird nicht disposed, update-Lambda erzwingt Reloads, und das alte Parsing der kompletten HTML lief auf dem Main-Thread.
3a. WebView sauber lifecycle-gebunden (WebViewSyncSection):
DisposableEffect/remember { ...; onDispose { webView.destroy() } }statt freischwebendem Ref — verhindert, dass der WebView den Screen blockiert.- Reload-Schleife in
update-Lambda entfernen (vergleicht nur noch, ob sich der Provider geändert hat, nicht jeden Frame).
3b. Parsing off-main: Die extrahierten JSON-Daten werden ohnehin über viewModelScope.launch(Dispatchers.IO) verarbeitet (bereits in importScrapedWebHistory), aber das JS-evaluateJavascript-Ergebnis wird vor dem Parsen als String geprüft — keine riesige HTML-Seite mehr, die den Main-Thread blockiert.
3c. Navi-Zurück-Verhalten: BackHandler im Sync-Screen, der bei geladenem WebView zuerst webView.goBack() macht (falls History vorhanden) und erst dann navController.popBackStack(). So kommt man sicher vom Sync-Screen weg.
Validierung
./gradlew assembleDebug(Java 21) baut fehlerfrei.adb install -rauf das S24 Ultra.- Manueller Smoke-Test: Sample-Daten → Filme-Tab zeigt Filme, Serien-Tab nur Serien, Dashboard zählt korrekt. Navi nach Sync funktioniert.
Alle drei Fixes sind voneinander unabhängig und werden in einem Build-Zyklus umgesetzt. Keine DB-Schema-Änderung (nur neue Queries auf bestehenden Spalten).