update_card()

This commit is contained in:
Damien Elmes 2020-03-26 18:54:20 +10:00
parent 1acfe7d3cc
commit 47504245dc
6 changed files with 115 additions and 30 deletions

View file

@ -48,6 +48,7 @@ message BackendInput {
OpenCollectionIn open_collection = 36;
Empty close_collection = 37;
int64 get_card = 38;
Card update_card = 39;
}
}
@ -79,6 +80,7 @@ message BackendOutput {
Empty open_collection = 36;
Empty close_collection = 37;
GetCardOut get_card = 38;
Empty update_card = 39;
BackendError error = 2047;
}

View file

@ -12,6 +12,7 @@ from anki import hooks
from anki.consts import *
from anki.models import NoteType, Template
from anki.notes import Note
from anki.rsbackend import BackendCard
from anki.sound import AVTag
from anki.utils import intTime, joinFields, timestampID
@ -33,9 +34,7 @@ class Card:
lastIvl: int
ord: int
def __init__(
self, col: anki.storage._Collection, id: Optional[int] = None
) -> None:
def __init__(self, col: anki.storage._Collection, id: Optional[int] = None) -> None:
self.col = col.weakref()
self.timerStarted = None
self._render_output: Optional[anki.template.TemplateRenderOutput] = None
@ -98,30 +97,27 @@ class Card:
def flush(self) -> None:
self._preFlush()
self.col.db.execute(
"""
insert or replace into cards values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
self.id,
self.nid,
self.did,
self.ord,
self.mod,
self.usn,
self.type,
self.queue,
self.due,
self.ivl,
self.factor,
self.reps,
self.lapses,
self.left,
self.odue,
self.odid,
self.flags,
self.data,
card = BackendCard(
id=self.id,
nid=self.nid,
did=self.did,
ord=self.ord,
mtime=self.mod,
usn=self.usn,
ctype=self.type,
queue=self.queue,
due=self.due,
ivl=self.ivl,
factor=self.factor,
reps=self.reps,
lapses=self.lapses,
left=self.left,
odue=self.odue,
odid=self.odid,
flags=self.flags,
data=self.data,
)
self.col.log(self)
self.col.backend.update_card(card)
def question(self, reload: bool = False, browser: bool = False) -> str:
return self.css() + self.render_output(reload, browser).question_text

View file

@ -36,6 +36,7 @@ assert ankirspy.buildhash() == anki.buildinfo.buildhash
SchedTimingToday = pb.SchedTimingTodayOut
BuiltinSortKind = pb.BuiltinSortKind
BackendCard = pb.Card
try:
import orjson
@ -481,9 +482,11 @@ class RustBackend:
).search_notes.note_ids
def get_card(self, cid: int) -> Optional[pb.Card]:
return self._run_command(
pb.BackendInput(get_card=cid)
).get_card.card
return self._run_command(pb.BackendInput(get_card=cid)).get_card.card
def update_card(self, card: BackendCard) -> None:
self._run_command(pb.BackendInput(update_card=card))
def translate_string_in(
key: TR, **kwargs: Union[str, int, float]

View file

@ -5,8 +5,10 @@ use crate::backend::dbproxy::db_command_bytes;
use crate::backend_proto::backend_input::Value;
use crate::backend_proto::{BuiltinSortKind, Empty, RenderedTemplateReplacement, SyncMediaIn};
use crate::card::{Card, CardID};
use crate::card::{CardQueue, CardType};
use crate::collection::{open_collection, Collection};
use crate::config::SortKind;
use crate::decks::DeckID;
use crate::err::{AnkiError, NetworkErrorKind, Result, SyncErrorKind};
use crate::i18n::{tr_args, FString, I18n};
use crate::latex::{extract_latex, extract_latex_expanding_clozes, ExtractedLatex};
@ -14,6 +16,7 @@ use crate::log::{default_logger, Logger};
use crate::media::check::MediaChecker;
use crate::media::sync::MediaSyncProgress;
use crate::media::MediaManager;
use crate::notes::NoteID;
use crate::sched::cutoff::{local_minutes_west_for_stamp, sched_timing_today};
use crate::sched::timespan::{answer_button_time, learning_congrats, studied_today, time_span};
use crate::search::{search_cards, search_notes, SortMode};
@ -22,10 +25,13 @@ use crate::template::{
RenderedNode,
};
use crate::text::{extract_av_tags, strip_av_tags, AVTag};
use crate::timestamp::TimestampSecs;
use crate::types::Usn;
use crate::{backend_proto as pb, log};
use fluent::FluentValue;
use prost::Message;
use std::collections::{HashMap, HashSet};
use std::convert::TryFrom;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use tokio::runtime::Runtime;
@ -250,6 +256,10 @@ impl Backend {
Value::SearchCards(input) => OValue::SearchCards(self.search_cards(input)?),
Value::SearchNotes(input) => OValue::SearchNotes(self.search_notes(input)?),
Value::GetCard(cid) => OValue::GetCard(self.get_card(cid)?),
Value::UpdateCard(card) => {
self.update_card(card)?;
OValue::UpdateCard(pb::Empty {})
}
})
}
@ -625,6 +635,11 @@ impl Backend {
card: card.map(card_to_pb),
})
}
fn update_card(&self, pbcard: pb::Card) -> Result<()> {
let card = pbcard_to_native(pbcard);
self.with_col(|col| col.with_ctx(|ctx| ctx.storage.update_card(&card)))
}
}
fn translate_arg_to_fluent_val(arg: &pb::TranslateArgValue) -> FluentValue {
@ -740,3 +755,26 @@ fn card_to_pb(c: Card) -> pb::Card {
data: c.data,
}
}
fn pbcard_to_native(c: pb::Card) -> Card {
Card {
id: CardID(c.id),
nid: NoteID(c.nid),
did: DeckID(c.did),
ord: c.ord as u16,
mtime: TimestampSecs(c.mtime),
usn: Usn(c.usn),
ctype: CardType::try_from(c.ctype as u8).unwrap_or(CardType::New),
queue: CardQueue::try_from(c.queue as i8).unwrap_or(CardQueue::New),
due: c.due,
ivl: c.ivl,
factor: c.factor as u16,
reps: c.reps,
lapses: c.lapses,
left: c.left,
odue: c.odue,
odid: DeckID(c.odid),
flags: c.flags,
data: c.data,
}
}

View file

@ -3,7 +3,7 @@
use crate::cached_sql;
use crate::card::{Card, CardID, CardQueue, CardType};
use crate::err::Result;
use crate::err::{AnkiError, Result};
use rusqlite::params;
use rusqlite::{
types::{FromSql, FromSqlError, ValueRef},
@ -69,4 +69,48 @@ flags, data from cards where id=?"
.optional()
.map_err(Into::into)
}
pub(crate) fn update_card(&mut self, card: &Card) -> Result<()> {
if card.id.0 == 0 {
return Err(AnkiError::invalid_input("card id not set"));
}
self.flush_card(card)
}
fn flush_card(&mut self, card: &Card) -> Result<()> {
let stmt = cached_sql!(
self.update_card_stmt,
self.db,
"
insert or replace into cards
(id, nid, did, ord, mod, usn, type, queue, due, ivl, factor,
reps, lapses, left, odue, odid, flags, data)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"
);
stmt.execute(params![
card.id,
card.nid,
card.did,
card.ord,
card.mtime,
card.usn,
card.ctype as u8,
card.queue as i8,
card.due,
card.ivl,
card.factor,
card.reps,
card.lapses,
card.left,
card.odue,
card.odid,
card.flags,
card.data,
])?;
Ok(())
}
}

View file

@ -224,6 +224,7 @@ pub(crate) struct StorageContext<'a> {
// cards
pub(super) get_card_stmt: Option<rusqlite::CachedStatement<'a>>,
pub(super) update_card_stmt: Option<rusqlite::CachedStatement<'a>>,
}
impl StorageContext<'_> {
@ -234,6 +235,7 @@ impl StorageContext<'_> {
usn: None,
timing_today: None,
get_card_stmt: None,
update_card_stmt: None,
}
}