diff --git a/proto/anki/scheduler.proto b/proto/anki/scheduler.proto
index 87a052e79..69430c070 100644
--- a/proto/anki/scheduler.proto
+++ b/proto/anki/scheduler.proto
@@ -327,6 +327,13 @@ message NextCardDataResponse {
repeated card_rendering.AVTag question_av_tags = 8;
repeated card_rendering.AVTag answer_av_tags = 9;
+ float autoAdvanceQuestionSeconds = 16;
+ float autoAdvanceAnswerSeconds = 17;
+ bool autoAdvanceWaitForAudio = 20;
+
+ deck_config.DeckConfig.Config.QuestionAction autoAdvanceQuestionAction = 18;
+ deck_config.DeckConfig.Config.AnswerAction autoAdvanceAnswerAction = 19;
+
// TODO: We can probably make this a little faster by using oneof and
// preventing the partial_front and back being sent to svelte where it isn't
// used. Alternatively we can use a completely different message for both
diff --git a/rslib/src/scheduler/service/mod.rs b/rslib/src/scheduler/service/mod.rs
index e5c9355c9..07a99cf91 100644
--- a/rslib/src/scheduler/service/mod.rs
+++ b/rslib/src/scheduler/service/mod.rs
@@ -500,6 +500,13 @@ impl crate::services::SchedulerService for Collection {
marked,
timer,
+ auto_advance_answer_seconds: deck_config.seconds_to_show_answer,
+ auto_advance_question_seconds: deck_config.seconds_to_show_question,
+ auto_advance_wait_for_audio: deck_config.wait_for_audio,
+
+ auto_advance_answer_action: deck_config.answer_action,
+ auto_advance_question_action: deck_config.question_action,
+
// Filled by python
accept_enter: true,
front: "".to_string(),
diff --git a/ts/routes/reviewer/reviewer-bottom/More.svelte b/ts/routes/reviewer/reviewer-bottom/More.svelte
index a0c498be5..980dc1d81 100644
--- a/ts/routes/reviewer/reviewer-bottom/More.svelte
+++ b/ts/routes/reviewer/reviewer-bottom/More.svelte
@@ -24,10 +24,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{ colour: tr.actionsFlagPurple(), shortcut: "Ctrl+7" },
];
- function todo() {
- alert("Not yet implemented in new reviewer.");
- }
-
const shortcuts: MoreMenuItemInfo[] = [
{
name: tr.studyingBuryCard(),
@@ -128,11 +124,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{
name: tr.actionsAutoAdvance(),
shortcut: "Shift+A",
- onClick: todo /* checked: autoAdvanceEnabled */,
+ onClick: () => state.toggleAutoAdvance(),
},
];
$: current_flag = state.flag;
+ // TOOD: Fix above capitals
+ $: autoAdvance = state.autoAdvance;
function prepKeycodeForShortcut(keycode: string) {
return keycode.replace("Ctrl", "Control");
@@ -212,11 +210,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{#if shortcut == "hr"}
{:else}
-
+ {@const highlighted = shortcut.shortcut == "Shift+A" && $autoAdvance}
+
| undefined;
+ autoAdvanceAnswerTimeout: ReturnType | undefined;
iframe: HTMLIFrameElement | undefined = undefined;
+ constructor() {
+ this.autoAdvance.subscribe($autoAdvance => {
+ if (this._answerShown) {
+ this.updateAutoAdvanceAnswer();
+ } else {
+ this.updateAutoAdvanceQuestion();
+ }
+ if (!$autoAdvance) {
+ clearInterval(this.autoAdvanceQuestionTimeout);
+ clearInterval(this.autoAdvanceAnswerTimeout);
+ }
+ });
+ }
+
+ public toggleAutoAdvance() {
+ this.autoAdvance.update(($autoAdvance) => {
+ // Reversed because the $autoAdvance will be flipped by the return.
+ this.showTooltip($autoAdvance ? tr.actionsAutoAdvanceDeactivated() : tr.actionsAutoAdvanceActivated());
+ return !$autoAdvance;
+ });
+ }
+
async onReady() {
const { json } = await getConfigJson({ val: "reviewerStorage" });
this.sendInnerRequest({ type: "setstorage", json_buffer: json });
@@ -323,6 +349,47 @@ export class ReviewerState {
this.sendInnerRequest({ type: "html", value: htmlString, css, bodyclass });
}
+ updateAutoAdvanceQuestion() {
+ clearTimeout(this.autoAdvanceAnswerTimeout);
+ if (get(this.autoAdvance) && this._cardData!.autoAdvanceQuestionSeconds) {
+ const action = ({
+ [DeckConfig_Config_QuestionAction.SHOW_ANSWER]: () => {
+ this.showAnswer();
+ },
+ [DeckConfig_Config_QuestionAction.SHOW_REMINDER]: () => {
+ this.showTooltip(tr.studyingQuestionTimeElapsed());
+ },
+ })[this._cardData!.autoAdvanceQuestionAction];
+
+ this.autoAdvanceQuestionTimeout = setTimeout(action, this._cardData!.autoAdvanceQuestionSeconds * 1000);
+ }
+ }
+
+ updateAutoAdvanceAnswer() {
+ clearTimeout(this.autoAdvanceQuestionTimeout);
+ if (get(this.autoAdvance) && this._cardData?.autoAdvanceAnswerSeconds) {
+ const action = ({
+ [DeckConfig_Config_AnswerAction.ANSWER_AGAIN]: () => {
+ this.easeButtonPressed(0);
+ },
+ [DeckConfig_Config_AnswerAction.ANSWER_HARD]: () => {
+ this.easeButtonPressed(1);
+ },
+ [DeckConfig_Config_AnswerAction.ANSWER_GOOD]: () => {
+ this.easeButtonPressed(2);
+ },
+ [DeckConfig_Config_AnswerAction.BURY_CARD]: () => {
+ this.buryOrSuspendCurrentCard(false);
+ },
+ [DeckConfig_Config_AnswerAction.SHOW_REMINDER]: () => {
+ this.showTooltip(tr.studyingAnswerTimeElapsed());
+ },
+ })[this._cardData.autoAdvanceAnswerAction];
+
+ this.autoAdvanceAnswerTimeout = setTimeout(action, this._cardData.autoAdvanceAnswerSeconds * 1000);
+ }
+ }
+
async showQuestion(answer: CardAnswer | null) {
if (answer !== null) {
this.setUndo(tr.actionsAnswerCard());
@@ -352,6 +419,7 @@ export class ReviewerState {
this.beginAnsweringMs = Date.now();
this.answerMs = undefined;
+ this.updateAutoAdvanceQuestion();
}
get currentCard() {
@@ -382,6 +450,7 @@ export class ReviewerState {
}
this.answerMs = Date.now();
this.updateHtml(await this.showTypedAnswer(this._cardData?.back || ""));
+ this.updateAutoAdvanceAnswer();
}
get _answerShown() {