use native boolkey instead of separate getters/setters

Makes it easier to add new config settings in the future, especially
if we don't need to export them via protobuf.
This commit is contained in:
Damien Elmes 2021-03-07 23:43:18 +10:00
parent b67947cfbc
commit 1dea8babee
13 changed files with 116 additions and 134 deletions

View File

@ -0,0 +1,22 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{backend_proto as pb, config::BoolKey};
use pb::config::bool::Key;
impl From<Key> for BoolKey {
fn from(k: Key) -> Self {
match k {
Key::BrowserSortBackwards => BoolKey::BrowserSortBackwards,
Key::PreviewBothSides => BoolKey::PreviewBothSides,
Key::CollapseTags => BoolKey::CollapseTags,
Key::CollapseNotetypes => BoolKey::CollapseNotetypes,
Key::CollapseDecks => BoolKey::CollapseDecks,
Key::CollapseSavedSearches => BoolKey::CollapseSavedSearches,
Key::CollapseToday => BoolKey::CollapseToday,
Key::CollapseCardState => BoolKey::CollapseCardState,
Key::CollapseFlags => BoolKey::CollapseFlags,
Key::Sched2021 => BoolKey::Sched2021,
}
}
}

View File

@ -2,6 +2,7 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
mod card;
mod config;
mod dbproxy;
mod generic;
mod http_sync_server;
@ -1513,13 +1514,13 @@ impl BackendService for Backend {
fn get_config_bool(&self, input: pb::config::Bool) -> BackendResult<pb::Bool> {
self.with_col(|col| {
Ok(pb::Bool {
val: col.get_bool(input),
val: col.get_bool(input.key().into()),
})
})
}
fn set_config_bool(&self, input: pb::SetConfigBoolIn) -> BackendResult<pb::Empty> {
self.with_col(|col| col.transact(None, |col| col.set_bool(input)))
self.with_col(|col| col.transact(None, |col| col.set_bool(input.key().into(), input.value)))
.map(Into::into)
}

View File

@ -5,7 +5,6 @@ use crate::{
backend_proto as pb, collection::Collection, decks::DeckID, err::Result, notetype::NoteTypeID,
timestamp::TimestampSecs,
};
pub use pb::config::bool::Key as BoolKey;
pub use pb::config::string::Key as StringKey;
use serde::{de::DeserializeOwned, Serialize};
use serde_aux::field_attributes::deserialize_bool_from_anything;
@ -42,21 +41,10 @@ pub(crate) fn schema11_config_as_string() -> String {
#[derive(IntoStaticStr)]
#[strum(serialize_all = "camelCase")]
pub(crate) enum ConfigKey {
CardCountsSeparateInactive,
CollapseCardState,
CollapseDecks,
CollapseFlags,
CollapseNotetypes,
CollapseSavedSearches,
CollapseTags,
CollapseToday,
CreationOffset,
FirstDayOfWeek,
FutureDueShowBacklog,
LocalOffset,
PreviewBothSides,
Rollover,
Sched2021,
SetDueBrowser,
SetDueReviewer,
@ -64,8 +52,6 @@ pub(crate) enum ConfigKey {
AnswerTimeLimitSecs,
#[strum(to_string = "sortType")]
BrowserSortKind,
#[strum(to_string = "sortBackwards")]
BrowserSortReverse,
#[strum(to_string = "curDeck")]
CurrentDeckID,
#[strum(to_string = "curModel")]
@ -78,10 +64,29 @@ pub(crate) enum ConfigKey {
NewReviewMix,
#[strum(to_string = "nextPos")]
NextNewCardPosition,
#[strum(to_string = "normalize_note_text")]
NormalizeNoteText,
#[strum(to_string = "schedVer")]
SchedulerVersion,
}
#[derive(Debug, Clone, Copy, IntoStaticStr)]
#[strum(serialize_all = "camelCase")]
pub enum BoolKey {
CardCountsSeparateInactive,
CollapseCardState,
CollapseDecks,
CollapseFlags,
CollapseNotetypes,
CollapseSavedSearches,
CollapseTags,
CollapseToday,
FutureDueShowBacklog,
PreviewBothSides,
Sched2021,
#[strum(to_string = "sortBackwards")]
BrowserSortBackwards,
#[strum(to_string = "normalize_note_text")]
NormalizeNoteText,
#[strum(to_string = "dayLearnFirst")]
ShowDayLearningCardsFirst,
#[strum(to_string = "estTimes")]
@ -90,23 +95,6 @@ pub(crate) enum ConfigKey {
ShowRemainingDueCountsInStudy,
}
impl From<BoolKey> for ConfigKey {
fn from(key: BoolKey) -> Self {
match key {
BoolKey::BrowserSortBackwards => ConfigKey::BrowserSortReverse,
BoolKey::CollapseCardState => ConfigKey::CollapseCardState,
BoolKey::CollapseDecks => ConfigKey::CollapseDecks,
BoolKey::CollapseFlags => ConfigKey::CollapseFlags,
BoolKey::CollapseNotetypes => ConfigKey::CollapseNotetypes,
BoolKey::CollapseSavedSearches => ConfigKey::CollapseSavedSearches,
BoolKey::CollapseTags => ConfigKey::CollapseTags,
BoolKey::CollapseToday => ConfigKey::CollapseToday,
BoolKey::PreviewBothSides => ConfigKey::PreviewBothSides,
BoolKey::Sched2021 => ConfigKey::Sched2021,
}
}
}
impl From<StringKey> for ConfigKey {
fn from(key: StringKey) -> Self {
match key {
@ -169,13 +157,31 @@ impl Collection {
self.storage.remove_config(key.into())
}
pub(crate) fn get_browser_sort_kind(&self) -> SortKind {
self.get_config_default(ConfigKey::BrowserSortKind)
pub(crate) fn get_bool(&self, key: BoolKey) -> bool {
match key {
BoolKey::BrowserSortBackwards => {
// older clients were storing this as an int
self.get_config_default::<BoolLike, _>(BoolKey::BrowserSortBackwards)
.0
}
// some keys default to true
BoolKey::FutureDueShowBacklog
| BoolKey::ShowRemainingDueCountsInStudy
| BoolKey::CardCountsSeparateInactive
| BoolKey::NormalizeNoteText => self.get_config_optional(key).unwrap_or(true),
// other options default to false
other => self.get_config_default(other),
}
}
pub(crate) fn get_browser_sort_reverse(&self) -> bool {
let b: BoolLike = self.get_config_default(ConfigKey::BrowserSortReverse);
b.0
pub(crate) fn set_bool(&self, key: BoolKey, value: bool) -> Result<()> {
self.set_config(key, &value)
}
pub(crate) fn get_browser_sort_kind(&self) -> SortKind {
self.get_config_default(ConfigKey::BrowserSortKind)
}
pub(crate) fn get_current_deck_id(&self) -> DeckID {
@ -256,12 +262,6 @@ impl Collection {
self.set_config(ConfigKey::LearnAheadSecs, &secs)
}
/// This is a stop-gap solution until we can decouple searching from canonical storage.
pub(crate) fn normalize_note_text(&self) -> bool {
self.get_config_optional(ConfigKey::NormalizeNoteText)
.unwrap_or(true)
}
pub(crate) fn get_new_review_mix(&self) -> NewReviewMix {
match self.get_config_default::<u8, _>(ConfigKey::NewReviewMix) {
1 => NewReviewMix::ReviewsFirst,
@ -283,42 +283,6 @@ impl Collection {
self.set_config(ConfigKey::FirstDayOfWeek, &weekday)
}
pub(crate) fn get_card_counts_separate_inactive(&self) -> bool {
self.get_config_optional(ConfigKey::CardCountsSeparateInactive)
.unwrap_or(true)
}
pub(crate) fn set_card_counts_separate_inactive(&self, separate: bool) -> Result<()> {
self.set_config(ConfigKey::CardCountsSeparateInactive, &separate)
}
pub(crate) fn get_future_due_show_backlog(&self) -> bool {
self.get_config_optional(ConfigKey::FutureDueShowBacklog)
.unwrap_or(true)
}
pub(crate) fn set_future_due_show_backlog(&self, show: bool) -> Result<()> {
self.set_config(ConfigKey::FutureDueShowBacklog, &show)
}
pub(crate) fn get_show_due_counts(&self) -> bool {
self.get_config_optional(ConfigKey::ShowRemainingDueCountsInStudy)
.unwrap_or(true)
}
pub(crate) fn set_show_due_counts(&self, on: bool) -> Result<()> {
self.set_config(ConfigKey::ShowRemainingDueCountsInStudy, &on)
}
pub(crate) fn get_show_intervals_above_buttons(&self) -> bool {
self.get_config_optional(ConfigKey::ShowIntervalsAboveAnswerButtons)
.unwrap_or(true)
}
pub(crate) fn set_show_intervals_above_buttons(&self, on: bool) -> Result<()> {
self.set_config(ConfigKey::ShowIntervalsAboveAnswerButtons, &on)
}
pub(crate) fn get_answer_time_limit_secs(&self) -> u32 {
self.get_config_optional(ConfigKey::AnswerTimeLimitSecs)
.unwrap_or_default()
@ -328,15 +292,6 @@ impl Collection {
self.set_config(ConfigKey::AnswerTimeLimitSecs, &secs)
}
pub(crate) fn get_day_learn_first(&self) -> bool {
self.get_config_optional(ConfigKey::ShowDayLearningCardsFirst)
.unwrap_or_default()
}
pub(crate) fn set_day_learn_first(&self, on: bool) -> Result<()> {
self.set_config(ConfigKey::ShowDayLearningCardsFirst, &on)
}
pub(crate) fn get_last_unburied_day(&self) -> u32 {
self.get_config_optional(ConfigKey::LastUnburiedDay)
.unwrap_or_default()
@ -346,23 +301,6 @@ impl Collection {
self.set_config(ConfigKey::LastUnburiedDay, &day)
}
#[allow(clippy::match_single_binding)]
pub(crate) fn get_bool(&self, config: pb::config::Bool) -> bool {
self.get_bool_key(config.key())
}
#[allow(clippy::match_single_binding)]
pub(crate) fn get_bool_key(&self, key: BoolKey) -> bool {
match key {
// all options default to false at the moment
other => self.get_config_default(ConfigKey::from(other)),
}
}
pub(crate) fn set_bool(&self, input: pb::SetConfigBoolIn) -> Result<()> {
self.set_config(ConfigKey::from(input.key()), &input.value)
}
pub(crate) fn get_string(&self, config: pb::config::String) -> String {
let key = config.key();
let default = match key {

View File

@ -230,7 +230,7 @@ impl Collection {
F: FnMut(DatabaseCheckProgress, bool),
{
let nids_by_notetype = self.storage.all_note_ids_by_notetype()?;
let norm = self.normalize_note_text();
let norm = self.get_bool(BoolKey::NormalizeNoteText);
let usn = self.usn()?;
let stamp = TimestampMillis::now();

View File

@ -283,7 +283,7 @@ impl Collection {
let dconf = self.storage.get_deck_config_map()?;
add_counts(&mut tree, &counts);
if self.scheduler_version() == SchedulerVersion::V2
&& !self.get_bool_key(BoolKey::Sched2021)
&& !self.get_bool(BoolKey::Sched2021)
{
apply_limits_v2_old(
&mut tree,

View File

@ -5,6 +5,7 @@ use crate::{
collection::Collection,
err::{AnkiError, Result},
notes::{NoteID, TransformNoteOutput},
prelude::*,
text::normalize_to_nfc,
};
use regex::Regex;
@ -46,7 +47,7 @@ impl Collection {
field_name: Option<String>,
) -> Result<usize> {
self.transact(None, |col| {
let norm = col.normalize_note_text();
let norm = col.get_bool(BoolKey::NormalizeNoteText);
let search = if norm {
normalize_to_nfc(search_re)
} else {

View File

@ -305,7 +305,7 @@ impl Collection {
.get_notetype(note.notetype_id)?
.ok_or_else(|| AnkiError::invalid_input("missing note type"))?;
let ctx = CardGenContext::new(&nt, col.usn()?);
let norm = col.normalize_note_text();
let norm = col.get_bool(BoolKey::NormalizeNoteText);
col.add_note_inner(&ctx, note, did, norm)
})
}
@ -345,7 +345,7 @@ impl Collection {
.get_notetype(note.notetype_id)?
.ok_or_else(|| AnkiError::invalid_input("missing note type"))?;
let ctx = CardGenContext::new(&nt, col.usn()?);
let norm = col.normalize_note_text();
let norm = col.get_bool(BoolKey::NormalizeNoteText);
col.update_note_inner_generating_cards(&ctx, note, &existing_note, true, norm)
})
}
@ -431,7 +431,7 @@ impl Collection {
F: FnMut(&mut Note, &NoteType) -> Result<TransformNoteOutput>,
{
let nids_by_notetype = self.storage.note_ids_by_notetype(nids)?;
let norm = self.normalize_note_text();
let norm = self.get_bool(BoolKey::NormalizeNoteText);
let mut changed_notes = 0;
let usn = self.usn()?;
@ -479,7 +479,7 @@ impl Collection {
pub(crate) fn note_is_duplicate_or_empty(&self, note: &Note) -> Result<DuplicateState> {
if let Some(field1) = note.fields.get(0) {
let field1 = if self.normalize_note_text() {
let field1 = if self.get_bool(BoolKey::NormalizeNoteText) {
normalize_to_nfc(field1)
} else {
field1.into()
@ -554,8 +554,8 @@ fn note_differs_from_db(existing_note: &mut Note, note: &mut Note) -> bool {
mod test {
use super::{anki_base91, field_checksum};
use crate::{
collection::open_test_collection, config::ConfigKey, decks::DeckID, err::Result,
prelude::*, search::SortMode,
collection::open_test_collection, config::BoolKey, decks::DeckID, err::Result, prelude::*,
search::SortMode,
};
#[test]
@ -642,8 +642,7 @@ mod test {
// if normalization turned off, note text is entered as-is
let mut note = nt.new_note();
note.fields[0] = "\u{fa47}".into();
col.set_config(ConfigKey::NormalizeNoteText, &false)
.unwrap();
col.set_config(BoolKey::NormalizeNoteText, &false).unwrap();
col.add_note(&mut note, DeckID(1))?;
assert_eq!(note.fields[0], "\u{fa47}");
// normalized searches won't match

View File

@ -28,6 +28,7 @@ use crate::{
define_newtype,
err::{AnkiError, Result},
notes::Note,
prelude::*,
template::{FieldRequirements, ParsedTemplate},
text::ensure_string_in_nfc,
timestamp::TimestampSecs,
@ -424,7 +425,7 @@ impl Collection {
/// or fields have been added/removed/reordered.
pub fn update_notetype(&mut self, nt: &mut NoteType, preserve_usn: bool) -> Result<()> {
let existing = self.get_notetype(nt.id)?;
let norm = self.normalize_note_text();
let norm = self.get_bool(BoolKey::NormalizeNoteText);
nt.prepare_for_update(existing.as_ref().map(AsRef::as_ref))?;
self.transact(None, |col| {
if let Some(existing_notetype) = existing {

View File

@ -7,6 +7,7 @@ use crate::{
Preferences,
},
collection::Collection,
config::BoolKey,
err::Result,
scheduler::timing::local_minutes_west_for_stamp,
};
@ -39,11 +40,11 @@ impl Collection {
crate::config::NewReviewMix::ReviewsFirst => NewRevMixPB::ReviewsFirst,
crate::config::NewReviewMix::NewFirst => NewRevMixPB::NewFirst,
} as i32,
show_remaining_due_counts: self.get_show_due_counts(),
show_intervals_on_buttons: self.get_show_intervals_above_buttons(),
show_remaining_due_counts: self.get_bool(BoolKey::ShowRemainingDueCountsInStudy),
show_intervals_on_buttons: self.get_bool(BoolKey::ShowIntervalsAboveAnswerButtons),
time_limit_secs: self.get_answer_time_limit_secs(),
new_timezone: self.get_creation_utc_offset().is_some(),
day_learn_first: self.get_day_learn_first(),
day_learn_first: self.get_bool(BoolKey::ShowDayLearningCardsFirst),
})
}
@ -53,10 +54,16 @@ impl Collection {
) -> Result<()> {
let s = settings;
self.set_day_learn_first(s.day_learn_first)?;
self.set_bool(BoolKey::ShowDayLearningCardsFirst, s.day_learn_first)?;
self.set_bool(
BoolKey::ShowRemainingDueCountsInStudy,
s.show_remaining_due_counts,
)?;
self.set_bool(
BoolKey::ShowIntervalsAboveAnswerButtons,
s.show_intervals_on_buttons,
)?;
self.set_answer_time_limit_secs(s.time_limit_secs)?;
self.set_show_due_counts(s.show_remaining_due_counts)?;
self.set_show_intervals_above_buttons(s.show_intervals_on_buttons)?;
self.set_learn_ahead_secs(s.learn_ahead_secs)?;
self.set_new_review_mix(match s.new_review_mix() {

View File

@ -4,6 +4,7 @@
pub use crate::{
card::{Card, CardID},
collection::Collection,
config::BoolKey,
deckconf::{DeckConf, DeckConfID},
decks::{Deck, DeckID, DeckKind},
err::{AnkiError, Result},

View File

@ -6,7 +6,11 @@ use super::{
sqlwriter::{RequiredTable, SqlWriter},
};
use crate::{
card::CardID, card::CardType, collection::Collection, config::SortKind, err::Result,
card::CardID,
card::CardType,
collection::Collection,
config::{BoolKey, SortKind},
err::Result,
search::parser::parse,
};
@ -124,7 +128,7 @@ impl Collection {
if mode == &SortMode::FromConfig {
*mode = SortMode::Builtin {
kind: self.get_browser_sort_kind(),
reverse: self.get_browser_sort_reverse(),
reverse: self.get_bool(BoolKey::BrowserSortBackwards),
}
}
}

View File

@ -9,6 +9,7 @@ use crate::{
err::Result,
notes::field_checksum,
notetype::NoteTypeID,
prelude::*,
storage::ids_to_string,
text::{
is_glob, matches_glob, normalize_to_nfc, strip_html_preserving_media_filenames,
@ -28,7 +29,7 @@ pub(crate) struct SqlWriter<'a> {
impl SqlWriter<'_> {
pub(crate) fn new(col: &mut Collection) -> SqlWriter<'_> {
let normalize_note_text = col.normalize_note_text();
let normalize_note_text = col.get_bool(BoolKey::NormalizeNoteText);
let sql = String::new();
let args = vec![];
SqlWriter {

View File

@ -2,7 +2,11 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{
backend_proto as pb, config::Weekday, prelude::*, revlog::RevlogEntry, search::SortMode,
backend_proto as pb,
config::{BoolKey, Weekday},
prelude::*,
revlog::RevlogEntry,
search::SortMode,
};
impl Collection {
@ -50,9 +54,9 @@ impl Collection {
pub(crate) fn get_graph_preferences(&self) -> Result<pb::GraphPreferences> {
Ok(pb::GraphPreferences {
calendar_first_day_of_week: self.get_first_day_of_week() as i32,
card_counts_separate_inactive: self.get_card_counts_separate_inactive(),
card_counts_separate_inactive: self.get_bool(BoolKey::CardCountsSeparateInactive),
browser_links_supported: true,
future_due_show_backlog: self.get_future_due_show_backlog(),
future_due_show_backlog: self.get_bool(BoolKey::FutureDueShowBacklog),
})
}
@ -63,8 +67,11 @@ impl Collection {
6 => Weekday::Saturday,
_ => Weekday::Sunday,
})?;
self.set_card_counts_separate_inactive(prefs.card_counts_separate_inactive)?;
self.set_future_due_show_backlog(prefs.future_due_show_backlog)?;
self.set_bool(
BoolKey::CardCountsSeparateInactive,
prefs.card_counts_separate_inactive,
)?;
self.set_bool(BoolKey::FutureDueShowBacklog, prefs.future_due_show_backlog)?;
Ok(())
}
}