Help with hook: state_did_undo

Hello,

I’m adding some features to my TTS add-on and one of them is speaking when it undoes an action. I got it to run at the correct time using the state_did_undo hook. I’m trying to parse its argument of changes: OpChangesAfterUndo from genhooks_GUI py. The following example is from when I undid suspending of a card:

changes {
  card: true
  mtime: true
  browser_table: true
  study_queues: true
}
operation: "Suspend"
reverted_to_timestamp: 1686933524
new_status {
  last_step: 3
}
counter: 2

How do I parse this to get just the text after operation:? (For the purpose of getting my add-on to speak “Undo: suspend”) The output looks like JSON but isn’t because the keys aren’t quoted. Am I using the wrong approach?

Edit: Also, is it possible to differentiate between undoing a suspended card and a suspended note?

OpChangesAfterUndo is a protobuf message. You can convert it to a Python dictionary with google.protobuf.json_format.MessageToDict().

from google.protobuf.json_format import MessageToDict

from anki.collection import OpChangesAfterUndo
from aqt.gui_hooks import state_did_undo


def on_state_did_undo(changes: OpChangesAfterUndo) -> None:
    dic = MessageToDict(changes)
    print(dic.get("operation"))


state_did_undo.append(on_state_did_undo)

I don’t know about this.

You can also skip the JSON step and access the fields directly, eg changes.changes.note && changes.operation == "Suspend". But bear in mind that the operation name will change if the user is using a different language.

1 Like