/// 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; }