mirror of
https://github.com/ankitects/anki.git
synced 2026-01-07 02:53:54 -05:00
Added: Show Timer + Stop timer on answer
This commit is contained in:
parent
312cbc2fba
commit
f5cdf0f22f
5 changed files with 29 additions and 9 deletions
|
|
@ -302,6 +302,11 @@ message NextCardDataResponse {
|
|||
string args = 2;
|
||||
}
|
||||
|
||||
message TimerPreferences {
|
||||
uint32 max_time_ms = 1;
|
||||
bool stop_on_answer = 2;
|
||||
}
|
||||
|
||||
message NextCardData {
|
||||
QueuedCards queue = 1;
|
||||
repeated AnswerButton answer_buttons = 2;
|
||||
|
|
@ -313,7 +318,7 @@ message NextCardDataResponse {
|
|||
bool autoplay = 7;
|
||||
bool marked = 13;
|
||||
optional TypedAnswer typed_answer = 12;
|
||||
uint32 max_time_ms = 14;
|
||||
optional TimerPreferences timer = 14;
|
||||
|
||||
repeated card_rendering.AVTag question_av_tags = 8;
|
||||
repeated card_rendering.AVTag answer_av_tags = 9;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use anki_proto::generic;
|
|||
use anki_proto::scheduler;
|
||||
use anki_proto::scheduler::next_card_data_response::AnswerButton;
|
||||
use anki_proto::scheduler::next_card_data_response::NextCardData;
|
||||
use anki_proto::scheduler::next_card_data_response::TimerPreferences;
|
||||
use anki_proto::scheduler::next_card_data_response::TypedAnswer;
|
||||
use anki_proto::scheduler::ComputeFsrsParamsResponse;
|
||||
use anki_proto::scheduler::ComputeMemoryStateResponse;
|
||||
|
|
@ -403,7 +404,7 @@ impl crate::services::SchedulerService for Collection {
|
|||
let next_card = queue.cards.first();
|
||||
if let Some(next_card) = next_card {
|
||||
let cid = next_card.card.id;
|
||||
let deck_config = self.deck_config_for_card(&next_card.card)?;
|
||||
let deck_config = self.deck_config_for_card(&next_card.card)?.inner;
|
||||
let note = self.get_note(next_card.card.note_id.into())?;
|
||||
|
||||
let render = self.render_existing_card(cid, false, true)?;
|
||||
|
|
@ -477,6 +478,11 @@ impl crate::services::SchedulerService for Collection {
|
|||
queue.new_count = 0;
|
||||
}
|
||||
|
||||
let timer = deck_config.show_timer.then_some(TimerPreferences {
|
||||
max_time_ms: deck_config.cap_answer_time_to_secs * 1000,
|
||||
stop_on_answer: deck_config.stop_timer_on_answer,
|
||||
});
|
||||
|
||||
Ok(NextCardDataResponse {
|
||||
next_card: Some(NextCardData {
|
||||
queue: Some(queue.into()),
|
||||
|
|
@ -486,13 +492,13 @@ impl crate::services::SchedulerService for Collection {
|
|||
partial_back: rendered_nodes_to_proto(render.anodes),
|
||||
|
||||
answer_buttons,
|
||||
autoplay: !deck_config.inner.disable_autoplay,
|
||||
autoplay: !deck_config.disable_autoplay,
|
||||
typed_answer: typed_answer.map(|answer| TypedAnswer {
|
||||
text: answer.1,
|
||||
args: answer.0,
|
||||
}),
|
||||
marked,
|
||||
max_time_ms: deck_config.inner.cap_answer_time_to_secs * 1000,
|
||||
timer,
|
||||
|
||||
// Filled by python
|
||||
front: "".to_string(),
|
||||
|
|
|
|||
|
|
@ -52,7 +52,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
</button>
|
||||
{/if}
|
||||
<div class="disappearing more">
|
||||
<Timer {state}></Timer>
|
||||
{#if $cardData?.timer}
|
||||
<Timer {state}></Timer>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="disappearing more">
|
||||
<More {state}></More>
|
||||
|
|
@ -82,7 +84,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
|
||||
.more {
|
||||
// text-align: right;
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,14 +12,20 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
let cls = "";
|
||||
|
||||
function step() {
|
||||
let time = Date.now() - state.beginAnsweringMs;
|
||||
const maxTime = state._cardData?.maxTimeMs ?? 0;
|
||||
const timerPreferences = state._cardData?.timer;
|
||||
let time = Date.now();
|
||||
if (timerPreferences?.stopOnAnswer && state.answerMs !== undefined) {
|
||||
time = state.answerMs;
|
||||
}
|
||||
time -= state.beginAnsweringMs;
|
||||
const maxTime = state._cardData?.timer?.maxTimeMs ?? 0;
|
||||
if (time >= maxTime) {
|
||||
time = maxTime;
|
||||
cls = "overtime";
|
||||
} else {
|
||||
cls = "";
|
||||
}
|
||||
|
||||
text = formatTime(time);
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +43,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
onDestroy(() => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
step();
|
||||
|
||||
function formatTime(time: number) {
|
||||
const seconds = time / 1000;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ export class ReviewerState {
|
|||
currentTypedAnswer = "";
|
||||
_cardData: NextCardDataResponse_NextCardData | undefined = undefined;
|
||||
beginAnsweringMs = Date.now();
|
||||
answerMs: number | undefined = undefined;
|
||||
readonly cardClass = writable("");
|
||||
readonly answerShown = writable(false);
|
||||
readonly cardData = writable<NextCardDataResponse_NextCardData | undefined>(undefined);
|
||||
|
|
@ -310,6 +311,7 @@ export class ReviewerState {
|
|||
}
|
||||
|
||||
this.beginAnsweringMs = Date.now();
|
||||
this.answerMs = undefined;
|
||||
}
|
||||
|
||||
get currentCard() {
|
||||
|
|
@ -338,6 +340,7 @@ export class ReviewerState {
|
|||
if (this._cardData?.autoplay) {
|
||||
playAvtags({ tags: this._cardData!.answerAvTags });
|
||||
}
|
||||
this.answerMs = Date.now();
|
||||
this.updateHtml(await this.showTypedAnswer(this._cardData?.back || ""));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue