mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
more methods
This commit is contained in:
parent
175afa9fee
commit
081a61a438
11 changed files with 196 additions and 169 deletions
|
@ -29,6 +29,10 @@ message String {
|
|||
string val = 1;
|
||||
}
|
||||
|
||||
message Bytes {
|
||||
bytes val = 1;
|
||||
}
|
||||
|
||||
// New style RPC definitions
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -41,9 +45,16 @@ service BackendService {
|
|||
rpc SearchNotes (SearchNotesIn) returns (SearchNotesOut);
|
||||
rpc CheckMedia (Empty) returns (CheckMediaOut);
|
||||
rpc LocalMinutesWest (Int64) returns (Int32);
|
||||
rpc StripAvTags (String) returns (String);
|
||||
rpc StripAVTags (String) returns (String);
|
||||
rpc ExtractAVTags (ExtractAVTagsIn) returns (ExtractAVTagsOut);
|
||||
rpc ExtractLatex (ExtractLatexIn) returns (ExtractLatexOut);
|
||||
rpc DeckTreeLegacy (Empty) returns (Bytes);
|
||||
rpc CheckDatabase (Empty) returns (CheckDatabaseOut);
|
||||
rpc GetEmptyCards (Empty) returns (EmptyCardsReport);
|
||||
rpc SyncMedia (SyncMediaIn) returns (Empty);
|
||||
rpc TrashMediaFiles (TrashMediaFilesIn) returns (Empty);
|
||||
rpc GetDeckLegacy (Int64) returns (Bytes);
|
||||
rpc GetDeckIDByName (String) returns (Int64);
|
||||
}
|
||||
|
||||
// Protobuf stored in .anki2 files
|
||||
|
@ -290,8 +301,6 @@ message I18nBackendInit {
|
|||
message BackendInput {
|
||||
oneof value {
|
||||
AddMediaFileIn add_media_file = 26;
|
||||
SyncMediaIn sync_media = 27;
|
||||
TrashMediaFilesIn trash_media_files = 29;
|
||||
TranslateStringIn translate_string = 30;
|
||||
FormatTimeSpanIn format_time_span = 31;
|
||||
StudiedTodayIn studied_today = 32;
|
||||
|
@ -320,7 +329,6 @@ message BackendInput {
|
|||
int32 get_changed_notetypes = 56;
|
||||
AddOrUpdateNotetypeIn add_or_update_notetype = 57;
|
||||
Empty get_all_decks = 58;
|
||||
Empty check_database = 59;
|
||||
StockNoteType get_stock_notetype_legacy = 60;
|
||||
int64 get_notetype_legacy = 61;
|
||||
Empty get_notetype_names = 62;
|
||||
|
@ -331,14 +339,10 @@ message BackendInput {
|
|||
AddNoteIn add_note = 67;
|
||||
Note update_note = 68;
|
||||
int64 get_note = 69;
|
||||
Empty get_empty_cards = 70;
|
||||
int64 get_deck_legacy = 71;
|
||||
string get_deck_id_by_name = 72;
|
||||
GetDeckNamesIn get_deck_names = 73;
|
||||
AddOrUpdateDeckLegacyIn add_or_update_deck_legacy = 74;
|
||||
bool new_deck_legacy = 75;
|
||||
int64 remove_deck = 76;
|
||||
Empty deck_tree_legacy = 77;
|
||||
FieldNamesForNotesIn field_names_for_notes = 78;
|
||||
FindAndReplaceIn find_and_replace = 79;
|
||||
AfterNoteUpdatesIn after_note_updates = 80;
|
||||
|
@ -363,8 +367,6 @@ message BackendOutput {
|
|||
|
||||
// fallible commands
|
||||
string add_media_file = 26;
|
||||
Empty sync_media = 27;
|
||||
Empty trash_media_files = 29;
|
||||
Empty empty_trash = 34;
|
||||
Empty restore_trash = 35;
|
||||
Empty open_collection = 36;
|
||||
|
@ -388,7 +390,6 @@ message BackendOutput {
|
|||
bytes get_changed_notetypes = 56;
|
||||
int64 add_or_update_notetype = 57;
|
||||
bytes get_all_decks = 58;
|
||||
CheckDatabaseOut check_database = 59;
|
||||
bytes get_notetype_legacy = 61;
|
||||
NoteTypeNames get_notetype_names = 62;
|
||||
NoteTypeUseCounts get_notetype_names_and_counts = 63;
|
||||
|
@ -398,14 +399,10 @@ message BackendOutput {
|
|||
int64 add_note = 67;
|
||||
Empty update_note = 68;
|
||||
Note get_note = 69;
|
||||
EmptyCardsReport get_empty_cards = 70;
|
||||
bytes get_deck_legacy = 71;
|
||||
int64 get_deck_id_by_name = 72;
|
||||
DeckNames get_deck_names = 73;
|
||||
int64 add_or_update_deck_legacy = 74;
|
||||
bytes new_deck_legacy = 75;
|
||||
Empty remove_deck = 76;
|
||||
bytes deck_tree_legacy = 77;
|
||||
FieldNamesForNotesOut field_names_for_notes = 78;
|
||||
uint32 find_and_replace = 79;
|
||||
Empty after_note_updates = 80;
|
||||
|
|
|
@ -593,7 +593,7 @@ select id from notes where mid = ?) limit 1"""
|
|||
"""
|
||||
self.save(trx=False)
|
||||
try:
|
||||
problems = self.backend.check_database()
|
||||
problems = list(self.backend.check_database())
|
||||
ok = not problems
|
||||
problems.append(self.tr(TR.DATABASE_CHECK_REBUILT))
|
||||
except DBError as e:
|
||||
|
|
|
@ -11,7 +11,7 @@ import anki.backend_pb2 as pb
|
|||
from anki.consts import *
|
||||
from anki.errors import DeckRenameError
|
||||
from anki.lang import _
|
||||
from anki.rsbackend import DeckTreeNode
|
||||
from anki.rsbackend import DeckTreeNode, NotFoundError, from_json_bytes
|
||||
from anki.utils import ids2str, intTime
|
||||
|
||||
# legacy code may pass this in as the type argument to .id()
|
||||
|
@ -113,10 +113,13 @@ class DeckManager:
|
|||
)
|
||||
|
||||
def id_for_name(self, name: str) -> Optional[int]:
|
||||
return self.col.backend.get_deck_id_by_name(name)
|
||||
return self.col.backend.get_deck_id_by_name(name) or None
|
||||
|
||||
def get_legacy(self, did: int) -> Optional[Dict]:
|
||||
return self.col.backend.get_deck_legacy(did)
|
||||
try:
|
||||
return from_json_bytes(self.col.backend.get_deck_legacy(did))
|
||||
except NotFoundError:
|
||||
return None
|
||||
|
||||
def have(self, id: int) -> bool:
|
||||
return not self.get_legacy(int(id))
|
||||
|
|
|
@ -246,17 +246,6 @@ class RustBackend:
|
|||
)
|
||||
).add_media_file
|
||||
|
||||
def sync_media(self, hkey: str, endpoint: str) -> None:
|
||||
self._run_command(
|
||||
pb.BackendInput(sync_media=pb.SyncMediaIn(hkey=hkey, endpoint=endpoint,)),
|
||||
release_gil=True,
|
||||
)
|
||||
|
||||
def trash_media_files(self, fnames: List[str]) -> None:
|
||||
self._run_command(
|
||||
pb.BackendInput(trash_media_files=pb.TrashMediaFilesIn(fnames=fnames))
|
||||
)
|
||||
|
||||
def translate(self, key: TR, **kwargs: Union[str, int, float]) -> str:
|
||||
return self._run_command(
|
||||
pb.BackendInput(translate_string=translate_string_in(key, **kwargs))
|
||||
|
@ -506,20 +495,6 @@ class RustBackend:
|
|||
except NotFoundError:
|
||||
return None
|
||||
|
||||
def empty_cards_report(self) -> pb.EmptyCardsReport:
|
||||
return self._run_command(
|
||||
pb.BackendInput(get_empty_cards=pb.Empty()), release_gil=True
|
||||
).get_empty_cards
|
||||
|
||||
def get_deck_legacy(self, did: int) -> Optional[Dict]:
|
||||
try:
|
||||
bytes = self._run_command(
|
||||
pb.BackendInput(get_deck_legacy=did)
|
||||
).get_deck_legacy
|
||||
return orjson.loads(bytes)
|
||||
except NotFoundError:
|
||||
return None
|
||||
|
||||
def get_deck_names_and_ids(
|
||||
self, skip_empty_default: bool, include_filtered: bool = True
|
||||
) -> Sequence[pb.DeckNameID]:
|
||||
|
@ -551,30 +526,9 @@ class RustBackend:
|
|||
).new_deck_legacy
|
||||
return orjson.loads(jstr)
|
||||
|
||||
def get_deck_id_by_name(self, name: str) -> Optional[int]:
|
||||
return (
|
||||
self._run_command(
|
||||
pb.BackendInput(get_deck_id_by_name=name)
|
||||
).get_deck_id_by_name
|
||||
or None
|
||||
)
|
||||
|
||||
def remove_deck(self, did: int) -> None:
|
||||
self._run_command(pb.BackendInput(remove_deck=did))
|
||||
|
||||
def check_database(self) -> List[str]:
|
||||
return list(
|
||||
self._run_command(
|
||||
pb.BackendInput(check_database=pb.Empty()), release_gil=True
|
||||
).check_database.problems
|
||||
)
|
||||
|
||||
def legacy_deck_tree(self) -> Sequence:
|
||||
bytes = self._run_command(
|
||||
pb.BackendInput(deck_tree_legacy=pb.Empty())
|
||||
).deck_tree_legacy
|
||||
return orjson.loads(bytes)[5]
|
||||
|
||||
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)),
|
||||
|
@ -725,7 +679,7 @@ class RustBackend:
|
|||
output.ParseFromString(self._run_command2(9, input))
|
||||
return output.val
|
||||
|
||||
def extract_a_v_tags(self, text: str, question_side: bool) -> pb.ExtractAVTagsOut:
|
||||
def extract_av_tags(self, text: str, question_side: bool) -> pb.ExtractAVTagsOut:
|
||||
input = pb.ExtractAVTagsIn(text=text, question_side=question_side)
|
||||
output = pb.ExtractAVTagsOut()
|
||||
output.ParseFromString(self._run_command2(10, input))
|
||||
|
@ -739,6 +693,48 @@ class RustBackend:
|
|||
output.ParseFromString(self._run_command2(11, input))
|
||||
return output
|
||||
|
||||
def deck_tree_legacy(self) -> bytes:
|
||||
input = pb.Empty()
|
||||
output = pb.Bytes()
|
||||
output.ParseFromString(self._run_command2(12, input))
|
||||
return output.val
|
||||
|
||||
def check_database(self) -> Sequence[str]:
|
||||
input = pb.Empty()
|
||||
output = pb.CheckDatabaseOut()
|
||||
output.ParseFromString(self._run_command2(13, input))
|
||||
return output.problems
|
||||
|
||||
def get_empty_cards(self) -> pb.EmptyCardsReport:
|
||||
input = pb.Empty()
|
||||
output = pb.EmptyCardsReport()
|
||||
output.ParseFromString(self._run_command2(14, input))
|
||||
return output
|
||||
|
||||
def sync_media(self, hkey: str, endpoint: str) -> pb.Empty:
|
||||
input = pb.SyncMediaIn(hkey=hkey, endpoint=endpoint)
|
||||
output = pb.Empty()
|
||||
output.ParseFromString(self._run_command2(15, input))
|
||||
return output
|
||||
|
||||
def trash_media_files(self, fnames: Sequence[str]) -> pb.Empty:
|
||||
input = pb.TrashMediaFilesIn(fnames=fnames)
|
||||
output = pb.Empty()
|
||||
output.ParseFromString(self._run_command2(16, input))
|
||||
return output
|
||||
|
||||
def get_deck_legacy(self, val: int) -> bytes:
|
||||
input = pb.Int64(val=val)
|
||||
output = pb.Bytes()
|
||||
output.ParseFromString(self._run_command2(17, input))
|
||||
return output.val
|
||||
|
||||
def get_deck_id_by_name(self, val: str) -> int:
|
||||
input = pb.String(val=val)
|
||||
output = pb.Int64()
|
||||
output.ParseFromString(self._run_command2(18, input))
|
||||
return output.val
|
||||
|
||||
# @@AUTOGEN@@
|
||||
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ order by due"""
|
|||
print(
|
||||
"deckDueTree() is deprecated; use decks.deck_tree() for a tree without counts, or sched.deck_due_tree()"
|
||||
)
|
||||
return self.col.backend.legacy_deck_tree()
|
||||
return self.col.backend.deck_tree_legacy()
|
||||
|
||||
def deck_due_tree(self, top_deck_id: int = 0) -> DeckTreeNode:
|
||||
"""Returns a tree of decks with counts.
|
||||
|
|
|
@ -215,10 +215,10 @@ class TemplateRenderContext:
|
|||
)
|
||||
|
||||
qtext = apply_custom_filters(partial.qnodes, self, front_side=None)
|
||||
qout = self.col().backend.extract_a_v_tags(qtext, True)
|
||||
qout = self.col().backend.extract_av_tags(qtext, True)
|
||||
|
||||
atext = apply_custom_filters(partial.anodes, self, front_side=qtext)
|
||||
aout = self.col().backend.extract_a_v_tags(atext, False)
|
||||
aout = self.col().backend.extract_av_tags(atext, False)
|
||||
|
||||
output = TemplateRenderOutput(
|
||||
question_text=qout.text,
|
||||
|
|
|
@ -51,7 +51,7 @@ def test_genrem():
|
|||
t = m["tmpls"][1]
|
||||
t["qfmt"] = "{{Back}}"
|
||||
mm.save(m, templates=True)
|
||||
rep = d.backend.empty_cards_report()
|
||||
rep = d.backend.get_empty_cards()
|
||||
for note in rep.notes:
|
||||
d.remCards(note.card_ids)
|
||||
assert len(f.cards()) == 1
|
||||
|
|
|
@ -55,6 +55,17 @@ def python_type_inner(field):
|
|||
raise Exception(f"unknown type: {type}")
|
||||
|
||||
|
||||
# get_deck_i_d -> get_deck_id etc
|
||||
def fix_snakecase(name):
|
||||
for fix in "a_v", "i_d":
|
||||
name = re.sub(
|
||||
f"(\w)({fix})(\w)",
|
||||
lambda m: m.group(1) + m.group(2).replace("_", "") + m.group(3),
|
||||
name,
|
||||
)
|
||||
return name
|
||||
|
||||
|
||||
def get_input_args(msg):
|
||||
fields = sorted(msg.fields, key=lambda x: x.number)
|
||||
return ", ".join(["self"] + [f"{f.name}: {python_type(f)}" for f in fields])
|
||||
|
@ -68,7 +79,7 @@ def get_input_assign(msg):
|
|||
def render_method(method, idx):
|
||||
input_args = get_input_args(method.input_type)
|
||||
input_assign = get_input_assign(method.input_type)
|
||||
name = stringcase.snakecase(method.name)
|
||||
name = fix_snakecase(stringcase.snakecase(method.name))
|
||||
if len(method.output_type.fields) == 1:
|
||||
# unwrap single return arg
|
||||
f = method.output_type.fields[0]
|
||||
|
|
|
@ -24,7 +24,7 @@ def show_empty_cards(mw: aqt.main.AnkiQt) -> None:
|
|||
diag = EmptyCardsDialog(mw, report)
|
||||
diag.show()
|
||||
|
||||
mw.taskman.run_in_background(mw.col.backend.empty_cards_report, on_done)
|
||||
mw.taskman.run_in_background(mw.col.backend.get_empty_cards, on_done)
|
||||
|
||||
|
||||
class EmptyCardsDialog(QDialog):
|
||||
|
|
|
@ -11,6 +11,7 @@ from typing import List
|
|||
import anki
|
||||
import aqt
|
||||
from anki.sound import SoundOrVideoTag
|
||||
from anki.template import av_tags_to_native
|
||||
from aqt.theme import theme_manager
|
||||
|
||||
# Routines removed from pylib/
|
||||
|
@ -24,8 +25,12 @@ def bodyClass(col, card) -> str:
|
|||
|
||||
def allSounds(text) -> List:
|
||||
print("allSounds() deprecated")
|
||||
text, tags = aqt.mw.col.backend.extract_av_tags(text, True)
|
||||
return [x.filename for x in tags if isinstance(x, SoundOrVideoTag)]
|
||||
out = aqt.mw.col.backend.extract_av_tags(text, True)
|
||||
return [
|
||||
x.filename
|
||||
for x in av_tags_to_native(out.av_tags)
|
||||
if isinstance(x, SoundOrVideoTag)
|
||||
]
|
||||
|
||||
|
||||
def stripSounds(text) -> str:
|
||||
|
|
|
@ -147,6 +147,30 @@ pub fn init_backend(init_msg: &[u8]) -> std::result::Result<Backend, String> {
|
|||
Ok(Backend::new(i18n, input.server))
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for pb::Bytes {
|
||||
fn from(val: Vec<u8>) -> Self {
|
||||
pb::Bytes { val }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for pb::String {
|
||||
fn from(val: String) -> Self {
|
||||
pb::String { val }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for pb::Int64 {
|
||||
fn from(val: i64) -> Self {
|
||||
pb::Int64 { val }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<()> for pb::Empty {
|
||||
fn from(_val: ()) -> Self {
|
||||
pb::Empty {}
|
||||
}
|
||||
}
|
||||
|
||||
impl BackendService for Backend {
|
||||
fn render_existing_card(
|
||||
&mut self,
|
||||
|
@ -310,6 +334,92 @@ impl BackendService for Backend {
|
|||
.collect(),
|
||||
})
|
||||
}
|
||||
|
||||
fn check_database(&mut self, _input: pb::Empty) -> BackendResult<pb::CheckDatabaseOut> {
|
||||
self.with_col(|col| {
|
||||
col.check_database().map(|problems| pb::CheckDatabaseOut {
|
||||
problems: problems.to_i18n_strings(&col.i18n),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn deck_tree_legacy(&mut self, _input: pb::Empty) -> BackendResult<pb::Bytes> {
|
||||
self.with_col(|col| {
|
||||
let tree = col.legacy_deck_tree()?;
|
||||
serde_json::to_vec(&tree)
|
||||
.map_err(Into::into)
|
||||
.map(Into::into)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_empty_cards(&mut self, _input: pb::Empty) -> Result<pb::EmptyCardsReport> {
|
||||
self.with_col(|col| {
|
||||
let mut empty = col.empty_cards()?;
|
||||
let report = col.empty_cards_report(&mut empty)?;
|
||||
|
||||
let mut outnotes = vec![];
|
||||
for (_ntid, notes) in empty {
|
||||
outnotes.extend(notes.into_iter().map(|e| pb::NoteWithEmptyCards {
|
||||
note_id: e.nid.0,
|
||||
will_delete_note: e.empty.len() == e.current_count,
|
||||
card_ids: e.empty.into_iter().map(|(_ord, id)| id.0).collect(),
|
||||
}))
|
||||
}
|
||||
Ok(pb::EmptyCardsReport {
|
||||
report,
|
||||
notes: outnotes,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn get_deck_legacy(&mut self, input: pb::Int64) -> Result<pb::Bytes> {
|
||||
self.with_col(|col| {
|
||||
let deck: DeckSchema11 = col
|
||||
.storage
|
||||
.get_deck(DeckID(input.val))?
|
||||
.ok_or(AnkiError::NotFound)?
|
||||
.into();
|
||||
serde_json::to_vec(&deck)
|
||||
.map_err(Into::into)
|
||||
.map(Into::into)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_deck_id_by_name(&mut self, input: pb::String) -> Result<pb::Int64> {
|
||||
self.with_col(|col| {
|
||||
col.get_deck_id(&input.val)
|
||||
.map(|d| d.map(|d| d.0).unwrap_or_default())
|
||||
.map(Into::into)
|
||||
})
|
||||
}
|
||||
|
||||
fn sync_media(&mut self, input: SyncMediaIn) -> BackendResult<Empty> {
|
||||
let mut guard = self.col.lock().unwrap();
|
||||
|
||||
let col = guard.as_mut().unwrap();
|
||||
col.set_media_sync_running()?;
|
||||
|
||||
let folder = col.media_folder.clone();
|
||||
let db = col.media_db.clone();
|
||||
let log = col.log.clone();
|
||||
|
||||
drop(guard);
|
||||
|
||||
let res = self.sync_media_inner(input, folder, db, log);
|
||||
|
||||
self.with_col(|col| col.set_media_sync_finished())?;
|
||||
|
||||
res.map(Into::into)
|
||||
}
|
||||
|
||||
fn trash_media_files(&mut self, input: pb::TrashMediaFilesIn) -> BackendResult<Empty> {
|
||||
self.with_col(|col| {
|
||||
let mgr = MediaManager::new(&col.media_folder, &col.media_db)?;
|
||||
let mut ctx = mgr.dbctx();
|
||||
mgr.remove_files(&mut ctx, &input.fnames)
|
||||
})
|
||||
.map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
|
@ -403,14 +513,6 @@ impl Backend {
|
|||
use pb::backend_output::Value as OValue;
|
||||
Ok(match ival {
|
||||
Value::AddMediaFile(input) => OValue::AddMediaFile(self.add_media_file(input)?),
|
||||
Value::SyncMedia(input) => {
|
||||
self.sync_media(input)?;
|
||||
OValue::SyncMedia(Empty {})
|
||||
}
|
||||
Value::TrashMediaFiles(input) => {
|
||||
self.remove_media_files(&input.fnames)?;
|
||||
OValue::TrashMediaFiles(Empty {})
|
||||
}
|
||||
Value::TranslateString(input) => OValue::TranslateString(self.translate_string(input)),
|
||||
Value::FormatTimeSpan(input) => OValue::FormatTimeSpan(self.format_time_span(input)),
|
||||
Value::StudiedToday(input) => OValue::StudiedToday(studied_today(
|
||||
|
@ -509,11 +611,6 @@ impl Backend {
|
|||
OValue::UpdateNote(pb::Empty {})
|
||||
}
|
||||
Value::GetNote(nid) => OValue::GetNote(self.get_note(nid)?),
|
||||
Value::GetEmptyCards(_) => OValue::GetEmptyCards(self.get_empty_cards()?),
|
||||
Value::GetDeckLegacy(did) => OValue::GetDeckLegacy(self.get_deck_legacy(did)?),
|
||||
Value::GetDeckIdByName(name) => {
|
||||
OValue::GetDeckIdByName(self.get_deck_id_by_name(&name)?)
|
||||
}
|
||||
Value::GetDeckNames(input) => OValue::GetDeckNames(self.get_deck_names(input)?),
|
||||
Value::AddOrUpdateDeckLegacy(input) => {
|
||||
OValue::AddOrUpdateDeckLegacy(self.add_or_update_deck_legacy(input)?)
|
||||
|
@ -526,8 +623,6 @@ impl Backend {
|
|||
self.remove_deck(did)?;
|
||||
pb::Empty {}
|
||||
}),
|
||||
Value::CheckDatabase(_) => OValue::CheckDatabase(self.check_database()?),
|
||||
Value::DeckTreeLegacy(_) => OValue::DeckTreeLegacy(self.deck_tree_legacy()?),
|
||||
Value::FieldNamesForNotes(input) => {
|
||||
OValue::FieldNamesForNotes(self.field_names_for_notes(input)?)
|
||||
}
|
||||
|
@ -625,25 +720,6 @@ impl Backend {
|
|||
})
|
||||
}
|
||||
|
||||
fn sync_media(&mut self, input: SyncMediaIn) -> Result<()> {
|
||||
let mut guard = self.col.lock().unwrap();
|
||||
|
||||
let col = guard.as_mut().unwrap();
|
||||
col.set_media_sync_running()?;
|
||||
|
||||
let folder = col.media_folder.clone();
|
||||
let db = col.media_db.clone();
|
||||
let log = col.log.clone();
|
||||
|
||||
drop(guard);
|
||||
|
||||
let res = self.sync_media_inner(input, folder, db, log);
|
||||
|
||||
self.with_col(|col| col.set_media_sync_finished())?;
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn sync_media_inner(
|
||||
&mut self,
|
||||
input: pb::SyncMediaIn,
|
||||
|
@ -679,14 +755,6 @@ impl Backend {
|
|||
}
|
||||
}
|
||||
|
||||
fn remove_media_files(&self, fnames: &[String]) -> Result<()> {
|
||||
self.with_col(|col| {
|
||||
let mgr = MediaManager::new(&col.media_folder, &col.media_db)?;
|
||||
let mut ctx = mgr.dbctx();
|
||||
mgr.remove_files(&mut ctx, fnames)
|
||||
})
|
||||
}
|
||||
|
||||
fn translate_string(&self, input: pb::TranslateStringIn) -> String {
|
||||
let key = match pb::FluentString::from_i32(input.key) {
|
||||
Some(key) => key,
|
||||
|
@ -1010,44 +1078,6 @@ impl Backend {
|
|||
})
|
||||
}
|
||||
|
||||
fn get_empty_cards(&self) -> Result<pb::EmptyCardsReport> {
|
||||
self.with_col(|col| {
|
||||
let mut empty = col.empty_cards()?;
|
||||
let report = col.empty_cards_report(&mut empty)?;
|
||||
|
||||
let mut outnotes = vec![];
|
||||
for (_ntid, notes) in empty {
|
||||
outnotes.extend(notes.into_iter().map(|e| pb::NoteWithEmptyCards {
|
||||
note_id: e.nid.0,
|
||||
will_delete_note: e.empty.len() == e.current_count,
|
||||
card_ids: e.empty.into_iter().map(|(_ord, id)| id.0).collect(),
|
||||
}))
|
||||
}
|
||||
Ok(pb::EmptyCardsReport {
|
||||
report,
|
||||
notes: outnotes,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn get_deck_legacy(&self, did: i64) -> Result<Vec<u8>> {
|
||||
self.with_col(|col| {
|
||||
let deck: DeckSchema11 = col
|
||||
.storage
|
||||
.get_deck(DeckID(did))?
|
||||
.ok_or(AnkiError::NotFound)?
|
||||
.into();
|
||||
serde_json::to_vec(&deck).map_err(Into::into)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_deck_id_by_name(&self, human_name: &str) -> Result<i64> {
|
||||
self.with_col(|col| {
|
||||
col.get_deck_id(human_name)
|
||||
.map(|d| d.map(|d| d.0).unwrap_or_default())
|
||||
})
|
||||
}
|
||||
|
||||
fn get_deck_names(&self, input: pb::GetDeckNamesIn) -> Result<pb::DeckNames> {
|
||||
self.with_col(|col| {
|
||||
let names = if input.include_filtered {
|
||||
|
@ -1094,21 +1124,6 @@ impl Backend {
|
|||
self.with_col(|col| col.remove_deck_and_child_decks(DeckID(did)))
|
||||
}
|
||||
|
||||
fn check_database(&self) -> Result<pb::CheckDatabaseOut> {
|
||||
self.with_col(|col| {
|
||||
col.check_database().map(|problems| pb::CheckDatabaseOut {
|
||||
problems: problems.to_i18n_strings(&col.i18n),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn deck_tree_legacy(&self) -> Result<Vec<u8>> {
|
||||
self.with_col(|col| {
|
||||
let tree = col.legacy_deck_tree()?;
|
||||
serde_json::to_vec(&tree).map_err(Into::into)
|
||||
})
|
||||
}
|
||||
|
||||
fn field_names_for_notes(
|
||||
&self,
|
||||
input: pb::FieldNamesForNotesIn,
|
||||
|
|
Loading…
Reference in a new issue