ManaBox import, with progress and a format explainer
Library → Import cards… now reads a ManaBox collection export, either the .csv or the .txt. The CSV is matched by Scryfall ID, falling back to name, set and collector number, and its Foil column picks the copy group's finish. Condition, language and prices are ignored; proxies count as owned. A decklist line that names a printing now resolves to that printing's card when several cards share the name (a card and its token, or an art-series entry), and a bare name prefers the real card. Imports run in one transaction (nestable via SAVEPOINT), which took the 942-row sample from 22s to 0.2s, and off the main thread, with a progress dialog for slow ones. An explainer of the supported formats now comes before the file picker.
This commit is contained in:
@@ -434,10 +434,34 @@ pub fn export_library_cards(db: Db, oracle_ids: Vec<String>, path: String) -> Re
|
||||
std::fs::write(&path, text).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn import_library_cards(db: Db, path: String) -> Res<LibraryImportResult> {
|
||||
let s = db.lock().unwrap();
|
||||
let text = std::fs::read_to_string(&path).map_err(|e| e.to_string())?;
|
||||
let (added, unresolved) = s.catalog()?.import_library_list(&text).map_err(|e| e.to_string())?;
|
||||
Ok(LibraryImportResult { added, unresolved })
|
||||
/// How far a library import has got, for the progress bar.
|
||||
#[derive(Clone, Serialize)]
|
||||
pub struct LibraryImportProgress {
|
||||
pub done: usize,
|
||||
pub total: usize,
|
||||
}
|
||||
|
||||
/// Import a card list (plain text or a ManaBox export) into the library.
|
||||
/// Runs on a blocking thread so the UI stays responsive, emitting
|
||||
/// `library-import-progress` as it goes.
|
||||
#[tauri::command]
|
||||
pub async fn import_library_cards(app: AppHandle, path: String) -> Res<LibraryImportResult> {
|
||||
crate::sync::blocking(move || {
|
||||
let text = std::fs::read_to_string(&path).map_err(|e| e.to_string())?;
|
||||
let s = crate::sync::lock(&app);
|
||||
// At most one event per percent, so a big file doesn't flood the UI.
|
||||
let mut last_percent = None;
|
||||
let (added, unresolved) = s
|
||||
.catalog()?
|
||||
.import_card_list(&text, |done, total| {
|
||||
let percent = (done * 100).checked_div(total).unwrap_or(100);
|
||||
if last_percent != Some(percent) {
|
||||
last_percent = Some(percent);
|
||||
let _ = app.emit("library-import-progress", LibraryImportProgress { done, total });
|
||||
}
|
||||
})
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(LibraryImportResult { added, unresolved })
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user