migrate cards and notes

This commit is contained in:
Damien Elmes 2020-05-23 16:19:48 +10:00
parent 7550e6241c
commit 95735f106a
7 changed files with 234 additions and 194 deletions

View file

@ -21,6 +21,10 @@ message Int32 {
sint32 val = 1; sint32 val = 1;
} }
message UInt32 {
uint32 val = 1;
}
message Int64 { message Int64 {
int64 val = 1; int64 val = 1;
} }
@ -37,6 +41,19 @@ message Bool {
bool val = 1; bool val = 1;
} }
message NoteTypeID {
int64 ntid = 1;
}
message NoteID {
int64 nid = 1;
}
message CardID {
int64 cid = 1;
}
// New style RPC definitions // New style RPC definitions
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -86,6 +103,22 @@ service BackendService {
rpc NewDeckConfigLegacy (Empty) returns (Bytes); rpc NewDeckConfigLegacy (Empty) returns (Bytes);
rpc RemoveDeckConfig (Int64) returns (Empty); rpc RemoveDeckConfig (Int64) returns (Empty);
// cards
rpc GetCard (CardID) returns (Card);
rpc UpdateCard (Card) returns (Empty);
rpc AddCard (Card) returns (CardID);
// notes
rpc NewNote (NoteTypeID) returns (Note);
rpc AddNote (AddNoteIn) returns (NoteID);
rpc UpdateNote (Note) returns (Empty);
rpc GetNote (NoteID) returns (Note);
rpc AddNoteTags (AddNoteTagsIn) returns (UInt32);
rpc UpdateNoteTags (UpdateNoteTagsIn) returns (UInt32);
rpc ClozeNumbersInNote (Note) returns (ClozeNumbersInNoteOut);
// misc // misc
rpc CheckDatabase (Empty) returns (CheckDatabaseOut); rpc CheckDatabase (Empty) returns (CheckDatabaseOut);
@ -344,9 +377,6 @@ message BackendInput {
Empty restore_trash = 35; Empty restore_trash = 35;
OpenCollectionIn open_collection = 36; OpenCollectionIn open_collection = 36;
CloseCollectionIn close_collection = 37; CloseCollectionIn close_collection = 37;
int64 get_card = 38;
Card update_card = 39;
Card add_card = 40;
Empty abort_media_sync = 46; Empty abort_media_sync = 46;
Empty before_upload = 47; Empty before_upload = 47;
RegisterTagsIn register_tags = 48; RegisterTagsIn register_tags = 48;
@ -364,19 +394,12 @@ message BackendInput {
Empty get_notetype_names_and_counts = 63; Empty get_notetype_names_and_counts = 63;
string get_notetype_id_by_name = 64; string get_notetype_id_by_name = 64;
int64 remove_notetype = 65; int64 remove_notetype = 65;
int64 new_note = 66;
AddNoteIn add_note = 67;
Note update_note = 68;
int64 get_note = 69;
FieldNamesForNotesIn field_names_for_notes = 78; FieldNamesForNotesIn field_names_for_notes = 78;
FindAndReplaceIn find_and_replace = 79; FindAndReplaceIn find_and_replace = 79;
AfterNoteUpdatesIn after_note_updates = 80; AfterNoteUpdatesIn after_note_updates = 80;
AddNoteTagsIn add_note_tags = 81;
UpdateNoteTagsIn update_note_tags = 82;
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;
Note cloze_numbers_in_note = 87;
} }
} }
@ -388,7 +411,6 @@ message BackendOutput {
string studied_today = 32; string studied_today = 32;
string congrats_learn_msg = 33; string congrats_learn_msg = 33;
Empty abort_media_sync = 46; Empty abort_media_sync = 46;
ClozeNumbersInNoteOut cloze_numbers_in_note = 87;
// fallible commands // fallible commands
string add_media_file = 26; string add_media_file = 26;
@ -396,9 +418,6 @@ message BackendOutput {
Empty restore_trash = 35; Empty restore_trash = 35;
Empty open_collection = 36; Empty open_collection = 36;
Empty close_collection = 37; Empty close_collection = 37;
GetCardOut get_card = 38;
Empty update_card = 39;
int64 add_card = 40;
Empty before_upload = 47; Empty before_upload = 47;
bool register_tags = 48; bool register_tags = 48;
AllTagsOut all_tags = 50; AllTagsOut all_tags = 50;
@ -414,15 +433,9 @@ message BackendOutput {
NoteTypeUseCounts get_notetype_names_and_counts = 63; NoteTypeUseCounts get_notetype_names_and_counts = 63;
int64 get_notetype_id_by_name = 64; int64 get_notetype_id_by_name = 64;
Empty remove_notetype = 65; Empty remove_notetype = 65;
Note new_note = 66;
int64 add_note = 67;
Empty update_note = 68;
Note get_note = 69;
FieldNamesForNotesOut field_names_for_notes = 78; FieldNamesForNotesOut field_names_for_notes = 78;
uint32 find_and_replace = 79; uint32 find_and_replace = 79;
Empty after_note_updates = 80; Empty after_note_updates = 80;
uint32 add_note_tags = 81;
uint32 update_note_tags = 82;
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;
@ -698,11 +711,6 @@ message BuiltinSearchOrder {
bool reverse = 2; bool reverse = 2;
} }
message GetCardOut {
Card card = 1;
}
message CloseCollectionIn { message CloseCollectionIn {
bool downgrade_to_schema11 = 1; bool downgrade_to_schema11 = 1;
} }

View file

@ -467,4 +467,4 @@ and notes.mid = ? and cards.ord = ?""",
def _availClozeOrds(self, m: NoteType, flds: str, allowEmpty: bool = True) -> List: def _availClozeOrds(self, m: NoteType, flds: str, allowEmpty: bool = True) -> List:
print("_availClozeOrds() is deprecated; use note.cloze_numbers_in_fields()") print("_availClozeOrds() is deprecated; use note.cloze_numbers_in_fields()")
note = anki.rsbackend.BackendNote(fields=[flds]) note = anki.rsbackend.BackendNote(fields=[flds])
return self.col.backend.cloze_numbers_in_note(note) return list(self.col.backend.cloze_numbers_in_note(note))

View file

@ -3,7 +3,7 @@
from __future__ import annotations from __future__ import annotations
from typing import Any, List, Optional, Tuple from typing import Any, List, Optional, Sequence, Tuple
import anki # pylint: disable=unused-import import anki # pylint: disable=unused-import
from anki import hooks from anki import hooks
@ -82,7 +82,7 @@ class Note:
_model = property(model) _model = property(model)
def cloze_numbers_in_fields(self) -> List[int]: def cloze_numbers_in_fields(self) -> Sequence[int]:
return self.col.backend.cloze_numbers_in_note(self.to_backend_note()) return self.col.backend.cloze_numbers_in_note(self.to_backend_note())
# Dict interface # Dict interface

View file

@ -306,20 +306,6 @@ class RustBackend:
def _db_command(self, input: Dict[str, Any]) -> Any: def _db_command(self, input: Dict[str, Any]) -> Any:
return orjson.loads(self._backend.db_command(orjson.dumps(input))) return orjson.loads(self._backend.db_command(orjson.dumps(input)))
def get_card(self, cid: int) -> Optional[pb.Card]:
output = self._run_command(pb.BackendInput(get_card=cid)).get_card
if output.HasField("card"):
return output.card
else:
return None
def update_card(self, card: BackendCard) -> None:
self._run_command(pb.BackendInput(update_card=card))
# returns the new card id
def add_card(self, card: BackendCard) -> int:
return self._run_command(pb.BackendInput(add_card=card)).add_card
def abort_media_sync(self): def abort_media_sync(self):
self._run_command(pb.BackendInput(abort_media_sync=pb.Empty())) self._run_command(pb.BackendInput(abort_media_sync=pb.Empty()))
@ -442,23 +428,6 @@ class RustBackend:
def remove_notetype(self, ntid: int) -> None: def remove_notetype(self, ntid: int) -> None:
self._run_command(pb.BackendInput(remove_notetype=ntid), release_gil=True) self._run_command(pb.BackendInput(remove_notetype=ntid), release_gil=True)
def new_note(self, ntid: int) -> BackendNote:
return self._run_command(pb.BackendInput(new_note=ntid)).new_note
def add_note(self, note: BackendNote, deck_id: int) -> int:
return self._run_command(
pb.BackendInput(add_note=pb.AddNoteIn(note=note, deck_id=deck_id))
).add_note
def update_note(self, note: BackendNote) -> None:
self._run_command(pb.BackendInput(update_note=note))
def get_note(self, nid) -> Optional[BackendNote]:
try:
return self._run_command(pb.BackendInput(get_note=nid)).get_note
except NotFoundError:
return None
def field_names_for_note_ids(self, nids: List[int]) -> Sequence[str]: def field_names_for_note_ids(self, nids: List[int]) -> Sequence[str]:
return self._run_command( return self._run_command(
pb.BackendInput(field_names_for_notes=pb.FieldNamesForNotesIn(nids=nids)), pb.BackendInput(field_names_for_notes=pb.FieldNamesForNotesIn(nids=nids)),
@ -502,22 +471,6 @@ class RustBackend:
release_gil=True, release_gil=True,
) )
def add_note_tags(self, nids: List[int], tags: str) -> int:
return self._run_command(
pb.BackendInput(add_note_tags=pb.AddNoteTagsIn(nids=nids, tags=tags))
).add_note_tags
def update_note_tags(
self, nids: List[int], tags: str, replacement: str, regex: bool
) -> int:
return self._run_command(
pb.BackendInput(
update_note_tags=pb.UpdateNoteTagsIn(
nids=nids, tags=tags, replacement=replacement, regex=regex
)
)
).update_note_tags
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))
@ -529,13 +482,6 @@ class RustBackend:
def set_preferences(self, prefs: pb.Preferences) -> None: def set_preferences(self, prefs: pb.Preferences) -> None:
self._run_command(pb.BackendInput(set_preferences=prefs)) self._run_command(pb.BackendInput(set_preferences=prefs))
def cloze_numbers_in_note(self, note: pb.Note) -> List[int]:
return list(
self._run_command(
pb.BackendInput(cloze_numbers_in_note=note)
).cloze_numbers_in_note.numbers
)
def _run_command2(self, method: int, input: Any) -> bytes: def _run_command2(self, method: int, input: Any) -> bytes:
input_bytes = input.SerializeToString() input_bytes = input.SerializeToString()
try: try:
@ -731,10 +677,70 @@ class RustBackend:
output.ParseFromString(self._run_command2(27, input)) output.ParseFromString(self._run_command2(27, input))
return output return output
def get_card(self, cid: int) -> pb.Card:
input = pb.CardID(cid=cid)
output = pb.Card()
output.ParseFromString(self._run_command2(28, input))
return output
def update_card(self, input: pb.Card) -> pb.Empty:
output = pb.Empty()
output.ParseFromString(self._run_command2(29, input))
return output
def add_card(self, input: pb.Card) -> int:
output = pb.CardID()
output.ParseFromString(self._run_command2(30, input))
return output.cid
def new_note(self, ntid: int) -> pb.Note:
input = pb.NoteTypeID(ntid=ntid)
output = pb.Note()
output.ParseFromString(self._run_command2(31, input))
return output
def add_note(self, note: pb.Note, deck_id: int) -> int:
input = pb.AddNoteIn(note=note, deck_id=deck_id)
output = pb.NoteID()
output.ParseFromString(self._run_command2(32, input))
return output.nid
def update_note(self, input: pb.Note) -> pb.Empty:
output = pb.Empty()
output.ParseFromString(self._run_command2(33, input))
return output
def get_note(self, nid: int) -> pb.Note:
input = pb.NoteID(nid=nid)
output = pb.Note()
output.ParseFromString(self._run_command2(34, input))
return output
def add_note_tags(self, nids: Sequence[int], tags: str) -> int:
input = pb.AddNoteTagsIn(nids=nids, tags=tags)
output = pb.UInt32()
output.ParseFromString(self._run_command2(35, input))
return output.val
def update_note_tags(
self, nids: Sequence[int], tags: str, replacement: str, regex: bool
) -> int:
input = pb.UpdateNoteTagsIn(
nids=nids, tags=tags, replacement=replacement, regex=regex
)
output = pb.UInt32()
output.ParseFromString(self._run_command2(36, input))
return output.val
def cloze_numbers_in_note(self, input: pb.Note) -> Sequence[int]:
output = pb.ClozeNumbersInNoteOut()
output.ParseFromString(self._run_command2(37, input))
return output.numbers
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(28, input)) output.ParseFromString(self._run_command2(38, input))
return output.problems return output.problems
# @@AUTOGEN@@ # @@AUTOGEN@@

View file

@ -2,6 +2,7 @@
import time import time
from anki.consts import MODEL_CLOZE from anki.consts import MODEL_CLOZE
from anki.rsbackend import NotFoundError
from anki.utils import isWin, stripHTML from anki.utils import isWin, stripHTML
from tests.shared import getEmptyCol from tests.shared import getEmptyCol
@ -323,7 +324,7 @@ def test_modelChange():
try: try:
c1.load() c1.load()
assert 0 assert 0
except AssertionError: except NotFoundError:
pass pass
# but we have two cards, as a new one was generated # but we have two cards, as a new one was generated
assert len(f.cards()) == 2 assert len(f.cards()) == 2

View file

@ -77,8 +77,16 @@ def get_input_assign(msg):
def render_method(method, idx): def render_method(method, idx):
input_name = method.input_type.name
if input_name.endswith("In") or len(method.input_type.fields) < 2:
input_args = get_input_args(method.input_type) input_args = get_input_args(method.input_type)
input_assign = get_input_assign(method.input_type) input_assign = get_input_assign(method.input_type)
input_assign_outer = (
f"input = pb.{method.input_type.name}({input_assign})\n "
)
else:
input_args = f"self, input: pb.{input_name}"
input_assign_outer = ""
name = fix_snakecase(stringcase.snakecase(method.name)) name = fix_snakecase(stringcase.snakecase(method.name))
if len(method.output_type.fields) == 1: if len(method.output_type.fields) == 1:
# unwrap single return arg # unwrap single return arg
@ -90,8 +98,7 @@ def render_method(method, idx):
return_type = f"pb.{method.output_type.name}" return_type = f"pb.{method.output_type.name}"
return f"""\ return f"""\
def {name}({input_args}) -> {return_type}: def {name}({input_args}) -> {return_type}:
input = pb.{method.input_type.name}({input_assign}) {input_assign_outer}output = pb.{method.output_type.name}()
output = pb.{method.output_type.name}()
output.ParseFromString(self._run_command2({idx+1}, input)) output.ParseFromString(self._run_command2({idx+1}, input))
return output{single_field} return output{single_field}
""" """

View file

@ -166,12 +166,36 @@ impl From<i64> for pb::Int64 {
} }
} }
impl From<u32> for pb::UInt32 {
fn from(val: u32) -> Self {
pb::UInt32 { val }
}
}
impl From<()> for pb::Empty { impl From<()> for pb::Empty {
fn from(_val: ()) -> Self { fn from(_val: ()) -> Self {
pb::Empty {} pb::Empty {}
} }
} }
impl From<pb::CardId> for CardID {
fn from(cid: pb::CardId) -> Self {
CardID(cid.cid)
}
}
impl From<pb::NoteId> for NoteID {
fn from(nid: pb::NoteId) -> Self {
NoteID(nid.nid)
}
}
impl From<pb::NoteTypeId> for NoteTypeID {
fn from(ntid: pb::NoteTypeId) -> Self {
NoteTypeID(ntid.ntid)
}
}
impl BackendService for Backend { impl BackendService for Backend {
// card rendering // card rendering
@ -486,6 +510,106 @@ impl BackendService for Backend {
.map(Into::into) .map(Into::into)
} }
// cards
//-------------------------------------------------------------------
fn get_card(&mut self, input: pb::CardId) -> BackendResult<pb::Card> {
self.with_col(|col| {
col.storage
.get_card(input.into())
.and_then(|opt| opt.ok_or(AnkiError::NotFound))
.map(card_to_pb)
})
}
fn update_card(&mut self, input: pb::Card) -> BackendResult<Empty> {
let mut card = pbcard_to_native(input)?;
self.with_col(|col| {
col.transact(None, |ctx| {
let orig = ctx
.storage
.get_card(card.id)?
.ok_or_else(|| AnkiError::invalid_input("missing card"))?;
ctx.update_card(&mut card, &orig)
})
})
.map(Into::into)
}
fn add_card(&mut self, input: pb::Card) -> BackendResult<pb::CardId> {
let mut card = pbcard_to_native(input)?;
self.with_col(|col| col.transact(None, |ctx| ctx.add_card(&mut card)))?;
Ok(pb::CardId { cid: card.id.0 })
}
// notes
//-------------------------------------------------------------------
fn new_note(&mut self, input: pb::NoteTypeId) -> BackendResult<pb::Note> {
self.with_col(|col| {
let nt = col.get_notetype(input.into())?.ok_or(AnkiError::NotFound)?;
Ok(nt.new_note().into())
})
}
fn add_note(&mut self, input: pb::AddNoteIn) -> BackendResult<pb::NoteId> {
self.with_col(|col| {
let mut note: Note = input.note.ok_or(AnkiError::NotFound)?.into();
col.add_note(&mut note, DeckID(input.deck_id))
.map(|_| pb::NoteId { nid: note.id.0 })
})
}
fn update_note(&mut self, input: pb::Note) -> BackendResult<Empty> {
self.with_col(|col| {
let mut note: Note = input.into();
col.update_note(&mut note)
})
.map(Into::into)
}
fn get_note(&mut self, input: pb::NoteId) -> BackendResult<pb::Note> {
self.with_col(|col| {
col.storage
.get_note(input.into())?
.ok_or(AnkiError::NotFound)
.map(Into::into)
})
}
fn add_note_tags(&mut self, input: pb::AddNoteTagsIn) -> BackendResult<pb::UInt32> {
self.with_col(|col| {
col.add_tags_for_notes(&to_nids(input.nids), &input.tags)
.map(|n| n as u32)
})
.map(Into::into)
}
fn update_note_tags(&mut self, input: pb::UpdateNoteTagsIn) -> BackendResult<pb::UInt32> {
self.with_col(|col| {
col.replace_tags_for_notes(
&to_nids(input.nids),
&input.tags,
&input.replacement,
input.regex,
)
.map(|n| (n as u32).into())
})
}
fn cloze_numbers_in_note(
&mut self,
note: pb::Note,
) -> BackendResult<pb::ClozeNumbersInNoteOut> {
let mut set = HashSet::with_capacity(4);
for field in &note.fields {
add_cloze_numbers_in_string(field, &mut set);
}
Ok(pb::ClozeNumbersInNoteOut {
numbers: set.into_iter().map(|n| n as u32).collect(),
})
}
// media // media
//------------------------------------------------------------------- //-------------------------------------------------------------------
@ -669,12 +793,6 @@ impl Backend {
self.close_collection(input.downgrade_to_schema11)?; self.close_collection(input.downgrade_to_schema11)?;
OValue::CloseCollection(Empty {}) OValue::CloseCollection(Empty {})
} }
Value::GetCard(cid) => OValue::GetCard(self.get_card(cid)?),
Value::UpdateCard(card) => {
self.update_card(card)?;
OValue::UpdateCard(pb::Empty {})
}
Value::AddCard(card) => OValue::AddCard(self.add_card(card)?),
Value::AbortMediaSync(_) => { Value::AbortMediaSync(_) => {
self.abort_media_sync(); self.abort_media_sync();
OValue::AbortMediaSync(pb::Empty {}) OValue::AbortMediaSync(pb::Empty {})
@ -721,13 +839,6 @@ impl Backend {
self.remove_notetype(id)?; self.remove_notetype(id)?;
OValue::RemoveNotetype(pb::Empty {}) OValue::RemoveNotetype(pb::Empty {})
} }
Value::NewNote(ntid) => OValue::NewNote(self.new_note(ntid)?),
Value::AddNote(input) => OValue::AddNote(self.add_note(input)?),
Value::UpdateNote(note) => {
self.update_note(note)?;
OValue::UpdateNote(pb::Empty {})
}
Value::GetNote(nid) => OValue::GetNote(self.get_note(nid)?),
Value::FieldNamesForNotes(input) => { Value::FieldNamesForNotes(input) => {
OValue::FieldNamesForNotes(self.field_names_for_notes(input)?) OValue::FieldNamesForNotes(self.field_names_for_notes(input)?)
} }
@ -735,8 +846,6 @@ impl Backend {
Value::AfterNoteUpdates(input) => { Value::AfterNoteUpdates(input) => {
OValue::AfterNoteUpdates(self.after_note_updates(input)?) OValue::AfterNoteUpdates(self.after_note_updates(input)?)
} }
Value::AddNoteTags(input) => OValue::AddNoteTags(self.add_note_tags(input)?),
Value::UpdateNoteTags(input) => OValue::UpdateNoteTags(self.update_note_tags(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 {}
@ -746,9 +855,6 @@ impl Backend {
self.set_preferences(prefs)?; self.set_preferences(prefs)?;
pb::Empty {} pb::Empty {}
}), }),
Value::ClozeNumbersInNote(note) => {
OValue::ClozeNumbersInNote(self.cloze_numbers_in_note(note))
}
}) })
} }
@ -924,32 +1030,6 @@ impl Backend {
self.with_col(|col| db_command_bytes(&col.storage, input)) self.with_col(|col| db_command_bytes(&col.storage, input))
} }
fn get_card(&self, cid: i64) -> Result<pb::GetCardOut> {
let card = self.with_col(|col| col.storage.get_card(CardID(cid)))?;
Ok(pb::GetCardOut {
card: card.map(card_to_pb),
})
}
fn update_card(&self, pbcard: pb::Card) -> Result<()> {
let mut card = pbcard_to_native(pbcard)?;
self.with_col(|col| {
col.transact(None, |ctx| {
let orig = ctx
.storage
.get_card(card.id)?
.ok_or_else(|| AnkiError::invalid_input("missing card"))?;
ctx.update_card(&mut card, &orig)
})
})
}
fn add_card(&self, pbcard: pb::Card) -> Result<i64> {
let mut card = pbcard_to_native(pbcard)?;
self.with_col(|col| col.transact(None, |ctx| ctx.add_card(&mut card)))?;
Ok(card.id.0)
}
fn before_upload(&self) -> Result<()> { fn before_upload(&self) -> Result<()> {
self.with_col(|col| col.before_upload()) self.with_col(|col| col.before_upload())
} }
@ -1104,39 +1184,6 @@ impl Backend {
self.with_col(|col| col.remove_notetype(NoteTypeID(id))) self.with_col(|col| col.remove_notetype(NoteTypeID(id)))
} }
fn new_note(&self, ntid: i64) -> Result<pb::Note> {
self.with_col(|col| {
let nt = col
.get_notetype(NoteTypeID(ntid))?
.ok_or(AnkiError::NotFound)?;
Ok(nt.new_note().into())
})
}
fn add_note(&self, input: pb::AddNoteIn) -> Result<i64> {
self.with_col(|col| {
let mut note: Note = input.note.ok_or(AnkiError::NotFound)?.into();
col.add_note(&mut note, DeckID(input.deck_id))
.map(|_| note.id.0)
})
}
fn update_note(&self, pbnote: pb::Note) -> Result<()> {
self.with_col(|col| {
let mut note: Note = pbnote.into();
col.update_note(&mut note)
})
}
fn get_note(&self, nid: i64) -> Result<pb::Note> {
self.with_col(|col| {
col.storage
.get_note(NoteID(nid))?
.ok_or(AnkiError::NotFound)
.map(Into::into)
})
}
fn field_names_for_notes( fn field_names_for_notes(
&self, &self,
input: pb::FieldNamesForNotesIn, input: pb::FieldNamesForNotesIn,
@ -1184,25 +1231,6 @@ impl Backend {
}) })
} }
fn add_note_tags(&self, input: pb::AddNoteTagsIn) -> Result<u32> {
self.with_col(|col| {
col.add_tags_for_notes(&to_nids(input.nids), &input.tags)
.map(|n| n as u32)
})
}
fn update_note_tags(&self, input: pb::UpdateNoteTagsIn) -> Result<u32> {
self.with_col(|col| {
col.replace_tags_for_notes(
&to_nids(input.nids),
&input.tags,
&input.replacement,
input.regex,
)
.map(|n| n as u32)
})
}
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)))
} }
@ -1215,16 +1243,6 @@ impl Backend {
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 cloze_numbers_in_note(&self, note: pb::Note) -> pb::ClozeNumbersInNoteOut {
let mut set = HashSet::with_capacity(4);
for field in &note.fields {
add_cloze_numbers_in_string(field, &mut set);
}
pb::ClozeNumbersInNoteOut {
numbers: set.into_iter().map(|n| n as u32).collect(),
}
}
fn get_stock_notetype_legacy(&self, kind: i32) -> Result<Vec<u8>> { fn get_stock_notetype_legacy(&self, kind: i32) -> Result<Vec<u8>> {
// fixme: use individual functions instead of full vec // fixme: use individual functions instead of full vec
let mut all = all_stock_notetypes(&self.i18n); let mut all = all_stock_notetypes(&self.i18n);