mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
embed deck config and expose to frontend
This commit is contained in:
parent
037df9522b
commit
42a4d11416
6 changed files with 103 additions and 74 deletions
|
@ -39,7 +39,7 @@ from anki.cards import Card, CardId
|
|||
from anki.config import Config, ConfigManager
|
||||
from anki.consts import *
|
||||
from anki.dbproxy import DBProxy
|
||||
from anki.decks import Deck, DeckId, DeckManager
|
||||
from anki.decks import Deck, DeckConfig, DeckConfigId, DeckId, DeckManager
|
||||
from anki.errors import AbortSchemaModification, DBError
|
||||
from anki.lang import FormatTimeSpan
|
||||
from anki.media import MediaManager, media_paths_from_col_path
|
||||
|
@ -335,6 +335,10 @@ class Collection:
|
|||
"Get a new-style deck object. Currently read-only."
|
||||
return self._backend.get_deck(id)
|
||||
|
||||
def get_deck_config(self, id: DeckConfigId) -> DeckConfig:
|
||||
"Get a new-style deck config object. Currently read-only."
|
||||
return self._backend.get_deck_config(id)
|
||||
|
||||
def get_notetype(self, id: NotetypeId) -> Notetype:
|
||||
"""Get a new-style notetype object. This is not cached; avoid calling frequently."""
|
||||
return self._backend.get_notetype(id)
|
||||
|
|
|
@ -32,12 +32,13 @@ DeckConfigDict = Dict[str, Any]
|
|||
|
||||
# currently only supports read-only access
|
||||
Deck = _pb.Deck
|
||||
DeckConfig = _pb.DeckConfig
|
||||
|
||||
DeckId = NewType("DeckId", int)
|
||||
DeckConfId = NewType("DeckConfId", int)
|
||||
DeckConfigId = NewType("DeckConfigId", int)
|
||||
|
||||
DEFAULT_DECK_ID = DeckId(1)
|
||||
DEFAULT_DECK_CONF_ID = DeckConfId(1)
|
||||
DEFAULT_DECK_CONF_ID = DeckConfigId(1)
|
||||
|
||||
|
||||
class DecksDictProxy:
|
||||
|
@ -128,7 +129,7 @@ class DeckManager:
|
|||
self,
|
||||
name: str,
|
||||
create: bool = True,
|
||||
type: DeckConfId = DeckConfId(0),
|
||||
type: DeckConfigId = DeckConfigId(0),
|
||||
) -> Optional[DeckId]:
|
||||
"Add a deck with NAME. Reuse deck if already exists. Return id as int."
|
||||
id = self.id_for_name(name)
|
||||
|
@ -323,7 +324,7 @@ class DeckManager:
|
|||
deck = self.get(did, default=False)
|
||||
assert deck
|
||||
if "conf" in deck:
|
||||
dcid = DeckConfId(int(deck["conf"])) # may be a string
|
||||
dcid = DeckConfigId(int(deck["conf"])) # may be a string
|
||||
conf = self.get_config(dcid)
|
||||
if not conf:
|
||||
# fall back on default
|
||||
|
@ -333,7 +334,7 @@ class DeckManager:
|
|||
# dynamic decks have embedded conf
|
||||
return deck
|
||||
|
||||
def get_config(self, conf_id: DeckConfId) -> Optional[DeckConfigDict]:
|
||||
def get_config(self, conf_id: DeckConfigId) -> Optional[DeckConfigDict]:
|
||||
try:
|
||||
return from_json_bytes(self.col._backend.get_deck_config_legacy(conf_id))
|
||||
except NotFoundError:
|
||||
|
@ -358,10 +359,10 @@ class DeckManager:
|
|||
|
||||
def add_config_returning_id(
|
||||
self, name: str, clone_from: Optional[DeckConfigDict] = None
|
||||
) -> DeckConfId:
|
||||
) -> DeckConfigId:
|
||||
return self.add_config(name, clone_from)["id"]
|
||||
|
||||
def remove_config(self, id: DeckConfId) -> None:
|
||||
def remove_config(self, id: DeckConfigId) -> None:
|
||||
"Remove a configuration and update all decks using it."
|
||||
self.col.modSchema(check=True)
|
||||
for g in self.all():
|
||||
|
@ -373,7 +374,7 @@ class DeckManager:
|
|||
self.save(g)
|
||||
self.col._backend.remove_deck_config(id)
|
||||
|
||||
def setConf(self, grp: DeckConfigDict, id: DeckConfId) -> None:
|
||||
def setConf(self, grp: DeckConfigDict, id: DeckConfigId) -> None:
|
||||
grp["conf"] = id
|
||||
self.save(grp)
|
||||
|
||||
|
|
|
@ -219,6 +219,7 @@ service CardRenderingService {
|
|||
service DeckConfigService {
|
||||
rpc AddOrUpdateDeckConfigLegacy(AddOrUpdateDeckConfigLegacyIn)
|
||||
returns (DeckConfigId);
|
||||
rpc GetDeckConfig(DeckConfigId) returns (DeckConfig);
|
||||
rpc AllDeckConfigLegacy(Empty) returns (Json);
|
||||
rpc GetDeckConfigLegacy(DeckConfigId) returns (Json);
|
||||
rpc NewDeckConfigLegacy(Empty) returns (Json);
|
||||
|
@ -294,71 +295,76 @@ service CardsService {
|
|||
// These should be moved to a separate file in the future
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
message DeckConfigInner {
|
||||
enum NewCardOrder {
|
||||
NEW_CARD_ORDER_DUE = 0;
|
||||
NEW_CARD_ORDER_RANDOM = 1;
|
||||
}
|
||||
enum ReviewCardOrder {
|
||||
REVIEW_CARD_ORDER_SHUFFLED_BY_DAY = 0;
|
||||
REVIEW_CARD_ORDER_SHUFFLED = 1;
|
||||
REVIEW_CARD_ORDER_INTERVALS_ASCENDING = 2;
|
||||
REVIEW_CARD_ORDER_INTERVALS_DESCENDING = 3;
|
||||
}
|
||||
enum ReviewMix {
|
||||
REVIEW_MIX_MIX_WITH_REVIEWS = 0;
|
||||
REVIEW_MIX_AFTER_REVIEWS = 1;
|
||||
REVIEW_MIX_BEFORE_REVIEWS = 2;
|
||||
}
|
||||
enum LeechAction {
|
||||
LEECH_ACTION_SUSPEND = 0;
|
||||
LEECH_ACTION_TAG_ONLY = 1;
|
||||
message DeckConfig {
|
||||
message Config {
|
||||
enum NewCardOrder {
|
||||
NEW_CARD_ORDER_DUE = 0;
|
||||
NEW_CARD_ORDER_RANDOM = 1;
|
||||
}
|
||||
enum ReviewCardOrder {
|
||||
REVIEW_CARD_ORDER_SHUFFLED_BY_DAY = 0;
|
||||
REVIEW_CARD_ORDER_SHUFFLED = 1;
|
||||
REVIEW_CARD_ORDER_INTERVALS_ASCENDING = 2;
|
||||
REVIEW_CARD_ORDER_INTERVALS_DESCENDING = 3;
|
||||
}
|
||||
enum ReviewMix {
|
||||
REVIEW_MIX_MIX_WITH_REVIEWS = 0;
|
||||
REVIEW_MIX_AFTER_REVIEWS = 1;
|
||||
REVIEW_MIX_BEFORE_REVIEWS = 2;
|
||||
}
|
||||
enum LeechAction {
|
||||
LEECH_ACTION_SUSPEND = 0;
|
||||
LEECH_ACTION_TAG_ONLY = 1;
|
||||
}
|
||||
|
||||
repeated float learn_steps = 1;
|
||||
repeated float relearn_steps = 2;
|
||||
|
||||
reserved 3 to 8;
|
||||
|
||||
uint32 new_per_day = 9;
|
||||
uint32 reviews_per_day = 10;
|
||||
uint32 new_per_day_minimum = 29;
|
||||
|
||||
float initial_ease = 11;
|
||||
float easy_multiplier = 12;
|
||||
float hard_multiplier = 13;
|
||||
float lapse_multiplier = 14;
|
||||
float interval_multiplier = 15;
|
||||
|
||||
uint32 maximum_review_interval = 16;
|
||||
uint32 minimum_lapse_interval = 17;
|
||||
|
||||
uint32 graduating_interval_good = 18;
|
||||
uint32 graduating_interval_easy = 19;
|
||||
|
||||
NewCardOrder new_card_order = 20;
|
||||
ReviewCardOrder review_order = 32;
|
||||
|
||||
ReviewMix new_mix = 30;
|
||||
ReviewMix interday_learning_mix = 31;
|
||||
|
||||
LeechAction leech_action = 21;
|
||||
uint32 leech_threshold = 22;
|
||||
|
||||
bool disable_autoplay = 23;
|
||||
uint32 cap_answer_time_to_secs = 24;
|
||||
uint32 visible_timer_secs = 25;
|
||||
bool skip_question_when_replaying_answer = 26;
|
||||
|
||||
bool bury_new = 27;
|
||||
bool bury_reviews = 28;
|
||||
|
||||
bytes other = 255;
|
||||
}
|
||||
|
||||
repeated float learn_steps = 1;
|
||||
repeated float relearn_steps = 2;
|
||||
|
||||
reserved 3 to 8;
|
||||
|
||||
uint32 new_per_day = 9;
|
||||
uint32 reviews_per_day = 10;
|
||||
uint32 new_per_day_minimum = 29;
|
||||
|
||||
float initial_ease = 11;
|
||||
float easy_multiplier = 12;
|
||||
float hard_multiplier = 13;
|
||||
float lapse_multiplier = 14;
|
||||
float interval_multiplier = 15;
|
||||
|
||||
uint32 maximum_review_interval = 16;
|
||||
uint32 minimum_lapse_interval = 17;
|
||||
|
||||
uint32 graduating_interval_good = 18;
|
||||
uint32 graduating_interval_easy = 19;
|
||||
|
||||
NewCardOrder new_card_order = 20;
|
||||
ReviewCardOrder review_order = 32;
|
||||
|
||||
ReviewMix new_mix = 30;
|
||||
ReviewMix interday_learning_mix = 31;
|
||||
|
||||
LeechAction leech_action = 21;
|
||||
uint32 leech_threshold = 22;
|
||||
|
||||
bool disable_autoplay = 23;
|
||||
uint32 cap_answer_time_to_secs = 24;
|
||||
uint32 visible_timer_secs = 25;
|
||||
bool skip_question_when_replaying_answer = 26;
|
||||
|
||||
bool bury_new = 27;
|
||||
bool bury_reviews = 28;
|
||||
|
||||
bytes other = 255;
|
||||
int64 id = 1;
|
||||
string name = 2;
|
||||
int64 mtime_secs = 3;
|
||||
int32 usn = 4;
|
||||
Config config = 5;
|
||||
}
|
||||
|
||||
// Containers for passing around database objects
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
message Deck {
|
||||
message Common {
|
||||
bool study_collapsed = 1;
|
||||
|
@ -504,6 +510,9 @@ message Notetype {
|
|||
repeated Template templates = 9;
|
||||
}
|
||||
|
||||
// Database objects
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
message Note {
|
||||
int64 id = 1;
|
||||
string guid = 2;
|
||||
|
|
|
@ -38,6 +38,10 @@ impl DeckConfigService for Backend {
|
|||
.map(Into::into)
|
||||
}
|
||||
|
||||
fn get_deck_config(&self, input: pb::DeckConfigId) -> Result<pb::DeckConfig> {
|
||||
self.with_col(|col| Ok(col.get_deck_config(input.into(), true)?.unwrap().into()))
|
||||
}
|
||||
|
||||
fn get_deck_config_legacy(&self, input: pb::DeckConfigId) -> Result<pb::Json> {
|
||||
self.with_col(|col| {
|
||||
let conf = col.get_deck_config(input.into(), true)?.unwrap();
|
||||
|
@ -58,3 +62,15 @@ impl DeckConfigService for Backend {
|
|||
.map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeckConf> for pb::DeckConfig {
|
||||
fn from(c: DeckConf) -> Self {
|
||||
pb::DeckConfig {
|
||||
id: c.id.0,
|
||||
name: c.name,
|
||||
mtime_secs: c.mtime_secs.0,
|
||||
usn: c.usn.0,
|
||||
config: Some(c.inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ use crate::{
|
|||
};
|
||||
|
||||
pub use crate::backend_proto::{
|
||||
deck_config_inner::{LeechAction, NewCardOrder, ReviewCardOrder, ReviewMix},
|
||||
DeckConfigInner,
|
||||
deck_config::config::{LeechAction, NewCardOrder, ReviewCardOrder, ReviewMix},
|
||||
deck_config::Config as DeckConfigInner,
|
||||
};
|
||||
pub use schema11::{DeckConfSchema11, NewCardOrderSchema11};
|
||||
/// Old deck config and cards table store 250% as 2500.
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use super::{DeckConf, DeckConfId, INITIAL_EASE_FACTOR_THOUSANDS};
|
||||
use crate::backend_proto::deck_config_inner::NewCardOrder;
|
||||
use crate::backend_proto::DeckConfigInner;
|
||||
use super::{DeckConfigInner, NewCardOrder};
|
||||
use crate::{serde::default_on_invalid, timestamp::TimestampSecs, types::Usn};
|
||||
use serde_aux::field_attributes::deserialize_number_from_string;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
|
Loading…
Reference in a new issue