Why
I’m making an addon that can modify other notes and do other collection-modifying side effects when a new note is added through
- the Add cards dialog or
- by another addon calling
col.add_note()
, e.g. AnkiConnect.
It would be desirable that you could only undo the side effects of adding the new note while keeping the note or undo the side effects together with undoing the note addition. So, I’d want to either merge this operation into the “Add Note” undo entry or make a custom entry after that.
Problems with existing hooks
add_cards_did_add_note
Because of wanting AnkiConnect to also trigger these side effects, using this is not an option.
note_will_be_added
In order of significance:
- Creating a custom undo entry in
note_will_be_added
results in that entry being before the “Add Note” undo entry.- Because of this it’s not possible to undo the side effects without also undoing the note addition
- Also, when one undoes the note addition, it’s pretty easy to forget to undo the side effects. This leaves the side effects without the new note…
note.id
doesn’t exist so it can’t be used in the side effect- Cards don’t exist yet, so can’t make any edits to those or use their
card.id
either.
note_will_flush
This actually got called after the note was added and seemed it was possible to make a hack to defer the the undoable side effects to note_will_flush
but then I found that this behaviour only occurs when using the Add Cards dialog and not when AnkiConnect calls col.add_note()
. And the comment on this hook does say
Allow to change a note before it is added/updated in the database.
So, of course it doesn’t work here.
New hook?
So, any objections If I try to PR a new hook did_add_note_to_collection
that’d be run after _to_backend_note
has finished in collection.py
. Like below, I suppose?
def add_note(self, note: Note, deck_id: DeckId) -> OpChanges:
hooks.note_will_be_added(self, note, deck_id)
out = self._backend.add_note(note=note._to_backend_note(), deck_id=deck_id)
note.id = NoteId(out.note_id)
# --------NEW HOOK---------
hooks.did_add_note_to_collection(self, note)
# /-------NEW HOOK---------
return out.changes
def add_notes(self, requests: Iterable[AddNoteRequest]) -> OpChanges:
for request in requests:
hooks.note_will_be_added(self, request.note, request.deck_id)
out = self._backend.add_notes(
requests=[
notes_pb2.AddNoteRequest(
note=request.note._to_backend_note(), deck_id=request.deck_id
)
for request in requests
]
)
for idx, request in enumerate(requests):
request.note.id = NoteId(out.nids[idx])
# --------NEW HOOK---------
hooks.did_add_note_to_collection(self, request.note)
# /-------NEW HOOK---------
return out.changes