# Unspooled — Android TV Streaming App

Open-source Android TV streaming app built on the Stremio addon protocol with native TMDB metadata, debrid integration, and a self-hosted scraper.

**Users bring their own debrid keys.** Everything happens client-side.

## Quick Start

```bash
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
./gradlew :app:assembleDebug
# APK → app/build/outputs/apk/debug/app-debug.apk
```

Requires `NEXSTREAM_SCRAPER_URL` in `local.properties` for full catalog scraping.

## Current Status

**Production-ready for D-pad navigation** — home, sidebar, catalog, and Settings focus paths are stable.

### Latest (Jul 03)
- **Simplified Addons** — Removed addon marketplace, discoverable addons, registry presets, and AIOStreams config/provider screens; manual `+ Add Addon URL` remains
- **AIOStreams removed** — No longer seeded or auto-enabled; existing `aiostreams` system rows are purged on startup
- **Addon dedupe** — System/user addon lists are deduped by id and normalized manifest URL
- **Genre chips across catalog pages** — Home, Movies, and TV Shows now use `All`, `Comedy`, `Horror`, `Sci-Fi`, `Action`, `Romance`, `Docs`
- **Trailer autoplay removed** — Poster focus no longer starts trailer playback; trailers require explicit user action
- **Focus cleanup** — Show More no longer cancels RIGHT, Debrid Services actions are reachable from Settings, and Clear Cache restores focus inside Advanced settings
- **Details Back focus restoration** — Returning from Details/meta screens now restores focus to the last-focused catalog card via `LifecycleEventObserver(ON_RESUME)` + `shouldRestoreFocus` flag
- **Settings visual refresh** — Fixed page-level `Settings` title, gradient shell, and reference-style content header spacing
- **Settings DPAD cleanup** — Explicit LEFT from content returns to the Settings category rail
- **Fake settings removed** — Playback no longer shows hardcoded empty-handler player/audio/decoder controls
- **Safer Advanced actions** — Clear Cache now requires confirmation and shows result feedback
- **Settings consistency pass** — Read-only rows no longer show chevrons; Trakt and legacy toggle rows use the shared white focused-card treatment
- **Addon focus cleanup** — Loading skeletons are disabled, and action buttons no longer cancel unspecified DPAD directions

### Previous UI Audit (Jun 23)
- **Hero/catalog source parity** — Home hero rows respect selected catalog source (CINEMETA/TMDB_NATIVE)
- **See All pagination** — Non-skip addons no longer dead-end on See All; `mergeCatalogPage` handles duplicates
- **Filter chips** — `LazyRow` filter chips above catalog rows, accessible via D-pad UP
- **Sources entry** — Long-press DPAD_CENTER on any catalog card to view ranked sources
- **Focus dead-end fix** — Cross-section navigation no longer loses focus; `registrar.reset()` detaches stale focus targets
- **Sidebar focus fix** — `selectableGroup()` → `focusGroup()`, removed `focusRestorer`/`focusedNavIndex` — all 7 items reachable
- **Catalog tokenization** — Hardcoded catalog `dp`/`sp` values replaced with `UnifiedTokens`

### Remaining
- Settings row-level focus restoration per category after dialogs/subpages
- Decide whether to integrate or remove remaining unreachable standalone `settings/...` routes (TMDB, Navigation Style)
- Quick action rail on expanded cards (Play / My List / Trailer / Info)
- Crossfade on route transitions
- Onboarding flow
- Anime page — proper ViewModel with real anime sources or polished empty state

## Tech Stack

Kotlin 2.1.0 · Jetpack Compose TV (tv-material3 1.1.0) · Media3 1.8.0 · Hilt 2.53.1 · Room 2.7.1 · Coil 3 · Gradle 8.13

**Services:** nexstream-scraper v3 (Node.js, Docker, port 3091) · addon-config-worker (Cloudflare Workers)

## Features

- Stremio addon protocol client (catalog, meta, stream, subtitle)
- TMDB-native metadata (cast, genres, trailers, similar, episodes)
- Debrid-agnostic: RealDebrid, AllDebrid, Premiumize, TorBox (OAuth, AES-256-GCM)
- 5-profile system with watch progress, continue watching, watchlist
- Premium TV UI: NuvioTheme, GlassSidebar, reference-style Settings, YouTube-style profile picker
- V5 focus system: zero `moveFocus()`, per-item FocusRequester graphs, `requestFocusAfterFrames()` everywhere

## Documentation

**[AGENTS.md](AGENTS.md)** — Project context, build guide, architecture, key decisions, pitfalls, current state. AI-assisted development context.
