diff --git a/pylib/tests/test_cards.py b/pylib/tests/test_cards.py index 907450c98..e7a1ba830 100644 --- a/pylib/tests/test_cards.py +++ b/pylib/tests/test_cards.py @@ -77,7 +77,8 @@ def test_gendeck(): assert note.cards()[0].did == 1 # set the model to a new default col newId = col.decks.id("new") - cloze["did"] = newId + # fixme: dedicated API for this + col.set_config(f"_nt_{cloze['id']}_lastDeck", newId) col.models.save(cloze, updateReqs=False) # a newly generated card should share the first card's col note["Text"] += "{{c2::two}}" diff --git a/rslib/backend.proto b/rslib/backend.proto index 1acfdb869..a46924882 100644 --- a/rslib/backend.proto +++ b/rslib/backend.proto @@ -466,7 +466,8 @@ message Notetype { Kind kind = 1; uint32 sort_field_idx = 2; string css = 3; - int64 target_deck_id = 4; // moved into config var + /// This is now stored separately; retrieve with DefaultsForAdding() + int64 target_deck_id_unused = 4; string latex_pre = 5; string latex_post = 6; bool latex_svg = 7; diff --git a/rslib/src/dbcheck.rs b/rslib/src/dbcheck.rs index 09fd78795..c4d9ea77c 100644 --- a/rslib/src/dbcheck.rs +++ b/rslib/src/dbcheck.rs @@ -256,7 +256,9 @@ impl Collection { note.notetype_id = nt.id; // write note, updating tags and generating missing cards - let ctx = genctx.get_or_insert_with(|| CardGenContext::new(&nt, usn)); + let ctx = genctx.get_or_insert_with(|| { + CardGenContext::new(&nt, self.get_last_deck_added_to_for_notetype(nt.id), usn) + }); self.update_note_inner_generating_cards(&ctx, &mut note, &original, false, norm)?; } } diff --git a/rslib/src/notes/mod.rs b/rslib/src/notes/mod.rs index ae744e6a6..692030eae 100644 --- a/rslib/src/notes/mod.rs +++ b/rslib/src/notes/mod.rs @@ -74,7 +74,8 @@ impl Collection { let nt = col .get_notetype(note.notetype_id)? .ok_or_else(|| AnkiError::invalid_input("missing note type"))?; - let ctx = CardGenContext::new(&nt, col.usn()?); + let last_deck = col.get_last_deck_added_to_for_notetype(note.notetype_id); + let ctx = CardGenContext::new(&nt, last_deck, col.usn()?); let norm = col.get_bool(BoolKey::NormalizeNoteText); col.add_note_inner(&ctx, note, did, norm) }) @@ -383,7 +384,8 @@ impl Collection { let nt = self .get_notetype(note.notetype_id)? .ok_or_else(|| AnkiError::invalid_input("missing note type"))?; - let ctx = CardGenContext::new(&nt, self.usn()?); + let last_deck = self.get_last_deck_added_to_for_notetype(note.notetype_id); + let ctx = CardGenContext::new(&nt, last_deck, self.usn()?); let norm = self.get_bool(BoolKey::NormalizeNoteText); self.update_note_inner_generating_cards(&ctx, note, &existing_note, true, norm)?; Ok(()) @@ -484,7 +486,13 @@ impl Collection { } if out.generate_cards { - let ctx = genctx.get_or_insert_with(|| CardGenContext::new(&nt, usn)); + let ctx = genctx.get_or_insert_with(|| { + CardGenContext::new( + &nt, + self.get_last_deck_added_to_for_notetype(nt.id), + usn, + ) + }); self.update_note_inner_generating_cards( &ctx, &mut note, diff --git a/rslib/src/notetype/cardgen.rs b/rslib/src/notetype/cardgen.rs index c269ea77a..1bc103d56 100644 --- a/rslib/src/notetype/cardgen.rs +++ b/rslib/src/notetype/cardgen.rs @@ -8,16 +8,8 @@ use rand::{rngs::StdRng, Rng, SeedableRng}; use super::Notetype; use crate::{ - card::{Card, CardId}, - cloze::add_cloze_numbers_in_string, - collection::Collection, - deckconfig::{DeckConfig, DeckConfigId}, - decks::DeckId, - error::{AnkiError, Result}, - notes::{Note, NoteId}, - notetype::NotetypeKind, + cloze::add_cloze_numbers_in_string, notetype::NotetypeKind, prelude::*, template::ParsedTemplate, - types::Usn, }; /// Info about an existing card required when generating new cards @@ -49,6 +41,8 @@ pub(crate) struct SingleCardGenContext { pub(crate) struct CardGenContext<'a> { pub usn: Usn, pub notetype: &'a Notetype, + /// The last deck that was added to with this note type + pub last_deck: Option, cards: Vec, } @@ -60,9 +54,10 @@ pub(crate) struct CardGenCache { } impl CardGenContext<'_> { - pub(crate) fn new(nt: &Notetype, usn: Usn) -> CardGenContext<'_> { + pub(crate) fn new(nt: &Notetype, last_deck: Option, usn: Usn) -> CardGenContext<'_> { CardGenContext { usn, + last_deck, notetype: &nt, cards: nt .templates @@ -233,13 +228,7 @@ impl Collection { note: &Note, ) -> Result<()> { let existing = self.storage.existing_cards_for_note(note.id)?; - self.generate_cards_for_note( - ctx, - note, - &existing, - Some(ctx.notetype.target_deck_id()), - &mut Default::default(), - ) + self.generate_cards_for_note(ctx, note, &existing, ctx.last_deck, &mut Default::default()) } fn generate_cards_for_note( diff --git a/rslib/src/notetype/emptycards.rs b/rslib/src/notetype/emptycards.rs index 228147e0b..b15e06455 100644 --- a/rslib/src/notetype/emptycards.rs +++ b/rslib/src/notetype/emptycards.rs @@ -17,7 +17,8 @@ pub struct EmptyCardsForNote { impl Collection { fn empty_cards_for_notetype(&self, nt: &Notetype) -> Result> { - let ctx = CardGenContext::new(nt, self.usn()?); + let last_deck = self.get_last_deck_added_to_for_notetype(nt.id); + let ctx = CardGenContext::new(nt, last_deck, self.usn()?); let existing_cards = self.storage.existing_cards_for_notetype(nt.id)?; let by_note = group_generated_cards_by_note(existing_cards); let mut out = Vec::with_capacity(by_note.len()); diff --git a/rslib/src/notetype/mod.rs b/rslib/src/notetype/mod.rs index acb342567..9ac15517f 100644 --- a/rslib/src/notetype/mod.rs +++ b/rslib/src/notetype/mod.rs @@ -35,16 +35,11 @@ pub use crate::backend_proto::{ Notetype as NotetypeProto, }; use crate::{ - collection::Collection, - decks::DeckId, define_newtype, - error::{AnkiError, Result, TemplateSaveError}, - notes::Note, + error::TemplateSaveError, prelude::*, template::{FieldRequirements, ParsedTemplate}, text::ensure_string_in_nfc, - timestamp::TimestampSecs, - types::Usn, }; define_newtype!(NotetypeId, i64); @@ -99,10 +94,6 @@ impl Notetype { template.ok_or(AnkiError::NotFound) } - - pub fn target_deck_id(&self) -> DeckId { - DeckId(self.config.target_deck_id) - } } impl Collection { @@ -320,14 +311,6 @@ impl Notetype { self.templates.push(CardTemplate::new(name, qfmt, afmt)); } - pub(crate) fn prepare_for_adding(&mut self) -> Result<()> { - // defaults to 0 - if self.config.target_deck_id == 0 { - self.config.target_deck_id = 1; - } - self.prepare_for_update(None) - } - pub(crate) fn prepare_for_update(&mut self, existing: Option<&Notetype>) -> Result<()> { if self.fields.is_empty() { return Err(AnkiError::invalid_input("1 field required")); @@ -489,7 +472,7 @@ impl Collection { } pub(crate) fn add_notetype_inner(&mut self, nt: &mut Notetype, usn: Usn) -> Result<()> { - nt.prepare_for_adding()?; + nt.prepare_for_update(None)?; self.ensure_notetype_name_unique(nt, usn)?; self.storage.add_new_notetype(nt) } diff --git a/rslib/src/notetype/schema11.rs b/rslib/src/notetype/schema11.rs index f708bd31a..fd2e9ffae 100644 --- a/rslib/src/notetype/schema11.rs +++ b/rslib/src/notetype/schema11.rs @@ -98,7 +98,7 @@ impl From for Notetype { kind: nt.kind as i32, sort_field_idx: nt.sortf as u32, css: nt.css, - target_deck_id: nt.did.unwrap_or(DeckId(0)).0, + target_deck_id_unused: nt.did.unwrap_or(DeckId(0)).0, latex_pre: nt.latex_pre, latex_post: nt.latex_post, latex_svg: nt.latexsvg, @@ -148,10 +148,10 @@ impl From for NotetypeSchema11 { mtime: p.mtime_secs, usn: p.usn, sortf: c.sort_field_idx as u16, - did: if c.target_deck_id == 0 { + did: if c.target_deck_id_unused == 0 { None } else { - Some(DeckId(c.target_deck_id)) + Some(DeckId(c.target_deck_id_unused)) }, tmpls: p.templates.into_iter().map(Into::into).collect(), flds: p.fields.into_iter().map(Into::into).collect(), diff --git a/rslib/src/notetype/schemachange.rs b/rslib/src/notetype/schemachange.rs index 296af2a92..57b2f1e8a 100644 --- a/rslib/src/notetype/schemachange.rs +++ b/rslib/src/notetype/schemachange.rs @@ -127,7 +127,8 @@ impl Collection { .move_cards_for_repositioned_templates(nt.id, &changes.moved)?; } - let ctx = CardGenContext::new(nt, self.usn()?); + let last_deck = self.get_last_deck_added_to_for_notetype(nt.id); + let ctx = CardGenContext::new(nt, last_deck, self.usn()?); self.generate_cards_for_notetype(&ctx)?; Ok(()) diff --git a/rslib/src/notetype/stock.rs b/rslib/src/notetype/stock.rs index 0d8cf6d3e..0679e882e 100644 --- a/rslib/src/notetype/stock.rs +++ b/rslib/src/notetype/stock.rs @@ -15,6 +15,7 @@ use crate::{ impl SqliteStorage { pub(crate) fn add_stock_notetypes(&self, tr: &I18n) -> Result<()> { for (idx, mut nt) in all_stock_notetypes(tr).into_iter().enumerate() { + nt.prepare_for_update(None)?; self.add_new_notetype(&mut nt)?; if idx == Kind::Basic as usize { self.set_config_entry(&ConfigEntry::boxed( @@ -63,7 +64,6 @@ pub(crate) fn basic(tr: &I18n) -> Notetype { fieldref(back), ), ); - nt.prepare_for_adding().unwrap(); nt } @@ -79,7 +79,6 @@ pub(crate) fn basic_typing(tr: &I18n) -> Notetype { fieldref(front), back ); - nt.prepare_for_adding().unwrap(); nt } @@ -97,7 +96,6 @@ pub(crate) fn basic_forward_reverse(tr: &I18n) -> Notetype { fieldref(front), ), ); - nt.prepare_for_adding().unwrap(); nt } @@ -108,7 +106,6 @@ pub(crate) fn basic_optional_reverse(tr: &I18n) -> Notetype { nt.add_field(addrev.as_ref()); let tmpl = &mut nt.templates[1].config; tmpl.q_format = format!("{{{{#{}}}}}{}{{{{/{}}}}}", addrev, tmpl.q_format, addrev); - nt.prepare_for_adding().unwrap(); nt } @@ -134,6 +131,5 @@ pub(crate) fn cloze(tr: &I18n) -> Notetype { color: lightblue; } "; - nt.prepare_for_adding().unwrap(); nt }