Add a Card Search tab and fix horizontal-card (Battle/Plane) preview orientation
Card Search browses the whole downloaded card universe (not just owned cards), reusing the Library tab's filter/group/sort/list/tiles UI; results show ownership and offer quick "own" and "add to deck" actions. Battles, Planes, and Phenomena store their Scryfall image portrait-shaped with the content itself rotated, so hover/click previews now detect this (a new `horizontal` flag threaded through ingest and every card query, with graceful fallback for a reference.db built before the column existed) and rotate the image back into place. Single-faced and non-DFC cases are verified fixed; a double-faced Battle's front face still needs another pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -461,8 +461,8 @@ fn load_oracle_cards(conn: &Connection, reader: impl Read, cancel: &CancelToken)
|
||||
let mut ins_card = conn.prepare(
|
||||
"INSERT OR IGNORE INTO oracle_cards
|
||||
(oracle_id,name,name_lower,mana_value,colors,color_identity,type_line,oracle_text,
|
||||
produced_mana,produces_colorless,legalities,themes,edhrec_rank)
|
||||
VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13)",
|
||||
produced_mana,produces_colorless,legalities,themes,edhrec_rank,horizontal)
|
||||
VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14)",
|
||||
)?;
|
||||
let mut ins_fts =
|
||||
conn.prepare("INSERT INTO oracle_names_fts(name,oracle_id) VALUES (?1,?2)")?;
|
||||
@@ -543,6 +543,10 @@ fn load_oracle_cards(conn: &Connection, reader: impl Read, cancel: &CancelToken)
|
||||
|
||||
let legalities = Legalities::from_scryfall(&c.legalities);
|
||||
let themes = crate::synergy::compute_themes(&oracle_text);
|
||||
// Battles and Planes/Phenomena store their card image portrait-shaped
|
||||
// with the content itself rotated — viewers must rotate it 90° to
|
||||
// read it right-side up (verified against real Scryfall images).
|
||||
let horizontal = matches!(c.layout.as_str(), "battle" | "planar");
|
||||
|
||||
let changed = ins_card.execute(params![
|
||||
oracle_id,
|
||||
@@ -558,6 +562,7 @@ fn load_oracle_cards(conn: &Connection, reader: impl Read, cancel: &CancelToken)
|
||||
legalities.0,
|
||||
themes,
|
||||
c.edhrec_rank,
|
||||
horizontal as i64,
|
||||
])?;
|
||||
// Only emit satellite rows the first time we see this oracle_id.
|
||||
if changed == 1 {
|
||||
@@ -1012,6 +1017,41 @@ mod tests {
|
||||
assert_eq!(van_rank, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn captures_horizontal_flag_for_battle_and_planar_layouts_only() {
|
||||
let oracle = r#"[
|
||||
{"oracle_id":"oid-battle","name":"Invasion of Zendikar","layout":"battle","cmc":4.0,
|
||||
"type_line":"Battle — Siege","color_identity":["G"],"keywords":[]},
|
||||
{"oracle_id":"oid-plane","name":"Academy at Tolaria West","layout":"planar","cmc":0.0,
|
||||
"type_line":"Plane — Dominaria","color_identity":[],"keywords":[]},
|
||||
{"oracle_id":"oid-scheme","name":"A Display of My Dark Power","layout":"scheme","cmc":0.0,
|
||||
"type_line":"Scheme","color_identity":[],"keywords":[]},
|
||||
{"oracle_id":"oid-normal","name":"Grizzly Bears","layout":"normal","cmc":2.0,
|
||||
"type_line":"Creature — Bear","color_identity":["G"],"keywords":[]}
|
||||
]"#;
|
||||
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let dest = dir.path().join("reference.db");
|
||||
let conn = open_reference_for_build(&dest).unwrap();
|
||||
load_oracle_cards(&conn, oracle.as_bytes(), &CancelToken::new()).unwrap();
|
||||
|
||||
let horizontal = |id: &str| -> bool {
|
||||
conn.query_row(
|
||||
"SELECT horizontal FROM oracle_cards WHERE oracle_id=?1",
|
||||
params![id],
|
||||
|r| r.get::<_, i64>(0),
|
||||
)
|
||||
.unwrap()
|
||||
!= 0
|
||||
};
|
||||
|
||||
assert!(horizontal("oid-battle"));
|
||||
assert!(horizontal("oid-plane"));
|
||||
// Schemes are oversized but not rotated — only battle/planar layouts are.
|
||||
assert!(!horizontal("oid-scheme"));
|
||||
assert!(!horizontal("oid-normal"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn captures_back_face_image_for_double_faced_cards() {
|
||||
// Transform/MDFC cards: two `card_faces`, each with its own image.
|
||||
|
||||
Reference in New Issue
Block a user