diff --git a/rslib/src/import_export/package/apkg/import/decks.rs b/rslib/src/import_export/package/apkg/import/decks.rs index 0b2aa2811..4ec1966ea 100644 --- a/rslib/src/import_export/package/apkg/import/decks.rs +++ b/rslib/src/import_export/package/apkg/import/decks.rs @@ -30,10 +30,15 @@ impl Context<'_> { pub(super) fn import_decks_and_configs( &mut self, keep_filtered: bool, + contains_scheduling: bool, ) -> Result> { let mut ctx = DeckContext::new(self.target_col, self.usn); ctx.import_deck_configs(mem::take(&mut self.data.deck_configs))?; - ctx.import_decks(mem::take(&mut self.data.decks), keep_filtered)?; + ctx.import_decks( + mem::take(&mut self.data.decks), + keep_filtered, + contains_scheduling, + )?; Ok(ctx.imported_decks) } } @@ -47,23 +52,39 @@ impl DeckContext<'_> { Ok(()) } - fn import_decks(&mut self, mut decks: Vec, keep_filtered: bool) -> Result<()> { + fn import_decks( + &mut self, + mut decks: Vec, + keep_filtered: bool, + contains_scheduling: bool, + ) -> Result<()> { // ensure parents are seen before children decks.sort_unstable_by_key(|deck| deck.level()); for deck in &mut decks { - self.prepare_deck(deck, keep_filtered); + self.prepare_deck(deck, keep_filtered, contains_scheduling); self.import_deck(deck)?; } Ok(()) } - fn prepare_deck(&self, deck: &mut Deck, keep_filtered: bool) { + fn prepare_deck(&self, deck: &mut Deck, keep_filtered: bool, contains_scheduling: bool) { self.maybe_reparent(deck); if !keep_filtered && deck.is_filtered() { deck.kind = DeckKind::Normal(NormalDeck { config_id: 1, ..Default::default() }); + } else if !contains_scheduling { + // reset things like today's study count and collapse state + deck.common = Default::default(); + deck.kind = match &mut deck.kind { + DeckKind::Normal(normal) => DeckKind::Normal(NormalDeck { + config_id: 1, + description: mem::take(&mut normal.description), + ..Default::default() + }), + DeckKind::Filtered(_) => unreachable!(), + } } } @@ -205,7 +226,7 @@ mod test { new_deck_with_machine_name("NEW PARENT\x1fchild", false), new_deck_with_machine_name("new parent", false), ]; - ctx.import_decks(imports, false).unwrap(); + ctx.import_decks(imports, false, false).unwrap(); let existing_decks: HashSet<_> = ctx .target_col .get_all_deck_names(true) diff --git a/rslib/src/import_export/package/apkg/import/mod.rs b/rslib/src/import_export/package/apkg/import/mod.rs index 7355acf88..ab87d5a15 100644 --- a/rslib/src/import_export/package/apkg/import/mod.rs +++ b/rslib/src/import_export/package/apkg/import/mod.rs @@ -83,7 +83,8 @@ impl<'a> Context<'a> { let mut media_map = self.prepare_media()?; let note_imports = self.import_notes_and_notetypes(&mut media_map)?; let keep_filtered = self.data.enables_filtered_decks(); - let imported_decks = self.import_decks_and_configs(keep_filtered)?; + let contains_scheduling = self.data.contains_scheduling(); + let imported_decks = self.import_decks_and_configs(keep_filtered, contains_scheduling)?; self.import_cards_and_revlog(¬e_imports.id_map, &imported_decks, keep_filtered)?; self.copy_media(&mut media_map)?; Ok(note_imports.log) @@ -112,12 +113,15 @@ impl ExchangeData { fn enables_filtered_decks(&self) -> bool { // Earlier versions relied on the importer handling filtered decks by converting // them into regular ones, so there is no guarantee that all original decks - // are included. - self.contains_scheduling() && self.contains_all_original_decks() + // are included. And the legacy exporter included the default deck config, so we + // can't use it to determine if scheduling is included. + self.contains_scheduling() + && self.contains_all_original_decks() + && !self.deck_configs.is_empty() } fn contains_scheduling(&self) -> bool { - !(self.revlog.is_empty() && self.deck_configs.is_empty()) + !self.revlog.is_empty() } fn contains_all_original_decks(&self) -> bool {