Some porting notes for add-ons wanting to support Anki 2.1.41:
(this has been made a wiki post - please add anything you feel would be useful here, and if you don’t have permission, please reply below)
Type Hints
Most of Anki’s codebase now has type hints, and beta builds are available on PyPI. Instead of just clicking around in your add-on to see what if anything has broken, investing some time getting mypy working is recommended, as it can help alert you to cases where you’re calling a function that doesn’t exist, or has a different type signature. See the beta docs for how to install a beta build into your local Python, and the add-on guide for how you can use it to get code completion and type checking with mypy.
Debug messages
Some deprecated functions will print a message to stdout, which will not be visible if you’re only
using the GUI. While developing add-ons, it’s recommended to run Anki from a console.
- On Windows, use anki-console.exe
- On Mac, run /Applications/Anki.app/Contents/MacOS/AnkiMac from Terminal.app
- On Linux, run ‘anki’ from a terminal
Changes by area
Sidebar
- The browser sidebar code has moved into sidebar.py.
- Each section has its own parent node
- Tags are now shown in a tree
- If you were using gui_hooks.browser_will_build_tree, some of the stages have been renamed, and some have been added
- If you were monkey-patching browser functions, using the hook above is recommended.
Browser
- Add-ons that were monkey-patching the browser startup may fail, as setupSearch()'s call signature has been changed. Switching to one of the browser hooks if appropriate is recommended.
- To (re)open the browse screen and perform a search, use
aqt.dialogs.open("Browser", self.mw, search=some_text)
or one of the named filters, such as
aqt.dialogs.open("Browser", self.mw, search=SearchTerm(deck="some name that will be automatically escaped"))
- The preview button has moved into the editor, and the filter button has been removed.
- The reschedule action has been replaced with “forget” & “set due date”
Editor
- The underlying javascript/HTML has been reworked, so code that was changing it will need to be reworked.
-
Use
getEditorField(n)
to access a specific editor field -
Use
forEditorField()
if you want to iterate over the editor fields. The first argument is a list, which can have one item for each editor field. -
If you registered your JS setup code on
gui_hooks.editor_will_load_note
, note that whereas previously the editor tore down the whole HTML structure, only to rebuild it again, now it will only update components it needs to. To prevent that your code initializes a field multiple times (e.g. adding graphical elements or registering event handlers), a typical pattern would be:
forEditorField([], (field, _data) => {
if (!field.hasAttribute("has-my-addon")) {
// setup field
field.setAttribute("has-my-addon", "")
}
})
- Instead of window.getSelection, you need to call .getSelection() on the field div itself.
- For example code, you can see here for Ze Frozen Fields, here for Collapsible Fields, or here for Persistent Editor.