Files
SoulStream/handoff/rounds/ins-r36-probe-head.txt
T
KeelrLeek 9f0601027c android: the handoff — the pending rounds, the pipeline, and what is unverified
Everything written this session that has not been through the device: rounds 43
to 48 (each patch adversarially verified, 43's transient-notice expectation
fixed), a partial round 49, the pipeline scripts, the Android Auto design and
the icon comparison mock. Also the two harness changes that were never A/B'd —
adaptive waits, which may only shorten a declared wait and never lengthen it,
and a ship that runs the mock walk and the deploy at the same time. The A/B and
its 255-step baseline are in handoff/tools; main stays at what the phone has
actually walked.
2026-09-14 07:57:41 -05:00

55 lines
2.1 KiB
Plaintext

/// Open a playlist file and stage it for review. Parsing and resolution only —
/// nothing is written until `playlist_import_commit`.
///
/// The phone has no dialog here, so it picks the file itself (the storage
/// plugin's document picker) and hands the path in — with the picked
/// document's own `name` beside it, because a document that had no path of
/// its own arrives as a copy in the app's cache, and the NAME is what
/// `detect_format` reads the extension off and what titles the draft. The
/// desktop passes neither and opens its own dialog.
#[tauri::command]
pub async fn playlist_import_probe(
app: tauri::AppHandle,
lib: State<'_, LibraryState>,
path: Option<String>,
name: Option<String>,
) -> Result<Option<ImportDraft>, String> {
let picked = match path {
Some(p) if !p.trim().is_empty() => Some(p),
_ => {
let (tx, rx) = tokio::sync::oneshot::channel::<Option<String>>();
#[cfg(desktop)]
{
use tauri_plugin_dialog::DialogExt;
app.dialog()
.file()
.add_filter(
"Playlist",
&["m3u", "m3u8", "pls", "xspf", "csv", "json", "txt"],
)
.pick_file(move |path| {
let _ = tx.send(path.map(|p| p.to_string()));
});
}
#[cfg(mobile)]
{
let _ = &app;
let _ = tx.send(None);
}
rx.await.unwrap_or(None)
}
};
let Some(source) = picked else {
return Ok(None);
};
let source_path = PathBuf::from(&source);
// The picked name wins over the path's own: a cache copy is named after
// the document, but only the document's name is guaranteed to be it.
let name = match name {
Some(n) if !n.trim().is_empty() => n,
_ => source_path
.file_name()
.map(|n| n.to_string_lossy().into_owned())
.unwrap_or_else(|| source.clone()),
};