Phase 1: pick a device folder via SAF (persisted grant, no new permission), browse its nested subfolders/tracks as a 5th Android Auto root folder (hidden until configured), and play tracks through the existing pipeline (EQ, art rotation, cold-start-safe source). No metadata/sort/filter/shuffle yet -- filename is the title, generic rotating art is the placeholder; deferred to a follow-up phase. Adds a new pluriwave/file_actions native method (listAudioChildren) and an onActivityResult override in MainActivity for the SAF folder picker -- both static-review-only, no Android build available here.
47 lines
1.6 KiB
Dart
47 lines
1.6 KiB
Dart
/// Local file-system node returned by the native `listAudioChildren`
|
|
/// channel call (Design "Interfaces / Contracts"): either a subfolder or an
|
|
/// audio file, one SAF tree level deep. Pure DTO — no behavior, so no unit
|
|
/// tests are warranted for it on its own (exercised indirectly through its
|
|
/// consumers, e.g. `ConstructorArbolAuto.itemsLocales`).
|
|
class NodoLocal {
|
|
const NodoLocal({
|
|
required this.documentId,
|
|
required this.nombre,
|
|
required this.esDirectorio,
|
|
});
|
|
|
|
/// Opaque SAF document id, unique within the picked tree. May itself
|
|
/// contain `:`/`/` (Design "Prefix stripped by length"), so callers must
|
|
/// never split/parse it — only wrap it verbatim in a media id.
|
|
final String documentId;
|
|
|
|
/// Raw on-device filename (or folder name), NOT yet title-stripped.
|
|
final String nombre;
|
|
|
|
/// Whether this node is a browsable subfolder (`true`) or a playable
|
|
/// audio file (`false`).
|
|
final bool esDirectorio;
|
|
}
|
|
|
|
/// Minimal playable local track (Design "Phase 1 minimal shape" — no
|
|
/// artist/album/duration metadata per spec's "Not in this delta"). Pure
|
|
/// DTO — no behavior, so no unit tests are warranted for it on its own.
|
|
class PistaLocal {
|
|
const PistaLocal({
|
|
required this.documentId,
|
|
required this.titulo,
|
|
required this.contentUri,
|
|
});
|
|
|
|
/// Opaque SAF document id for this track.
|
|
final String documentId;
|
|
|
|
/// Display title, already computed by the caller (filename minus
|
|
/// extension, or a derived fallback — see `navegacion_auto.dart`).
|
|
final String titulo;
|
|
|
|
/// Playable `content://` URI resolved via
|
|
/// `FuenteMusicaLocalAuto.uriContenidoDePista`.
|
|
final String contentUri;
|
|
}
|