mirror of
https://github.com/ankitects/anki.git
synced 2025-11-21 20:17:12 -05:00
Instead of calling a method inside the transaction body, routines can now pass Op::SkipUndo if they wish the changes to be discarded at the end of the transaction. The advantage of doing it this way is that the list of changes can still be returned, allowing the sync indicator to update immediately. Closes #1252
68 lines
2.4 KiB
Rust
68 lines
2.4 KiB
Rust
// Copyright: Ankitects Pty Ltd and contributors
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
use crate::{ops::StateChanges, prelude::*};
|
|
|
|
impl Collection {
|
|
fn transact_inner<F, R>(&mut self, op: Option<Op>, func: F) -> Result<OpOutput<R>>
|
|
where
|
|
F: FnOnce(&mut Collection) -> Result<R>,
|
|
{
|
|
let have_op = op.is_some();
|
|
let skip_undo_queue = op == Some(Op::SkipUndo);
|
|
|
|
self.storage.begin_rust_trx()?;
|
|
self.begin_undoable_operation(op);
|
|
|
|
func(self)
|
|
.and_then(|output| {
|
|
// any changes mean an mtime bump
|
|
if !have_op || (self.current_undo_step_has_changes() && !self.undoing_or_redoing())
|
|
{
|
|
self.set_modified()?;
|
|
}
|
|
// then commit
|
|
self.storage.commit_rust_trx()?;
|
|
// finalize undo
|
|
let changes = if have_op {
|
|
let changes = self.op_changes();
|
|
self.maybe_clear_study_queues_after_op(&changes);
|
|
self.maybe_coalesce_note_undo_entry(&changes);
|
|
changes
|
|
} else {
|
|
self.clear_study_queues();
|
|
// dummy value for transact_no_undo() case
|
|
OpChanges {
|
|
op: Op::SetFlag,
|
|
changes: StateChanges::default(),
|
|
}
|
|
};
|
|
self.end_undoable_operation(skip_undo_queue);
|
|
Ok(OpOutput { output, changes })
|
|
})
|
|
// roll back on error
|
|
.or_else(|err| {
|
|
self.discard_undo_and_study_queues();
|
|
self.storage.rollback_rust_trx()?;
|
|
Err(err)
|
|
})
|
|
}
|
|
|
|
/// Execute the provided closure in a transaction, rolling back if
|
|
/// an error is returned. Records undo state, and returns changes.
|
|
pub(crate) fn transact<F, R>(&mut self, op: Op, func: F) -> Result<OpOutput<R>>
|
|
where
|
|
F: FnOnce(&mut Collection) -> Result<R>,
|
|
{
|
|
self.transact_inner(Some(op), func)
|
|
}
|
|
|
|
/// Execute the provided closure in a transaction, rolling back if
|
|
/// an error is returned.
|
|
pub(crate) fn transact_no_undo<F, R>(&mut self, func: F) -> Result<R>
|
|
where
|
|
F: FnOnce(&mut Collection) -> Result<R>,
|
|
{
|
|
self.transact_inner(None, func).map(|out| out.output)
|
|
}
|
|
}
|