move remaining undo ops into separate files
This commit is contained in:
parent
ad74e26c84
commit
d70e35e0a2
@ -1,13 +1,16 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
mod counts;
|
||||
mod schema11;
|
||||
mod tree;
|
||||
mod undo;
|
||||
|
||||
pub use crate::backend_proto::{
|
||||
deck_kind::Kind as DeckKind, filtered_search_term::FilteredSearchOrder, Deck as DeckProto,
|
||||
DeckCommon, DeckKind as DeckKindProto, FilteredDeck, FilteredSearchTerm, NormalDeck,
|
||||
};
|
||||
use crate::{
|
||||
backend_proto as pb, markdown::render_markdown, text::sanitize_html_no_images, undo::Undo,
|
||||
};
|
||||
use crate::{backend_proto as pb, markdown::render_markdown, text::sanitize_html_no_images};
|
||||
use crate::{
|
||||
collection::Collection,
|
||||
deckconf::DeckConfID,
|
||||
@ -18,9 +21,6 @@ use crate::{
|
||||
timestamp::TimestampSecs,
|
||||
types::Usn,
|
||||
};
|
||||
mod counts;
|
||||
mod schema11;
|
||||
mod tree;
|
||||
pub(crate) use counts::DueCounts;
|
||||
pub use schema11::DeckSchema11;
|
||||
use std::{borrow::Cow, sync::Arc};
|
||||
@ -285,7 +285,7 @@ impl Collection {
|
||||
// rename children
|
||||
col.rename_child_decks(&existing_deck, &deck.name, usn)?;
|
||||
}
|
||||
col.update_single_deck_inner_undo_only(deck, &existing_deck)?;
|
||||
col.update_single_deck_undoable(deck, &existing_deck)?;
|
||||
if name_changed {
|
||||
// after updating, we need to ensure all grandparents exist, which may not be the case
|
||||
// in the parent->child case
|
||||
@ -312,18 +312,6 @@ impl Collection {
|
||||
self.storage.add_or_update_deck_with_existing_id(deck)
|
||||
}
|
||||
|
||||
/// Update an individual, existing deck. Caller is responsible for ensuring deck
|
||||
/// is normalized, matches parents, is not a duplicate name, and bumping mtime.
|
||||
pub(crate) fn update_single_deck_inner_undo_only(
|
||||
&mut self,
|
||||
deck: &mut Deck,
|
||||
original: &Deck,
|
||||
) -> Result<()> {
|
||||
self.state.deck_cache.clear();
|
||||
self.save_undo(Box::new(DeckUpdated(original.clone())));
|
||||
self.storage.update_deck(deck)
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_deck_name_unique(&self, deck: &mut Deck, usn: Usn) -> Result<()> {
|
||||
loop {
|
||||
match self.storage.get_deck_id(&deck.name)? {
|
||||
@ -371,7 +359,7 @@ impl Collection {
|
||||
let new_name = format!("{}\x1f{}", new_name, child_only.join("\x1f"));
|
||||
child.name = new_name;
|
||||
child.set_modified(usn);
|
||||
self.update_single_deck_inner_undo_only(&mut child, &original)?;
|
||||
self.update_single_deck_undoable(&mut child, &original)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -601,7 +589,7 @@ impl Collection {
|
||||
deck.reset_stats_if_day_changed(today);
|
||||
mutator(&mut deck.common);
|
||||
deck.set_modified(usn);
|
||||
self.update_single_deck_inner_undo_only(deck, &original)
|
||||
self.update_single_deck_undoable(deck, &original)
|
||||
}
|
||||
|
||||
pub fn drag_drop_decks(
|
||||
@ -647,19 +635,6 @@ impl Collection {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DeckUpdated(Deck);
|
||||
|
||||
impl Undo for DeckUpdated {
|
||||
fn undo(mut self: Box<Self>, col: &mut crate::collection::Collection) -> Result<()> {
|
||||
let current = col
|
||||
.storage
|
||||
.get_deck(self.0.id)?
|
||||
.ok_or_else(|| AnkiError::invalid_input("deck disappeared"))?;
|
||||
col.update_single_deck_inner_undo_only(&mut self.0, ¤t)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{human_deck_name_to_native, immediate_parent_name, normalize_native_name};
|
||||
|
33
rslib/src/decks/undo.rs
Normal file
33
rslib/src/decks/undo.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::undo::Undo;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DeckUpdated(Deck);
|
||||
|
||||
impl Undo for DeckUpdated {
|
||||
fn undo(mut self: Box<Self>, col: &mut crate::collection::Collection) -> Result<()> {
|
||||
let current = col
|
||||
.storage
|
||||
.get_deck(self.0.id)?
|
||||
.ok_or_else(|| AnkiError::invalid_input("deck disappeared"))?;
|
||||
col.update_single_deck_undoable(&mut self.0, ¤t)
|
||||
}
|
||||
}
|
||||
|
||||
impl Collection {
|
||||
/// Update an individual, existing deck. Caller is responsible for ensuring deck
|
||||
/// is normalized, matches parents, is not a duplicate name, and bumping mtime.
|
||||
/// Clears deck cache.
|
||||
pub(super) fn update_single_deck_undoable(
|
||||
&mut self,
|
||||
deck: &mut Deck,
|
||||
original: &Deck,
|
||||
) -> Result<()> {
|
||||
self.state.deck_cache.clear();
|
||||
self.save_undo(Box::new(DeckUpdated(original.clone())));
|
||||
self.storage.update_deck(deck)
|
||||
}
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
mod undo;
|
||||
|
||||
use crate::serde::{default_on_invalid, deserialize_int_from_number};
|
||||
use crate::{define_newtype, prelude::*};
|
||||
use crate::{
|
||||
serde::{default_on_invalid, deserialize_int_from_number},
|
||||
undo::Undo,
|
||||
};
|
||||
use num_enum::TryFromPrimitive;
|
||||
use serde::Deserialize;
|
||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
@ -82,14 +81,6 @@ impl RevlogEntry {
|
||||
}
|
||||
|
||||
impl Collection {
|
||||
/// Add the provided revlog entry, modifying the ID if it is not unique.
|
||||
pub(crate) fn add_revlog_entry(&mut self, mut entry: RevlogEntry) -> Result<RevlogID> {
|
||||
entry.id = self.storage.add_revlog_entry(&entry, true)?;
|
||||
let id = entry.id;
|
||||
self.save_undo(Box::new(RevlogAdded(entry)));
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
pub(crate) fn log_manually_scheduled_review(
|
||||
&mut self,
|
||||
card: &Card,
|
||||
@ -107,28 +98,7 @@ impl Collection {
|
||||
taken_millis: 0,
|
||||
review_kind: RevlogReviewKind::Manual,
|
||||
};
|
||||
self.add_revlog_entry(entry)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RevlogAdded(RevlogEntry);
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RevlogRemoved(RevlogEntry);
|
||||
|
||||
impl Undo for RevlogAdded {
|
||||
fn undo(self: Box<Self>, col: &mut crate::collection::Collection) -> Result<()> {
|
||||
col.storage.remove_revlog_entry(self.0.id)?;
|
||||
col.save_undo(Box::new(RevlogRemoved(self.0)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Undo for RevlogRemoved {
|
||||
fn undo(self: Box<Self>, col: &mut crate::collection::Collection) -> Result<()> {
|
||||
col.storage.add_revlog_entry(&self.0, false)?;
|
||||
col.save_undo(Box::new(RevlogAdded(self.0)));
|
||||
self.add_revlog_entry_undoable(entry)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
36
rslib/src/revlog/undo.rs
Normal file
36
rslib/src/revlog/undo.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use super::RevlogEntry;
|
||||
use crate::{prelude::*, undo::Undo};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RevlogAdded(RevlogEntry);
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RevlogRemoved(RevlogEntry);
|
||||
|
||||
impl Undo for RevlogAdded {
|
||||
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
|
||||
col.storage.remove_revlog_entry(self.0.id)?;
|
||||
col.save_undo(Box::new(RevlogRemoved(self.0)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Undo for RevlogRemoved {
|
||||
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
|
||||
col.storage.add_revlog_entry(&self.0, false)?;
|
||||
col.save_undo(Box::new(RevlogAdded(self.0)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Collection {
|
||||
/// Add the provided revlog entry, modifying the ID if it is not unique.
|
||||
pub(crate) fn add_revlog_entry_undoable(&mut self, mut entry: RevlogEntry) -> Result<RevlogID> {
|
||||
entry.id = self.storage.add_revlog_entry(&entry, true)?;
|
||||
let id = entry.id;
|
||||
self.save_undo(Box::new(RevlogAdded(entry)));
|
||||
Ok(id)
|
||||
}
|
||||
}
|
@ -305,7 +305,7 @@ impl Collection {
|
||||
answer.answered_at,
|
||||
answer.milliseconds_taken,
|
||||
);
|
||||
self.add_revlog_entry(revlog)?;
|
||||
self.add_revlog_entry_undoable(revlog)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
mod undo;
|
||||
|
||||
use crate::{
|
||||
backend_proto::TagTreeNode,
|
||||
collection::Collection,
|
||||
@ -9,7 +11,6 @@ use crate::{
|
||||
prelude::*,
|
||||
text::{normalize_to_nfc, to_re},
|
||||
types::Usn,
|
||||
undo::Undo,
|
||||
};
|
||||
|
||||
use regex::{NoExpand, Regex, Replacer};
|
||||
@ -244,23 +245,11 @@ impl Collection {
|
||||
} else if let Cow::Owned(new_name) = normalized_name {
|
||||
tag.name = new_name;
|
||||
}
|
||||
self.register_tag_inner(&tag)?;
|
||||
self.register_tag_undoable(&tag)?;
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds an already-validated tag to the DB and undo list.
|
||||
/// Caller is responsible for setting usn.
|
||||
pub(crate) fn register_tag_inner(&mut self, tag: &Tag) -> Result<()> {
|
||||
self.save_undo(Box::new(AddedTag(tag.clone())));
|
||||
self.storage.register_tag(&tag)
|
||||
}
|
||||
|
||||
pub(crate) fn remove_single_tag(&mut self, tag: &Tag) -> Result<()> {
|
||||
self.save_undo(Box::new(RemovedTag(tag.clone())));
|
||||
self.storage.remove_single_tag(&tag.name)
|
||||
}
|
||||
|
||||
/// If parent tag(s) exist and differ in case, return a rewritten tag.
|
||||
fn adjusted_case_for_parents(&self, tag: &str) -> Result<Option<String>> {
|
||||
if let Some(parent_tag) = self.first_existing_parent_tag(&tag)? {
|
||||
@ -482,24 +471,6 @@ impl Collection {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AddedTag(Tag);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RemovedTag(Tag);
|
||||
|
||||
impl Undo for AddedTag {
|
||||
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
|
||||
col.remove_single_tag(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Undo for RemovedTag {
|
||||
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
|
||||
col.register_tag_inner(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
37
rslib/src/tags/undo.rs
Normal file
37
rslib/src/tags/undo.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use super::Tag;
|
||||
use crate::{prelude::*, undo::Undo};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AddedTag(Tag);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RemovedTag(Tag);
|
||||
|
||||
impl Undo for AddedTag {
|
||||
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
|
||||
col.remove_single_tag_undoable(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Undo for RemovedTag {
|
||||
fn undo(self: Box<Self>, col: &mut Collection) -> Result<()> {
|
||||
col.register_tag_undoable(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Collection {
|
||||
/// Adds an already-validated tag to the DB and undo list.
|
||||
/// Caller is responsible for setting usn.
|
||||
pub(super) fn register_tag_undoable(&mut self, tag: &Tag) -> Result<()> {
|
||||
self.save_undo(Box::new(AddedTag(tag.clone())));
|
||||
self.storage.register_tag(&tag)
|
||||
}
|
||||
|
||||
fn remove_single_tag_undoable(&mut self, tag: &Tag) -> Result<()> {
|
||||
self.save_undo(Box::new(RemovedTag(tag.clone())));
|
||||
self.storage.remove_single_tag(&tag.name)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user