mirror of
https://github.com/ankitects/anki.git
synced 2025-11-06 12:47:11 -05:00
Added: TypeAnswer replacement
This commit is contained in:
parent
cf9c265570
commit
bbf575e491
4 changed files with 50 additions and 3 deletions
|
|
@ -306,6 +306,7 @@ message NextCardDataResponse {
|
||||||
string css = 5;
|
string css = 5;
|
||||||
string body_class = 6;
|
string body_class = 6;
|
||||||
bool autoplay = 7;
|
bool autoplay = 7;
|
||||||
|
optional string typed_answer = 12;
|
||||||
|
|
||||||
repeated card_rendering.AVTag question_av_tags = 8;
|
repeated card_rendering.AVTag question_av_tags = 8;
|
||||||
repeated card_rendering.AVTag answer_av_tags = 9;
|
repeated card_rendering.AVTag answer_av_tags = 9;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
mod answering;
|
mod answering;
|
||||||
mod states;
|
mod states;
|
||||||
|
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use anki_proto::cards;
|
use anki_proto::cards;
|
||||||
use anki_proto::generic;
|
use anki_proto::generic;
|
||||||
use anki_proto::scheduler;
|
use anki_proto::scheduler;
|
||||||
|
|
@ -25,6 +27,7 @@ use fsrs::ComputeParametersInput;
|
||||||
use fsrs::FSRSItem;
|
use fsrs::FSRSItem;
|
||||||
use fsrs::FSRSReview;
|
use fsrs::FSRSReview;
|
||||||
use fsrs::FSRS;
|
use fsrs::FSRS;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::backend::Backend;
|
use crate::backend::Backend;
|
||||||
use crate::card_rendering::service::rendered_nodes_to_proto;
|
use crate::card_rendering::service::rendered_nodes_to_proto;
|
||||||
|
|
@ -34,7 +37,9 @@ use crate::scheduler::new::NewCardDueOrder;
|
||||||
use crate::scheduler::states::CardState;
|
use crate::scheduler::states::CardState;
|
||||||
use crate::scheduler::states::SchedulingStates;
|
use crate::scheduler::states::SchedulingStates;
|
||||||
use crate::search::SortMode;
|
use crate::search::SortMode;
|
||||||
|
use crate::services::NotesService;
|
||||||
use crate::stats::studied_today;
|
use crate::stats::studied_today;
|
||||||
|
use crate::template::RenderedNode;
|
||||||
|
|
||||||
impl crate::services::SchedulerService for Collection {
|
impl crate::services::SchedulerService for Collection {
|
||||||
/// This behaves like _updateCutoff() in older code - it also unburies at
|
/// This behaves like _updateCutoff() in older code - it also unburies at
|
||||||
|
|
@ -411,16 +416,48 @@ impl crate::services::SchedulerService for Collection {
|
||||||
|
|
||||||
let config = self.deck_config_for_card(&next_card.card)?;
|
let config = self.deck_config_for_card(&next_card.card)?;
|
||||||
|
|
||||||
|
// Typed answer replacements
|
||||||
|
static ANSWER_REGEX: LazyLock<Regex> =
|
||||||
|
LazyLock::new(|| Regex::new(r"\[\[type:(.+?:)?(.+?)\]\]").unwrap());
|
||||||
|
|
||||||
|
const ANSWER_HTML: &str = "<center>
|
||||||
|
<input type=text id=typeans onkeypress=\"_typeAnsPress();\"
|
||||||
|
style=\"font-family: '{self.typeFont}'; font-size: {self.typeSize}px;\">
|
||||||
|
</center>";
|
||||||
|
|
||||||
|
let mut q_nodes = render.qnodes;
|
||||||
|
let typed_answer_parent_node = q_nodes.iter_mut().find_map(|node| {
|
||||||
|
if let RenderedNode::Text { text } = node {
|
||||||
|
let mut out = None;
|
||||||
|
*text = ANSWER_REGEX
|
||||||
|
.replace(text, |cap: ®ex::Captures<'_>| {
|
||||||
|
out = Some(cap[2].to_string());
|
||||||
|
ANSWER_HTML
|
||||||
|
})
|
||||||
|
.to_string();
|
||||||
|
out
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let typed_answer = typed_answer_parent_node.map(|field| {
|
||||||
|
let note = self.get_note(next_card.card.note_id.into()).unwrap();
|
||||||
|
let notetype = self.get_notetype(note.notetype_id.into()).unwrap().unwrap();
|
||||||
|
note.fields[notetype.get_field_ord(&field).unwrap()].clone()
|
||||||
|
});
|
||||||
|
|
||||||
Ok(NextCardDataResponse {
|
Ok(NextCardDataResponse {
|
||||||
next_card: Some(NextCardData {
|
next_card: Some(NextCardData {
|
||||||
queue: Some(queue.into()),
|
queue: Some(queue.into()),
|
||||||
|
|
||||||
css: render.css.clone(),
|
css: render.css.clone(),
|
||||||
partial_front: rendered_nodes_to_proto(render.qnodes),
|
partial_front: rendered_nodes_to_proto(q_nodes),
|
||||||
partial_back: rendered_nodes_to_proto(render.anodes),
|
partial_back: rendered_nodes_to_proto(render.anodes),
|
||||||
|
|
||||||
answer_buttons,
|
answer_buttons,
|
||||||
autoplay: !config.inner.disable_autoplay,
|
autoplay: !config.inner.disable_autoplay,
|
||||||
|
typed_answer,
|
||||||
|
|
||||||
// Filled by python
|
// Filled by python
|
||||||
front: "".to_string(),
|
front: "".to_string(),
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ export function updateNightMode() {
|
||||||
|
|
||||||
export class ReviewerState {
|
export class ReviewerState {
|
||||||
answerHtml = "";
|
answerHtml = "";
|
||||||
|
currentTypedAnswer = "";
|
||||||
_cardData: NextCardDataResponse_NextCardData | undefined = undefined;
|
_cardData: NextCardDataResponse_NextCardData | undefined = undefined;
|
||||||
beginAnsweringMs = Date.now();
|
beginAnsweringMs = Date.now();
|
||||||
readonly cardClass = writable("");
|
readonly cardClass = writable("");
|
||||||
|
|
@ -42,13 +43,16 @@ export class ReviewerState {
|
||||||
addEventListener("message", this.onMessage.bind(this));
|
addEventListener("message", this.onMessage.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
onMessage(e: MessageEvent<ReviewerRequest>) {
|
async onMessage(e: MessageEvent<ReviewerRequest>) {
|
||||||
switch (e.data.type) {
|
switch (e.data.type) {
|
||||||
case "audio": {
|
case "audio": {
|
||||||
const tags = get(this.answerShown) ? this._cardData!.answerAvTags : this._cardData!.questionAvTags;
|
const tags = get(this.answerShown) ? this._cardData!.answerAvTags : this._cardData!.questionAvTags;
|
||||||
playAvtags({ tags: [tags[e.data.index]] });
|
playAvtags({ tags: [tags[e.data.index]] });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "typed": {
|
||||||
|
this.currentTypedAnswer = e.data.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,9 @@ interface AudioMessage {
|
||||||
index: number;
|
index: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ReviewerRequest = AudioMessage;
|
interface CompareTypedAnswerMessage {
|
||||||
|
type: "typed";
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ReviewerRequest = AudioMessage | CompareTypedAnswerMessage;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue