Folders over the 50-item cap now show a "Mas..." item that reveals the next page on tap, instead of silently dropping the rest. Paging slices the cheap raw list before building any MediaItem, so items beyond the requested page are never resolved (art, title) -- proven by a call-count test. Also swaps the raw SAF content:// URI shown in settings for a parsed, human-readable folder name with a localized fallback across all 13 locales. servicio_audio.dart is untouched; this stays entirely within the local-music tree/dispatch layer.
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.