Add a "not owned" quick filter and horizontal tile view to Card Search
"Not owned" moves into the shared Quick filters icon-toggle row (hidden on the Library tab, where it'd always be a no-op since that view is owned-only already) instead of a standalone button. Tiles view gains a "Horizontal" toggle that rotates actually-horizontal cards (Battles, Planes, Phenomena) into their natural landscape orientation via a container-query-sized wrapper, spanning two grid columns so the rotated card isn't squeezed into a single portrait column's width and left too small to read. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -254,6 +254,10 @@ impl Catalog {
|
||||
let mut vals: Vec<Value> = Vec::new();
|
||||
push_card_filters(&mut sql, &mut vals, filter, self.has_universes_beyond, self.has_vanilla);
|
||||
|
||||
if filter.not_owned {
|
||||
sql.push_str(" AND COALESCE(lc.quantity_owned, 0) = 0");
|
||||
}
|
||||
|
||||
sql.push_str(" ORDER BY oc.edhrec_rank IS NULL, oc.edhrec_rank, oc.name COLLATE NOCASE LIMIT ?");
|
||||
vals.push(Value::Integer(limit as i64));
|
||||
|
||||
@@ -765,6 +769,31 @@ mod tests {
|
||||
assert_eq!(bolt.quantity_owned, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn search_reference_not_owned_excludes_owned_cards() {
|
||||
let fx = test_support::make();
|
||||
let cat = &fx.catalog;
|
||||
cat.add_owned("sol-ring", 1).unwrap();
|
||||
|
||||
let unowned = cat.search_reference(&LibraryFilter {
|
||||
not_owned: true,
|
||||
..Default::default()
|
||||
}, 50).unwrap();
|
||||
assert!(!unowned.iter().any(|c| c.card.oracle_id == "sol-ring"));
|
||||
// The other four fixture cards are all unowned and still show up.
|
||||
assert_eq!(unowned.len(), 4);
|
||||
|
||||
// A card set to 0 owned (never actually acquired, or reset back to 0)
|
||||
// counts as not-owned too, not just "no library_cards row at all".
|
||||
cat.add_owned("lightning-bolt", 1).unwrap();
|
||||
cat.set_owned("lightning-bolt", 0).unwrap();
|
||||
let unowned = cat.search_reference(&LibraryFilter {
|
||||
not_owned: true,
|
||||
..Default::default()
|
||||
}, 50).unwrap();
|
||||
assert!(unowned.iter().any(|c| c.card.oracle_id == "lightning-bolt"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn search_reference_respects_limit() {
|
||||
let fx = test_support::make();
|
||||
|
||||
@@ -341,6 +341,12 @@ pub struct LibraryFilter {
|
||||
pub power_max: Option<f64>,
|
||||
pub toughness_min: Option<f64>,
|
||||
pub toughness_max: Option<f64>,
|
||||
/// Only cards with zero owned copies. Meaningless against
|
||||
/// [`Catalog::search_library`] (which already only returns owned cards),
|
||||
/// so it's only honored by [`Catalog::search_reference`] — the Card
|
||||
/// Search tab's "Not owned" quick filter.
|
||||
#[serde(default)]
|
||||
pub not_owned: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user