Files
Javier Bautista Fernández d579a0e107 feat: Implement startup retry mechanism for custom stations and equalizer persistence
- Added state management for startup retry and custom station handling in `EstadoRadio`.
- Created tasks for implementing strict TDD with RED tests for HTTP failure retries and EQ persistence.
- Developed verification report to ensure compliance with TDD practices.
- Introduced fake services for testing, including `FakeServicioAudio`, `FakeServicioFavoritos`, and `FakeServicioRadio`.
- Implemented widget tests for `PantallaInicio` and `PantallaFavoritos` to validate UI behavior with custom stations.
- Enhanced `ServicioRadio` to support host rotation and retry logic for API calls.
- Established a new configuration file to enforce project constraints and testing rules.
2026-04-27 17:34:04 +02:00

4.9 KiB

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.