# Exploration: Startup retry, custom stations, and equalizer persistence ## Current State - `lib/main.dart` only initializes `AudioService` and launches `PluriWaveApp`; app data initialization starts later when `EstadoRadio` is created by `ChangeNotifierProvider` in `lib/app.dart`. - `EstadoRadio` constructor calls `_init()` without awaiting it. `_init()` runs `Future.wait([cargarPopulares(), cargarFavoritos(), _cargarEmisoresCustom()])`. - `cargarPopulares()` fetches `radio.obtenerPopulares()` and `radio.obtenerTendencias()` once. On any failure it sets `_errorCarga = 'Sin conexion a la API de radio'`; the UI exposes a manual "Reintentar" button but there is no automatic startup retry. - `ServicioRadio._get()` picks one fallback Radio Browser host, applies a 10s timeout, and clears `_servidorActual` on error so a later call can rotate. It does not retry within the same request. - Custom stations are stored as JSON from inside `EstadoRadio` (`emisoras_custom.json`) and are only rendered in `_SeccionEmisoras` in `pantalla_ajustes.dart`. `PantallaInicio` lists API stations only, so custom stations never enter the main grid. `TarjetaEmisora` already supports favorites for any `Emisora`. - Equalizer state is in memory only: `_presetActual` plus `_presetsEmisoraMap` in `EstadoRadio`. Export/import includes station preset maps, but startup never loads EQ state from app storage. - Per-station EQ is currently unreliable because `EstadoRadio.cambiarPresetEcualizador()` stores by `emisoraActual`, while `PluriWaveAudioHandler.emisoraActual` is declared but never assigned when playback starts. - Existing tests are only `test/widget_test.dart`, a placeholder asserting `true`. Strict TDD is active, so the implementation needs test seams before behavior changes. ## Affected Areas - `lib/servicios/servicio_radio.dart` - startup/API fetch resilience and host retry behavior. - `lib/estado/estado_radio.dart` - startup orchestration, custom station listing, EQ load/save, station EQ selection. - `lib/servicios/servicio_audio.dart` - current station tracking needed for mini player and per-station EQ. - `lib/pantallas/pantalla_inicio.dart` - main listing must include custom stations. - `lib/pantallas/pantalla_ajustes.dart` / `lib/widgets/ecualizador_widget.dart` - EQ scope controls and persisted graph display. - `lib/modelos/preset_ecualizador.dart` - equality/copy helpers may be needed for persistence tests. - `test/` - new unit/widget tests for startup retry, custom station listing/favorites, and EQ persistence. ## Approaches 1. **Retry in `EstadoRadio.cargarPopulares()`** - Pros: small change; directly targets startup; easy to preserve `ServicioRadio`. - Cons: search calls still lack retry; duplicated retry policy if other API calls need it. - Effort: Low. 2. **Retry inside `ServicioRadio._get()` with host rotation** - Pros: centralizes network resilience; startup and search benefit; keeps `EstadoRadio` simpler. - Cons: needs injectable HTTP client/delay for tests; must avoid long blocking startup. - Effort: Medium. 3. **Merge custom stations into main grid via `EstadoRadio` getter** - Pros: minimal UI disruption; `TarjetaEmisora` already handles favorite toggles. - Cons: custom and API stations share one grid; no separate "My stations" visual grouping. - Effort: Low. 4. **Separate "Mis emisoras" section on `PantallaInicio`** - Pros: clearer UX; no confusion with API popularity ranking. - Cons: more UI work and widget tests; still must define empty/genre-filter behavior. - Effort: Medium. 5. **Persist EQ in SharedPreferences through a dedicated service** - Pros: dependency already exists; JSON values fit `PresetEcualizador`; avoids SQLite migration. - Cons: less relational than SQLite; needs careful key/version handling. - Effort: Medium. 6. **Persist EQ in SQLite favorites table** - Pros: station-specific EQ close to favorite rows. - Cons: requires DB migration and does not naturally store global/main EQ. - Effort: High. ## Recommendation Use service-level radio retry with host rotation, expose a combined main-station getter for custom stations, and introduce a small `ServicioEcualizador` backed by SharedPreferences. Represent station EQ as "entry exists = own EQ; no entry = use main EQ". Also fix current-station tracking in the audio layer before wiring station EQ; otherwise the UI and per-station persistence sit on arena sand, not concrete. ## Risks - Retrying both popular and trending in parallel can lengthen startup; cap attempts and use short backoff. - SharedPreferences persistence must be loaded before the first playback applies EQ. - Android equalizer availability is runtime-dependent; persisted EQ must still load even when native EQ is not available yet. - Adding test seams can touch constructors; keep backward-compatible defaults. ## Ready for Proposal Yes. The code paths are clear enough to plan without production changes.