mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 15:32:23 -04:00
migrate notetypes, update GIL list
This commit is contained in:
parent
6710e3d528
commit
a105037ec9
8 changed files with 302 additions and 274 deletions
|
@ -128,6 +128,18 @@ service BackendService {
|
||||||
rpc AddNoteTags (AddNoteTagsIn) returns (UInt32);
|
rpc AddNoteTags (AddNoteTagsIn) returns (UInt32);
|
||||||
rpc UpdateNoteTags (UpdateNoteTagsIn) returns (UInt32);
|
rpc UpdateNoteTags (UpdateNoteTagsIn) returns (UInt32);
|
||||||
rpc ClozeNumbersInNote (Note) returns (ClozeNumbersInNoteOut);
|
rpc ClozeNumbersInNote (Note) returns (ClozeNumbersInNoteOut);
|
||||||
|
rpc AfterNoteUpdates (AfterNoteUpdatesIn) returns (Empty);
|
||||||
|
rpc FieldNamesForNotes (FieldNamesForNotesIn) returns (FieldNamesForNotesOut);
|
||||||
|
|
||||||
|
// note types
|
||||||
|
|
||||||
|
rpc AddOrUpdateNotetype (AddOrUpdateNotetypeIn) returns (NoteTypeID);
|
||||||
|
rpc GetStockNotetypeLegacy (GetStockNotetypeIn) returns (Json);
|
||||||
|
rpc GetNotetypeLegacy (NoteTypeID) returns (Json);
|
||||||
|
rpc GetNotetypeNames (Empty) returns (NoteTypeNames);
|
||||||
|
rpc GetNotetypeNamesAndCounts (Empty) returns (NoteTypeUseCounts);
|
||||||
|
rpc GetNotetypeIDByName (String) returns (NoteTypeID);
|
||||||
|
rpc RemoveNotetype (NoteTypeID) returns (Empty);
|
||||||
|
|
||||||
// misc
|
// misc
|
||||||
|
|
||||||
|
@ -379,34 +391,31 @@ message I18nBackendInit {
|
||||||
message BackendInput {
|
message BackendInput {
|
||||||
oneof value {
|
oneof value {
|
||||||
AddMediaFileIn add_media_file = 26;
|
AddMediaFileIn add_media_file = 26;
|
||||||
|
Empty empty_trash = 34;
|
||||||
|
Empty restore_trash = 35;
|
||||||
|
Empty abort_media_sync = 46;
|
||||||
|
|
||||||
TranslateStringIn translate_string = 30;
|
TranslateStringIn translate_string = 30;
|
||||||
FormatTimeSpanIn format_time_span = 31;
|
FormatTimeSpanIn format_time_span = 31;
|
||||||
StudiedTodayIn studied_today = 32;
|
StudiedTodayIn studied_today = 32;
|
||||||
CongratsLearnMsgIn congrats_learn_msg = 33;
|
CongratsLearnMsgIn congrats_learn_msg = 33;
|
||||||
Empty empty_trash = 34;
|
|
||||||
Empty restore_trash = 35;
|
|
||||||
OpenCollectionIn open_collection = 36;
|
OpenCollectionIn open_collection = 36;
|
||||||
CloseCollectionIn close_collection = 37;
|
CloseCollectionIn close_collection = 37;
|
||||||
Empty abort_media_sync = 46;
|
|
||||||
Empty before_upload = 47;
|
Empty before_upload = 47;
|
||||||
|
|
||||||
RegisterTagsIn register_tags = 48;
|
RegisterTagsIn register_tags = 48;
|
||||||
Empty all_tags = 50;
|
Empty all_tags = 50;
|
||||||
int32 get_changed_tags = 51;
|
int32 get_changed_tags = 51;
|
||||||
|
|
||||||
string get_config_json = 52;
|
string get_config_json = 52;
|
||||||
SetConfigJson set_config_json = 53;
|
SetConfigJson set_config_json = 53;
|
||||||
bytes set_all_config = 54;
|
bytes set_all_config = 54;
|
||||||
Empty get_all_config = 55;
|
Empty get_all_config = 55;
|
||||||
int32 get_changed_notetypes = 56;
|
|
||||||
AddOrUpdateNotetypeIn add_or_update_notetype = 57;
|
|
||||||
StockNoteType get_stock_notetype_legacy = 60;
|
|
||||||
int64 get_notetype_legacy = 61;
|
|
||||||
Empty get_notetype_names = 62;
|
|
||||||
Empty get_notetype_names_and_counts = 63;
|
|
||||||
string get_notetype_id_by_name = 64;
|
|
||||||
int64 remove_notetype = 65;
|
|
||||||
FieldNamesForNotesIn field_names_for_notes = 78;
|
|
||||||
FindAndReplaceIn find_and_replace = 79;
|
FindAndReplaceIn find_and_replace = 79;
|
||||||
AfterNoteUpdatesIn after_note_updates = 80;
|
|
||||||
int32 set_local_minutes_west = 83;
|
int32 set_local_minutes_west = 83;
|
||||||
Empty get_preferences = 84;
|
Empty get_preferences = 84;
|
||||||
Preferences set_preferences = 85;
|
Preferences set_preferences = 85;
|
||||||
|
@ -436,20 +445,12 @@ message BackendOutput {
|
||||||
Empty set_config_json = 53;
|
Empty set_config_json = 53;
|
||||||
Empty set_all_config = 54;
|
Empty set_all_config = 54;
|
||||||
bytes get_all_config = 55;
|
bytes get_all_config = 55;
|
||||||
bytes get_changed_notetypes = 56;
|
|
||||||
int64 add_or_update_notetype = 57;
|
|
||||||
bytes get_notetype_legacy = 61;
|
|
||||||
NoteTypeNames get_notetype_names = 62;
|
|
||||||
NoteTypeUseCounts get_notetype_names_and_counts = 63;
|
|
||||||
int64 get_notetype_id_by_name = 64;
|
|
||||||
Empty remove_notetype = 65;
|
|
||||||
FieldNamesForNotesOut field_names_for_notes = 78;
|
|
||||||
uint32 find_and_replace = 79;
|
uint32 find_and_replace = 79;
|
||||||
Empty after_note_updates = 80;
|
|
||||||
Empty set_local_minutes_west = 83;
|
Empty set_local_minutes_west = 83;
|
||||||
Preferences get_preferences = 84;
|
Preferences get_preferences = 84;
|
||||||
Empty set_preferences = 85;
|
Empty set_preferences = 85;
|
||||||
bytes get_stock_notetype_legacy = 60;
|
|
||||||
|
|
||||||
BackendError error = 2047;
|
BackendError error = 2047;
|
||||||
}
|
}
|
||||||
|
@ -766,6 +767,10 @@ enum StockNoteType {
|
||||||
STOCK_NOTE_TYPE_CLOZE = 4;
|
STOCK_NOTE_TYPE_CLOZE = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message GetStockNotetypeIn {
|
||||||
|
StockNoteType kind = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message NoteTypeNames {
|
message NoteTypeNames {
|
||||||
repeated NoteTypeNameID entries = 1;
|
repeated NoteTypeNameID entries = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ def findReplace(
|
||||||
|
|
||||||
|
|
||||||
def fieldNamesForNotes(col: Collection, nids: List[int]) -> List[str]:
|
def fieldNamesForNotes(col: Collection, nids: List[int]) -> List[str]:
|
||||||
return list(col.backend.field_names_for_note_ids(nids))
|
return list(col.backend.field_names_for_notes(nids))
|
||||||
|
|
||||||
|
|
||||||
# Find duplicates
|
# Find duplicates
|
||||||
|
|
|
@ -5,13 +5,13 @@ from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import time
|
import time
|
||||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
|
||||||
|
|
||||||
import anki # pylint: disable=unused-import
|
import anki # pylint: disable=unused-import
|
||||||
import anki.backend_pb2 as pb
|
import anki.backend_pb2 as pb
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
from anki.rsbackend import StockNoteType
|
from anki.rsbackend import NotFoundError, StockNoteType, from_json_bytes, to_json_bytes
|
||||||
from anki.utils import checksum, ids2str, intTime, joinFields, splitFields
|
from anki.utils import checksum, ids2str, intTime, joinFields, splitFields
|
||||||
|
|
||||||
# types
|
# types
|
||||||
|
@ -109,11 +109,11 @@ class ModelManager:
|
||||||
# Listing note types
|
# Listing note types
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
||||||
def all_names_and_ids(self) -> List[pb.NoteTypeNameID]:
|
def all_names_and_ids(self) -> Sequence[pb.NoteTypeNameID]:
|
||||||
return self.col.backend.get_notetype_names_and_ids()
|
return self.col.backend.get_notetype_names()
|
||||||
|
|
||||||
def all_use_counts(self) -> List[pb.NoteTypeNameIDUseCount]:
|
def all_use_counts(self) -> Sequence[pb.NoteTypeNameIDUseCount]:
|
||||||
return self.col.backend.get_notetype_use_counts()
|
return self.col.backend.get_notetype_names_and_counts()
|
||||||
|
|
||||||
# legacy
|
# legacy
|
||||||
|
|
||||||
|
@ -149,7 +149,10 @@ class ModelManager:
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
||||||
def id_for_name(self, name: str) -> Optional[int]:
|
def id_for_name(self, name: str) -> Optional[int]:
|
||||||
|
try:
|
||||||
return self.col.backend.get_notetype_id_by_name(name)
|
return self.col.backend.get_notetype_id_by_name(name)
|
||||||
|
except NotFoundError:
|
||||||
|
return None
|
||||||
|
|
||||||
def get(self, id: int) -> Optional[NoteType]:
|
def get(self, id: int) -> Optional[NoteType]:
|
||||||
"Get model with ID, or None."
|
"Get model with ID, or None."
|
||||||
|
@ -161,9 +164,11 @@ class ModelManager:
|
||||||
|
|
||||||
nt = self._get_cached(id)
|
nt = self._get_cached(id)
|
||||||
if not nt:
|
if not nt:
|
||||||
nt = self.col.backend.get_notetype_legacy(id)
|
try:
|
||||||
if nt:
|
nt = from_json_bytes(self.col.backend.get_notetype_legacy(id))
|
||||||
self._update_cache(nt)
|
self._update_cache(nt)
|
||||||
|
except NotFoundError:
|
||||||
|
return None
|
||||||
return nt
|
return nt
|
||||||
|
|
||||||
def all(self) -> List[NoteType]:
|
def all(self) -> List[NoteType]:
|
||||||
|
@ -181,9 +186,11 @@ class ModelManager:
|
||||||
def new(self, name: str) -> NoteType:
|
def new(self, name: str) -> NoteType:
|
||||||
"Create a new model, and return it."
|
"Create a new model, and return it."
|
||||||
# caller should call save() after modifying
|
# caller should call save() after modifying
|
||||||
nt = self.col.backend.get_stock_notetype_legacy(
|
nt = from_json_bytes(
|
||||||
|
self.col.backend.get_stock_notetype_legacy(
|
||||||
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
||||||
)
|
)
|
||||||
|
)
|
||||||
nt["flds"] = []
|
nt["flds"] = []
|
||||||
nt["tmpls"] = []
|
nt["tmpls"] = []
|
||||||
nt["name"] = name
|
nt["name"] = name
|
||||||
|
@ -215,7 +222,9 @@ class ModelManager:
|
||||||
"Add or update an existing model. Use .save() instead."
|
"Add or update an existing model. Use .save() instead."
|
||||||
self._remove_from_cache(m["id"])
|
self._remove_from_cache(m["id"])
|
||||||
self.ensureNameUnique(m)
|
self.ensureNameUnique(m)
|
||||||
self.col.backend.add_or_update_notetype(m, preserve_usn=preserve_usn)
|
m["id"] = self.col.backend.add_or_update_notetype(
|
||||||
|
to_json_bytes(m), preserve_usn_and_mtime=preserve_usn
|
||||||
|
)
|
||||||
self.setCurrent(m)
|
self.setCurrent(m)
|
||||||
self._mutate_after_write(m)
|
self._mutate_after_write(m)
|
||||||
|
|
||||||
|
@ -268,9 +277,11 @@ class ModelManager:
|
||||||
|
|
||||||
def new_field(self, name: str) -> Field:
|
def new_field(self, name: str) -> Field:
|
||||||
assert isinstance(name, str)
|
assert isinstance(name, str)
|
||||||
nt = self.col.backend.get_stock_notetype_legacy(
|
nt = from_json_bytes(
|
||||||
|
self.col.backend.get_stock_notetype_legacy(
|
||||||
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
||||||
)
|
)
|
||||||
|
)
|
||||||
field = nt["flds"][0]
|
field = nt["flds"][0]
|
||||||
field["name"] = name
|
field["name"] = name
|
||||||
field["ord"] = None
|
field["ord"] = None
|
||||||
|
@ -327,9 +338,11 @@ class ModelManager:
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
def new_template(self, name: str) -> Template:
|
def new_template(self, name: str) -> Template:
|
||||||
nt = self.col.backend.get_stock_notetype_legacy(
|
nt = from_json_bytes(
|
||||||
|
self.col.backend.get_stock_notetype_legacy(
|
||||||
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
||||||
)
|
)
|
||||||
|
)
|
||||||
template = nt["tmpls"][0]
|
template = nt["tmpls"][0]
|
||||||
template["name"] = name
|
template["name"] = name
|
||||||
template["qfmt"] = ""
|
template["qfmt"] = ""
|
||||||
|
|
|
@ -370,70 +370,6 @@ class RustBackend:
|
||||||
def set_all_config(self, conf: Dict[str, Any]):
|
def set_all_config(self, conf: Dict[str, Any]):
|
||||||
self._run_command(pb.BackendInput(set_all_config=orjson.dumps(conf)))
|
self._run_command(pb.BackendInput(set_all_config=orjson.dumps(conf)))
|
||||||
|
|
||||||
def get_changed_notetypes(self, usn: int) -> Dict[str, Dict[str, Any]]:
|
|
||||||
jstr = self._run_command(
|
|
||||||
pb.BackendInput(get_changed_notetypes=usn)
|
|
||||||
).get_changed_notetypes
|
|
||||||
return orjson.loads(jstr)
|
|
||||||
|
|
||||||
def get_stock_notetype_legacy(self, kind: StockNoteType) -> Dict[str, Any]:
|
|
||||||
bytes = self._run_command(
|
|
||||||
pb.BackendInput(get_stock_notetype_legacy=kind)
|
|
||||||
).get_stock_notetype_legacy
|
|
||||||
return orjson.loads(bytes)
|
|
||||||
|
|
||||||
def get_notetype_names_and_ids(self) -> List[pb.NoteTypeNameID]:
|
|
||||||
return list(
|
|
||||||
self._run_command(
|
|
||||||
pb.BackendInput(get_notetype_names=pb.Empty())
|
|
||||||
).get_notetype_names.entries
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_notetype_use_counts(self) -> List[pb.NoteTypeNameIDUseCount]:
|
|
||||||
return list(
|
|
||||||
self._run_command(
|
|
||||||
pb.BackendInput(get_notetype_names_and_counts=pb.Empty())
|
|
||||||
).get_notetype_names_and_counts.entries
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_notetype_legacy(self, ntid: int) -> Optional[Dict]:
|
|
||||||
try:
|
|
||||||
bytes = self._run_command(
|
|
||||||
pb.BackendInput(get_notetype_legacy=ntid)
|
|
||||||
).get_notetype_legacy
|
|
||||||
except NotFoundError:
|
|
||||||
return None
|
|
||||||
return orjson.loads(bytes)
|
|
||||||
|
|
||||||
def get_notetype_id_by_name(self, name: str) -> Optional[int]:
|
|
||||||
return (
|
|
||||||
self._run_command(
|
|
||||||
pb.BackendInput(get_notetype_id_by_name=name)
|
|
||||||
).get_notetype_id_by_name
|
|
||||||
or None
|
|
||||||
)
|
|
||||||
|
|
||||||
def add_or_update_notetype(self, nt: Dict[str, Any], preserve_usn: bool) -> None:
|
|
||||||
bjson = orjson.dumps(nt)
|
|
||||||
id = self._run_command(
|
|
||||||
pb.BackendInput(
|
|
||||||
add_or_update_notetype=pb.AddOrUpdateNotetypeIn(
|
|
||||||
json=bjson, preserve_usn_and_mtime=preserve_usn
|
|
||||||
)
|
|
||||||
),
|
|
||||||
release_gil=True,
|
|
||||||
).add_or_update_notetype
|
|
||||||
nt["id"] = id
|
|
||||||
|
|
||||||
def remove_notetype(self, ntid: int) -> None:
|
|
||||||
self._run_command(pb.BackendInput(remove_notetype=ntid), release_gil=True)
|
|
||||||
|
|
||||||
def field_names_for_note_ids(self, nids: List[int]) -> Sequence[str]:
|
|
||||||
return self._run_command(
|
|
||||||
pb.BackendInput(field_names_for_notes=pb.FieldNamesForNotesIn(nids=nids)),
|
|
||||||
release_gil=True,
|
|
||||||
).field_names_for_notes.fields
|
|
||||||
|
|
||||||
def find_and_replace(
|
def find_and_replace(
|
||||||
self,
|
self,
|
||||||
nids: List[int],
|
nids: List[int],
|
||||||
|
@ -457,20 +393,6 @@ class RustBackend:
|
||||||
release_gil=True,
|
release_gil=True,
|
||||||
).find_and_replace
|
).find_and_replace
|
||||||
|
|
||||||
def after_note_updates(
|
|
||||||
self, nids: List[int], generate_cards: bool, mark_notes_modified: bool
|
|
||||||
) -> None:
|
|
||||||
self._run_command(
|
|
||||||
pb.BackendInput(
|
|
||||||
after_note_updates=pb.AfterNoteUpdatesIn(
|
|
||||||
nids=nids,
|
|
||||||
generate_cards=generate_cards,
|
|
||||||
mark_notes_modified=mark_notes_modified,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
release_gil=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def set_local_minutes_west(self, mins: int) -> None:
|
def set_local_minutes_west(self, mins: int) -> None:
|
||||||
self._run_command(pb.BackendInput(set_local_minutes_west=mins))
|
self._run_command(pb.BackendInput(set_local_minutes_west=mins))
|
||||||
|
|
||||||
|
@ -599,15 +521,15 @@ class RustBackend:
|
||||||
|
|
||||||
def deck_tree_legacy(self) -> bytes:
|
def deck_tree_legacy(self) -> bytes:
|
||||||
input = pb.Empty()
|
input = pb.Empty()
|
||||||
output = pb.Bytes()
|
output = pb.Json()
|
||||||
output.ParseFromString(self._run_command2(16, input))
|
output.ParseFromString(self._run_command2(16, input))
|
||||||
return output.val
|
return output.json
|
||||||
|
|
||||||
def get_all_decks_legacy(self) -> bytes:
|
def get_all_decks_legacy(self) -> bytes:
|
||||||
input = pb.Empty()
|
input = pb.Empty()
|
||||||
output = pb.Bytes()
|
output = pb.Json()
|
||||||
output.ParseFromString(self._run_command2(17, input))
|
output.ParseFromString(self._run_command2(17, input))
|
||||||
return output.val
|
return output.json
|
||||||
|
|
||||||
def get_deck_id_by_name(self, val: str) -> int:
|
def get_deck_id_by_name(self, val: str) -> int:
|
||||||
input = pb.String(val=val)
|
input = pb.String(val=val)
|
||||||
|
@ -617,9 +539,9 @@ class RustBackend:
|
||||||
|
|
||||||
def get_deck_legacy(self, did: int) -> bytes:
|
def get_deck_legacy(self, did: int) -> bytes:
|
||||||
input = pb.DeckID(did=did)
|
input = pb.DeckID(did=did)
|
||||||
output = pb.Bytes()
|
output = pb.Json()
|
||||||
output.ParseFromString(self._run_command2(19, input))
|
output.ParseFromString(self._run_command2(19, input))
|
||||||
return output.val
|
return output.json
|
||||||
|
|
||||||
def get_deck_names(
|
def get_deck_names(
|
||||||
self, skip_empty_default: bool, include_filtered: bool
|
self, skip_empty_default: bool, include_filtered: bool
|
||||||
|
@ -633,9 +555,9 @@ class RustBackend:
|
||||||
|
|
||||||
def new_deck_legacy(self, val: bool) -> bytes:
|
def new_deck_legacy(self, val: bool) -> bytes:
|
||||||
input = pb.Bool(val=val)
|
input = pb.Bool(val=val)
|
||||||
output = pb.Bytes()
|
output = pb.Json()
|
||||||
output.ParseFromString(self._run_command2(21, input))
|
output.ParseFromString(self._run_command2(21, input))
|
||||||
return output.val
|
return output.json
|
||||||
|
|
||||||
def remove_deck(self, did: int) -> pb.Empty:
|
def remove_deck(self, did: int) -> pb.Empty:
|
||||||
input = pb.DeckID(did=did)
|
input = pb.DeckID(did=did)
|
||||||
|
@ -655,21 +577,21 @@ class RustBackend:
|
||||||
|
|
||||||
def all_deck_config_legacy(self) -> bytes:
|
def all_deck_config_legacy(self) -> bytes:
|
||||||
input = pb.Empty()
|
input = pb.Empty()
|
||||||
output = pb.Bytes()
|
output = pb.Json()
|
||||||
output.ParseFromString(self._run_command2(24, input))
|
output.ParseFromString(self._run_command2(24, input))
|
||||||
return output.val
|
return output.json
|
||||||
|
|
||||||
def get_deck_config_legacy(self, dcid: int) -> bytes:
|
def get_deck_config_legacy(self, dcid: int) -> bytes:
|
||||||
input = pb.DeckConfigID(dcid=dcid)
|
input = pb.DeckConfigID(dcid=dcid)
|
||||||
output = pb.Bytes()
|
output = pb.Json()
|
||||||
output.ParseFromString(self._run_command2(25, input))
|
output.ParseFromString(self._run_command2(25, input))
|
||||||
return output.val
|
return output.json
|
||||||
|
|
||||||
def new_deck_config_legacy(self) -> bytes:
|
def new_deck_config_legacy(self) -> bytes:
|
||||||
input = pb.Empty()
|
input = pb.Empty()
|
||||||
output = pb.Bytes()
|
output = pb.Json()
|
||||||
output.ParseFromString(self._run_command2(26, input))
|
output.ParseFromString(self._run_command2(26, input))
|
||||||
return output.val
|
return output.json
|
||||||
|
|
||||||
def remove_deck_config(self, dcid: int) -> pb.Empty:
|
def remove_deck_config(self, dcid: int) -> pb.Empty:
|
||||||
input = pb.DeckConfigID(dcid=dcid)
|
input = pb.DeckConfigID(dcid=dcid)
|
||||||
|
@ -737,10 +659,72 @@ class RustBackend:
|
||||||
output.ParseFromString(self._run_command2(37, input))
|
output.ParseFromString(self._run_command2(37, input))
|
||||||
return output.numbers
|
return output.numbers
|
||||||
|
|
||||||
|
def after_note_updates(
|
||||||
|
self, nids: Sequence[int], mark_notes_modified: bool, generate_cards: bool
|
||||||
|
) -> pb.Empty:
|
||||||
|
input = pb.AfterNoteUpdatesIn(
|
||||||
|
nids=nids,
|
||||||
|
mark_notes_modified=mark_notes_modified,
|
||||||
|
generate_cards=generate_cards,
|
||||||
|
)
|
||||||
|
output = pb.Empty()
|
||||||
|
output.ParseFromString(self._run_command2(38, input))
|
||||||
|
return output
|
||||||
|
|
||||||
|
def field_names_for_notes(self, nids: Sequence[int]) -> Sequence[str]:
|
||||||
|
input = pb.FieldNamesForNotesIn(nids=nids)
|
||||||
|
output = pb.FieldNamesForNotesOut()
|
||||||
|
output.ParseFromString(self._run_command2(39, input))
|
||||||
|
return output.fields
|
||||||
|
|
||||||
|
def add_or_update_notetype(self, json: bytes, preserve_usn_and_mtime: bool) -> int:
|
||||||
|
input = pb.AddOrUpdateNotetypeIn(
|
||||||
|
json=json, preserve_usn_and_mtime=preserve_usn_and_mtime
|
||||||
|
)
|
||||||
|
output = pb.NoteTypeID()
|
||||||
|
output.ParseFromString(self._run_command2(40, input))
|
||||||
|
return output.ntid
|
||||||
|
|
||||||
|
def get_stock_notetype_legacy(self, kind: pb.StockNoteType) -> bytes:
|
||||||
|
input = pb.GetStockNotetypeIn(kind=kind)
|
||||||
|
output = pb.Json()
|
||||||
|
output.ParseFromString(self._run_command2(41, input))
|
||||||
|
return output.json
|
||||||
|
|
||||||
|
def get_notetype_legacy(self, ntid: int) -> bytes:
|
||||||
|
input = pb.NoteTypeID(ntid=ntid)
|
||||||
|
output = pb.Json()
|
||||||
|
output.ParseFromString(self._run_command2(42, input))
|
||||||
|
return output.json
|
||||||
|
|
||||||
|
def get_notetype_names(self) -> Sequence[pb.NoteTypeNameID]:
|
||||||
|
input = pb.Empty()
|
||||||
|
output = pb.NoteTypeNames()
|
||||||
|
output.ParseFromString(self._run_command2(43, input))
|
||||||
|
return output.entries
|
||||||
|
|
||||||
|
def get_notetype_names_and_counts(self) -> Sequence[pb.NoteTypeNameIDUseCount]:
|
||||||
|
input = pb.Empty()
|
||||||
|
output = pb.NoteTypeUseCounts()
|
||||||
|
output.ParseFromString(self._run_command2(44, input))
|
||||||
|
return output.entries
|
||||||
|
|
||||||
|
def get_notetype_id_by_name(self, val: str) -> int:
|
||||||
|
input = pb.String(val=val)
|
||||||
|
output = pb.NoteTypeID()
|
||||||
|
output.ParseFromString(self._run_command2(45, input))
|
||||||
|
return output.ntid
|
||||||
|
|
||||||
|
def remove_notetype(self, ntid: int) -> pb.Empty:
|
||||||
|
input = pb.NoteTypeID(ntid=ntid)
|
||||||
|
output = pb.Empty()
|
||||||
|
output.ParseFromString(self._run_command2(46, input))
|
||||||
|
return output
|
||||||
|
|
||||||
def check_database(self) -> Sequence[str]:
|
def check_database(self) -> Sequence[str]:
|
||||||
input = pb.Empty()
|
input = pb.Empty()
|
||||||
output = pb.CheckDatabaseOut()
|
output = pb.CheckDatabaseOut()
|
||||||
output.ParseFromString(self._run_command2(38, input))
|
output.ParseFromString(self._run_command2(47, input))
|
||||||
return output.problems
|
return output.problems
|
||||||
|
|
||||||
# @@AUTOGEN@@
|
# @@AUTOGEN@@
|
||||||
|
|
|
@ -5,7 +5,7 @@ from typing import Callable, List, Tuple
|
||||||
|
|
||||||
from anki.collection import Collection
|
from anki.collection import Collection
|
||||||
from anki.models import NoteType
|
from anki.models import NoteType
|
||||||
from anki.rsbackend import StockNoteType
|
from anki.rsbackend import StockNoteType, from_json_bytes
|
||||||
|
|
||||||
# add-on authors can add ("note type name", function_like_addBasicModel)
|
# add-on authors can add ("note type name", function_like_addBasicModel)
|
||||||
# to this list to have it shown in the add/clone note type screen
|
# to this list to have it shown in the add/clone note type screen
|
||||||
|
@ -13,7 +13,7 @@ models: List[Tuple] = []
|
||||||
|
|
||||||
|
|
||||||
def add_stock_notetype(col: Collection, kind: StockNoteType) -> NoteType:
|
def add_stock_notetype(col: Collection, kind: StockNoteType) -> NoteType:
|
||||||
m = col.backend.get_stock_notetype_legacy(kind)
|
m = from_json_bytes(col.backend.get_stock_notetype_legacy(kind))
|
||||||
col.models.add(m)
|
col.models.add(m)
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ def get_stock_notetypes(
|
||||||
),
|
),
|
||||||
(StockNoteType.STOCK_NOTE_TYPE_CLOZE, addClozeModel),
|
(StockNoteType.STOCK_NOTE_TYPE_CLOZE, addClozeModel),
|
||||||
]:
|
]:
|
||||||
m = col.backend.get_stock_notetype_legacy(kind)
|
m = from_json_bytes(col.backend.get_stock_notetype_legacy(kind))
|
||||||
out.append((m["name"], func))
|
out.append((m["name"], func))
|
||||||
# add extras from add-ons
|
# add extras from add-ons
|
||||||
for (name_or_func, func) in models:
|
for (name_or_func, func) in models:
|
||||||
|
|
|
@ -49,8 +49,10 @@ def python_type_inner(field):
|
||||||
return "str"
|
return "str"
|
||||||
elif type == TYPE_BYTES:
|
elif type == TYPE_BYTES:
|
||||||
return "bytes"
|
return "bytes"
|
||||||
elif type == 11:
|
elif type == TYPE_MESSAGE:
|
||||||
return "pb." + field.message_type.name
|
return "pb." + field.message_type.name
|
||||||
|
elif type == TYPE_ENUM:
|
||||||
|
return "pb." + field.enum_type.name
|
||||||
else:
|
else:
|
||||||
raise Exception(f"unknown type: {type}")
|
raise Exception(f"unknown type: {type}")
|
||||||
|
|
||||||
|
|
|
@ -623,6 +623,120 @@ impl BackendService for Backend {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn field_names_for_notes(
|
||||||
|
&mut self,
|
||||||
|
input: pb::FieldNamesForNotesIn,
|
||||||
|
) -> BackendResult<pb::FieldNamesForNotesOut> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
let nids: Vec<_> = input.nids.into_iter().map(NoteID).collect();
|
||||||
|
col.storage
|
||||||
|
.field_names_for_notes(&nids)
|
||||||
|
.map(|fields| pb::FieldNamesForNotesOut { fields })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn after_note_updates(&mut self, input: pb::AfterNoteUpdatesIn) -> BackendResult<Empty> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
col.transact(None, |col| {
|
||||||
|
col.after_note_updates(
|
||||||
|
&to_nids(input.nids),
|
||||||
|
input.generate_cards,
|
||||||
|
input.mark_notes_modified,
|
||||||
|
)?;
|
||||||
|
Ok(pb::Empty {})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// notetypes
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn get_stock_notetype_legacy(
|
||||||
|
&mut self,
|
||||||
|
input: pb::GetStockNotetypeIn,
|
||||||
|
) -> BackendResult<pb::Json> {
|
||||||
|
// fixme: use individual functions instead of full vec
|
||||||
|
let mut all = all_stock_notetypes(&self.i18n);
|
||||||
|
let idx = (input.kind as usize).min(all.len() - 1);
|
||||||
|
let nt = all.swap_remove(idx);
|
||||||
|
let schema11: NoteTypeSchema11 = nt.into();
|
||||||
|
serde_json::to_vec(&schema11)
|
||||||
|
.map_err(Into::into)
|
||||||
|
.map(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_notetype_names(&mut self, _input: Empty) -> BackendResult<pb::NoteTypeNames> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
let entries: Vec<_> = col
|
||||||
|
.storage
|
||||||
|
.get_all_notetype_names()?
|
||||||
|
.into_iter()
|
||||||
|
.map(|(id, name)| pb::NoteTypeNameId { id: id.0, name })
|
||||||
|
.collect();
|
||||||
|
Ok(pb::NoteTypeNames { entries })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_notetype_names_and_counts(
|
||||||
|
&mut self,
|
||||||
|
_input: Empty,
|
||||||
|
) -> BackendResult<pb::NoteTypeUseCounts> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
let entries: Vec<_> = col
|
||||||
|
.storage
|
||||||
|
.get_notetype_use_counts()?
|
||||||
|
.into_iter()
|
||||||
|
.map(|(id, name, use_count)| pb::NoteTypeNameIdUseCount {
|
||||||
|
id: id.0,
|
||||||
|
name,
|
||||||
|
use_count,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Ok(pb::NoteTypeUseCounts { entries })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_notetype_legacy(&mut self, input: pb::NoteTypeId) -> BackendResult<pb::Json> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
let schema11: NoteTypeSchema11 = col
|
||||||
|
.storage
|
||||||
|
.get_notetype(input.into())?
|
||||||
|
.ok_or(AnkiError::NotFound)?
|
||||||
|
.into();
|
||||||
|
Ok(serde_json::to_vec(&schema11)?).map(Into::into)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_notetype_id_by_name(&mut self, input: pb::String) -> BackendResult<pb::NoteTypeId> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
col.storage
|
||||||
|
.get_notetype_id(&input.val)
|
||||||
|
.and_then(|nt| nt.ok_or(AnkiError::NotFound))
|
||||||
|
.map(|ntid| pb::NoteTypeId { ntid: ntid.0 })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_or_update_notetype(
|
||||||
|
&mut self,
|
||||||
|
input: pb::AddOrUpdateNotetypeIn,
|
||||||
|
) -> BackendResult<pb::NoteTypeId> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
let legacy: NoteTypeSchema11 = serde_json::from_slice(&input.json)?;
|
||||||
|
let mut nt: NoteType = legacy.into();
|
||||||
|
if nt.id.0 == 0 {
|
||||||
|
col.add_notetype(&mut nt)?;
|
||||||
|
} else {
|
||||||
|
col.update_notetype(&mut nt, input.preserve_usn_and_mtime)?;
|
||||||
|
}
|
||||||
|
Ok(pb::NoteTypeId { ntid: nt.id.0 })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_notetype(&mut self, input: pb::NoteTypeId) -> BackendResult<Empty> {
|
||||||
|
self.with_col(|col| col.remove_notetype(input.into()))
|
||||||
|
.map(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
// media
|
// media
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -828,37 +942,7 @@ impl Backend {
|
||||||
pb::Empty {}
|
pb::Empty {}
|
||||||
}),
|
}),
|
||||||
Value::GetAllConfig(_) => OValue::GetAllConfig(self.get_all_config()?),
|
Value::GetAllConfig(_) => OValue::GetAllConfig(self.get_all_config()?),
|
||||||
Value::GetChangedNotetypes(_) => {
|
|
||||||
OValue::GetChangedNotetypes(self.get_changed_notetypes()?)
|
|
||||||
}
|
|
||||||
Value::GetStockNotetypeLegacy(kind) => {
|
|
||||||
OValue::GetStockNotetypeLegacy(self.get_stock_notetype_legacy(kind)?)
|
|
||||||
}
|
|
||||||
Value::GetNotetypeLegacy(id) => {
|
|
||||||
OValue::GetNotetypeLegacy(self.get_notetype_legacy(id)?)
|
|
||||||
}
|
|
||||||
Value::GetNotetypeNames(_) => OValue::GetNotetypeNames(self.get_notetype_names()?),
|
|
||||||
Value::GetNotetypeNamesAndCounts(_) => {
|
|
||||||
OValue::GetNotetypeNamesAndCounts(self.get_notetype_use_counts()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::GetNotetypeIdByName(name) => {
|
|
||||||
OValue::GetNotetypeIdByName(self.get_notetype_id_by_name(name)?)
|
|
||||||
}
|
|
||||||
Value::AddOrUpdateNotetype(input) => {
|
|
||||||
OValue::AddOrUpdateNotetype(self.add_or_update_notetype_legacy(input)?)
|
|
||||||
}
|
|
||||||
Value::RemoveNotetype(id) => {
|
|
||||||
self.remove_notetype(id)?;
|
|
||||||
OValue::RemoveNotetype(pb::Empty {})
|
|
||||||
}
|
|
||||||
Value::FieldNamesForNotes(input) => {
|
|
||||||
OValue::FieldNamesForNotes(self.field_names_for_notes(input)?)
|
|
||||||
}
|
|
||||||
Value::FindAndReplace(input) => OValue::FindAndReplace(self.find_and_replace(input)?),
|
Value::FindAndReplace(input) => OValue::FindAndReplace(self.find_and_replace(input)?),
|
||||||
Value::AfterNoteUpdates(input) => {
|
|
||||||
OValue::AfterNoteUpdates(self.after_note_updates(input)?)
|
|
||||||
}
|
|
||||||
Value::SetLocalMinutesWest(mins) => OValue::SetLocalMinutesWest({
|
Value::SetLocalMinutesWest(mins) => OValue::SetLocalMinutesWest({
|
||||||
self.set_local_mins_west(mins)?;
|
self.set_local_mins_west(mins)?;
|
||||||
pb::Empty {}
|
pb::Empty {}
|
||||||
|
@ -1125,90 +1209,6 @@ impl Backend {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_changed_notetypes(&self) -> Result<Vec<u8>> {
|
|
||||||
todo!("filter by usn");
|
|
||||||
// self.with_col(|col| {
|
|
||||||
// let nts = col.storage.get_all_notetypes_as_schema11()?;
|
|
||||||
// serde_json::to_vec(&nts).map_err(Into::into)
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_notetype_names(&self) -> Result<pb::NoteTypeNames> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
let entries: Vec<_> = col
|
|
||||||
.storage
|
|
||||||
.get_all_notetype_names()?
|
|
||||||
.into_iter()
|
|
||||||
.map(|(id, name)| pb::NoteTypeNameId { id: id.0, name })
|
|
||||||
.collect();
|
|
||||||
Ok(pb::NoteTypeNames { entries })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_notetype_use_counts(&self) -> Result<pb::NoteTypeUseCounts> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
let entries: Vec<_> = col
|
|
||||||
.storage
|
|
||||||
.get_notetype_use_counts()?
|
|
||||||
.into_iter()
|
|
||||||
.map(|(id, name, use_count)| pb::NoteTypeNameIdUseCount {
|
|
||||||
id: id.0,
|
|
||||||
name,
|
|
||||||
use_count,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
Ok(pb::NoteTypeUseCounts { entries })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_notetype_legacy(&self, id: i64) -> Result<Vec<u8>> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
let schema11: NoteTypeSchema11 = col
|
|
||||||
.storage
|
|
||||||
.get_notetype(NoteTypeID(id))?
|
|
||||||
.ok_or(AnkiError::NotFound)?
|
|
||||||
.into();
|
|
||||||
Ok(serde_json::to_vec(&schema11)?)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_notetype_id_by_name(&self, name: String) -> Result<i64> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
col.storage
|
|
||||||
.get_notetype_id(&name)
|
|
||||||
.map(|nt| nt.unwrap_or(NoteTypeID(0)).0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_or_update_notetype_legacy(&self, input: pb::AddOrUpdateNotetypeIn) -> Result<i64> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
let legacy: NoteTypeSchema11 = serde_json::from_slice(&input.json)?;
|
|
||||||
let mut nt: NoteType = legacy.into();
|
|
||||||
if nt.id.0 == 0 {
|
|
||||||
col.add_notetype(&mut nt)?;
|
|
||||||
} else {
|
|
||||||
col.update_notetype(&mut nt, input.preserve_usn_and_mtime)?;
|
|
||||||
}
|
|
||||||
Ok(nt.id.0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_notetype(&self, id: i64) -> Result<()> {
|
|
||||||
self.with_col(|col| col.remove_notetype(NoteTypeID(id)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field_names_for_notes(
|
|
||||||
&self,
|
|
||||||
input: pb::FieldNamesForNotesIn,
|
|
||||||
) -> Result<pb::FieldNamesForNotesOut> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
let nids: Vec<_> = input.nids.into_iter().map(NoteID).collect();
|
|
||||||
col.storage
|
|
||||||
.field_names_for_notes(&nids)
|
|
||||||
.map(|fields| pb::FieldNamesForNotesOut { fields })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_and_replace(&self, input: pb::FindAndReplaceIn) -> Result<u32> {
|
fn find_and_replace(&self, input: pb::FindAndReplaceIn) -> Result<u32> {
|
||||||
let mut search = if input.regex {
|
let mut search = if input.regex {
|
||||||
input.search
|
input.search
|
||||||
|
@ -1231,19 +1231,6 @@ impl Backend {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn after_note_updates(&self, input: pb::AfterNoteUpdatesIn) -> Result<pb::Empty> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
col.transact(None, |col| {
|
|
||||||
col.after_note_updates(
|
|
||||||
&to_nids(input.nids),
|
|
||||||
input.generate_cards,
|
|
||||||
input.mark_notes_modified,
|
|
||||||
)?;
|
|
||||||
Ok(pb::Empty {})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_local_mins_west(&self, mins: i32) -> Result<()> {
|
fn set_local_mins_west(&self, mins: i32) -> Result<()> {
|
||||||
self.with_col(|col| col.transact(None, |col| col.set_local_mins_west(mins)))
|
self.with_col(|col| col.transact(None, |col| col.set_local_mins_west(mins)))
|
||||||
}
|
}
|
||||||
|
@ -1255,15 +1242,6 @@ impl Backend {
|
||||||
fn set_preferences(&self, prefs: pb::Preferences) -> Result<()> {
|
fn set_preferences(&self, prefs: pb::Preferences) -> Result<()> {
|
||||||
self.with_col(|col| col.transact(None, |col| col.set_preferences(prefs)))
|
self.with_col(|col| col.transact(None, |col| col.set_preferences(prefs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_stock_notetype_legacy(&self, kind: i32) -> Result<Vec<u8>> {
|
|
||||||
// fixme: use individual functions instead of full vec
|
|
||||||
let mut all = all_stock_notetypes(&self.i18n);
|
|
||||||
let idx = (kind as usize).min(all.len() - 1);
|
|
||||||
let nt = all.swap_remove(idx);
|
|
||||||
let schema11: NoteTypeSchema11 = nt.into();
|
|
||||||
serde_json::to_vec(&schema11).map_err(Into::into)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_nids(ids: Vec<i64>) -> Vec<NoteID> {
|
fn to_nids(ids: Vec<i64>) -> Vec<NoteID> {
|
||||||
|
|
|
@ -35,7 +35,53 @@ fn open_backend(init_msg: &PyBytes) -> PyResult<Backend> {
|
||||||
fn want_release_gil(method: u32) -> bool {
|
fn want_release_gil(method: u32) -> bool {
|
||||||
if let Ok(method) = BackendMethod::try_from(method) {
|
if let Ok(method) = BackendMethod::try_from(method) {
|
||||||
match method {
|
match method {
|
||||||
_ => false,
|
BackendMethod::ExtractAVTags => false,
|
||||||
|
BackendMethod::ExtractLatex => false,
|
||||||
|
BackendMethod::GetEmptyCards => true,
|
||||||
|
BackendMethod::RenderExistingCard => false,
|
||||||
|
BackendMethod::RenderUncommittedCard => false,
|
||||||
|
BackendMethod::StripAVTags => false,
|
||||||
|
BackendMethod::SearchCards => true,
|
||||||
|
BackendMethod::SearchNotes => true,
|
||||||
|
BackendMethod::LocalMinutesWest => false,
|
||||||
|
BackendMethod::SchedTimingToday => false,
|
||||||
|
BackendMethod::CheckMedia => true,
|
||||||
|
BackendMethod::SyncMedia => true,
|
||||||
|
BackendMethod::TrashMediaFiles => true,
|
||||||
|
BackendMethod::AddOrUpdateDeckLegacy => false,
|
||||||
|
BackendMethod::DeckTree => true,
|
||||||
|
BackendMethod::DeckTreeLegacy => true,
|
||||||
|
BackendMethod::GetAllDecksLegacy => true,
|
||||||
|
BackendMethod::GetDeckIDByName => true,
|
||||||
|
BackendMethod::GetDeckLegacy => true,
|
||||||
|
BackendMethod::GetDeckNames => true,
|
||||||
|
BackendMethod::NewDeckLegacy => false,
|
||||||
|
BackendMethod::RemoveDeck => true,
|
||||||
|
BackendMethod::AddOrUpdateDeckConfigLegacy => true,
|
||||||
|
BackendMethod::AllDeckConfigLegacy => true,
|
||||||
|
BackendMethod::GetDeckConfigLegacy => true,
|
||||||
|
BackendMethod::NewDeckConfigLegacy => false,
|
||||||
|
BackendMethod::RemoveDeckConfig => true,
|
||||||
|
BackendMethod::GetCard => true,
|
||||||
|
BackendMethod::UpdateCard => true,
|
||||||
|
BackendMethod::AddCard => true,
|
||||||
|
BackendMethod::NewNote => true,
|
||||||
|
BackendMethod::AddNote => true,
|
||||||
|
BackendMethod::UpdateNote => true,
|
||||||
|
BackendMethod::GetNote => true,
|
||||||
|
BackendMethod::AddNoteTags => true,
|
||||||
|
BackendMethod::UpdateNoteTags => true,
|
||||||
|
BackendMethod::ClozeNumbersInNote => true,
|
||||||
|
BackendMethod::AfterNoteUpdates => true,
|
||||||
|
BackendMethod::FieldNamesForNotes => true,
|
||||||
|
BackendMethod::AddOrUpdateNotetype => true,
|
||||||
|
BackendMethod::GetStockNotetypeLegacy => false,
|
||||||
|
BackendMethod::GetNotetypeLegacy => true,
|
||||||
|
BackendMethod::GetNotetypeNames => true,
|
||||||
|
BackendMethod::GetNotetypeNamesAndCounts => true,
|
||||||
|
BackendMethod::GetNotetypeIDByName => true,
|
||||||
|
BackendMethod::RemoveNotetype => true,
|
||||||
|
BackendMethod::CheckDatabase => true,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|
Loading…
Reference in a new issue