- Construct the audio player with an enlarged live-stream buffer (15-50s forward cushion, 2.5s to start, 5s after rebuffer) so short network drops play through silently
- Add reconnect-on-stall state machine with bounded exponential backoff (1/2/4/8/16s, ~90s total window, 5 attempts) that re-prepares to the live edge; backoff/decision logic extracted to controlador_reconexion.dart as pure testable code
- Surface a new reconnecting playback state in the mini player and full player (localized in all 13 locales) instead of error dialogs during the retry window; a single friendly error appears only after exhaustion
- Guard interplay: user pause/stop cancels retries, audio interruptions cancel reconnect, alarm wake-up path keeps precedence, recording fails cleanly during drops
- Reset retry budget on station change; route stream timeouts through the network-error class
- 10 new tests (99 total green), flutter analyze clean
- Use mediaPlayback|systemExempted FGS type with FOREGROUND_SERVICE_SYSTEM_EXEMPTED so alarms fire on Android 14+ (FOREGROUND_SERVICE_ALARM does not exist in the SDK)
- Deduplicate fire notifications: the foreground service FSI notification is the single owner; receiver path removed
- Notification channel v2 with alarm sound URI and USAGE_ALARM attributes, one-time guarded migration from legacy channels
- Pass fallback station through the MethodChannel (NativeAlarmSpec schemaVersion 3) with a three-stage audio chain: primary -> fallback station -> bundled WAV
- Native fade-in volume ramp honoring fadeInSegundos when the app is killed
- Request battery-optimization exemption once, tracked with a persisted asked-once flag
- Fix snooze end-to-end: native ACTION_SNOOZE now reports back to Flutter (snoozed event + cold-start sync), snooze anchor unified to occurrence+minutes on both sides, periodic recalc no longer erases an active snooze
- Add snooze buttons (3/5/10/custom) to the ringing screen with shared audio teardown
- Redesign ringing screen on PluriWaveScaffold with reduced-motion-aware entry animation (new PluriAnimate helper)
- Alarm editor: live next-trigger preview, searchable station pickers (primary and fallback), configurable snooze duration, volume floor down to 0
- New alarm strings localized across all 13 locales
- New unit/widget tests for the snooze flow, alarm bridge payloads, ringing screen and editor (77 tests green)
- SDD artifacts for the app-quality-and-native-alarms change (explore, proposal, spec, design, tasks, apply progress)
- Updated Japanese, Portuguese, Russian, and Chinese localization files with new strings for search and alarm functionalities.
- Enhanced the search screen with localized titles, subtitles, and filter labels.
- Integrated localization into the alarm screen, including actions and messages related to alarm management.
- Refactored country and language lists to use localized keys for better maintainability.
- Improved user experience by providing localized hints and messages throughout the application.
- 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.
**Fix 1 — HTTP cleartext (streams sin HTTPS):**
- Añadir android/app/src/main/res/xml/network_security_config.xml con
cleartextTrafficPermitted=true para permitir streams de radio HTTP
- Referenciar en AndroidManifest.xml con android:networkSecurityConfig
- Resuelve: 'Cleartext HTTP traffic to [host] not permitted' en ExoPlayer
- Radio Paradise (Dance Wave, HTTP) y otras radios HTTP funcionan ahora
**Fix 2 — Gestión de error TYPE_SOURCE y todos los PlaybackException:**
- Añadir listener en playbackEventStream.onError en PluriWaveAudioHandler
- _gestionarErrorReproduccion() emite AudioProcessingState.error al UI,
loggea el error y resetea el player a estado idle limpio
- _mensajeAmigable() traduce códigos ERROR_CODE_IO_*, ERROR_CODE_PARSING_*,
ERROR_CODE_DECODING_* y mensajes de Cleartext/HandshakeException a texto legible
- EstadoRadio.reproducir() captura la excepción y cancela el timer si estaba activo
- EstadoRadio escucha el estadoStream y cancela timer ante cualquier error
**Fix 3 — Artwork con certificado autofirmado:**
- errorWidget en CachedNetworkImage captura HandshakeException silenciosamente
- Muestra _iconoFallback (icono de radio) en lugar de imagen rota
- El error de artwork no se propaga ni interrumpe la reproducción
**Fix 4 — UI consistente en estado de error:**
- PantallaReproductor._Controles muestra mensaje + botón Reintentar en error
- PantallaReproductor._Artwork muestra overlay wifi_off en estado de error
- MiniReproductor muestra botón refresh (reintentar) en estado de error
- EstadoReproduccion.error ya estaba definido; ahora el estadoStream lo emite
- Timer cancelado automáticamente cuando la reproducción falla
- Test de smoke corregido (boilerplate MyApp → placeholder válido)
Fixes: cleartext HTTP, cert autofirmado, ExoPlayer TYPE_SOURCE, UI inconsistente
- VisualizadorAudio: 24 barras verticales con movimiento orgánico
(senos compuestos con fases aleatorias). Activo=animación fluida,
parado=decaimiento suave. Sin FFT/micrófono. Integrado en
PantallaReproductor entre info emisora y controles.
- IndicadorReproduccion: 3 barras compactas para MiniReproductor.
Reemplaza el icono estático, pulsa mientras hay audio activo.