diff --git a/ftl/core/deck-config.ftl b/ftl/core/deck-config.ftl index bbc7ac222..5b4551b6b 100644 --- a/ftl/core/deck-config.ftl +++ b/ftl/core/deck-config.ftl @@ -173,6 +173,8 @@ deck-config-interval-modifier-tooltip = deck-config-hard-interval-tooltip = The multiplier applied to a review interval when answering `Hard`. deck-config-new-interval-tooltip = The multiplier applied to a review interval when answering `Again`. deck-config-minimum-interval-tooltip = The minimum interval given to a review card after answering `Again`. +deck-config-custom-scheduling = Custom scheduling +deck-config-custom-scheduling-tooltip = Affects the entire collection. Use at your own risk! ## Adding/renaming diff --git a/rslib/backend.proto b/rslib/backend.proto index 7d72276b4..df595c666 100644 --- a/rslib/backend.proto +++ b/rslib/backend.proto @@ -965,6 +965,8 @@ message DeckConfigsForUpdate { bool schema_modified = 4; bool v3_scheduler = 5; bool have_addons = 6; + // only applies to v3 scheduler + string card_state_customizer = 7; } message UpdateDeckConfigsRequest { @@ -974,6 +976,7 @@ message UpdateDeckConfigsRequest { repeated DeckConfig configs = 2; repeated int64 removed_config_ids = 3; bool apply_to_children = 4; + string card_state_customizer = 5; } message SetTagCollapsedRequest { @@ -1470,6 +1473,7 @@ message Config { SET_DUE_BROWSER = 0; SET_DUE_REVIEWER = 1; DEFAULT_SEARCH_TEXT = 2; + CARD_STATE_CUSTOMIZER = 3; } Key key = 1; } diff --git a/rslib/src/backend/config.rs b/rslib/src/backend/config.rs index f28a43d86..d17feb53b 100644 --- a/rslib/src/backend/config.rs +++ b/rslib/src/backend/config.rs @@ -43,6 +43,7 @@ impl From for StringKey { StringKeyProto::SetDueBrowser => StringKey::SetDueBrowser, StringKeyProto::SetDueReviewer => StringKey::SetDueReviewer, StringKeyProto::DefaultSearchText => StringKey::DefaultSearchText, + StringKeyProto::CardStateCustomizer => StringKey::CardStateCustomizer, } } } diff --git a/rslib/src/backend/deckconfig.rs b/rslib/src/backend/deckconfig.rs index 2820bfcd8..53db0ca05 100644 --- a/rslib/src/backend/deckconfig.rs +++ b/rslib/src/backend/deckconfig.rs @@ -88,6 +88,7 @@ impl From for UpdateDeckConfigsRequest { configs: c.configs.into_iter().map(Into::into).collect(), removed_config_ids: c.removed_config_ids.into_iter().map(Into::into).collect(), apply_to_children: c.apply_to_children, + card_state_customizer: c.card_state_customizer, } } } diff --git a/rslib/src/config/string.rs b/rslib/src/config/string.rs index 10da7c206..edf42c868 100644 --- a/rslib/src/config/string.rs +++ b/rslib/src/config/string.rs @@ -11,6 +11,7 @@ pub enum StringKey { SetDueBrowser, SetDueReviewer, DefaultSearchText, + CardStateCustomizer, } impl Collection { diff --git a/rslib/src/deckconfig/update.rs b/rslib/src/deckconfig/update.rs index 66df07e72..3007046b3 100644 --- a/rslib/src/deckconfig/update.rs +++ b/rslib/src/deckconfig/update.rs @@ -11,6 +11,7 @@ use std::{ use crate::{ backend_proto as pb, backend_proto::deck_configs_for_update::{ConfigWithExtra, CurrentDeck}, + config::StringKey, prelude::*, }; @@ -21,6 +22,7 @@ pub struct UpdateDeckConfigsRequest { pub configs: Vec, pub removed_config_ids: Vec, pub apply_to_children: bool, + pub card_state_customizer: String, } impl Collection { @@ -39,6 +41,7 @@ impl Collection { .schema_changed_since_sync(), v3_scheduler: self.get_config_bool(BoolKey::Sched2021), have_addons: false, + card_state_customizer: self.get_config_string(StringKey::CardStateCustomizer), }) } @@ -178,6 +181,8 @@ impl Collection { } } + self.set_config_string_inner(StringKey::CardStateCustomizer, &input.card_state_customizer)?; + Ok(()) } } @@ -199,6 +204,9 @@ mod test { col.add_note(&mut note, DeckId(1))?; } + // add the key so it doesn't trigger a change below + col.set_config_string_inner(StringKey::CardStateCustomizer, "")?; + // pretend we're in sync let stamps = col.storage.get_collection_timestamps()?; col.storage.set_last_sync(stamps.schema_change)?; @@ -228,6 +236,7 @@ mod test { .collect(), removed_config_ids: vec![], apply_to_children: false, + card_state_customizer: "".to_string(), }; assert!(!col.update_deck_configs(input.clone())?.changes.had_change()); diff --git a/ts/deckoptions/AdvancedOptions.svelte b/ts/deckoptions/AdvancedOptions.svelte index ed953b260..62640889c 100644 --- a/ts/deckoptions/AdvancedOptions.svelte +++ b/ts/deckoptions/AdvancedOptions.svelte @@ -9,12 +9,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import SpinBoxRow from "./SpinBoxRow.svelte"; import SpinBoxFloatRow from "./SpinBoxFloatRow.svelte"; import type { DeckOptionsState } from "./lib"; + import CardStateCustomizer from "./CardStateCustomizer.svelte"; export let state: DeckOptionsState; export let api: Record; let config = state.currentConfig; let defaults = state.defaults; + let cardStateCustomizer = state.cardStateCustomizer; @@ -88,4 +90,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html {tr.schedulingNewInterval()} + + {#if state.v3Scheduler} + + + + {/if} diff --git a/ts/deckoptions/CardStateCustomizer.svelte b/ts/deckoptions/CardStateCustomizer.svelte new file mode 100644 index 000000000..c9dc2a0e3 --- /dev/null +++ b/ts/deckoptions/CardStateCustomizer.svelte @@ -0,0 +1,37 @@ + + + + + +
+ + {tr.deckConfigCustomScheduling()}: + +
+ +
+ +