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.
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
itemsLocaleswith 50-per-page on-demand paging for local-music folders, via a synthetic browsable non-playable "Más…" trailing item (establishedMediaBrowserServiceworkaround — the car UI has no native "load more" signal). - Memory efficiency: hold only the cheap full
NodoLocallist per browsed level; constructMediaItems (art/title) ONLY for the requested page. Verified by unit test. - Friendly folder-name display in settings
_SeccionMusicaLocalinstead of the rawcontent://…/tree/…URI. - Update ALL 13
app_*.arblocale 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:
listAudioChildrenalready 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_*.arbfiles carry the new label. - No station browse/play regression; pure-Dart fully unit-tested; native unchanged.