From 36531ea96dca54447fce01924f3bd855ed058f8c Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sun, 26 Apr 2020 16:55:16 +1000 Subject: [PATCH] add (currently disabled) check for missing/empty decks on card add --- rslib/src/collection.rs | 2 ++ rslib/src/decks/mod.rs | 24 ++++++++++++++++++++++- rslib/src/notetype/cardgen.rs | 36 ++++++++++++++++++++++++++--------- rslib/src/storage/deck/mod.rs | 6 ++++++ 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/rslib/src/collection.rs b/rslib/src/collection.rs index 780fbbce2..90b092847 100644 --- a/rslib/src/collection.rs +++ b/rslib/src/collection.rs @@ -7,6 +7,7 @@ use crate::log::Logger; use crate::timestamp::TimestampSecs; use crate::types::Usn; use crate::{ + decks::{Deck, DeckID}, notetype::{NoteType, NoteTypeID}, sched::cutoff::{sched_timing_today, SchedTimingToday}, storage::SqliteStorage, @@ -52,6 +53,7 @@ pub struct CollectionState { pub(crate) undo: UndoManager, timing_today: Option, pub(crate) notetype_cache: HashMap>, + pub(crate) deck_cache: HashMap>, } #[derive(Debug, PartialEq)] diff --git a/rslib/src/decks/mod.rs b/rslib/src/decks/mod.rs index 038698874..c0fe58831 100644 --- a/rslib/src/decks/mod.rs +++ b/rslib/src/decks/mod.rs @@ -1,10 +1,11 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -use crate::define_newtype; +use crate::{collection::Collection, define_newtype, err::Result}; mod schema11; pub use schema11::Deck; +use std::sync::Arc; define_newtype!(DeckID, i64); @@ -25,3 +26,24 @@ pub(crate) fn get_deck(decks: &[Deck], id: DeckID) -> Option<&Deck> { None } + +impl Deck { + pub(crate) fn is_filtered(&self) -> bool { + matches!(self, Deck::Filtered(_)) + } +} + +impl Collection { + pub(crate) fn get_deck(&mut self, did: DeckID) -> Result>> { + if let Some(deck) = self.state.deck_cache.get(&did) { + return Ok(Some(deck.clone())); + } + if let Some(deck) = self.storage.get_deck(did)? { + let deck = Arc::new(deck); + self.state.deck_cache.insert(did, deck.clone()); + Ok(Some(deck)) + } else { + Ok(None) + } + } +} diff --git a/rslib/src/notetype/cardgen.rs b/rslib/src/notetype/cardgen.rs index 29c1b293e..900c69b0c 100644 --- a/rslib/src/notetype/cardgen.rs +++ b/rslib/src/notetype/cardgen.rs @@ -216,7 +216,7 @@ impl Collection { note: &Note, ) -> Result<()> { let existing = self.storage.existing_cards_for_note(note.id)?; - self.generate_cards_for_note(ctx, note, &existing, None) + self.generate_cards_for_note(ctx, note, &existing, Some(ctx.notetype.target_deck_id())) } fn generate_cards_for_note( @@ -230,7 +230,7 @@ impl Collection { if cards.is_empty() { return Ok(()); } - self.add_generated_cards(ctx, note.id, &cards, target_deck_id) + self.add_generated_cards(note.id, &cards, target_deck_id) } pub(crate) fn generate_cards_for_notetype(&mut self, ctx: &CardGenContext) -> Result<()> { @@ -253,19 +253,13 @@ impl Collection { pub(crate) fn add_generated_cards( &mut self, - ctx: &CardGenContext, nid: NoteID, cards: &[CardToGenerate], target_deck_id: Option, ) -> Result<()> { let mut next_pos = None; for c in cards { - // fixme: deal with case where invalid deck pointed to - // fixme: deprecated note type deck id - let did = c - .did - .or(target_deck_id) - .unwrap_or_else(|| ctx.notetype.target_deck_id()); + let did = self.deck_id_for_adding(c.did.or(target_deck_id))?; let due = c.due.unwrap_or_else(|| { if next_pos.is_none() { next_pos = Some(self.get_and_update_next_card_position().unwrap_or(0)); @@ -278,4 +272,28 @@ impl Collection { Ok(()) } + + /// If deck ID does not exist or points to a filtered deck, fall back on default. + fn deck_id_for_adding(&mut self, did: Option) -> Result { + if let Some(did) = did.and_then(|did| self.deck_id_if_normal(did)) { + Ok(did) + } else { + self.default_deck_id() + } + } + + fn default_deck_id(&mut self) -> Result { + // currently hard-coded, we could create this as needed in the future + Ok(DeckID(1)) + } + + /// If deck exists and and is a normal deck, return it. + fn deck_id_if_normal(&mut self, did: DeckID) -> Option { + // fixme: currently disabled until deck writes are immediate + return Some(did); + + self.get_deck(did) + .ok() + .and_then(|opt| opt.and_then(|d| if !d.is_filtered() { Some(d.id()) } else { None })) + } } diff --git a/rslib/src/storage/deck/mod.rs b/rslib/src/storage/deck/mod.rs index 577d59dfd..7e3f88a8c 100644 --- a/rslib/src/storage/deck/mod.rs +++ b/rslib/src/storage/deck/mod.rs @@ -22,4 +22,10 @@ impl SqliteStorage { self.db.execute("update col set decks = ?", &[json])?; Ok(()) } + + pub(crate) fn get_deck(&self, did: DeckID) -> Result> { + // fixme: this is just temporary until we create an extra table + let mut decks = self.get_all_decks()?; + Ok(decks.remove(&did)) + } }