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.
8.7 KiB
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/ pageditemsLocales/ pagedhijosMusicaLocal(Phases 2-4) — RED confirmed via a fullflutter test test/servicios/navegacion_auto_test.dartrun 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 viaflutter test test/servicios/musica_local_auto_test.dartshowing 5Method 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-levelpaginaDe<T>,hayPaginaSiguiente; added_prefijoCarpetaLocalPaginada,esCarpetaLocalPaginadaMediaId,paginaCarpetaLocalDesde,_tituloMasLocal,_itemMasLocal; extendeditemsLocalessignature (documentIdPadre,pagina,tamano,@visibleForTesting construirItem) with slice-then-map ordering (ADR-3); added paged branch tohijosMusicaLocal.lib/servicios/musica_local_auto.dart(+47 lines) — added purenombreCarpetaDesdeUri(String treeUri, {required String nombreGenerico}). Signature note: takes the localized fallback text as a plainStringparameter rather than aBuildContext, so the function stays pure and unit-testable without a widget tree (mirrors the_formatearDuracion(AppLocalizations l10n, ...)precedent inpantalla_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 foritemsLocales's full signature.lib/pantallas/pantalla_ajustes.dart(+5/-2 lines) —_SeccionMusicaLocalsubtitle now rendersnombreCarpetaDesdeUri(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) — addedlocalMusicFolderGenericName, matching each locale's existinglocalMusicFolder*/localMusicChoosePathregister. No "Más…" arb key added anywhere (ADR-5 — that label is hardcoded Spanish car-tree text, matching every other car-tree label innavegacion_auto.dart).
Tests:
test/servicios/navegacion_auto_test.dart(+453 lines) — new groups:paginaDe,hayPaginaSiguiente,esCarpetaLocalPaginadaMediaId / paginaCarpetaLocalDesde; rewrote/extendedConstructorArbolAuto.itemsLocalesgroup (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 passdocumentIdPadre); extendedhijosMusicaLocalgroup with 4 new paged-branch tests.test/servicios/musica_local_auto_test.dart(+84 lines) — newnombreCarpetaDesdeUrigroup: 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 rawcontent://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 innavegacion_auto_test.dart+ 10 tests inmusica_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 onceflutter gen-l10nis 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
pantalla_ajustes_test.dartcannot compile in this sandbox — pre-existing, not introduced by this change. The trackedlib/l10n/gen/app_localizations.dartis stale: it predates even the PARENT local-music change and is missinglocalMusicFolderNotConfigured,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 requiresflutter 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 newlocalMusicFolderGenericNamegetter this change adds will appear automatically once that regeneration happens — no code change is needed on top of what's here.- The pre-existing 60-item
itemsLocalescap 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/ fullflutter testwere not run in this session (environment constraint) — task 8.2's original deviation note stands, now also explains Deviation #1 above.