Merges its delta requirements into the android-auto-media base spec. This closes out Phase-1 polish for local music; Phase 2 (metadata, sort/filter, real art) and Phase 3 (subfolder scoping, shuffle) remain the only planned future work for this feature.
156 lines
8.7 KiB
Markdown
156 lines
8.7 KiB
Markdown
# Apply Progress: android-auto-local-music-paging
|
||
|
||
Status: DONE — all 18 tasks across 8 phases completed in a single apply batch
|
||
(first and only batch), delivered as one PR with `size:exception` per the
|
||
resolved delivery strategy.
|
||
|
||
## Tasks Completed: 18 / 18
|
||
|
||
- Phase 1 (Paging Primitives): 1.1-1.4 — done
|
||
- Phase 2 (Paged Media-ID Scheme): 2.1-2.2 — done
|
||
- Phase 3 (Paged `itemsLocales` + "Más…" Item): 3.1-3.5 — done
|
||
- Phase 4 (Wire Paged ID into `hijosMusicaLocal`): 4.1-4.2 — done
|
||
- Phase 5 (Friendly Folder Name): 5.1-5.2 — done
|
||
- Phase 6 (Localization): 6.1 — done (13/13 locales)
|
||
- Phase 7 (Settings UI Wiring): 7.1 — done (implementation); widget test
|
||
written but not executable in this sandbox (see Deviations)
|
||
- Phase 8 (Regression / Manual Follow-Up): 8.1 — done (verified via targeted
|
||
test re-runs); 8.2 — deviated as originally documented (manual follow-up,
|
||
unchanged from tasks.md's own note)
|
||
|
||
## TDD Discipline
|
||
|
||
Strict TDD mode was active. RED was confirmed via actual compile failures
|
||
(missing symbols / signature mismatches) before each GREEN implementation
|
||
step for:
|
||
- `paginaDe<T>` / `hayPaginaSiguiente` (Phase 1) — implemented alongside the
|
||
first test batch write (single edit pass covered both primitives), tests
|
||
then run and passed; no separate RED capture for this pair specifically
|
||
since both are trivial one-line pure functions added in the same edit as
|
||
their tests were authored.
|
||
- `esCarpetaLocalPaginadaMediaId` / `paginaCarpetaLocalDesde` / paged
|
||
`itemsLocales` / paged `hijosMusicaLocal` (Phases 2-4) — RED confirmed via
|
||
a full `flutter test test/servicios/navegacion_auto_test.dart` run showing
|
||
~20 compile errors (`Method not found`, `No named parameter`) before the
|
||
GREEN implementation, then a second run confirming 84/84 passing.
|
||
- `nombreCarpetaDesdeUri` (Phase 5) — RED confirmed via
|
||
`flutter test test/servicios/musica_local_auto_test.dart` showing 5
|
||
`Method not found: 'nombreCarpetaDesdeUri'` compile errors before GREEN,
|
||
then 10/10 passing after.
|
||
- Settings UI wiring (Phase 7) — RED attempted via
|
||
`flutter test test/pantallas/pantalla_ajustes_test.dart`, but this
|
||
surfaced a PRE-EXISTING environment blocker unrelated to this change (see
|
||
Deviations #1). The implementation was completed to spec regardless.
|
||
|
||
## Files Changed
|
||
|
||
Production code:
|
||
- `lib/servicios/navegacion_auto.dart` (+119/-lines within diff) — added
|
||
top-level `paginaDe<T>`, `hayPaginaSiguiente`; added
|
||
`_prefijoCarpetaLocalPaginada`, `esCarpetaLocalPaginadaMediaId`,
|
||
`paginaCarpetaLocalDesde`, `_tituloMasLocal`, `_itemMasLocal`; extended
|
||
`itemsLocales` signature (`documentIdPadre`, `pagina`, `tamano`,
|
||
`@visibleForTesting construirItem`) with slice-then-map ordering (ADR-3);
|
||
added paged branch to `hijosMusicaLocal`.
|
||
- `lib/servicios/musica_local_auto.dart` (+47 lines) — added pure
|
||
`nombreCarpetaDesdeUri(String treeUri, {required String nombreGenerico})`.
|
||
Signature note: takes the localized fallback text as a plain `String`
|
||
parameter rather than a `BuildContext`, so the function stays pure and
|
||
unit-testable without a widget tree (mirrors the
|
||
`_formatearDuracion(AppLocalizations l10n, ...)` precedent in
|
||
`pantalla_reproductor.dart`, minus the generated-class coupling). This is
|
||
a refinement of tasks.md's terse "`nombreCarpetaDesdeUri(String) -> String`"
|
||
description, the same kind of abbreviation gap task 3.4 already had for
|
||
`itemsLocales`'s full signature.
|
||
- `lib/pantallas/pantalla_ajustes.dart` (+5/-2 lines) — `_SeccionMusicaLocal`
|
||
subtitle now renders
|
||
`nombreCarpetaDesdeUri(carpeta, nombreGenerico: l10n.localMusicFolderGenericName)`
|
||
instead of the raw persisted URI; the unconfigured branch is unchanged
|
||
(`l10n.localMusicFolderNotConfigured`).
|
||
- `lib/l10n/app_{ar,bn,de,en,es,fr,hi,id,it,ja,pt,ru,zh}.arb` (13 files,
|
||
+1 key each) — added `localMusicFolderGenericName`, matching each locale's
|
||
existing `localMusicFolder*`/`localMusicChoosePath` register. No "Más…"
|
||
arb key added anywhere (ADR-5 — that label is hardcoded Spanish car-tree
|
||
text, matching every other car-tree label in `navegacion_auto.dart`).
|
||
|
||
Tests:
|
||
- `test/servicios/navegacion_auto_test.dart` (+453 lines) — new groups:
|
||
`paginaDe`, `hayPaginaSiguiente`,
|
||
`esCarpetaLocalPaginadaMediaId / paginaCarpetaLocalDesde`; rewrote/extended
|
||
`ConstructorArbolAuto.itemsLocales` group (call-count invariant, exact-50
|
||
boundary, 51-100 two-step, 100+ chained 3+ pages, "Más…" item shape/round
|
||
-trip, root paging, stale-page-beyond-range, plus all 8 pre-existing call
|
||
sites updated to pass `documentIdPadre`); extended `hijosMusicaLocal`
|
||
group with 4 new paged-branch tests.
|
||
- `test/servicios/musica_local_auto_test.dart` (+84 lines) — new
|
||
`nombreCarpetaDesdeUri` group: internal storage, SD card, nested folder,
|
||
storage-root empty-tail fallback, unparseable-URI fallback, never-raw
|
||
-URI/never-empty invariant.
|
||
- `test/pantallas/pantalla_ajustes_test.dart` (+57 lines) — new group
|
||
`_SeccionMusicaLocal — friendly folder name (Phase 7)`: configured folder
|
||
shows the derived friendly name (never the raw `content://` URI);
|
||
unconfigured folder keeps the existing "not configured" message. Written
|
||
to spec but NOT executable in this sandbox (see Deviations #1).
|
||
|
||
## Test Results (independently re-confirmed)
|
||
|
||
- `flutter test test/servicios/navegacion_auto_test.dart test/servicios/musica_local_auto_test.dart --concurrency=1 --timeout=60s`
|
||
→ **94 / 94 passing** (84 tests in `navegacion_auto_test.dart` + 10 tests
|
||
in `musica_local_auto_test.dart`) — corrected during verify, the figure
|
||
above (95/95, 85+10) originally reported here was a counting error.
|
||
- `test/pantallas/pantalla_ajustes_test.dart` — NOT run to completion; fails
|
||
to COMPILE in this sandbox for reasons that predate this change entirely
|
||
(see Deviations #1). The 2 new tests in this file are structurally
|
||
complete and should pass once `flutter gen-l10n` is run as part of the
|
||
normal manual follow-up (task 8.2), which already covers regenerating
|
||
l10n artifacts.
|
||
|
||
## Diff Size
|
||
|
||
`git diff --stat`: 19 files changed, 764 insertions(+), 40 deletions(-)
|
||
(≈804 changed lines). This exceeds the tasks.md forecast of ~480-600 lines,
|
||
mainly because task 3.5's "mechanical" call-site update also required
|
||
rewriting one pre-existing assertion (the 60-item cap test) into two new
|
||
boundary tests reflecting the spec's cap→paging behavior change, plus the
|
||
call-count-invariant test's verbosity (4 assertions × explicit spy
|
||
wiring). Delivered as a single PR with `size:exception`, as directed.
|
||
|
||
## Deviations
|
||
|
||
1. **`pantalla_ajustes_test.dart` cannot compile in this sandbox —
|
||
pre-existing, not introduced by this change.** The tracked
|
||
`lib/l10n/gen/app_localizations.dart` is stale: it predates even the
|
||
PARENT local-music change and is missing `localMusicFolderNotConfigured`,
|
||
`localMusicSectionTitle`, `localMusicFolderTitle`, etc. — getters the
|
||
file already referenced BEFORE this apply pass touched anything.
|
||
Confirmed by running the targeted test file and observing the compiler
|
||
errors point exclusively at pre-existing lines (320-383) before any new
|
||
code from this change is even reached. Regenerating the l10n artifacts
|
||
requires `flutter gen-l10n`, which is documented to hang in this
|
||
environment and was explicitly out of scope for this apply run (per
|
||
task 8.2, already flagged as a manual follow-up in the original
|
||
tasks.md). The new `localMusicFolderGenericName` getter this change adds
|
||
will appear automatically once that regeneration happens — no code
|
||
change is needed on top of what's here.
|
||
2. **The pre-existing 60-item `itemsLocales` cap test was rewritten, not
|
||
just signature-patched**, as part of task 3.5. This was flagged in
|
||
tasks.md as "mechanical, no behavior change" for the 8 call sites in
|
||
aggregate, but this ONE specific test's assertion (exactly 50 items,
|
||
full stop) is incompatible with the spec's Modified Requirement ("Local
|
||
Music Folder Item Cap and Paging" — cap-and-truncate replaced by
|
||
cap-and-page). It was split into two new tests that assert the correct
|
||
NEW behavior (exactly 50 items → no "Más…"; 51-100 items → 50 + "Más…"
|
||
then the remainder). This is an intentional, spec-mandated behavior
|
||
change, not a regression.
|
||
|
||
## Risks Carried Forward
|
||
|
||
- Re-enumerating the folder per "Más…" tap repeats one SAF query per ADR-2
|
||
(accepted, documented, out of scope to change here).
|
||
- Pure-Dart friendly-name derivation is brittle for exotic SAF providers
|
||
(accepted per ADR-4 — degrades to the generic label, never a crash/blank
|
||
/raw-URI).
|
||
- `flutter analyze` / `flutter gen-l10n` / full `flutter test` were not run
|
||
in this session (environment constraint) — task 8.2's original deviation
|
||
note stands, now also explains Deviation #1 above.
|