support card state mutator in test scheduler
Documentation to come
This commit is contained in:
parent
1f16ce2096
commit
9edac805ad
@ -37,12 +37,21 @@ copy_files_into_group(
|
||||
package = "//ts/editor",
|
||||
)
|
||||
|
||||
copy_files_into_group(
|
||||
name = "reviewer_extras",
|
||||
srcs = [
|
||||
"reviewer_extras.js",
|
||||
],
|
||||
package = "//ts/reviewer",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "js",
|
||||
srcs = [
|
||||
"aqt_es5",
|
||||
"editor",
|
||||
"mathjax.js",
|
||||
"reviewer_extras",
|
||||
"//qt/aqt/data/web/js/vendor",
|
||||
],
|
||||
visibility = ["//qt:__subpackages__"],
|
||||
|
@ -22,6 +22,7 @@ import aqt
|
||||
from anki import hooks
|
||||
from anki.collection import GraphPreferences, OpChanges
|
||||
from anki.decks import UpdateDeckConfigs
|
||||
from anki.scheduler.v3 import NextStates
|
||||
from anki.utils import devMode, from_json_bytes
|
||||
from aqt.deckoptions import DeckOptionsDialog
|
||||
from aqt.operations.deck import update_deck_configs
|
||||
@ -307,12 +308,29 @@ def update_deck_configs_request() -> bytes:
|
||||
return b""
|
||||
|
||||
|
||||
def next_card_states() -> bytes:
|
||||
if states := aqt.mw.reviewer.get_next_states():
|
||||
return states.SerializeToString()
|
||||
else:
|
||||
return b""
|
||||
|
||||
|
||||
def set_next_card_states() -> bytes:
|
||||
key = request.headers.get("key", "")
|
||||
input = NextStates()
|
||||
input.ParseFromString(request.data)
|
||||
aqt.mw.reviewer.set_next_states(key, input)
|
||||
return b""
|
||||
|
||||
|
||||
post_handlers = {
|
||||
"graphData": graph_data,
|
||||
"graphPreferences": graph_preferences,
|
||||
"setGraphPreferences": set_graph_preferences,
|
||||
"deckConfigsForUpdate": deck_configs_for_update,
|
||||
"updateDeckConfigs": update_deck_configs_request,
|
||||
"nextCardStates": next_card_states,
|
||||
"setNextCardStates": set_next_card_states,
|
||||
# pylint: disable=unnecessary-lambda
|
||||
"i18nResources": i18n_resources,
|
||||
"congratsInfo": congrats_info,
|
||||
|
@ -6,6 +6,7 @@ from __future__ import annotations
|
||||
import difflib
|
||||
import html
|
||||
import json
|
||||
import random
|
||||
import re
|
||||
import unicodedata as ucd
|
||||
from dataclasses import dataclass
|
||||
@ -124,6 +125,7 @@ class Reviewer:
|
||||
self.state: Optional[str] = None
|
||||
self._refresh_needed: Optional[RefreshNeeded] = None
|
||||
self._v3: Optional[V3CardInfo] = None
|
||||
self._state_mutation_key = str(random.randint(0, 2 ** 64 - 1))
|
||||
self.bottom = BottomBar(mw, mw.bottomWeb)
|
||||
hooks.card_did_leech.append(self.onLeech)
|
||||
|
||||
@ -131,6 +133,7 @@ class Reviewer:
|
||||
self.mw.setStateShortcuts(self._shortcutKeys()) # type: ignore
|
||||
self.web.set_bridge_command(self._linkHandler, self)
|
||||
self.bottom.web.set_bridge_command(self._linkHandler, ReviewerBottomBar(self))
|
||||
self._state_mutation_js = self.mw.col.get_config("cardStateCustomizer")
|
||||
self._reps: int = None
|
||||
self._refresh_needed = RefreshNeeded.QUEUES
|
||||
self.refresh_if_needed()
|
||||
@ -231,6 +234,25 @@ class Reviewer:
|
||||
self.card = Card(self.mw.col, backend_card=self._v3.top_card().card)
|
||||
self.card.startTimer()
|
||||
|
||||
def get_next_states(self) -> Optional[NextStates]:
|
||||
if v3 := self._v3:
|
||||
return v3.next_states
|
||||
else:
|
||||
return None
|
||||
|
||||
def set_next_states(self, key: str, states: NextStates) -> None:
|
||||
if key != self._state_mutation_key:
|
||||
return
|
||||
|
||||
if v3 := self._v3:
|
||||
v3.next_states = states
|
||||
|
||||
def _run_state_mutation_hook(self) -> None:
|
||||
if self._v3 and (js := self._state_mutation_js):
|
||||
self.web.eval(
|
||||
f"anki.mutateNextCardStates('{self._state_mutation_key}', (states) => {{ {js} }})"
|
||||
)
|
||||
|
||||
# Audio
|
||||
##########################################################################
|
||||
|
||||
@ -268,6 +290,8 @@ class Reviewer:
|
||||
"js/mathjax.js",
|
||||
"js/vendor/mathjax/tex-chtml.js",
|
||||
"js/reviewer.js",
|
||||
"js/vendor/protobuf.min.js",
|
||||
"js/reviewer_extras.js",
|
||||
],
|
||||
context=self,
|
||||
)
|
||||
@ -308,6 +332,7 @@ class Reviewer:
|
||||
# render & update bottom
|
||||
q = self._mungeQA(q)
|
||||
q = gui_hooks.card_will_show(q, c, "reviewQuestion")
|
||||
self._run_state_mutation_hook()
|
||||
|
||||
bodyclass = theme_manager.body_classes_for_card_ord(c.ord)
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
export async function postRequest(
|
||||
path: string,
|
||||
body: string | Uint8Array
|
||||
body: string | Uint8Array,
|
||||
headers: Record<string, string> = {}
|
||||
): Promise<Uint8Array> {
|
||||
const headers = {};
|
||||
if (body instanceof Uint8Array) {
|
||||
headers["Content-type"] = "application/octet-stream";
|
||||
}
|
||||
|
54
ts/reviewer/BUILD.bazel
Normal file
54
ts/reviewer/BUILD.bazel
Normal file
@ -0,0 +1,54 @@
|
||||
load("@npm//@bazel/typescript:index.bzl", "ts_library")
|
||||
load("//ts:prettier.bzl", "prettier_test")
|
||||
load("//ts:eslint.bzl", "eslint_test")
|
||||
load("//ts/svelte:svelte.bzl", "svelte", "svelte_check")
|
||||
load("//ts:esbuild.bzl", "esbuild")
|
||||
load("//ts:compile_sass.bzl", "compile_sass")
|
||||
|
||||
ts_library(
|
||||
name = "lib",
|
||||
srcs = glob(["*.ts"]),
|
||||
deps = [
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
],
|
||||
)
|
||||
|
||||
esbuild(
|
||||
name = "reviewer_extras",
|
||||
srcs = [
|
||||
"//ts:protobuf-shim.js",
|
||||
],
|
||||
args = [
|
||||
"--inject:$(location //ts:protobuf-shim.js)",
|
||||
"--resolve-extensions=.mjs,.js",
|
||||
"--log-level=warning",
|
||||
],
|
||||
entry_point = "index.ts",
|
||||
external = [
|
||||
"protobufjs/light",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":lib",
|
||||
"//ts/lib",
|
||||
"//ts/lib:backend_proto",
|
||||
],
|
||||
)
|
||||
|
||||
# Tests
|
||||
################
|
||||
|
||||
prettier_test(
|
||||
name = "format_check",
|
||||
srcs = glob([
|
||||
"*.ts",
|
||||
]),
|
||||
)
|
||||
|
||||
eslint_test(
|
||||
name = "eslint",
|
||||
srcs = glob([
|
||||
"*.ts",
|
||||
]),
|
||||
)
|
28
ts/reviewer/answering.ts
Normal file
28
ts/reviewer/answering.ts
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import * as pb from "lib/backend_proto";
|
||||
import { postRequest } from "lib/postrequest";
|
||||
|
||||
async function getNextStates(): Promise<pb.BackendProto.NextCardStates> {
|
||||
return pb.BackendProto.NextCardStates.decode(
|
||||
await postRequest("/_anki/nextCardStates", "")
|
||||
);
|
||||
}
|
||||
|
||||
async function setNextStates(
|
||||
key: string,
|
||||
states: pb.BackendProto.NextCardStates
|
||||
): Promise<void> {
|
||||
const data: Uint8Array = pb.BackendProto.NextCardStates.encode(states).finish();
|
||||
await postRequest("/_anki/setNextCardStates", data, { key });
|
||||
}
|
||||
|
||||
export async function mutateNextCardStates(
|
||||
key: string,
|
||||
mutator: (states: pb.BackendProto.NextCardStates) => void
|
||||
): Promise<void> {
|
||||
const states = await getNextStates();
|
||||
mutator(states);
|
||||
await setNextStates(key, states);
|
||||
}
|
9
ts/reviewer/index.ts
Normal file
9
ts/reviewer/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
// This is a temporary extra file we load separately from reviewer.ts. Once
|
||||
// reviewer.ts has been migrated into ts/, the code here can be merged into
|
||||
// it.
|
||||
|
||||
import { mutateNextCardStates } from "./answering";
|
||||
globalThis.anki = { ...globalThis.anki, mutateNextCardStates };
|
Loading…
Reference in New Issue
Block a user