Files
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

5.1 KiB

Proposal: Android Auto Local Music — On-Demand Paging + Friendly Folder Name

Fast-follow polish to the archived android-auto-local-music Phase 1 (archive/2026-07-19-android-auto-local-music/). NOT Phase 2/3.

Intent

Phase 1 capped each local-music folder at _maxItemsCarpetaLocal = 50 and silently truncated the rest alphabetically — items past 50 are unreachable. The user rejects silent data loss and wants on-demand incremental loading, with an explicit memory goal: do NOT eagerly build full MediaItems (art, title) for items beyond the page actually shown. Also fold in an archived verify SUGGESTION: settings shows the raw SAF content URI instead of a human-friendly folder name.

Scope

In Scope

  • Replace silent truncation in itemsLocales with 50-per-page on-demand paging for local-music folders, via a synthetic browsable non-playable "Más…" trailing item (established MediaBrowserService workaround — the car UI has no native "load more" signal).
  • Memory efficiency: hold only the cheap full NodoLocal list per browsed level; construct MediaItems (art/title) ONLY for the requested page. Verified by unit test.
  • Friendly folder-name display in settings _SeccionMusicaLocal instead of the raw content://…/tree/… URI.
  • Update ALL 13 app_*.arb locale files for any new string (the "Más…" label) — Phase 1's verify caught an en/es-only omission; do not repeat.

Out of Scope

  • Phase 2 (metadata/sort/filter/embedded art) and Phase 3 (subfolder scoping/shuffle) — remain deferred.
  • Radio-station folders (_maxItemsPorCarpeta = 50) keep cap-and-truncate; paging is NOT generalized to radio (user raised local music only; no architectural need forces sharing now).
  • Native Kotlin paging: listAudioChildren already returns the full level; no native offset/limit added.

Capabilities

New Capabilities

None.

Modified Capabilities

  • android-auto-media: local-music folder browse replaces silent 50-item truncation with on-demand "Más…" paging. (sdd-spec: confirm exact requirement location; the settings friendly-name fix is phone-UI and may need only a light or no spec delta.)

Approach

Pure-Dart, additive on existing seams. itemsLocales(nodos, pagina) sorts the full (cheap) NodoLocal list deterministically, then .skip(pagina*50).take(50).map(_itemLocal) — so only the page's items are built — and appends a "Más…" item when more remain. The "Más…" media-id encodes (documentId, siguientePagina) (new prefix, e.g. carpeta_local_pag:); tapping it re-invokes getChildren, which re-enumerates that one folder (native already returns the whole level) and returns the next slice. Nothing is cached between taps → minimal memory; deterministic sort keeps page boundaries stable across re-queries. Friendly name via pure-Dart nombreCarpetaDesdeUri(treeUri) (decode the tree documentId's trailing path segment; fall back to the raw URI when empty) — zero native surface, fully unit-testable.

Affected Areas

Area Impact Description
lib/servicios/navegacion_auto.dart Modified itemsLocales gains page param + "Más…" item; paged media-id predicate/parse; hijosMusicaLocal routes paged ids
lib/servicios/servicio_audio.dart Modified getChildren branch for the paged "Más…" media-id
lib/servicios/musica_local_auto.dart Modified Add nombreCarpetaDesdeUri helper (pure Dart)
lib/pantallas/pantalla_ajustes.dart Modified _SeccionMusicaLocal renders friendly name (line ~361)
lib/l10n/app_{ar,bn,de,en,es,fr,hi,id,it,ja,pt,ru,zh}.arb Modified New "Más…" label across all 13 locales
MainActivity.kt / pubspec.yaml Unchanged No native/dep change

Risks

Risk Likelihood Mitigation
Re-enumerating the folder on each "Más…" tap repeats one SAF query Med Acceptable per-tap cost; deterministic sort keeps pages stable; no cache = minimal memory
Pure-Dart friendly-name derivation brittle for exotic SAF providers Med Fallback to raw URI; native DocumentFile.getName left as a design fallback
Very deep folders still hold full NodoLocal list per level Low DTOs are tiny; only paged MediaItem build is bounded
l10n omission regresses (missing locales) Med Scope all 13 arb files into tasks from the start

Rollback Plan

Behavioral/additive. Revert = restore .take(_maxItemsCarpetaLocal) truncation, drop the paged media-id + "Más…" item, revert the settings subtitle to the raw URI, remove the new arb key. Stations untouched.

Dependencies

None (no new packages, no native changes).

Success Criteria

  • A folder with >50 items exposes every item via "Más…" paging; none silently dropped.
  • Only the requested page's MediaItems are constructed — proven by a unit test (page N+1 items not built until page N+1 is requested).
  • Settings shows a human-friendly folder name, not the raw content URI.
  • All 13 app_*.arb files carry the new label.
  • No station browse/play regression; pure-Dart fully unit-tested; native unchanged.