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.
This commit is contained in:
+155
@@ -0,0 +1,155 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user