mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -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 UpdateNoteTags (UpdateNoteTagsIn) returns (UInt32);
|
||||
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
|
||||
|
||||
|
@ -379,34 +391,31 @@ message I18nBackendInit {
|
|||
message BackendInput {
|
||||
oneof value {
|
||||
AddMediaFileIn add_media_file = 26;
|
||||
Empty empty_trash = 34;
|
||||
Empty restore_trash = 35;
|
||||
Empty abort_media_sync = 46;
|
||||
|
||||
TranslateStringIn translate_string = 30;
|
||||
FormatTimeSpanIn format_time_span = 31;
|
||||
StudiedTodayIn studied_today = 32;
|
||||
CongratsLearnMsgIn congrats_learn_msg = 33;
|
||||
Empty empty_trash = 34;
|
||||
Empty restore_trash = 35;
|
||||
|
||||
OpenCollectionIn open_collection = 36;
|
||||
CloseCollectionIn close_collection = 37;
|
||||
Empty abort_media_sync = 46;
|
||||
|
||||
Empty before_upload = 47;
|
||||
|
||||
RegisterTagsIn register_tags = 48;
|
||||
Empty all_tags = 50;
|
||||
int32 get_changed_tags = 51;
|
||||
|
||||
string get_config_json = 52;
|
||||
SetConfigJson set_config_json = 53;
|
||||
bytes set_all_config = 54;
|
||||
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;
|
||||
AfterNoteUpdatesIn after_note_updates = 80;
|
||||
|
||||
int32 set_local_minutes_west = 83;
|
||||
Empty get_preferences = 84;
|
||||
Preferences set_preferences = 85;
|
||||
|
@ -436,20 +445,12 @@ message BackendOutput {
|
|||
Empty set_config_json = 53;
|
||||
Empty set_all_config = 54;
|
||||
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;
|
||||
Empty after_note_updates = 80;
|
||||
|
||||
Empty set_local_minutes_west = 83;
|
||||
Preferences get_preferences = 84;
|
||||
Empty set_preferences = 85;
|
||||
bytes get_stock_notetype_legacy = 60;
|
||||
|
||||
BackendError error = 2047;
|
||||
}
|
||||
|
@ -766,6 +767,10 @@ enum StockNoteType {
|
|||
STOCK_NOTE_TYPE_CLOZE = 4;
|
||||
}
|
||||
|
||||
message GetStockNotetypeIn {
|
||||
StockNoteType kind = 1;
|
||||
}
|
||||
|
||||
message NoteTypeNames {
|
||||
repeated NoteTypeNameID entries = 1;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ def findReplace(
|
|||
|
||||
|
||||
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
|
||||
|
|
|
@ -5,13 +5,13 @@ from __future__ import annotations
|
|||
|
||||
import copy
|
||||
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.backend_pb2 as pb
|
||||
from anki.consts 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
|
||||
|
||||
# types
|
||||
|
@ -109,11 +109,11 @@ class ModelManager:
|
|||
# Listing note types
|
||||
#############################################################
|
||||
|
||||
def all_names_and_ids(self) -> List[pb.NoteTypeNameID]:
|
||||
return self.col.backend.get_notetype_names_and_ids()
|
||||
def all_names_and_ids(self) -> Sequence[pb.NoteTypeNameID]:
|
||||
return self.col.backend.get_notetype_names()
|
||||
|
||||
def all_use_counts(self) -> List[pb.NoteTypeNameIDUseCount]:
|
||||
return self.col.backend.get_notetype_use_counts()
|
||||
def all_use_counts(self) -> Sequence[pb.NoteTypeNameIDUseCount]:
|
||||
return self.col.backend.get_notetype_names_and_counts()
|
||||
|
||||
# legacy
|
||||
|
||||
|
@ -149,7 +149,10 @@ class ModelManager:
|
|||
#############################################################
|
||||
|
||||
def id_for_name(self, name: str) -> Optional[int]:
|
||||
return self.col.backend.get_notetype_id_by_name(name)
|
||||
try:
|
||||
return self.col.backend.get_notetype_id_by_name(name)
|
||||
except NotFoundError:
|
||||
return None
|
||||
|
||||
def get(self, id: int) -> Optional[NoteType]:
|
||||
"Get model with ID, or None."
|
||||
|
@ -161,9 +164,11 @@ class ModelManager:
|
|||
|
||||
nt = self._get_cached(id)
|
||||
if not nt:
|
||||
nt = self.col.backend.get_notetype_legacy(id)
|
||||
if nt:
|
||||
try:
|
||||
nt = from_json_bytes(self.col.backend.get_notetype_legacy(id))
|
||||
self._update_cache(nt)
|
||||
except NotFoundError:
|
||||
return None
|
||||
return nt
|
||||
|
||||
def all(self) -> List[NoteType]:
|
||||
|
@ -181,8 +186,10 @@ class ModelManager:
|
|||
def new(self, name: str) -> NoteType:
|
||||
"Create a new model, and return it."
|
||||
# caller should call save() after modifying
|
||||
nt = self.col.backend.get_stock_notetype_legacy(
|
||||
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
||||
nt = from_json_bytes(
|
||||
self.col.backend.get_stock_notetype_legacy(
|
||||
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
||||
)
|
||||
)
|
||||
nt["flds"] = []
|
||||
nt["tmpls"] = []
|
||||
|
@ -215,7 +222,9 @@ class ModelManager:
|
|||
"Add or update an existing model. Use .save() instead."
|
||||
self._remove_from_cache(m["id"])
|
||||
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._mutate_after_write(m)
|
||||
|
||||
|
@ -268,8 +277,10 @@ class ModelManager:
|
|||
|
||||
def new_field(self, name: str) -> Field:
|
||||
assert isinstance(name, str)
|
||||
nt = self.col.backend.get_stock_notetype_legacy(
|
||||
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
||||
nt = from_json_bytes(
|
||||
self.col.backend.get_stock_notetype_legacy(
|
||||
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
||||
)
|
||||
)
|
||||
field = nt["flds"][0]
|
||||
field["name"] = name
|
||||
|
@ -327,8 +338,10 @@ class ModelManager:
|
|||
##################################################
|
||||
|
||||
def new_template(self, name: str) -> Template:
|
||||
nt = self.col.backend.get_stock_notetype_legacy(
|
||||
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
||||
nt = from_json_bytes(
|
||||
self.col.backend.get_stock_notetype_legacy(
|
||||
StockNoteType.STOCK_NOTE_TYPE_BASIC
|
||||
)
|
||||
)
|
||||
template = nt["tmpls"][0]
|
||||
template["name"] = name
|
||||
|
|
|
@ -370,70 +370,6 @@ class RustBackend:
|
|||
def set_all_config(self, conf: Dict[str, Any]):
|
||||
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(
|
||||
self,
|
||||
nids: List[int],
|
||||
|
@ -457,20 +393,6 @@ class RustBackend:
|
|||
release_gil=True,
|
||||
).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:
|
||||
self._run_command(pb.BackendInput(set_local_minutes_west=mins))
|
||||
|
||||
|
@ -599,15 +521,15 @@ class RustBackend:
|
|||
|
||||
def deck_tree_legacy(self) -> bytes:
|
||||
input = pb.Empty()
|
||||
output = pb.Bytes()
|
||||
output = pb.Json()
|
||||
output.ParseFromString(self._run_command2(16, input))
|
||||
return output.val
|
||||
return output.json
|
||||
|
||||
def get_all_decks_legacy(self) -> bytes:
|
||||
input = pb.Empty()
|
||||
output = pb.Bytes()
|
||||
output = pb.Json()
|
||||
output.ParseFromString(self._run_command2(17, input))
|
||||
return output.val
|
||||
return output.json
|
||||
|
||||
def get_deck_id_by_name(self, val: str) -> int:
|
||||
input = pb.String(val=val)
|
||||
|
@ -617,9 +539,9 @@ class RustBackend:
|
|||
|
||||
def get_deck_legacy(self, did: int) -> bytes:
|
||||
input = pb.DeckID(did=did)
|
||||
output = pb.Bytes()
|
||||
output = pb.Json()
|
||||
output.ParseFromString(self._run_command2(19, input))
|
||||
return output.val
|
||||
return output.json
|
||||
|
||||
def get_deck_names(
|
||||
self, skip_empty_default: bool, include_filtered: bool
|
||||
|
@ -633,9 +555,9 @@ class RustBackend:
|
|||
|
||||
def new_deck_legacy(self, val: bool) -> bytes:
|
||||
input = pb.Bool(val=val)
|
||||
output = pb.Bytes()
|
||||
output = pb.Json()
|
||||
output.ParseFromString(self._run_command2(21, input))
|
||||
return output.val
|
||||
return output.json
|
||||
|
||||
def remove_deck(self, did: int) -> pb.Empty:
|
||||
input = pb.DeckID(did=did)
|
||||
|
@ -655,21 +577,21 @@ class RustBackend:
|
|||
|
||||
def all_deck_config_legacy(self) -> bytes:
|
||||
input = pb.Empty()
|
||||
output = pb.Bytes()
|
||||
output = pb.Json()
|
||||
output.ParseFromString(self._run_command2(24, input))
|
||||
return output.val
|
||||
return output.json
|
||||
|
||||
def get_deck_config_legacy(self, dcid: int) -> bytes:
|
||||
input = pb.DeckConfigID(dcid=dcid)
|
||||
output = pb.Bytes()
|
||||
output = pb.Json()
|
||||
output.ParseFromString(self._run_command2(25, input))
|
||||
return output.val
|
||||
return output.json
|
||||
|
||||
def new_deck_config_legacy(self) -> bytes:
|
||||
input = pb.Empty()
|
||||
output = pb.Bytes()
|
||||
output = pb.Json()
|
||||
output.ParseFromString(self._run_command2(26, input))
|
||||
return output.val
|
||||
return output.json
|
||||
|
||||
def remove_deck_config(self, dcid: int) -> pb.Empty:
|
||||
input = pb.DeckConfigID(dcid=dcid)
|
||||
|
@ -737,10 +659,72 @@ class RustBackend:
|
|||
output.ParseFromString(self._run_command2(37, input))
|
||||
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]:
|
||||
input = pb.Empty()
|
||||
output = pb.CheckDatabaseOut()
|
||||
output.ParseFromString(self._run_command2(38, input))
|
||||
output.ParseFromString(self._run_command2(47, input))
|
||||
return output.problems
|
||||
|
||||
# @@AUTOGEN@@
|
||||
|
|
|
@ -5,7 +5,7 @@ from typing import Callable, List, Tuple
|
|||
|
||||
from anki.collection import Collection
|
||||
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)
|
||||
# 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:
|
||||
m = col.backend.get_stock_notetype_legacy(kind)
|
||||
m = from_json_bytes(col.backend.get_stock_notetype_legacy(kind))
|
||||
col.models.add(m)
|
||||
return m
|
||||
|
||||
|
@ -55,7 +55,7 @@ def get_stock_notetypes(
|
|||
),
|
||||
(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))
|
||||
# add extras from add-ons
|
||||
for (name_or_func, func) in models:
|
||||
|
|
|
@ -49,8 +49,10 @@ def python_type_inner(field):
|
|||
return "str"
|
||||
elif type == TYPE_BYTES:
|
||||
return "bytes"
|
||||
elif type == 11:
|
||||
elif type == TYPE_MESSAGE:
|
||||
return "pb." + field.message_type.name
|
||||
elif type == TYPE_ENUM:
|
||||
return "pb." + field.enum_type.name
|
||||
else:
|
||||
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
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
@ -828,37 +942,7 @@ impl Backend {
|
|||
pb::Empty {}
|
||||
}),
|
||||
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::AfterNoteUpdates(input) => {
|
||||
OValue::AfterNoteUpdates(self.after_note_updates(input)?)
|
||||
}
|
||||
Value::SetLocalMinutesWest(mins) => OValue::SetLocalMinutesWest({
|
||||
self.set_local_mins_west(mins)?;
|
||||
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> {
|
||||
let mut search = if input.regex {
|
||||
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<()> {
|
||||
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<()> {
|
||||
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> {
|
||||
|
|
|
@ -35,7 +35,53 @@ fn open_backend(init_msg: &PyBytes) -> PyResult<Backend> {
|
|||
fn want_release_gil(method: u32) -> bool {
|
||||
if let Ok(method) = BackendMethod::try_from(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 {
|
||||
false
|
||||
|
|
Loading…
Reference in a new issue