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.
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.
|