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:
@@ -301,6 +301,38 @@ export function InfoDialog({
|
||||
);
|
||||
}
|
||||
|
||||
/** Modal progress for work that can't be cancelled or dismissed (e.g. a
|
||||
* library import): a title, a bar, and "N of M <unit>". `total` 0 shows an
|
||||
* empty bar while the work is still starting. */
|
||||
export function ProgressDialog({
|
||||
title,
|
||||
done,
|
||||
total,
|
||||
unit,
|
||||
}: {
|
||||
title: string;
|
||||
done: number;
|
||||
total: number;
|
||||
unit: string;
|
||||
}) {
|
||||
const percent = total > 0 ? Math.round((done / total) * 100) : 0;
|
||||
return (
|
||||
<div className="dialog-backdrop">
|
||||
<div className="dialog" role="progressbar" aria-valuenow={percent} aria-valuemin={0} aria-valuemax={100}>
|
||||
<h3 className="dialog-title">{title}</h3>
|
||||
<div className="ingest-segment active progress-dialog-bar">
|
||||
<div className="ingest-segment-track">
|
||||
<div className="ingest-segment-fill" style={{ width: `${percent}%` }} />
|
||||
</div>
|
||||
</div>
|
||||
<p className="dialog-message muted">
|
||||
{total > 0 ? `${done.toLocaleString()} of ${total.toLocaleString()} ${unit}` : "Starting…"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/** Floating snackbar offering to reverse the caller's last action. Auto-
|
||||
* dismisses on a timer managed by the caller (this component is purely
|
||||
* presentational) — pass `null`/omit rendering it once the window lapses. */
|
||||
|
||||
Reference in New Issue
Block a user