Files
pluriwave/openspec/changes/archive/2026-07-19-android-auto-local-music-paging/apply-progress.md
T
FreeTLab e030a0975d docs(openspec): archive android-auto-local-music-paging
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.
2026-07-19 22:21:45 +02:00

8.7 KiB
Raw Blame History

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=60s94 / 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.