support updating multiple notes in one transaction/undo op

This commit is contained in:
Damien Elmes 2021-08-02 17:07:26 +10:00
parent 88a3fd8d7b
commit 7ba35b7249
5 changed files with 32 additions and 16 deletions

View file

@ -15,7 +15,7 @@ service NotesService {
rpc AddNote(AddNoteRequest) returns (AddNoteResponse);
rpc DefaultsForAdding(DefaultsForAddingRequest) returns (DeckAndNotetype);
rpc DefaultDeckForNotetype(notetypes.NotetypeId) returns (decks.DeckId);
rpc UpdateNote(UpdateNoteRequest) returns (collection.OpChanges);
rpc UpdateNotes(UpdateNotesRequest) returns (collection.OpChanges);
rpc GetNote(NoteId) returns (Note);
rpc RemoveNotes(RemoveNotesRequest) returns (collection.OpChangesWithCount);
rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteResponse);
@ -56,8 +56,8 @@ message AddNoteResponse {
collection.OpChanges changes = 2;
}
message UpdateNoteRequest {
Note note = 1;
message UpdateNotesRequest {
repeated Note notes = 1;
bool skip_undo_entry = 2;
}

View file

@ -329,12 +329,17 @@ class Collection(DeprecatedNamesMixin):
def get_note(self, id: NoteId) -> Note:
return Note(self, id=id)
def update_notes(self, notes: Sequence[Note]) -> OpChanges:
"""Save note changes to database, and add an undo entry.
Unlike note.flush(), this will invalidate any current checkpoint."""
return self._backend.update_notes(
notes=[n._to_backend_note() for n in notes], skip_undo_entry=False
)
def update_note(self, note: Note) -> OpChanges:
"""Save note changes to database, and add an undo entry.
Unlike note.flush(), this will invalidate any current checkpoint."""
return self._backend.update_note(
note=note._to_backend_note(), skip_undo_entry=False
)
return self.update_notes([note])
getCard = get_card
getNote = get_note

View file

@ -79,8 +79,8 @@ class Note(DeprecatedNamesMixin):
"""This preserves any current checkpoint.
For an undo entry, use col.update_note() instead."""
assert self.id != 0
self.col._backend.update_note(
note=self._to_backend_note(), skip_undo_entry=True
self.col._backend.update_notes(
notes=[self._to_backend_note()], skip_undo_entry=True
)
def joined_fields(self) -> str:

View file

@ -49,10 +49,14 @@ impl NotesService for Backend {
})
}
fn update_note(&self, input: pb::UpdateNoteRequest) -> Result<pb::OpChanges> {
fn update_notes(&self, input: pb::UpdateNotesRequest) -> Result<pb::OpChanges> {
self.with_col(|col| {
let mut note: Note = input.note.ok_or(AnkiError::NotFound)?.into();
col.update_note_maybe_undoable(&mut note, !input.skip_undo_entry)
let notes = input
.notes
.into_iter()
.map(Into::into)
.collect::<Vec<Note>>();
col.update_notes_maybe_undoable(notes, !input.skip_undo_entry)
})
.map(Into::into)
}

View file

@ -348,19 +348,26 @@ impl Collection {
#[cfg(test)]
pub(crate) fn update_note(&mut self, note: &mut Note) -> Result<OpOutput<()>> {
self.update_note_maybe_undoable(note, true)
self.transact(Op::UpdateNote, |col| col.update_note_inner(note))
}
pub(crate) fn update_note_maybe_undoable(
pub(crate) fn update_notes_maybe_undoable(
&mut self,
note: &mut Note,
notes: Vec<Note>,
undoable: bool,
) -> Result<OpOutput<()>> {
if undoable {
self.transact(Op::UpdateNote, |col| col.update_note_inner(note))
self.transact(Op::UpdateNote, |col| {
for mut note in notes {
col.update_note_inner(&mut note)?;
}
Ok(())
})
} else {
self.transact_no_undo(|col| {
col.update_note_inner(note)?;
for mut note in notes {
col.update_note_inner(&mut note)?;
}
Ok(OpOutput {
output: (),
changes: OpChanges {