mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 14:32:22 -04:00
support updating multiple notes in one transaction/undo op
This commit is contained in:
parent
88a3fd8d7b
commit
7ba35b7249
5 changed files with 32 additions and 16 deletions
|
@ -15,7 +15,7 @@ service NotesService {
|
||||||
rpc AddNote(AddNoteRequest) returns (AddNoteResponse);
|
rpc AddNote(AddNoteRequest) returns (AddNoteResponse);
|
||||||
rpc DefaultsForAdding(DefaultsForAddingRequest) returns (DeckAndNotetype);
|
rpc DefaultsForAdding(DefaultsForAddingRequest) returns (DeckAndNotetype);
|
||||||
rpc DefaultDeckForNotetype(notetypes.NotetypeId) returns (decks.DeckId);
|
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 GetNote(NoteId) returns (Note);
|
||||||
rpc RemoveNotes(RemoveNotesRequest) returns (collection.OpChangesWithCount);
|
rpc RemoveNotes(RemoveNotesRequest) returns (collection.OpChangesWithCount);
|
||||||
rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteResponse);
|
rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteResponse);
|
||||||
|
@ -56,8 +56,8 @@ message AddNoteResponse {
|
||||||
collection.OpChanges changes = 2;
|
collection.OpChanges changes = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UpdateNoteRequest {
|
message UpdateNotesRequest {
|
||||||
Note note = 1;
|
repeated Note notes = 1;
|
||||||
bool skip_undo_entry = 2;
|
bool skip_undo_entry = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -329,12 +329,17 @@ class Collection(DeprecatedNamesMixin):
|
||||||
def get_note(self, id: NoteId) -> Note:
|
def get_note(self, id: NoteId) -> Note:
|
||||||
return Note(self, id=id)
|
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:
|
def update_note(self, note: Note) -> OpChanges:
|
||||||
"""Save note changes to database, and add an undo entry.
|
"""Save note changes to database, and add an undo entry.
|
||||||
Unlike note.flush(), this will invalidate any current checkpoint."""
|
Unlike note.flush(), this will invalidate any current checkpoint."""
|
||||||
return self._backend.update_note(
|
return self.update_notes([note])
|
||||||
note=note._to_backend_note(), skip_undo_entry=False
|
|
||||||
)
|
|
||||||
|
|
||||||
getCard = get_card
|
getCard = get_card
|
||||||
getNote = get_note
|
getNote = get_note
|
||||||
|
|
|
@ -79,8 +79,8 @@ class Note(DeprecatedNamesMixin):
|
||||||
"""This preserves any current checkpoint.
|
"""This preserves any current checkpoint.
|
||||||
For an undo entry, use col.update_note() instead."""
|
For an undo entry, use col.update_note() instead."""
|
||||||
assert self.id != 0
|
assert self.id != 0
|
||||||
self.col._backend.update_note(
|
self.col._backend.update_notes(
|
||||||
note=self._to_backend_note(), skip_undo_entry=True
|
notes=[self._to_backend_note()], skip_undo_entry=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def joined_fields(self) -> str:
|
def joined_fields(self) -> str:
|
||||||
|
|
|
@ -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| {
|
self.with_col(|col| {
|
||||||
let mut note: Note = input.note.ok_or(AnkiError::NotFound)?.into();
|
let notes = input
|
||||||
col.update_note_maybe_undoable(&mut note, !input.skip_undo_entry)
|
.notes
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect::<Vec<Note>>();
|
||||||
|
col.update_notes_maybe_undoable(notes, !input.skip_undo_entry)
|
||||||
})
|
})
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,19 +348,26 @@ impl Collection {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) fn update_note(&mut self, note: &mut Note) -> Result<OpOutput<()>> {
|
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,
|
&mut self,
|
||||||
note: &mut Note,
|
notes: Vec<Note>,
|
||||||
undoable: bool,
|
undoable: bool,
|
||||||
) -> Result<OpOutput<()>> {
|
) -> Result<OpOutput<()>> {
|
||||||
if undoable {
|
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 {
|
} else {
|
||||||
self.transact_no_undo(|col| {
|
self.transact_no_undo(|col| {
|
||||||
col.update_note_inner(note)?;
|
for mut note in notes {
|
||||||
|
col.update_note_inner(&mut note)?;
|
||||||
|
}
|
||||||
Ok(OpOutput {
|
Ok(OpOutput {
|
||||||
output: (),
|
output: (),
|
||||||
changes: OpChanges {
|
changes: OpChanges {
|
||||||
|
|
Loading…
Reference in a new issue