Persist the exploration, proposal, spec, design, tasks, and verify/archive reports produced during the multi-device EQ, alarm-countdown, and notification-visual-polish SDD cycles.
6.6 KiB
6.6 KiB
Tasks: Alarm Live Countdown
Review Workload Forecast
| Field | Value |
|---|---|
| Estimated changed lines | ~175–200 (additions + deletions) |
| 400-line budget risk | Low |
| Chained PRs recommended | No |
| Suggested split | Single PR |
| Delivery strategy | ask-on-risk |
| Chain strategy | pending |
Decision needed before apply: No Chained PRs recommended: No Chain strategy: pending 400-line budget risk: Low
Suggested Work Units
| Unit | Goal | Likely PR | Notes |
|---|---|---|---|
| 1 | All changes (l10n + MethodChannel + Kotlin receiver + snooze guard) | PR 1 | Two logically isolated features; same PR acceptable given low line count |
Phase 1: Foundation — ARB Keys and Contracts
- 1.1 Add
preNoticeCountdownkey (value:"Starts in {minutes} min") tolib/l10n/app_en.arbas the canonical English source key. - 1.2 [RED] Write a Dart unit test asserting
AppLocalizations.of(ctx).preNoticeCountdown(minutes: 30)returns the expected English string; confirm it fails (key missing). - 1.3 Add
preNoticeCountdownkey to all 12 remaininglib/l10n/app_*.arbfiles (es, fr, de, pt, it, ja, ko, zh, ar, ru, nl, pl) using locale-appropriate translation following thedurationMinutesOnlysentence pattern. Each value must contain the{minutes}placeholder. - 1.4 [GREEN] Run
flutter gen-l10n; confirm test 1.2 now passes. - 1.5 [REFACTOR] Verify ARB placeholder annotations (
"@preNoticeCountdown"withplaceholders.minutes.type: "int") are present inapp_en.arbper ARB spec convention.
Phase 2: Flutter Side — MethodChannel Argument
- 2.1 [RED] Write a unit/widget test for
ServicioAlarmasAndroid.programar()asserting the MethodChannel call includes apreNoticeTemplatekey whose value contains{minutes}. - 2.2 In
lib/servicios/servicio_alarmas_android.dart, computepreNoticeTemplatefroml10n.preNoticeCountdown(minutes: '{minutes}')(passing the literal placeholder string) and add it to thescheduleAlarmMethodChannel arguments map. - 2.3 [GREEN] Confirm test 2.1 passes.
- 2.4 [REFACTOR] Ensure the
preNoticeTemplateargument is added adjacent to the existingtitlelocalization call; no dead code left over.
Phase 3: Kotlin — AlarmScheduler and NativeAlarmSpec
- 3.1 [RED] Write a Kotlin unit test asserting
AlarmScheduler.scheduleAlarm()with apreNoticeTemplatestring stores it in the resultingNativeAlarmSpecand embeds it into the PendingIntent extras under key"preNoticeTemplate". - 3.2 Add
preNoticeTemplate: String? = nullfield toNativeAlarmSpecdata class inandroid/.../AlarmScheduler.kt(nullable for backward compat; schema stays v3). - 3.3 Update
MainActivity.ktto readpreNoticeTemplatefrom the MethodChannel arguments map and pass it toAlarmScheduler.scheduleAlarm(). - 3.4 In
AlarmScheduler.scheduleAlarm(), acceptpreNoticeTemplateparam and embed it into the pre-noticeIntentextras asEXTRA_PRE_NOTICE_TEMPLATE = "preNoticeTemplate". - 3.5 [GREEN] Confirm test 3.1 passes.
- 3.6 [REFACTOR] Confirm
EXTRA_PRE_NOTICE_TEMPLATEconstant is declared once (inAlarmScheduleror a shared constants file) and not duplicated between scheduler and receiver.
Phase 4: Kotlin — BroadcastReceiver Countdown Computation
- 4.1 [RED] Write a Kotlin unit test for
PluriWaveAlarmReceiver.showPreNoticeNotification()covering: (a) normal case returns template with computed minutes, (b) clamped to 1 whentriggerAtMillis <= currentTimeMillis, (c) null template falls back to English default text. - 4.2 In
android/.../PluriWaveAlarmReceiver.kt, readEXTRA_PRE_NOTICE_TEMPLATEfrom the intent extras. Computeremaining = max(1L, (triggerAtMillis - System.currentTimeMillis()) / 60_000). Replace{minutes}placeholder in the template and pass result toNotificationCompat.Builder.setContentText(). - 4.3 Add null-safety fallback: if
preNoticeTemplateis null or blank, use"Starts in $remaining min"as the default English string. - 4.4 Remove the existing hardcoded Spanish
"Empieza en 30 minutos"string from the receiver. - 4.5 [GREEN] Confirm all test cases in 4.1 pass.
- 4.6 [REFACTOR] Extract the minutes-computation expression into a private function
computeRemainingMinutes(triggerAtMillis: Long): Longfor readability and testability.
Phase 5: Dart — Snooze Dismiss Guard
- 5.1 [RED] Write a widget test for
PantallaAlarmaSonando._posponer()inlib/pantallas/pantalla_alarma_sonando.dartasserting: (a) whenNavigator.canPop()is true,Navigator.pop()is called andSystemNavigator.pop()is NOT called; (b) whencanPop()is false,SystemNavigator.pop()is called instead. - 5.2 In
lib/pantallas/pantalla_alarma_sonando.dart, replace the bareNavigator.of(context).pop()in_posponer()withif (Navigator.of(context).canPop()) { Navigator.of(context).pop(); } else { SystemNavigator.pop(); }. Apply the same guard to_detener()if it also callspop()without a guard. - 5.3 Verify that
_liberarAudioLocal(),radio.audio.pausar(), andalarmas.posponerAlarma()all execute BEFORE the navigation action (ordering unchanged). - 5.4 [GREEN] Confirm tests from 5.1 pass.
- 5.5 [REFACTOR] Extract the guard into a private helper
_dismissScreen()called from both_posponer()and_detener()to eliminate duplication.
Phase 6: Integration Verification
- 6.1 Extend existing
scheduleAlarmintegration test (MethodChannel round-trip) to assertpreNoticeTemplatesurvives the Flutter → Kotlin boundary correctly. - 6.2 Confirm
notificationIdForAlarm(alarmId)is used inshowPreNoticeNotification()(notification ID stability — re-posting same ID updates in place). No change needed if already correct; add assertion to test if not. - 6.3 Run full test suite (
flutter test+ Kotlin./gradlew test); all pre-existing tests must remain green. - 6.4 Manual smoke test: schedule an alarm ~2 min out; verify pre-notice notification shows correct locale and computed minutes; tap Snooze from a fresh app launch; confirm screen dismisses cleanly.
Phase 7: Cleanup
- 7.1 Confirm no hardcoded Spanish strings remain in
PluriWaveAlarmReceiver.ktnotification path (rg "Empieza" android/). - 7.2 Confirm
preNoticeTemplateis the only new MethodChannel key added; no dead args left inscheduleAlarmmap. - 7.3 Update inline code comments in
AlarmScheduler.ktandPluriWaveAlarmReceiver.ktto document the template-at-schedule-time, replace-at-fire-time pattern.