Commit Graph
201 Commits
Author SHA1 Message Date
ShanaiaBot a8a2db4b64 chore: bump version to 0.1.67+68 [ci skip] 2026-07-02 10:53:12 +02:00
Javier Bautista Fernández 7cfde24811 fix(alarm): avoid ClassCastException casting snooze millis to Long
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m29s
Flutter's StandardMethodCodec encodes Dart ints that fit in 32 bits as
Java Integer, not Long. scheduleAlarm sends preNoticeAtMillis=0 when
rescheduling a snooze, which crashed the unchecked argument<Long>()
cast. Read all millis args as Number and convert with toLong().
2026-07-02 10:52:07 +02:00
ShanaiaBot da9d32849c chore: bump version to 0.1.66+67 [ci skip] 2026-07-01 00:24:18 +02:00
FreeTLab 6acbd7ca93 fix(alarm): handle snooze reschedule failures instead of silently dropping them
Build & Deploy PluriWave / Análisis de código (push) Successful in 47s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m1s
posponerAlarma() and posponerProximaDesdePreaviso() called the native
scheduler with no error handling, unlike guardarAlarma(). When the
native call failed (e.g. revoked exact-alarm permission), the
exception escaped before notifyListeners() ran, leaving the alarm
list stuck on stale data with no real alarm scheduled and no snooze
countdown notification.

Both methods now mirror guardarAlarma()'s pattern: permission
pre-check, try/catch into _error, and an unconditional
notifyListeners() so the UI always reflects the outcome. Failures
surface via SnackBar in the ringing screen and in app.dart's
postpone-next handler.
2026-07-01 00:22:58 +02:00
ShanaiaBot cc98f3f331 chore: bump version to 0.1.65+66 [ci skip] 2026-06-30 22:11:58 +02:00
FreeTLab 5877c2a4ee feat(alarm): add true per-minute live countdown to pre-notice
Build & Deploy PluriWave / Análisis de código (push) Successful in 41s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m34s
Mirror the shipped snooze-countdown chain for the 30-min pre-notice
notification: re-arm ACTION_PRE_NOTICE at each minute boundary via
slot 9, self-stop at remaining<=1, self-heal from wall clock on
missed ticks. Wire cancellation at all 5 sites (cancelAlarm,
scheduleSpec no-trigger branch, snooze-transition branch,
ACTION_SKIP_NEXT, ACTION_POSTPONE_NEXT) using AlarmScheduler's own
requestCode formula to keep PendingIntent identity consistent.
2026-06-30 22:10:41 +02:00
ShanaiaBot f5cf261f12 chore: bump version to 0.1.64+65 [ci skip] 2026-06-30 15:44:24 +02:00
Javier Bautista Fernández ffd09a2179 i18n(alarm): localize all native notification, channel and chooser texts
Build & Deploy PluriWave / Análisis de código (push) Successful in 40s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m33s
Centralize every native-side user-facing string in a single
AlarmNotificationStrings store written by Flutter via a new
setNotificationStrings MethodChannel whenever the app locale changes,
and read at notification/channel build time (with English fallbacks)
even when the engine is dead. This replaces the hardcoded Spanish text
in the ringing notification ("Alarma PluriWave", "Posponer", "Detener"),
the pre-notice notification ("Posponer", "Omitir esta vez"), both
notification channels (names + descriptions) and the file-action
choosers ("Abrir carpeta", "Abrir grabación").

The per-alarm preNoticeTemplate/snoozeCountdown template+label args are
dropped from scheduleAlarm and the persisted spec and folded into the
shared store, so a locale change now also relocalizes already-scheduled
alarms. Channels are re-created on each use so their name/description
refresh after a language switch.

Adds alarmRingingNotificationTitle, alarmFire/PreNoticeChannelName,
alarmFire/PreNoticeChannelDescription and openFolder/openRecording
chooser keys across all 13 locales (reusing snoozeAction, stopAlarmAction,
skipNextAction, snoozeAgainAction). Rewrites the template test around
setNotificationStrings. Kotlin is static-reviewed only; no Android build
environment available here.
2026-06-30 15:41:29 +02:00
Javier Bautista Fernández 481944815f fix(alarm): unfreeze snooze modal and add per-minute snooze countdown
The snooze button was fire-and-forget without error handling: if
posponerAlarma threw (e.g. native scheduleAlarm returns false on a
device without exact-alarm permission), _dismissScreen never ran. The
stuck modal also kept _alarmaSonandoActiva true, which made the next
ring get ignored. _posponer/_detener now dismiss in a finally and stop
audio defensively.

Add a native, AlarmManager-driven snooze countdown notification that
re-posts every minute ("Rings in N min", 3->2->1) while the engine is
dead. scheduleSpec drives scheduleSnoozeCountdown for snoozes (instead
of the 30-min pre-notice). Localized text and button labels travel
Dart->Kotlin as {minutes} templates, same pattern as preNoticeTemplate.

Notification actions: "snooze again" (snoozeAgain, anchored to now)
reports back via the existing snoozed event; "stop" (cancelSnooze)
records a handled occurrence for cold-start reconciliation and emits a
new snoozeCancelled event handled in EstadoAlarmas.

Adds snoozeCountdown/snoozeAgainAction keys across all 13 locales and a
test for the snoozeCancelled event. Kotlin changes are static-reviewed
only; no Android build environment available here.
2026-06-30 15:27:05 +02:00
ShanaiaBot 89ff6a3912 chore: bump version to 0.1.63+64 [ci skip] 2026-06-28 11:56:21 +02:00
FreeTLab 4ffd73d136 fix(alarm): localize pre-notice countdown and fix snooze dismiss
Build & Deploy PluriWave / Análisis de código (push) Successful in 39s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m33s
Replace hardcoded Spanish pre-notice text with computed remaining
minutes using l10n template passed via MethodChannel. Fix snooze
dismiss in dead-app state with canPop guard and SystemNavigator.pop
fallback.
2026-06-28 11:55:15 +02:00
FreeTLab 58922de6fc fix(eq): seed device ID at startup and add device management UI
Fix multi-device EQ auto-switching by calling obtenerDispositivoActual()
during cargarPersistido() to seed the initial device ID. Add device
management modal with rename support, EQ preset editing, and connection
status indicator. Translate device UI keys to all 13 locales.
2026-06-28 11:55:15 +02:00
ShanaiaBot 71978de68f chore: bump version to 0.1.62+63 [ci skip] 2026-06-27 12:16:24 +02:00
FreeTLab d1d4afb88f i18n(eq): translate advanced EQ keys to all 11 remaining locales
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m25s
Add advancedEq* translations for ar, bn, de, fr, hi, id, it, ja, pt,
ru, zh — matching register and style conventions of each locale.
2026-06-27 11:38:45 +02:00
FreeTLab 4632d53eb8 feat(eq): add per-device equalizer with 4-level preset resolution
Introduce multi-device EQ support allowing each audio output device
(built-in speaker, wired, USB, individual Bluetooth by MAC) to have
its own equalizer preset, combined with existing per-station presets
for a full station×device matrix.

- Add DispositivoAudio model and ServicioDispositivoAudio interface
- Add Android platform channel (AudioDeviceCallback) for device detection
- Add iOS AudioDevicesPlugin (AVAudioSession route tracking)
- Extend ServicioEcualizador with device and matrix persistence keys
- Implement 4-level resolution: matrix > station > device > global
- Add advanced EQ settings section with feature toggle (off by default)
- Extend export/import to v3 with backward compatibility
- 184 tests passing, zero analyzer issues
2026-06-27 11:33:53 +02:00
ShanaiaBot 8f42e67b48 chore: bump version to 0.1.61+62 [ci skip] 2026-06-26 23:05:20 +02:00
FreeTLab f7753c8402 Merge branch 'feat/s6-quality-gates' into main
Build & Deploy PluriWave / Análisis de código (push) Successful in 1m10s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 3m29s
2026-06-12 00:12:43 +02:00
FreeTLab 8a032e6e62 feat(quality): harden lint rules and add quality-gate tests 2026-06-12 00:05:06 +02:00
FreeTLab 202bef3539 feat(ui): design token discipline, accessibility and i18n pass
- Replace all hardcoded Color literals outside lib/tema with theme tokens (new static brand palette in PluriWaveTokens); media notification uses the brand color instead of the Material default purple
- Favorite button on station cards grows to a 48dp target and becomes an independent semantics node for screen readers (Semantics container fix)
- All flutter_animate call sites route through the PluriAnimate reduced-motion gate (zero direct .animate() left)
- Locale-aware short dates via intl DateFormat (new lib/l10n/formato_fechas.dart) replacing the hardcoded DD/MM/YYYY; proper plural messages for the favorites counter; example stream URL as a localized key - all 13 locales
- Rounded shimmer placeholders matching card radii; shimmer loading state in search instead of a bare spinner; rounded icon variants unified in settings; bottom-sheet conventions on the custom station form
- Fix latent debug crash: vacation editor read AppLocalizations in initState
- 11 new tests (121 total green), flutter analyze clean
2026-06-11 23:42:16 +02:00
FreeTLab 52855e75c2 refactor(state): extract recording and search state, scope screen rebuilds
- New EstadoGrabacion owns the recording service, subscription, directory/size preferences and open-file actions
- New EstadoBusqueda owns search, nearby stations, pagination and the min-bitrate filter
- New orden_emisoras.dart with the OrdenEmisoras enum, shared sorter and list identity memoization so context.select comparisons work on derived lists
- Large screens (inicio, buscar, favoritos, ajustes, reproductor) consume scoped selects/dedicated notifiers instead of root context.watch<EstadoRadio>, so audio buffer events no longer rebuild whole screens
- Remove all 15 TODO(S4b) compat members from EstadoRadio; consumers use the dedicated providers. EstadoRadio drops from ~1121 to 753 lines, keeping playback/stations/favorites orchestration
- 8 new tests including a rebuild-scoping probe (110 total green), flutter analyze clean
2026-06-11 21:43:18 +02:00
FreeTLab 0416b301b2 refactor(state): extract export/import service and equalizer state from EstadoRadio
- New ServicioExportImport owns the v2 backup envelope, pretty JSON encode and graceful decode; byte-compatible with existing exports, locked by a round-trip test
- pantalla_ajustes delegates backup serialization to the service (inline jsonDecode/jsonEncode removed)
- New EstadoEcualizador ChangeNotifier owns all EQ state and persistence (principal/current/per-station presets, active flag), exposed via its own provider so EQ changes no longer rebuild EstadoRadio consumers
- EstadoRadio slims down ~210 lines and keeps 15 delegating compat members marked TODO(S4b) for the next slice to remove
- Player EQ toggle rewired to the new provider to avoid going stale
- 4 new tests (103 total green), flutter analyze clean
2026-06-11 21:16:30 +02:00
FreeTLab 0380bbb1e7 feat(streaming): buffer resilience and automatic reconnection
- 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
2026-06-11 19:54:30 +02:00
FreeTLab 079e19f0ee feat(audio): audio session integration and runtime robustness
- Integrate audio_session (new servicio_audio_session.dart): incoming calls pause the radio and resume on end, headphone unplug pauses without auto-resume, permanent focus loss never auto-resumes, duck lowers volume
- Add play-intent flag to ServicioAudio so interruption handling and future reconnect logic can distinguish user pause from system-driven stops
- Eliminate read-modify-write race in ServicioAlarmas with an in-memory cache and single-writer queue across all mutations; recalcularTodas persists only when state actually changed
- Convert ServicioAlarmasAndroid static StreamController/handler to injectable instance fields, restoring test isolation
- Inject a single cached SharedPreferences from main.dart across services and state (removes 23 inline getInstance() calls)
- Move configurarLocalizaciones out of MiniReproductor.build() (was running on every rebuild during playback)
- Bound the alarm fire-dedup set (cap 200 entries, 24h pruning)
- 12 new tests (89 total green), flutter analyze clean
2026-06-11 16:25:09 +02:00
FreeTLab f3e9487215 feat(alarms): native reliability fixes and end-to-end snooze
- 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)
2026-06-11 15:33:30 +02:00
ShanaiaBot b5acf97ba4 chore: bump version to 0.1.60+61 [ci skip] 2026-06-04 16:30:30 +02:00
Javier Bautista Fernández cf9422dff3 Exportar e importar absolutamente toda la información de las preferencias de la aplicación
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m25s
2026-06-04 16:05:58 +02:00
ShanaiaBot 957615dcd6 chore: bump version to 0.1.59+60 [ci skip] 2026-06-03 22:07:12 +02:00
FreeTLab 089b8b4227 fix(i18n): normalize translations and fallbacks
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m34s
2026-06-03 21:20:08 +02:00
ShanaiaBot a5475ce118 chore: bump version to 0.1.58+59 [ci skip] 2026-06-03 14:55:56 +02:00
Javier Bautista Fernández 00fe49c309 fix: resolver advertencias de analisis i18n
Build & Deploy PluriWave / Análisis de código (push) Successful in 35s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m26s
2026-06-03 14:54:50 +02:00
Javier Bautista Fernández 643ba1eb45 fix: completar migracion i18n de literales visibles
Build & Deploy PluriWave / Análisis de código (push) Failing after 28s
Build & Deploy PluriWave / Build APK + AAB release (push) Has been skipped
2026-06-03 13:43:43 +02:00
ShanaiaBot 7abc8c3b0f chore: bump version to 0.1.57+58 [ci skip] 2026-06-02 10:20:40 +02:00
Javier Bautista Fernández 2e17dfd511 Merge branch 'main' of https://git.freetimelab.es/FreeTLab/pluriwave
Build & Deploy PluriWave / Análisis de código (push) Successful in 35s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m24s
2026-06-02 10:19:38 +02:00
Javier Bautista Fernández d449d8577b Add localization support for search and alarm features in multiple languages
- 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.
2026-06-02 10:19:37 +02:00
Javier Bautista Fernández ffe1c41458 eliminados los snooze 2026-06-02 09:21:43 +02:00
ShanaiaBot d423676623 chore: bump version to 0.1.56+57 [ci skip] 2026-06-01 13:21:13 +02:00
Javier Bautista Fernández de07316d79 feat(alarmas): agregar fade-in configurable en activacion
Build & Deploy PluriWave / Análisis de código (push) Successful in 37s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m29s
2026-06-01 13:20:06 +02:00
ShanaiaBot c3a22c4658 chore: bump version to 0.1.55+56 [ci skip] 2026-05-31 00:34:24 +02:00
FreeTLab 7c7bd64e85 Merge pull request 'fix(ci): remove keytool verification step that fails on runner' (#10) from fix/remove-keytool-verify into main
Build & Deploy PluriWave / Análisis de código (push) Successful in 47s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m5s
Reviewed-on: #10
2026-05-31 00:33:01 +02:00
FreeTLab 2aeef1626c fix(ci): remove keytool verification step that fails on runner 2026-05-31 00:32:21 +02:00
ShanaiaBot 1d39293fe3 chore: bump version to 0.1.54+55 [ci skip] 2026-05-31 00:25:54 +02:00
FreeTLab ef4b8ab323 Merge pull request 'fix(ci): simplify Flutter test execution' (#9) from fix/simplify-ci-tests into main
Build & Deploy PluriWave / Análisis de código (push) Successful in 41s
Build & Deploy PluriWave / Build APK + AAB release (push) Failing after 2m29s
Reviewed-on: #9
2026-05-31 00:11:44 +02:00
FreeTLab 20c135a848 fix(ci): simplify Flutter test execution
- Remove complex Python wrapper that caused timeout issues
- Use direct flutter test with --concurrency=1 --timeout=60s
- Simplify cleanup with pkill instead of Python loop
- Increase timeout from 4m to 15m (tests take ~10s but CI overhead is high)
2026-05-31 00:08:01 +02:00
Javier Bautista Fernández 82f70e2fa3 fix(ci): poll flutter test output from file
Build & Deploy PluriWave / Análisis de código (push) Failing after 10m55s
Build & Deploy PluriWave / Build APK + AAB release (push) Has been skipped
2026-05-29 13:55:29 +02:00
Javier Bautista Fernández eb23a438b6 fix(ci): stop flutter tests after success sentinel
Build & Deploy PluriWave / Análisis de código (push) Failing after 12m35s
Build & Deploy PluriWave / Build APK + AAB release (push) Has been skipped
2026-05-29 13:36:51 +02:00
Javier Bautista Fernández d45fbe60db fix(alarms): skip handled occurrence when recalculating
Build & Deploy PluriWave / Build APK + AAB release (push) Has been cancelled
Build & Deploy PluriWave / Análisis de código (push) Has been cancelled
2026-05-29 13:29:41 +02:00
Javier Bautista Fernández 3640a76253 fix(ci): enforce critical test watchdog
Build & Deploy PluriWave / Build APK + AAB release (push) Has been cancelled
Build & Deploy PluriWave / Análisis de código (push) Has been cancelled
2026-05-29 13:26:15 +02:00
Javier Bautista Fernández 4a00472a83 fix(ci): isolate critical flutter tests
Build & Deploy PluriWave / Build APK + AAB release (push) Has been cancelled
Build & Deploy PluriWave / Análisis de código (push) Has been cancelled
2026-05-29 13:16:52 +02:00
Javier Bautista Fernández 028e2d69b1 fix(alarms): harden native alarm lifecycle
Build & Deploy PluriWave / Build APK + AAB release (push) Has been cancelled
Build & Deploy PluriWave / Análisis de código (push) Has been cancelled
2026-05-29 13:13:39 +02:00
FreeTLab 8f6124fc1a fix(ci): avoid killing flutter between test files
Build & Deploy PluriWave / Análisis de código (push) Failing after 13m30s
Build & Deploy PluriWave / Build APK + AAB release (push) Has been skipped
2026-05-29 00:02:51 +02:00