Threads Scryfall's per-format legalities through the reference db and adds a
deck-page indicator (structural rules + banned/restricted lists) that lists
violation reasons inline. Decks and selected library cards can now be
exported to/imported from plain-text decklists, with best-effort name
resolution and a report of anything that didn't match. Also adds a shuffle-
and-draw sample hand modal, and an Alt+/ command palette for jumping to a
tab, deck, or card without leaving the keyboard.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Prices come from Scryfall's prices.usd on printings, shown as a hover badge
on card tiles. The price is picked independently of whichever printing
supplies the display image (the cheapest known price across all printings),
since the display printing is often a promo/variant with no listed price.
The maybeboard lets a deck track cards under consideration without counting
them in deck analysis stats or library assignment totals. Cards move between
mainboard and maybeboard via a per-card toggle; maybeboarding the commander
clears commander status.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Threads a new produced_mana/produces_colorless field through the whole card
read path (ingest, library, filters, decks, search) so the deck view can
show what colors a deck's manabase actually produces, alongside its existing
color identity. Also adds a mana consumption bar (colored casting costs of
nonland spells) and stacks the mana curve histogram by color. Adds an
oracle-text substring filter to the library search, mirroring the existing
location filter. Rearranges the deck sidebar list into two rows (name, then
format chip + actions) so long names and action buttons no longer collide,
and removes the drop shadows from the commander hero panel/image.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
LibraryFilter.location does a case-insensitive substring match against
the stored location (e.g. "Box 1"), mirroring the existing text filter.
Tested for substring/case-insensitivity and the empty-string no-op case.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New LibraryStats (unique cards owned, total copies, deck count, and
per-color copy counts including colorless) via Catalog::library_stats,
tested against the fixture catalog.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New Catalog::rename_deck / duplicate_deck (duplicating format, commander,
notes, and every deck_cards row under a new name), with tests covering
the UNIQUE(name) collision cases the UI needs to surface as friendly
errors rather than raw SQL messages.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add a back_image_uri column to printings, populated during ingest from
a card's second card_faces image (only present for transform/MDFC/
reversible cards — split/adventure cards share one combined image and
correctly get ""). Plumb it through CardRef across every query path
(search, library, filters, deck contents) via the same printing row,
using a shared deterministic ORDER BY so front/back always come from
one printing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Exclude Scryfall Art Series cards (layout "art_series") from ingest —
they aren't playable cards and were polluting search results.
- Replace the coarse per-stage progress text with a byte-accurate,
weighted multi-segment progress bar (Index / Card data / Printings /
Indexing) that fills as one continuous bar instead of swapping per
stage; segment weights are computed from the real download sizes
reported by Scryfall's bulk-data index (the download responses
themselves are chunked with no Content-Length to rely on).
- Add a Cancel button, wired through a new CancelToken checked once per
parsed record so cancellation lands almost instantly.
- Fix a related correctness bug this surfaced: ingest used to delete the
existing reference.db before writing its replacement, so a cancelled
or crashed update left the app with no card database at all. It now
builds into a temp file and only atomically replaces reference.db on
full success.
- Split the topbar's single "Choose library…" action into separate
"Open Library…" (existing file) and "New Library…" (save-dialog for a
new file) buttons.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>