From 6869e9fd3605a48dcc6fb4e4b47836d2b85f18cf Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Mon, 25 Aug 2025 18:42:20 +0100 Subject: [PATCH 01/37] reviewer-bottom entrypoint --- build/configure/src/aqt.rs | 2 +- build/configure/src/web.rs | 12 ++++++++++++ qt/aqt/reviewer.py | 7 +------ ts/routes/reviewer-bottom/AnswerButton.svelte | 0 .../routes/reviewer-bottom/index.scss | 6 +++--- ts/routes/reviewer-bottom/index.svelte | 0 .../routes/reviewer-bottom/index.ts | 5 +++++ 7 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 ts/routes/reviewer-bottom/AnswerButton.svelte rename qt/aqt/data/web/css/reviewer-bottom.scss => ts/routes/reviewer-bottom/index.scss (89%) create mode 100644 ts/routes/reviewer-bottom/index.svelte rename qt/aqt/data/web/js/reviewer-bottom.ts => ts/routes/reviewer-bottom/index.ts (96%) diff --git a/build/configure/src/aqt.rs b/build/configure/src/aqt.rs index 83be77e91..183b7f0b3 100644 --- a/build/configure/src/aqt.rs +++ b/build/configure/src/aqt.rs @@ -170,7 +170,7 @@ fn build_imgs(build: &mut Build) -> Result<()> { } fn build_js(build: &mut Build) -> Result<()> { - for ts_file in &["deckbrowser", "webview", "toolbar", "reviewer-bottom"] { + for ts_file in &["deckbrowser", "webview", "toolbar"] { build.add_action( "qt:aqt:data:web:js", EsbuildScript { diff --git a/build/configure/src/web.rs b/build/configure/src/web.rs index ef2d268bb..9ee5d74b5 100644 --- a/build/configure/src/web.rs +++ b/build/configure/src/web.rs @@ -1,6 +1,7 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html +use anyhow::Ok; use anyhow::Result; use ninja_gen::action::BuildAction; use ninja_gen::copy::CopyFiles; @@ -228,6 +229,17 @@ fn build_and_check_pages(build: &mut Build) -> Result<()> { ":sveltekit" ], )?; + build_page( + "reviewer-bottom", + true, + inputs![ + // + ":ts:lib", + ":ts:components", + ":sass", + ":sveltekit" + ], + )?; Ok(()) } diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index a8839c598..4d7f175ab 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -355,12 +355,7 @@ class Reviewer: self.web.allow_drops = True self.web.eval("_blockDefaultDragDropBehavior();") # show answer / ease buttons - self.bottom.web.stdHtml( - self._bottomHTML(), - css=["css/toolbar-bottom.css", "css/reviewer-bottom.css"], - js=["js/vendor/jquery.min.js", "js/reviewer-bottom.js"], - context=ReviewerBottomBar(self), - ) + self.bottom.web.load_ts_page("reviewer-bottom") # Showing the question ########################################################################## diff --git a/ts/routes/reviewer-bottom/AnswerButton.svelte b/ts/routes/reviewer-bottom/AnswerButton.svelte new file mode 100644 index 000000000..e69de29bb diff --git a/qt/aqt/data/web/css/reviewer-bottom.scss b/ts/routes/reviewer-bottom/index.scss similarity index 89% rename from qt/aqt/data/web/css/reviewer-bottom.scss rename to ts/routes/reviewer-bottom/index.scss index 59098a5fb..fbe069779 100644 --- a/qt/aqt/data/web/css/reviewer-bottom.scss +++ b/ts/routes/reviewer-bottom/index.scss @@ -1,9 +1,9 @@ /* Copyright: Ankitects Pty Ltd and contributors * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ -@use "../../../../../ts/lib/sass/root-vars"; -@use "../../../../../ts/lib/sass/vars" as *; -@use "../../../../../ts/lib/sass/card-counts"; +@use "../../lib/sass/root-vars"; +@use "../../lib/sass/vars" as *; +@use "../../lib/sass/card-counts"; :root { --focus-color: #{palette-of(border-focus)}; diff --git a/ts/routes/reviewer-bottom/index.svelte b/ts/routes/reviewer-bottom/index.svelte new file mode 100644 index 000000000..e69de29bb diff --git a/qt/aqt/data/web/js/reviewer-bottom.ts b/ts/routes/reviewer-bottom/index.ts similarity index 96% rename from qt/aqt/data/web/js/reviewer-bottom.ts rename to ts/routes/reviewer-bottom/index.ts index 4ebf34510..ecb93d309 100644 --- a/qt/aqt/data/web/js/reviewer-bottom.ts +++ b/ts/routes/reviewer-bottom/index.ts @@ -5,6 +5,10 @@ @typescript-eslint/no-unused-vars: "off", */ +import "./index.scss" + +console.log("Hello world") + let time: number; // set in python code let timerStopped = false; @@ -61,3 +65,4 @@ function selectedAnswerButton(): string { } return node.dataset.ease; } + From 244aade83630dfdf2d6678c02789a13b20681256 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Mon, 25 Aug 2025 18:46:35 +0100 Subject: [PATCH 02/37] Fix: Showquestion is not defined --- qt/aqt/reviewer.py | 2 +- ts/routes/reviewer-bottom/index.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 4d7f175ab..2ae054184 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -847,7 +847,7 @@ timerStopped = false; maxTime = self.card.time_limit() / 1000 else: maxTime = 0 - self.bottom.web.eval("showQuestion(%s,%d);" % (json.dumps(middle), maxTime)) + self.bottom.web.eval("anki.showQuestion(%s,%d);" % (json.dumps(middle), maxTime)) def _showEaseButtons(self) -> None: if not self._states_mutated: diff --git a/ts/routes/reviewer-bottom/index.ts b/ts/routes/reviewer-bottom/index.ts index ecb93d309..0f495bcdd 100644 --- a/ts/routes/reviewer-bottom/index.ts +++ b/ts/routes/reviewer-bottom/index.ts @@ -7,8 +7,6 @@ import "./index.scss" -console.log("Hello world") - let time: number; // set in python code let timerStopped = false; @@ -35,7 +33,7 @@ function updateTime(): void { let intervalId: number | undefined; -function showQuestion(txt: string, maxTime_: number): void { +export function showQuestion(txt: string, maxTime_: number): void { showAnswer(txt); time = 0; maxTime = maxTime_; From 34c1dfd8497a1ff9a8e16d57020ef8a5a6ff1ab3 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Mon, 25 Aug 2025 20:34:26 +0100 Subject: [PATCH 03/37] Added: Svelte component --- ts/routes/reviewer-bottom/index.svelte | 3 +++ ts/routes/reviewer-bottom/index.ts | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/ts/routes/reviewer-bottom/index.svelte b/ts/routes/reviewer-bottom/index.svelte index e69de29bb..049eff39e 100644 --- a/ts/routes/reviewer-bottom/index.svelte +++ b/ts/routes/reviewer-bottom/index.svelte @@ -0,0 +1,3 @@ +
+ Hello from svelte +
\ No newline at end of file diff --git a/ts/routes/reviewer-bottom/index.ts b/ts/routes/reviewer-bottom/index.ts index 0f495bcdd..e4bec417a 100644 --- a/ts/routes/reviewer-bottom/index.ts +++ b/ts/routes/reviewer-bottom/index.ts @@ -5,7 +5,9 @@ @typescript-eslint/no-unused-vars: "off", */ +import { mount } from "svelte"; import "./index.scss" +import ReviewerBottom from "./index.svelte" let time: number; // set in python code let timerStopped = false; @@ -64,3 +66,7 @@ function selectedAnswerButton(): string { return node.dataset.ease; } +mount( + ReviewerBottom, + {target: document.body}, +) From 758cfa269360d8d75716c46265894af26d674d94 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Mon, 25 Aug 2025 21:03:40 +0100 Subject: [PATCH 04/37] Buttons template --- qt/aqt/reviewer.py | 4 +++- ts/routes/reviewer-bottom/index.scss | 1 + ts/routes/reviewer-bottom/index.svelte | 25 ++++++++++++++++++++++--- ts/routes/reviewer-bottom/index.ts | 8 ++++---- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 2ae054184..b75f64fb3 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -847,7 +847,9 @@ timerStopped = false; maxTime = self.card.time_limit() / 1000 else: maxTime = 0 - self.bottom.web.eval("anki.showQuestion(%s,%d);" % (json.dumps(middle), maxTime)) + self.bottom.web.eval( + "anki.showQuestion(%s,%d);" % (json.dumps(middle), maxTime) + ) def _showEaseButtons(self) -> None: if not self._states_mutated: diff --git a/ts/routes/reviewer-bottom/index.scss b/ts/routes/reviewer-bottom/index.scss index fbe069779..7c9985ba6 100644 --- a/ts/routes/reviewer-bottom/index.scss +++ b/ts/routes/reviewer-bottom/index.scss @@ -4,6 +4,7 @@ @use "../../lib/sass/root-vars"; @use "../../lib/sass/vars" as *; @use "../../lib/sass/card-counts"; +@use "../../lib/sass/buttons"; :root { --focus-color: #{palette-of(border-focus)}; diff --git a/ts/routes/reviewer-bottom/index.svelte b/ts/routes/reviewer-bottom/index.svelte index 049eff39e..b4a9ba53b 100644 --- a/ts/routes/reviewer-bottom/index.svelte +++ b/ts/routes/reviewer-bottom/index.svelte @@ -1,3 +1,22 @@ -
- Hello from svelte -
\ No newline at end of file +
+
+
+ +
+
+ +
+
+ +
+
+
+ + diff --git a/ts/routes/reviewer-bottom/index.ts b/ts/routes/reviewer-bottom/index.ts index e4bec417a..d8b7a4c55 100644 --- a/ts/routes/reviewer-bottom/index.ts +++ b/ts/routes/reviewer-bottom/index.ts @@ -6,8 +6,8 @@ */ import { mount } from "svelte"; -import "./index.scss" -import ReviewerBottom from "./index.svelte" +import "./index.scss"; +import ReviewerBottom from "./index.svelte"; let time: number; // set in python code let timerStopped = false; @@ -68,5 +68,5 @@ function selectedAnswerButton(): string { mount( ReviewerBottom, - {target: document.body}, -) + { target: document.body }, +); From 7788aa7785524c7bd114451b7094bf9b0f51c0ba Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Mon, 25 Aug 2025 21:55:21 +0100 Subject: [PATCH 05/37] Answer buttons --- qt/aqt/reviewer.py | 30 ++++++++----------- ts/routes/reviewer-bottom/AnswerButton.svelte | 9 ++++++ ts/routes/reviewer-bottom/index.svelte | 17 ++++++++++- ts/routes/reviewer-bottom/index.ts | 10 ++++--- ts/routes/reviewer-bottom/types.ts | 7 +++++ 5 files changed, 50 insertions(+), 23 deletions(-) create mode 100644 ts/routes/reviewer-bottom/types.ts diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index b75f64fb3..ab51ff805 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -858,7 +858,7 @@ timerStopped = false; middle = self._answerButtons() conf = self.mw.col.decks.config_dict_for_deck_id(self.card.current_deck_id()) self.bottom.web.eval( - f"showAnswer({json.dumps(middle)}, {json.dumps(conf['stopTimerOnAnswer'])});" + f"anki.showAnswer({json.dumps(middle)}, {json.dumps(conf['stopTimerOnAnswer'])});" ) def _remaining(self) -> str: @@ -912,31 +912,25 @@ timerStopped = false; def but(i: int, label: str) -> str: if i == default: - extra = """id="defease" """ + id = "defease" else: - extra = "" + id = "" due = self._buttonTime(i, v3_labels=labels) key = ( tr.actions_shortcut_key(val=aqt.mw.pm.get_answer_key(i)) if aqt.mw.pm.get_answer_key(i) else "" ) - return """ -""" % ( - extra, - key, - i, - i, - label, - due, - ) + return { + "id": id, + "key": key, + "i": i, + "label": label, + "due": due, + } - buf = "
" - for ease, label in self._answerButtonList(): - buf += but(ease, label) - buf += "
" - return buf + return [but(ease, label) for ease, label in self._answerButtonList()] + def _buttonTime(self, i: int, v3_labels: Sequence[str]) -> str: if self.mw.col.conf["estTimes"]: diff --git a/ts/routes/reviewer-bottom/AnswerButton.svelte b/ts/routes/reviewer-bottom/AnswerButton.svelte index e69de29bb..2a04b7a20 100644 --- a/ts/routes/reviewer-bottom/AnswerButton.svelte +++ b/ts/routes/reviewer-bottom/AnswerButton.svelte @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/ts/routes/reviewer-bottom/index.svelte b/ts/routes/reviewer-bottom/index.svelte index b4a9ba53b..f2c8ff02d 100644 --- a/ts/routes/reviewer-bottom/index.svelte +++ b/ts/routes/reviewer-bottom/index.svelte @@ -1,10 +1,25 @@ + +
- + {#if $answerButtons.length} + {#each $answerButtons as answerButton} + + {/each} + {:else} + + {/if}
diff --git a/ts/routes/reviewer-bottom/index.ts b/ts/routes/reviewer-bottom/index.ts index d8b7a4c55..95ab43f00 100644 --- a/ts/routes/reviewer-bottom/index.ts +++ b/ts/routes/reviewer-bottom/index.ts @@ -8,6 +8,7 @@ import { mount } from "svelte"; import "./index.scss"; import ReviewerBottom from "./index.svelte"; +import { writable } from "svelte/store"; let time: number; // set in python code let timerStopped = false; @@ -34,9 +35,10 @@ function updateTime(): void { } let intervalId: number | undefined; +let answerButtons = writable([]) export function showQuestion(txt: string, maxTime_: number): void { - showAnswer(txt); + showAnswer([]); time = 0; maxTime = maxTime_; updateTime(); @@ -53,8 +55,8 @@ export function showQuestion(txt: string, maxTime_: number): void { }, 1000); } -function showAnswer(txt: string, stopTimer = false): void { - document.getElementById("middle").innerHTML = txt; +export function showAnswer(info: AnswerButtonInfo[], stopTimer = false): void { + answerButtons.set(info); timerStopped = stopTimer; } @@ -68,5 +70,5 @@ function selectedAnswerButton(): string { mount( ReviewerBottom, - { target: document.body }, + { target: document.body, props: {answerButtons} }, ); diff --git a/ts/routes/reviewer-bottom/types.ts b/ts/routes/reviewer-bottom/types.ts new file mode 100644 index 000000000..5a4ec8116 --- /dev/null +++ b/ts/routes/reviewer-bottom/types.ts @@ -0,0 +1,7 @@ +interface AnswerButtonInfo { + "extra": string, + "key": string, + "i": number, + "label": string, + "due": string, +} \ No newline at end of file From 5d536f2f8eb890924c95eb3a0e9e0a4c14e92f20 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Mon, 25 Aug 2025 22:01:48 +0100 Subject: [PATCH 06/37] Added: edit button --- ts/routes/reviewer-bottom/index.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ts/routes/reviewer-bottom/index.svelte b/ts/routes/reviewer-bottom/index.svelte index f2c8ff02d..468de32c4 100644 --- a/ts/routes/reviewer-bottom/index.svelte +++ b/ts/routes/reviewer-bottom/index.svelte @@ -2,6 +2,7 @@ import type { Writable } from "svelte/store"; import AnswerButton from "./AnswerButton.svelte"; import { bridgeCommand } from "@tslib/bridgecommand"; + import * as tr from "@generated/ftl" export let answerButtons: Writable $: console.log($answerButtons) @@ -10,7 +11,7 @@
- +
{#if $answerButtons.length} From 8c0d1d1720e30f7757535b5df8fb3968c44069ac Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Mon, 25 Aug 2025 22:30:28 +0100 Subject: [PATCH 07/37] More i18n --- ts/routes/reviewer-bottom/index.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ts/routes/reviewer-bottom/index.svelte b/ts/routes/reviewer-bottom/index.svelte index 468de32c4..280f1c500 100644 --- a/ts/routes/reviewer-bottom/index.svelte +++ b/ts/routes/reviewer-bottom/index.svelte @@ -2,7 +2,7 @@ import type { Writable } from "svelte/store"; import AnswerButton from "./AnswerButton.svelte"; import { bridgeCommand } from "@tslib/bridgecommand"; - import * as tr from "@generated/ftl" + import * as tr from "@generated/ftl"; export let answerButtons: Writable $: console.log($answerButtons) @@ -19,11 +19,11 @@ {/each} {:else} - + {/if}
- +
From f4eb7e0ff9fd3d93f2cfb4a41aa91275ba88a71c Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Mon, 25 Aug 2025 23:32:33 +0100 Subject: [PATCH 08/37] Use sveltekit --- build/configure/src/web.rs | 12 --- qt/aqt/mediasrv.py | 1 + qt/aqt/reviewer.py | 6 +- ts/routes/reviewer-bottom/+page.svelte | 69 +++++++++++++++++ .../{index.svelte => ReviewerBottom.svelte} | 0 ts/routes/reviewer-bottom/index.ts | 74 ------------------- 6 files changed, 73 insertions(+), 89 deletions(-) create mode 100644 ts/routes/reviewer-bottom/+page.svelte rename ts/routes/reviewer-bottom/{index.svelte => ReviewerBottom.svelte} (100%) delete mode 100644 ts/routes/reviewer-bottom/index.ts diff --git a/build/configure/src/web.rs b/build/configure/src/web.rs index 9ee5d74b5..56ef63bad 100644 --- a/build/configure/src/web.rs +++ b/build/configure/src/web.rs @@ -229,18 +229,6 @@ fn build_and_check_pages(build: &mut Build) -> Result<()> { ":sveltekit" ], )?; - build_page( - "reviewer-bottom", - true, - inputs![ - // - ":ts:lib", - ":ts:components", - ":sass", - ":sveltekit" - ], - )?; - Ok(()) } diff --git a/qt/aqt/mediasrv.py b/qt/aqt/mediasrv.py index 820e762d9..0a4fd0ea0 100644 --- a/qt/aqt/mediasrv.py +++ b/qt/aqt/mediasrv.py @@ -334,6 +334,7 @@ def is_sveltekit_page(path: str) -> bool: "import-csv", "import-page", "image-occlusion", + "reviewer-bottom" ] diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index ab51ff805..c6779063f 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -355,7 +355,7 @@ class Reviewer: self.web.allow_drops = True self.web.eval("_blockDefaultDragDropBehavior();") # show answer / ease buttons - self.bottom.web.load_ts_page("reviewer-bottom") + self.bottom.web.load_sveltekit_page("reviewer-bottom") # Showing the question ########################################################################## @@ -848,7 +848,7 @@ timerStopped = false; else: maxTime = 0 self.bottom.web.eval( - "anki.showQuestion(%s,%d);" % (json.dumps(middle), maxTime) + "_showQuestion(%s,%d);" % (json.dumps(middle), maxTime) ) def _showEaseButtons(self) -> None: @@ -858,7 +858,7 @@ timerStopped = false; middle = self._answerButtons() conf = self.mw.col.decks.config_dict_for_deck_id(self.card.current_deck_id()) self.bottom.web.eval( - f"anki.showAnswer({json.dumps(middle)}, {json.dumps(conf['stopTimerOnAnswer'])});" + f"_showAnswer({json.dumps(middle)}, {json.dumps(conf['stopTimerOnAnswer'])});" ) def _remaining(self) -> str: diff --git a/ts/routes/reviewer-bottom/+page.svelte b/ts/routes/reviewer-bottom/+page.svelte new file mode 100644 index 000000000..fa264b129 --- /dev/null +++ b/ts/routes/reviewer-bottom/+page.svelte @@ -0,0 +1,69 @@ + + + \ No newline at end of file diff --git a/ts/routes/reviewer-bottom/index.svelte b/ts/routes/reviewer-bottom/ReviewerBottom.svelte similarity index 100% rename from ts/routes/reviewer-bottom/index.svelte rename to ts/routes/reviewer-bottom/ReviewerBottom.svelte diff --git a/ts/routes/reviewer-bottom/index.ts b/ts/routes/reviewer-bottom/index.ts deleted file mode 100644 index 95ab43f00..000000000 --- a/ts/routes/reviewer-bottom/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright: Ankitects Pty Ltd and contributors - * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ - -/* eslint -@typescript-eslint/no-unused-vars: "off", -*/ - -import { mount } from "svelte"; -import "./index.scss"; -import ReviewerBottom from "./index.svelte"; -import { writable } from "svelte/store"; - -let time: number; // set in python code -let timerStopped = false; - -let maxTime = 0; - -function updateTime(): void { - const timeNode = document.getElementById("time"); - if (maxTime === 0) { - timeNode.textContent = ""; - return; - } - time = Math.min(maxTime, time); - const m = Math.floor(time / 60); - const s = time % 60; - const sStr = String(s).padStart(2, "0"); - const timeString = `${m}:${sStr}`; - - if (maxTime === time) { - timeNode.innerHTML = `${timeString}`; - } else { - timeNode.textContent = timeString; - } -} - -let intervalId: number | undefined; -let answerButtons = writable([]) - -export function showQuestion(txt: string, maxTime_: number): void { - showAnswer([]); - time = 0; - maxTime = maxTime_; - updateTime(); - - if (intervalId !== undefined) { - clearInterval(intervalId); - } - - intervalId = setInterval(function() { - if (!timerStopped) { - time += 1; - updateTime(); - } - }, 1000); -} - -export function showAnswer(info: AnswerButtonInfo[], stopTimer = false): void { - answerButtons.set(info); - timerStopped = stopTimer; -} - -function selectedAnswerButton(): string { - const node = document.activeElement as HTMLElement; - if (!node) { - return; - } - return node.dataset.ease; -} - -mount( - ReviewerBottom, - { target: document.body, props: {answerButtons} }, -); From 7e92c4016938be6964d3d85e89bdf8f4c19b873b Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Mon, 25 Aug 2025 23:35:22 +0100 Subject: [PATCH 09/37] Added: More bridge command --- ts/routes/reviewer-bottom/ReviewerBottom.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/routes/reviewer-bottom/ReviewerBottom.svelte b/ts/routes/reviewer-bottom/ReviewerBottom.svelte index 280f1c500..0345097ae 100644 --- a/ts/routes/reviewer-bottom/ReviewerBottom.svelte +++ b/ts/routes/reviewer-bottom/ReviewerBottom.svelte @@ -23,7 +23,7 @@ {/if}
- +
From 992c8ad73101b4e18534759329203242fda3b941 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 00:45:58 +0100 Subject: [PATCH 10/37] Added: Remaining --- qt/aqt/reviewer.py | 16 +-- ts/routes/reviewer-bottom/+page.svelte | 126 ++++++++++-------- .../reviewer-bottom/RemainingNumber.svelte | 12 ++ .../reviewer-bottom/ReviewerBottom.svelte | 35 +++-- 4 files changed, 114 insertions(+), 75 deletions(-) create mode 100644 ts/routes/reviewer-bottom/RemainingNumber.svelte diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index c6779063f..5ba90995f 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -259,8 +259,6 @@ class Reviewer: if self._reps is None: self._initWeb() - self._showQuestion() - def _get_next_v3_card(self) -> None: assert isinstance(self.mw.col.sched, V3Scheduler) output = self.mw.col.sched.get_queued_cards() @@ -676,6 +674,9 @@ class Reviewer: self.mw.onEditCurrent() elif url == "more": self.showContextMenu() + elif url == "bottomReady": + self._showQuestion() + self._remaining() elif url.startswith("play:"): play_clicked_audio(url, self.card) elif url.startswith("updateToolbar"): @@ -866,15 +867,8 @@ timerStopped = false; return "" counts: list[int | str] - idx, counts_ = self._v3.counts() - counts = cast(list[Union[int, str]], counts_) - counts[idx] = f"{counts[idx]}" - - return f""" -{counts[0]} + -{counts[1]} + -{counts[2]} -""" + idx, counts = self._v3.counts() + self.bottom.web.eval(f"_updateRemaining({json.dumps(counts)},{idx})") def _defaultEase(self) -> Literal[2, 3]: return 3 diff --git a/ts/routes/reviewer-bottom/+page.svelte b/ts/routes/reviewer-bottom/+page.svelte index fa264b129..a5ea9fe09 100644 --- a/ts/routes/reviewer-bottom/+page.svelte +++ b/ts/routes/reviewer-bottom/+page.svelte @@ -1,69 +1,85 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/ts/routes/reviewer-bottom/RemainingNumber.svelte b/ts/routes/reviewer-bottom/RemainingNumber.svelte new file mode 100644 index 000000000..6192df946 --- /dev/null +++ b/ts/routes/reviewer-bottom/RemainingNumber.svelte @@ -0,0 +1,12 @@ + + + + {#if underlined} + + {:else} + + {/if} + diff --git a/ts/routes/reviewer-bottom/ReviewerBottom.svelte b/ts/routes/reviewer-bottom/ReviewerBottom.svelte index 0345097ae..dedf7f011 100644 --- a/ts/routes/reviewer-bottom/ReviewerBottom.svelte +++ b/ts/routes/reviewer-bottom/ReviewerBottom.svelte @@ -3,9 +3,13 @@ import AnswerButton from "./AnswerButton.svelte"; import { bridgeCommand } from "@tslib/bridgecommand"; import * as tr from "@generated/ftl"; + import RemainingNumber from "./RemainingNumber.svelte"; export let answerButtons: Writable - $: console.log($answerButtons) + export let remaining: Writable + export let remainingIndex: Writable + + $: console.log($remaining)
@@ -13,14 +17,21 @@
-
- {#if $answerButtons.length} - {#each $answerButtons as answerButton} - - {/each} - {:else} - - {/if} +
+ + {$remaining[0]} + + {$remaining[1]} + + {$remaining[2]} + +
+ {#if $answerButtons.length} + {#each $answerButtons as answerButton} + + {/each} + {:else} + + {/if} +
@@ -35,4 +46,10 @@ grid-template-columns: auto 1fr auto; justify-items: center; } + + .review-buttons { + display: flex; + flex-direction: column; + align-items: center + } From 8a57d1c5e10ca9208a13652dbe44762f2633da48 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 01:36:17 +0100 Subject: [PATCH 11/37] Fix: showQuestion issues --- qt/aqt/reviewer.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 5ba90995f..fd13584f4 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -259,6 +259,8 @@ class Reviewer: if self._reps is None: self._initWeb() + self._showQuestion() + def _get_next_v3_card(self) -> None: assert isinstance(self.mw.col.sched, V3Scheduler) output = self.mw.col.sched.get_queued_cards() @@ -675,7 +677,6 @@ class Reviewer: elif url == "more": self.showContextMenu() elif url == "bottomReady": - self._showQuestion() self._remaining() elif url.startswith("play:"): play_clicked_audio(url, self.card) @@ -833,23 +834,13 @@ timerStopped = false; ) def _showAnswerButton(self) -> None: - middle = """ -""".format( - tr.actions_shortcut_key(val=tr.studying_space()), - tr.studying_show_answer(), - self._remaining(), - ) # wrap it in a table so it has the same top margin as the ease buttons - middle = ( - "
%s
" - % middle - ) if self.card.should_show_timer(): maxTime = self.card.time_limit() / 1000 else: maxTime = 0 self.bottom.web.eval( - "_showQuestion(%s,%d);" % (json.dumps(middle), maxTime) + "_showQuestion(%s,%d);" % ("", maxTime) ) def _showEaseButtons(self) -> None: From 9dbb7abdbbebef24d21191089acbb3940724d2d6 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 01:46:27 +0100 Subject: [PATCH 12/37] Remove unneeded globals --- ts/routes/reviewer-bottom/+page.svelte | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ts/routes/reviewer-bottom/+page.svelte b/ts/routes/reviewer-bottom/+page.svelte index a5ea9fe09..2b801cf3a 100644 --- a/ts/routes/reviewer-bottom/+page.svelte +++ b/ts/routes/reviewer-bottom/+page.svelte @@ -5,9 +5,9 @@ import ReviewerBottom from "./ReviewerBottom.svelte"; import "./index.scss" - globalThis.answerButtons = writable([]) - globalThis.remaining = writable<[number, number, number]>([0, 0, 0]) - globalThis.remainingIndex = writable(-1) + let answerButtons = writable([]) + let remaining = writable<[number, number, number]>([0, 0, 0]) + let remainingIndex = writable(-1) onMount(() => { let timerStopped = false; @@ -56,13 +56,13 @@ function _showAnswer(info: AnswerButtonInfo[], stopTimer = false): void { console.log(info) - globalThis.answerButtons.set(info); + answerButtons.set(info); timerStopped = stopTimer; } function _updateRemaining(counts: [number, number, number], idx: number) { - globalThis.remaining.set(counts) - globalThis.remainingIndex.set(idx) + remaining.set(counts) + remainingIndex.set(idx) } globalThis._showQuestion = _showQuestion; @@ -82,4 +82,4 @@ - \ No newline at end of file + \ No newline at end of file From b256e88b1d62f9fd28467ba93974caf1ae15c11c Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 01:56:30 +0100 Subject: [PATCH 13/37] Fix: Large font size --- ts/routes/reviewer-bottom/index.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/ts/routes/reviewer-bottom/index.scss b/ts/routes/reviewer-bottom/index.scss index 7c9985ba6..331f2de00 100644 --- a/ts/routes/reviewer-bottom/index.scss +++ b/ts/routes/reviewer-bottom/index.scss @@ -17,6 +17,7 @@ body { margin: 0; padding: 0; + font-size: 12px; } #middle td[align="center"] { From 28402c548db22b970e2085e5484c6225ab903b16 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 01:58:00 +0100 Subject: [PATCH 14/37] Fix: Id not class --- ts/routes/reviewer-bottom/ReviewerBottom.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/routes/reviewer-bottom/ReviewerBottom.svelte b/ts/routes/reviewer-bottom/ReviewerBottom.svelte index dedf7f011..bc1c7b88f 100644 --- a/ts/routes/reviewer-bottom/ReviewerBottom.svelte +++ b/ts/routes/reviewer-bottom/ReviewerBottom.svelte @@ -12,7 +12,7 @@ $: console.log($remaining) -
+
From a3653695626e41cd4e2160c9da859a04c66325ae Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 01:58:52 +0100 Subject: [PATCH 15/37] align items: center --- ts/routes/reviewer-bottom/ReviewerBottom.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/ts/routes/reviewer-bottom/ReviewerBottom.svelte b/ts/routes/reviewer-bottom/ReviewerBottom.svelte index bc1c7b88f..31e3f82fd 100644 --- a/ts/routes/reviewer-bottom/ReviewerBottom.svelte +++ b/ts/routes/reviewer-bottom/ReviewerBottom.svelte @@ -45,6 +45,7 @@ display: grid; grid-template-columns: auto 1fr auto; justify-items: center; + align-items: center; } .review-buttons { From 6c540c89f10593122cc9a62e6169dd35b638c921 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 02:03:13 +0100 Subject: [PATCH 16/37] ./check --- qt/aqt/reviewer.py | 2 +- ts/routes/reviewer-bottom/+page.svelte | 24 +++++++++++-------- ts/routes/reviewer-bottom/AnswerButton.svelte | 1 + .../reviewer-bottom/ReviewerBottom.svelte | 1 + ts/routes/reviewer-bottom/types.ts | 2 +- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index fd13584f4..b3232a9cf 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -10,7 +10,7 @@ from collections.abc import Callable, Generator, Sequence from dataclasses import dataclass from enum import Enum, auto from functools import partial -from typing import Any, Literal, Match, Union, cast +from typing import Any, Literal, Match, cast import aqt import aqt.browser diff --git a/ts/routes/reviewer-bottom/+page.svelte b/ts/routes/reviewer-bottom/+page.svelte index 2b801cf3a..566b287e6 100644 --- a/ts/routes/reviewer-bottom/+page.svelte +++ b/ts/routes/reviewer-bottom/+page.svelte @@ -3,13 +3,15 @@ import { writable } from "svelte/store"; import { bridgeCommand } from "@tslib/bridgecommand"; import ReviewerBottom from "./ReviewerBottom.svelte"; + import type {AnswerButtonInfo} from "./types" import "./index.scss" - let answerButtons = writable([]) - let remaining = writable<[number, number, number]>([0, 0, 0]) - let remainingIndex = writable(-1) + const answerButtons = writable([]) + const remaining = writable<[number, number, number]>([0, 0, 0]) + const remainingIndex = writable(-1) onMount(() => { + /* let timerStopped = false; let maxTime = 0; @@ -31,33 +33,34 @@ } else { timeNode.textContent = timeString; } - } + }*/ let intervalId: number | undefined; - function _showQuestion(txt: string, maxTime_: number): void { + function _showQuestion(_txt: string, _maxTime_: number): void { _showAnswer([]); globalThis.time = 0; - maxTime = maxTime_; + // maxTime = maxTime_; // updateTime(); if (intervalId !== undefined) { clearInterval(intervalId); } + /* intervalId = setInterval(function() { if (!timerStopped) { globalThis.time += 1; //updateTime(); } - }, 1000); + }, 1000);*/ } - function _showAnswer(info: AnswerButtonInfo[], stopTimer = false): void { + function _showAnswer(info: AnswerButtonInfo[], _stopTimer = false): void { console.log(info) answerButtons.set(info); - timerStopped = stopTimer; + // timerStopped = stopTimer; } function _updateRemaining(counts: [number, number, number], idx: number) { @@ -69,6 +72,7 @@ globalThis._showAnswer = _showAnswer; globalThis._updateRemaining = _updateRemaining; + /* function selectedAnswerButton(): string | undefined { const node = document.activeElement as HTMLElement; if (!node) { @@ -76,7 +80,7 @@ } return node.dataset.ease; } - + */ bridgeCommand("bottomReady"); }); diff --git a/ts/routes/reviewer-bottom/AnswerButton.svelte b/ts/routes/reviewer-bottom/AnswerButton.svelte index 2a04b7a20..645a4f4fe 100644 --- a/ts/routes/reviewer-bottom/AnswerButton.svelte +++ b/ts/routes/reviewer-bottom/AnswerButton.svelte @@ -1,5 +1,6 @@ diff --git a/ts/routes/reviewer-bottom/ReviewerBottom.svelte b/ts/routes/reviewer-bottom/ReviewerBottom.svelte index 31e3f82fd..0e2bded32 100644 --- a/ts/routes/reviewer-bottom/ReviewerBottom.svelte +++ b/ts/routes/reviewer-bottom/ReviewerBottom.svelte @@ -4,6 +4,7 @@ import { bridgeCommand } from "@tslib/bridgecommand"; import * as tr from "@generated/ftl"; import RemainingNumber from "./RemainingNumber.svelte"; + import type { AnswerButtonInfo } from "./types"; export let answerButtons: Writable export let remaining: Writable diff --git a/ts/routes/reviewer-bottom/types.ts b/ts/routes/reviewer-bottom/types.ts index 5a4ec8116..48fe4567d 100644 --- a/ts/routes/reviewer-bottom/types.ts +++ b/ts/routes/reviewer-bottom/types.ts @@ -1,4 +1,4 @@ -interface AnswerButtonInfo { +export interface AnswerButtonInfo { "extra": string, "key": string, "i": number, From 860a8b429539b81199e456ae1e0d712831840ee5 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 02:08:24 +0100 Subject: [PATCH 17/37] ./check --- qt/aqt/mediasrv.py | 2 +- qt/aqt/reviewer.py | 12 ++--- ts/routes/reviewer-bottom/+page.svelte | 24 +++++----- ts/routes/reviewer-bottom/AnswerButton.svelte | 10 +++-- .../reviewer-bottom/RemainingNumber.svelte | 12 +++-- .../reviewer-bottom/ReviewerBottom.svelte | 44 ++++++++++++++----- ts/routes/reviewer-bottom/types.ts | 14 +++--- 7 files changed, 74 insertions(+), 44 deletions(-) diff --git a/qt/aqt/mediasrv.py b/qt/aqt/mediasrv.py index 0a4fd0ea0..530b5d022 100644 --- a/qt/aqt/mediasrv.py +++ b/qt/aqt/mediasrv.py @@ -334,7 +334,7 @@ def is_sveltekit_page(path: str) -> bool: "import-csv", "import-page", "image-occlusion", - "reviewer-bottom" + "reviewer-bottom", ] diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index b3232a9cf..9acfd1254 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -839,9 +839,7 @@ timerStopped = false; maxTime = self.card.time_limit() / 1000 else: maxTime = 0 - self.bottom.web.eval( - "_showQuestion(%s,%d);" % ("", maxTime) - ) + self.bottom.web.eval("_showQuestion(%s,%d);" % ("", maxTime)) def _showEaseButtons(self) -> None: if not self._states_mutated: @@ -853,11 +851,10 @@ timerStopped = false; f"_showAnswer({json.dumps(middle)}, {json.dumps(conf['stopTimerOnAnswer'])});" ) - def _remaining(self) -> str: + def _remaining(self): if not self.mw.col.conf["dueCounts"]: return "" - counts: list[int | str] idx, counts = self._v3.counts() self.bottom.web.eval(f"_updateRemaining({json.dumps(counts)},{idx})") @@ -889,13 +886,13 @@ timerStopped = false; ) return buttons_tuple - def _answerButtons(self) -> str: + def _answerButtons(self): default = self._defaultEase() assert isinstance(self.mw.col.sched, V3Scheduler) labels = self.mw.col.sched.describe_next_states(self._v3.states) - def but(i: int, label: str) -> str: + def but(i: int, label: str): if i == default: id = "defease" else: @@ -915,7 +912,6 @@ timerStopped = false; } return [but(ease, label) for ease, label in self._answerButtonList()] - def _buttonTime(self, i: int, v3_labels: Sequence[str]) -> str: if self.mw.col.conf["estTimes"]: diff --git a/ts/routes/reviewer-bottom/+page.svelte b/ts/routes/reviewer-bottom/+page.svelte index 566b287e6..c92e56462 100644 --- a/ts/routes/reviewer-bottom/+page.svelte +++ b/ts/routes/reviewer-bottom/+page.svelte @@ -1,14 +1,18 @@ + - - \ No newline at end of file + diff --git a/ts/routes/reviewer-bottom/AnswerButton.svelte b/ts/routes/reviewer-bottom/AnswerButton.svelte index 645a4f4fe..96918be95 100644 --- a/ts/routes/reviewer-bottom/AnswerButton.svelte +++ b/ts/routes/reviewer-bottom/AnswerButton.svelte @@ -1,10 +1,14 @@ + - \ No newline at end of file + diff --git a/ts/routes/reviewer-bottom/RemainingNumber.svelte b/ts/routes/reviewer-bottom/RemainingNumber.svelte index 6192df946..4761dfdcd 100644 --- a/ts/routes/reviewer-bottom/RemainingNumber.svelte +++ b/ts/routes/reviewer-bottom/RemainingNumber.svelte @@ -1,12 +1,16 @@ + {#if underlined} - + {:else} - + {/if} diff --git a/ts/routes/reviewer-bottom/ReviewerBottom.svelte b/ts/routes/reviewer-bottom/ReviewerBottom.svelte index 0e2bded32..9dd6160b7 100644 --- a/ts/routes/reviewer-bottom/ReviewerBottom.svelte +++ b/ts/routes/reviewer-bottom/ReviewerBottom.svelte @@ -1,3 +1,7 @@ +
- +
- {$remaining[0]} + - {$remaining[1]} + - {$remaining[2]} + + {$remaining[0]} + + + + {$remaining[1]} + + + + {$remaining[2]} +
{#if $answerButtons.length} @@ -30,12 +45,19 @@ {/each} {:else} - + {/if}
- +
@@ -52,6 +74,6 @@ .review-buttons { display: flex; flex-direction: column; - align-items: center + align-items: center; } diff --git a/ts/routes/reviewer-bottom/types.ts b/ts/routes/reviewer-bottom/types.ts index 48fe4567d..4068ca1f9 100644 --- a/ts/routes/reviewer-bottom/types.ts +++ b/ts/routes/reviewer-bottom/types.ts @@ -1,7 +1,9 @@ +// Copyright: Ankitects Pty Ltd and contributors +// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html export interface AnswerButtonInfo { - "extra": string, - "key": string, - "i": number, - "label": string, - "due": string, -} \ No newline at end of file + "extra": string; + "key": string; + "i": number; + "label": string; + "due": string; +} From d49f1eb430a4c5d860a07721b6a5f71468c54a2b Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 02:23:23 +0100 Subject: [PATCH 18/37] Fix: Update remaining on answer shown --- qt/aqt/reviewer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 9acfd1254..6edd73efc 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -839,6 +839,7 @@ timerStopped = false; maxTime = self.card.time_limit() / 1000 else: maxTime = 0 + self._remaining() self.bottom.web.eval("_showQuestion(%s,%d);" % ("", maxTime)) def _showEaseButtons(self) -> None: From fac5d64558c80b889486c8450d066c735a70d279 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Tue, 26 Aug 2025 16:11:45 +0100 Subject: [PATCH 19/37] Manually specify height --- ts/routes/reviewer-bottom/index.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/ts/routes/reviewer-bottom/index.scss b/ts/routes/reviewer-bottom/index.scss index 331f2de00..9675a96a1 100644 --- a/ts/routes/reviewer-bottom/index.scss +++ b/ts/routes/reviewer-bottom/index.scss @@ -18,6 +18,7 @@ body { margin: 0; padding: 0; font-size: 12px; + height: 72px; } #middle td[align="center"] { From 4bf38ec2af5be2c8a435d144913e15e42e01bd75 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 18:40:37 +0100 Subject: [PATCH 20/37] Added: Reviewer entrypoint --- qt/aqt/mediasrv.py | 2 +- qt/aqt/reviewer.py | 13 ++----------- ts/routes/reviewer/+page.svelte | 5 +++++ ts/routes/reviewer/index.ts | 0 .../reviewer-bottom/AnswerButton.svelte | 0 .../reviewer-bottom/RemainingNumber.svelte | 0 .../reviewer-bottom/ReviewerBottom.svelte | 0 .../reviewer-bottom/ReviewerBottomOuter.svelte} | 0 ts/routes/{ => reviewer}/reviewer-bottom/index.scss | 8 ++++---- ts/routes/{ => reviewer}/reviewer-bottom/types.ts | 0 10 files changed, 12 insertions(+), 16 deletions(-) create mode 100644 ts/routes/reviewer/+page.svelte create mode 100644 ts/routes/reviewer/index.ts rename ts/routes/{ => reviewer}/reviewer-bottom/AnswerButton.svelte (100%) rename ts/routes/{ => reviewer}/reviewer-bottom/RemainingNumber.svelte (100%) rename ts/routes/{ => reviewer}/reviewer-bottom/ReviewerBottom.svelte (100%) rename ts/routes/{reviewer-bottom/+page.svelte => reviewer/reviewer-bottom/ReviewerBottomOuter.svelte} (100%) rename ts/routes/{ => reviewer}/reviewer-bottom/index.scss (89%) rename ts/routes/{ => reviewer}/reviewer-bottom/types.ts (100%) diff --git a/qt/aqt/mediasrv.py b/qt/aqt/mediasrv.py index 530b5d022..83f45c933 100644 --- a/qt/aqt/mediasrv.py +++ b/qt/aqt/mediasrv.py @@ -334,7 +334,7 @@ def is_sveltekit_page(path: str) -> bool: "import-csv", "import-page", "image-occlusion", - "reviewer-bottom", + "reviewer", ] diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 6edd73efc..535f87b22 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -341,21 +341,12 @@ class Reviewer: def _initWeb(self) -> None: self._reps = 0 # main window - self.web.stdHtml( - self.revHtml(), - css=["css/reviewer.css"], - js=[ - "js/mathjax.js", - "js/vendor/mathjax/tex-chtml-full.js", - "js/reviewer.js", - ], - context=self, - ) + self.web.load_sveltekit_page("reviewer") # block default drag & drop behavior while allowing drop events to be received by JS handlers self.web.allow_drops = True self.web.eval("_blockDefaultDragDropBehavior();") # show answer / ease buttons - self.bottom.web.load_sveltekit_page("reviewer-bottom") + self.bottom.web = self.web # Showing the question ########################################################################## diff --git a/ts/routes/reviewer/+page.svelte b/ts/routes/reviewer/+page.svelte new file mode 100644 index 000000000..2299e944d --- /dev/null +++ b/ts/routes/reviewer/+page.svelte @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/ts/routes/reviewer/index.ts b/ts/routes/reviewer/index.ts new file mode 100644 index 000000000..e69de29bb diff --git a/ts/routes/reviewer-bottom/AnswerButton.svelte b/ts/routes/reviewer/reviewer-bottom/AnswerButton.svelte similarity index 100% rename from ts/routes/reviewer-bottom/AnswerButton.svelte rename to ts/routes/reviewer/reviewer-bottom/AnswerButton.svelte diff --git a/ts/routes/reviewer-bottom/RemainingNumber.svelte b/ts/routes/reviewer/reviewer-bottom/RemainingNumber.svelte similarity index 100% rename from ts/routes/reviewer-bottom/RemainingNumber.svelte rename to ts/routes/reviewer/reviewer-bottom/RemainingNumber.svelte diff --git a/ts/routes/reviewer-bottom/ReviewerBottom.svelte b/ts/routes/reviewer/reviewer-bottom/ReviewerBottom.svelte similarity index 100% rename from ts/routes/reviewer-bottom/ReviewerBottom.svelte rename to ts/routes/reviewer/reviewer-bottom/ReviewerBottom.svelte diff --git a/ts/routes/reviewer-bottom/+page.svelte b/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte similarity index 100% rename from ts/routes/reviewer-bottom/+page.svelte rename to ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte diff --git a/ts/routes/reviewer-bottom/index.scss b/ts/routes/reviewer/reviewer-bottom/index.scss similarity index 89% rename from ts/routes/reviewer-bottom/index.scss rename to ts/routes/reviewer/reviewer-bottom/index.scss index 9675a96a1..0f189d6b9 100644 --- a/ts/routes/reviewer-bottom/index.scss +++ b/ts/routes/reviewer/reviewer-bottom/index.scss @@ -1,10 +1,10 @@ /* Copyright: Ankitects Pty Ltd and contributors * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ -@use "../../lib/sass/root-vars"; -@use "../../lib/sass/vars" as *; -@use "../../lib/sass/card-counts"; -@use "../../lib/sass/buttons"; +@use "../../../lib/sass/root-vars"; +@use "../../../lib/sass/vars" as *; +@use "../../../lib/sass/card-counts"; +@use "../../../lib/sass/buttons"; :root { --focus-color: #{palette-of(border-focus)}; diff --git a/ts/routes/reviewer-bottom/types.ts b/ts/routes/reviewer/reviewer-bottom/types.ts similarity index 100% rename from ts/routes/reviewer-bottom/types.ts rename to ts/routes/reviewer/reviewer-bottom/types.ts From d81ec73205633b631d1273128e481c9414a30094 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 21:59:34 +0100 Subject: [PATCH 21/37] Use inheritance for reviewer --- qt/aqt/data/web/js/reviewer-bottom.ts | 63 ++++++++++++ qt/aqt/reviewer.py | 141 +++++++++++++++++++++----- 2 files changed, 181 insertions(+), 23 deletions(-) create mode 100644 qt/aqt/data/web/js/reviewer-bottom.ts diff --git a/qt/aqt/data/web/js/reviewer-bottom.ts b/qt/aqt/data/web/js/reviewer-bottom.ts new file mode 100644 index 000000000..c11fa2aa2 --- /dev/null +++ b/qt/aqt/data/web/js/reviewer-bottom.ts @@ -0,0 +1,63 @@ +/* Copyright: Ankitects Pty Ltd and contributors + * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ + +/* eslint +@typescript-eslint/no-unused-vars: "off", +*/ + +let time: number; // set in python code +let timerStopped = false; + +let maxTime = 0; + +function updateTime(): void { + const timeNode = document.getElementById("time"); + if (maxTime === 0) { + timeNode.textContent = ""; + return; + } + time = Math.min(maxTime, time); + const m = Math.floor(time / 60); + const s = time % 60; + const sStr = String(s).padStart(2, "0"); + const timeString = `${m}:${sStr}`; + + if (maxTime === time) { + timeNode.innerHTML = `${timeString}`; + } else { + timeNode.textContent = timeString; + } +} + +let intervalId: number | undefined; + +function showQuestion(txt: string, maxTime_: number): void { + showAnswer(txt); + time = 0; + maxTime = maxTime_; + updateTime(); + + if (intervalId !== undefined) { + clearInterval(intervalId); + } + + intervalId = setInterval(function() { + if (!timerStopped) { + time += 1; + updateTime(); + } + }, 1000); +} + +function showAnswer(txt: string, stopTimer = false): void { + document.getElementById("middle").innerHTML = txt; + timerStopped = stopTimer; +} + +function selectedAnswerButton(): string { + const node = document.activeElement as HTMLElement; + if (!node) { + return; + } + return node.dataset.ease; +} \ No newline at end of file diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 535f87b22..6bbc4f986 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -10,7 +10,7 @@ from collections.abc import Callable, Generator, Sequence from dataclasses import dataclass from enum import Enum, auto from functools import partial -from typing import Any, Literal, Match, cast +from typing import Any, Literal, Match, Union, cast import aqt import aqt.browser @@ -341,12 +341,26 @@ class Reviewer: def _initWeb(self) -> None: self._reps = 0 # main window - self.web.load_sveltekit_page("reviewer") + self.web.stdHtml( + self.revHtml(), + css=["css/reviewer.css"], + js=[ + "js/mathjax.js", + "js/vendor/mathjax/tex-chtml-full.js", + "js/reviewer.js", + ], + context=self, + ) # block default drag & drop behavior while allowing drop events to be received by JS handlers self.web.allow_drops = True self.web.eval("_blockDefaultDragDropBehavior();") # show answer / ease buttons - self.bottom.web = self.web + self.bottom.web.stdHtml( + self._bottomHTML(), + css=["css/toolbar-bottom.css", "css/reviewer-bottom.css"], + js=["js/vendor/jquery.min.js", "js/reviewer-bottom.js"], + context=ReviewerBottomBar(self), + ) # Showing the question ########################################################################## @@ -667,8 +681,6 @@ class Reviewer: self.mw.onEditCurrent() elif url == "more": self.showContextMenu() - elif url == "bottomReady": - self._remaining() elif url.startswith("play:"): play_clicked_audio(url, self.card) elif url.startswith("updateToolbar"): @@ -825,13 +837,22 @@ timerStopped = false; ) def _showAnswerButton(self) -> None: + middle = """ +""".format( + tr.actions_shortcut_key(val=tr.studying_space()), + tr.studying_show_answer(), + self._remaining(), + ) # wrap it in a table so it has the same top margin as the ease buttons + middle = ( + "
%s
" + % middle + ) if self.card.should_show_timer(): maxTime = self.card.time_limit() / 1000 else: maxTime = 0 - self._remaining() - self.bottom.web.eval("_showQuestion(%s,%d);" % ("", maxTime)) + self.bottom.web.eval("showQuestion(%s,%d);" % (json.dumps(middle), maxTime)) def _showEaseButtons(self) -> None: if not self._states_mutated: @@ -840,15 +861,23 @@ timerStopped = false; middle = self._answerButtons() conf = self.mw.col.decks.config_dict_for_deck_id(self.card.current_deck_id()) self.bottom.web.eval( - f"_showAnswer({json.dumps(middle)}, {json.dumps(conf['stopTimerOnAnswer'])});" + f"showAnswer({json.dumps(middle)}, {json.dumps(conf['stopTimerOnAnswer'])});" ) - def _remaining(self): + def _remaining(self) -> str: if not self.mw.col.conf["dueCounts"]: return "" - idx, counts = self._v3.counts() - self.bottom.web.eval(f"_updateRemaining({json.dumps(counts)},{idx})") + counts: list[int | str] + idx, counts_ = self._v3.counts() + counts = cast(list[Union[int, str]], counts_) + counts[idx] = f"{counts[idx]}" + + return f""" +{counts[0]} + +{counts[1]} + +{counts[2]} +""" def _defaultEase(self) -> Literal[2, 3]: return 3 @@ -878,32 +907,39 @@ timerStopped = false; ) return buttons_tuple - def _answerButtons(self): + def _answerButtons(self) -> str: default = self._defaultEase() assert isinstance(self.mw.col.sched, V3Scheduler) labels = self.mw.col.sched.describe_next_states(self._v3.states) - def but(i: int, label: str): + def but(i: int, label: str) -> str: if i == default: - id = "defease" + extra = """id="defease" """ else: - id = "" + extra = "" due = self._buttonTime(i, v3_labels=labels) key = ( tr.actions_shortcut_key(val=aqt.mw.pm.get_answer_key(i)) if aqt.mw.pm.get_answer_key(i) else "" ) - return { - "id": id, - "key": key, - "i": i, - "label": label, - "due": due, - } + return """ +""" % ( + extra, + key, + i, + i, + label, + due, + ) - return [but(ease, label) for ease, label in self._answerButtonList()] + buf = "
" + for ease, label in self._answerButtonList(): + buf += but(ease, label) + buf += "
" + return buf def _buttonTime(self, i: int, v3_labels: Sequence[str]) -> str: if self.mw.col.conf["estTimes"]: @@ -1191,6 +1227,65 @@ timerStopped = false; onMark = toggle_mark_on_current_note setFlag = set_flag_on_current_card +class SvelteReviewer(Reviewer): + def _answerButtons(self) -> str: + default = self._defaultEase() + + assert isinstance(self.mw.col.sched, V3Scheduler) + labels = self.mw.col.sched.describe_next_states(self._v3.states) + + def but(i: int, label: str): + if i == default: + id = "defease" + else: + id = "" + due = self._buttonTime(i, v3_labels=labels) + key = ( + tr.actions_shortcut_key(val=aqt.mw.pm.get_answer_key(i)) + if aqt.mw.pm.get_answer_key(i) + else "" + ) + return { + "id": id, + "key": key, + "i": i, + "label": label, + "due": due, + } + + return [but(ease, label) for ease, label in self._answerButtonList()] + + def _remaining(self) -> str: + if not self.mw.col.conf["dueCounts"]: + return "" + + idx, counts = self._v3.counts() + self.bottom.web.eval(f"_updateRemaining({json.dumps(counts)},{idx})") + + def _showAnswerButton(self) -> None: + if self.card.should_show_timer(): + maxTime = self.card.time_limit() / 1000 + else: + maxTime = 0 + self._remaining() + self.bottom.web.eval("_showQuestion(%s,%d);" % ("", maxTime)) + + def _linkHandler(self, url: str) -> None: + if url == "bottomReady": + self._remaining() + return + super()._linkHandler(url) + + def _initWeb(self) -> None: + self._reps = 0 + # main window + self.web.load_sveltekit_page("reviewer") + # block default drag & drop behavior while allowing drop events to be received by JS handlers + self.web.allow_drops = True + self.web.eval("_blockDefaultDragDropBehavior();") + # ensure bottom web functions trigger + self.bottom.web = self.web + # if the last element is a comment, then the RUN_STATE_MUTATION code # breaks due to the comment wrongly commenting out python code. From 7cb8e622547900f3c9a42303bdfc2c31e3d6fb4c Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 21:59:46 +0100 Subject: [PATCH 22/37] revert random rust changes --- build/configure/src/web.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/configure/src/web.rs b/build/configure/src/web.rs index 56ef63bad..3e695e01e 100644 --- a/build/configure/src/web.rs +++ b/build/configure/src/web.rs @@ -1,7 +1,6 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -use anyhow::Ok; use anyhow::Result; use ninja_gen::action::BuildAction; use ninja_gen::copy::CopyFiles; @@ -229,6 +228,7 @@ fn build_and_check_pages(build: &mut Build) -> Result<()> { ":sveltekit" ], )?; + Ok(()) } From f01e0f8d0b0133af8a22a95024c9ec05c802801a Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 22:01:41 +0100 Subject: [PATCH 23/37] toggle svelte reviewer on --- qt/aqt/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qt/aqt/main.py b/qt/aqt/main.py index c707d1b2a..0c009a16c 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -1075,9 +1075,9 @@ title="{}" {}>{}""".format( self.overview = Overview(self) def setupReviewer(self) -> None: - from aqt.reviewer import Reviewer + from aqt.reviewer import Reviewer, SvelteReviewer - self.reviewer = Reviewer(self) + self.reviewer = SvelteReviewer(self) if True else Reviewer(self) # Syncing ########################################################################## From e46d98e2e044ec45f286d3b30e9f968ab6fe5a88 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 22:05:35 +0100 Subject: [PATCH 24/37] ./check --- build/configure/src/web.rs | 2 +- qt/aqt/data/web/js/reviewer-bottom.ts | 2 +- qt/aqt/main.py | 2 +- qt/aqt/reviewer.py | 1 + ts/routes/reviewer/+page.svelte | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build/configure/src/web.rs b/build/configure/src/web.rs index 3e695e01e..ef2d268bb 100644 --- a/build/configure/src/web.rs +++ b/build/configure/src/web.rs @@ -228,7 +228,7 @@ fn build_and_check_pages(build: &mut Build) -> Result<()> { ":sveltekit" ], )?; - + Ok(()) } diff --git a/qt/aqt/data/web/js/reviewer-bottom.ts b/qt/aqt/data/web/js/reviewer-bottom.ts index c11fa2aa2..4ebf34510 100644 --- a/qt/aqt/data/web/js/reviewer-bottom.ts +++ b/qt/aqt/data/web/js/reviewer-bottom.ts @@ -60,4 +60,4 @@ function selectedAnswerButton(): string { return; } return node.dataset.ease; -} \ No newline at end of file +} diff --git a/qt/aqt/main.py b/qt/aqt/main.py index 0c009a16c..3affb3a2e 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -1077,7 +1077,7 @@ title="{}" {}>{}""".format( def setupReviewer(self) -> None: from aqt.reviewer import Reviewer, SvelteReviewer - self.reviewer = SvelteReviewer(self) if True else Reviewer(self) + self.reviewer = SvelteReviewer(self) if True else Reviewer(self) # Syncing ########################################################################## diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 6bbc4f986..8cd02813d 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -1227,6 +1227,7 @@ timerStopped = false; onMark = toggle_mark_on_current_note setFlag = set_flag_on_current_card + class SvelteReviewer(Reviewer): def _answerButtons(self) -> str: default = self._defaultEase() diff --git a/ts/routes/reviewer/+page.svelte b/ts/routes/reviewer/+page.svelte index 2299e944d..8892f24c8 100644 --- a/ts/routes/reviewer/+page.svelte +++ b/ts/routes/reviewer/+page.svelte @@ -2,4 +2,4 @@ import ReviewerBottomOuter from "./reviewer-bottom/ReviewerBottomOuter.svelte"; - \ No newline at end of file + From 9d3451f97b92b127b392adb35c8734c47531662f Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 22:07:44 +0100 Subject: [PATCH 25/37] fix py issues --- qt/aqt/reviewer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 8cd02813d..1108b9e8f 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -1254,7 +1254,7 @@ class SvelteReviewer(Reviewer): "due": due, } - return [but(ease, label) for ease, label in self._answerButtonList()] + return [but(ease, label) for ease, label in self._answerButtonList()] # type: ignore def _remaining(self) -> str: if not self.mw.col.conf["dueCounts"]: @@ -1262,6 +1262,7 @@ class SvelteReviewer(Reviewer): idx, counts = self._v3.counts() self.bottom.web.eval(f"_updateRemaining({json.dumps(counts)},{idx})") + return "" def _showAnswerButton(self) -> None: if self.card.should_show_timer(): From c64dd6c9593ae2ae2ca20c38868b73eda13a5975 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 22:29:23 +0100 Subject: [PATCH 26/37] Neaten bottom code --- .../ReviewerBottomOuter.svelte | 83 ++---------------- .../reviewer/reviewer-bottom/reviewer.ts | 86 +++++++++++++++++++ 2 files changed, 92 insertions(+), 77 deletions(-) create mode 100644 ts/routes/reviewer/reviewer-bottom/reviewer.ts diff --git a/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte b/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte index c92e56462..2e95d1965 100644 --- a/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte +++ b/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte @@ -4,88 +4,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html --> - +{#if reviewerInfo} + +{/if} diff --git a/ts/routes/reviewer/reviewer-bottom/reviewer.ts b/ts/routes/reviewer/reviewer-bottom/reviewer.ts new file mode 100644 index 000000000..ce25f719c --- /dev/null +++ b/ts/routes/reviewer/reviewer-bottom/reviewer.ts @@ -0,0 +1,86 @@ +import { writable } from "svelte/store"; +import type { AnswerButtonInfo } from "./types"; +import { bridgeCommand } from "@tslib/bridgecommand"; + +export function setupBottomBar() { + /* + let timerStopped = false; + + let maxTime = 0; + + function updateTime(): void { + const timeNode = document.getElementById("time"); + if (maxTime === 0) { + timeNode.textContent = ""; + return; + } + globalThis.time = Math.min(maxTime, globalThis.time); + const m = Math.floor(globalThis.time / 60); + const s = globalThis.time % 60; + const sStr = String(s).padStart(2, "0"); + const timeString = `${m}:${sStr}`; + + if (maxTime === time) { + timeNode.innerHTML = `${timeString}`; + } else { + timeNode.textContent = timeString; + } + }*/ + + const answerButtons = writable([]); + const remaining = writable<[number, number, number]>([0, 0, 0]); + const remainingIndex = writable(-1); + + let intervalId: number | undefined; + + function _showQuestion(_txt: string, _maxTime_: number): void { + _showAnswer([]); + globalThis.time = 0; + // maxTime = maxTime_; + // updateTime(); + + if (intervalId !== undefined) { + clearInterval(intervalId); + } + + /* + intervalId = setInterval(function() { + if (!timerStopped) { + globalThis.time += 1; + //updateTime(); + } + }, 1000);*/ + } + + function _showAnswer(info: AnswerButtonInfo[], _stopTimer = false): void { + console.log(info); + answerButtons.set(info); + // timerStopped = stopTimer; + } + + function _updateRemaining(counts: [number, number, number], idx: number) { + remaining.set(counts); + remainingIndex.set(idx); + } + + globalThis._showQuestion = _showQuestion; + globalThis._showAnswer = _showAnswer; + globalThis._updateRemaining = _updateRemaining; + + /* + function selectedAnswerButton(): string | undefined { + const node = document.activeElement as HTMLElement; + if (!node) { + return; + } + return node.dataset.ease; + } + */ + bridgeCommand("bottomReady"); + + return { + answerButtons, + remaining, + remainingIndex, + }; +} \ No newline at end of file From 7805b1b426bd53a28bb7f89dbd21fbde859f436f Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 22:34:26 +0100 Subject: [PATCH 27/37] Fix: Wrong function name --- ts/routes/reviewer/reviewer-bottom/reviewer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/routes/reviewer/reviewer-bottom/reviewer.ts b/ts/routes/reviewer/reviewer-bottom/reviewer.ts index ce25f719c..1729f8c2c 100644 --- a/ts/routes/reviewer/reviewer-bottom/reviewer.ts +++ b/ts/routes/reviewer/reviewer-bottom/reviewer.ts @@ -64,7 +64,7 @@ export function setupBottomBar() { } globalThis._showQuestion = _showQuestion; - globalThis._showAnswer = _showAnswer; + globalThis.showAnswer = _showAnswer; globalThis._updateRemaining = _updateRemaining; /* From eac356139c4bdf0e019d32acb0e4e68b213df614 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 22:48:51 +0100 Subject: [PATCH 28/37] Added: Reviewer framework --- ts/routes/reviewer/+page.svelte | 14 ++++++++++++- .../ReviewerBottomOuter.svelte | 2 +- .../{reviewer.ts => reviewer-bottom.ts} | 0 ts/routes/reviewer/reviewer.svelte | 15 +++++++++++++ ts/routes/reviewer/reviewer.ts | 7 +++++++ ts/routes/reviewer/reviewerOuter.svelte | 21 +++++++++++++++++++ 6 files changed, 57 insertions(+), 2 deletions(-) rename ts/routes/reviewer/reviewer-bottom/{reviewer.ts => reviewer-bottom.ts} (100%) create mode 100644 ts/routes/reviewer/reviewer.svelte create mode 100644 ts/routes/reviewer/reviewer.ts create mode 100644 ts/routes/reviewer/reviewerOuter.svelte diff --git a/ts/routes/reviewer/+page.svelte b/ts/routes/reviewer/+page.svelte index 8892f24c8..2baa1b1f6 100644 --- a/ts/routes/reviewer/+page.svelte +++ b/ts/routes/reviewer/+page.svelte @@ -1,5 +1,17 @@ - +
+ + +
+ + diff --git a/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte b/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte index 2e95d1965..5c66485e0 100644 --- a/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte +++ b/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte @@ -6,7 +6,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import { onMount } from "svelte"; import ReviewerBottom from "./ReviewerBottom.svelte"; import "./index.scss"; - import { setupBottomBar } from "./reviewer"; + import { setupBottomBar } from "./reviewer-bottom"; let reviewerInfo: null | ReturnType = null; diff --git a/ts/routes/reviewer/reviewer-bottom/reviewer.ts b/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts similarity index 100% rename from ts/routes/reviewer/reviewer-bottom/reviewer.ts rename to ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts diff --git a/ts/routes/reviewer/reviewer.svelte b/ts/routes/reviewer/reviewer.svelte new file mode 100644 index 000000000..85124fb0a --- /dev/null +++ b/ts/routes/reviewer/reviewer.svelte @@ -0,0 +1,15 @@ + + +
+ {@html $html} +
+ + diff --git a/ts/routes/reviewer/reviewer.ts b/ts/routes/reviewer/reviewer.ts new file mode 100644 index 000000000..866e74d57 --- /dev/null +++ b/ts/routes/reviewer/reviewer.ts @@ -0,0 +1,7 @@ +import { writable } from "svelte/store" + +export function setupReviewer() { + const html = writable("") + + return {html} +} \ No newline at end of file diff --git a/ts/routes/reviewer/reviewerOuter.svelte b/ts/routes/reviewer/reviewerOuter.svelte new file mode 100644 index 000000000..71a818942 --- /dev/null +++ b/ts/routes/reviewer/reviewerOuter.svelte @@ -0,0 +1,21 @@ + + + +{#if reviewerInfo} + +{/if} From d0d1c519e6d08db52a447166734515b8ad963774 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 22:57:36 +0100 Subject: [PATCH 29/37] Naive reviewer --- ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts | 2 +- ts/routes/reviewer/reviewer.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts b/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts index 1729f8c2c..267531d2d 100644 --- a/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts +++ b/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts @@ -63,7 +63,7 @@ export function setupBottomBar() { remainingIndex.set(idx); } - globalThis._showQuestion = _showQuestion; + globalThis.showQuestion = _showQuestion; globalThis.showAnswer = _showAnswer; globalThis._updateRemaining = _updateRemaining; diff --git a/ts/routes/reviewer/reviewer.ts b/ts/routes/reviewer/reviewer.ts index 866e74d57..d1f2f77f0 100644 --- a/ts/routes/reviewer/reviewer.ts +++ b/ts/routes/reviewer/reviewer.ts @@ -1,7 +1,16 @@ import { writable } from "svelte/store" +import { preloadAnswerImages } from "../../reviewer/images" export function setupReviewer() { const html = writable("") + function showQuestion(q, a, bodyclass) { + html.set(q) + preloadAnswerImages(a) + } + + globalThis._showAnswer = html.set + globalThis._showQuestion = showQuestion + return {html} } \ No newline at end of file From f35b2cf5d219ecc1d3413ea6ac874542f4f27442 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 23:07:04 +0100 Subject: [PATCH 30/37] bodyclass --- ts/routes/reviewer/reviewer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ts/routes/reviewer/reviewer.ts b/ts/routes/reviewer/reviewer.ts index d1f2f77f0..48d35f7ba 100644 --- a/ts/routes/reviewer/reviewer.ts +++ b/ts/routes/reviewer/reviewer.ts @@ -6,6 +6,7 @@ export function setupReviewer() { function showQuestion(q, a, bodyclass) { html.set(q) + document.body.className = bodyclass preloadAnswerImages(a) } From 0acc8d14e0227a8daf1fd016875385d910654177 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 23:14:19 +0100 Subject: [PATCH 31/37] Fix: Card style --- ts/routes/reviewer/reviewer.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/routes/reviewer/reviewer.svelte b/ts/routes/reviewer/reviewer.svelte index 85124fb0a..d01486806 100644 --- a/ts/routes/reviewer/reviewer.svelte +++ b/ts/routes/reviewer/reviewer.svelte @@ -4,12 +4,12 @@ export let html: Writable -
+
{@html $html}
From a08bca267353cc78dbb3ed25be274b8fe2517fdc Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 23:24:45 +0100 Subject: [PATCH 32/37] dumb initial _showQuestion call --- qt/aqt/reviewer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 1108b9e8f..d51c7c32c 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -1274,6 +1274,7 @@ class SvelteReviewer(Reviewer): def _linkHandler(self, url: str) -> None: if url == "bottomReady": + self._showQuestion() self._remaining() return super()._linkHandler(url) From 45793b3b64763b44522aca59562c9517818805a9 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 23:36:29 +0100 Subject: [PATCH 33/37] Added: Todo --- ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts b/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts index 267531d2d..bb44dad2b 100644 --- a/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts +++ b/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts @@ -76,6 +76,10 @@ export function setupBottomBar() { return node.dataset.ease; } */ + + // TODO This should probably be a "ready" command now that it is part of the actual reviewer, + // Currently this depends on this component mounting after the reviewer which it should but seems hacky. + // Maybe use a counter with a counter.subscribe($counter == 2 then call("ready")) bridgeCommand("bottomReady"); return { From 2e0a75ed83658ab464b0c2f7ba33d6c4422d9368 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 23:38:28 +0100 Subject: [PATCH 34/37] fix: "card" class included bottombar --- ts/routes/reviewer/reviewer.svelte | 3 ++- ts/routes/reviewer/reviewer.ts | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ts/routes/reviewer/reviewer.svelte b/ts/routes/reviewer/reviewer.svelte index d01486806..f4fdd37af 100644 --- a/ts/routes/reviewer/reviewer.svelte +++ b/ts/routes/reviewer/reviewer.svelte @@ -2,9 +2,10 @@ import type { Writable } from "svelte/store"; export let html: Writable + export let cardClass: Writable -
+
{@html $html}
diff --git a/ts/routes/reviewer/reviewer.ts b/ts/routes/reviewer/reviewer.ts index 48d35f7ba..d7d1fa35f 100644 --- a/ts/routes/reviewer/reviewer.ts +++ b/ts/routes/reviewer/reviewer.ts @@ -3,15 +3,16 @@ import { preloadAnswerImages } from "../../reviewer/images" export function setupReviewer() { const html = writable("") + const cardClass = writable("") - function showQuestion(q, a, bodyclass) { + function showQuestion(q, a, cc) { html.set(q) - document.body.className = bodyclass + cardClass.set(cc) preloadAnswerImages(a) } globalThis._showAnswer = html.set globalThis._showQuestion = showQuestion - return {html} + return {html, cardClass} } \ No newline at end of file From d775efcb0627db7e3c941ed87359231b059bacaa Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Wed, 3 Sep 2025 23:40:37 +0100 Subject: [PATCH 35/37] hide bottomweb --- qt/aqt/reviewer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index d51c7c32c..ccbb43773 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -1288,6 +1288,7 @@ class SvelteReviewer(Reviewer): self.web.eval("_blockDefaultDragDropBehavior();") # ensure bottom web functions trigger self.bottom.web = self.web + self.mw.bottomWeb.hide() # if the last element is a comment, then the RUN_STATE_MUTATION code From c7fd7a096579f0d8e0996940cb158b6e2c7107d5 Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Thu, 4 Sep 2025 00:25:22 +0100 Subject: [PATCH 36/37] re-add reviewer-bottom to build script --- build/configure/src/aqt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/configure/src/aqt.rs b/build/configure/src/aqt.rs index 183b7f0b3..83be77e91 100644 --- a/build/configure/src/aqt.rs +++ b/build/configure/src/aqt.rs @@ -170,7 +170,7 @@ fn build_imgs(build: &mut Build) -> Result<()> { } fn build_js(build: &mut Build) -> Result<()> { - for ts_file in &["deckbrowser", "webview", "toolbar"] { + for ts_file in &["deckbrowser", "webview", "toolbar", "reviewer-bottom"] { build.add_action( "qt:aqt:data:web:js", EsbuildScript { From 1e67a773c6e21dc9938d9e148f02452b94cbf8be Mon Sep 17 00:00:00 2001 From: Luc Mcgrady Date: Thu, 4 Sep 2025 00:26:10 +0100 Subject: [PATCH 37/37] ./check --- .../ReviewerBottomOuter.svelte | 2 +- .../reviewer-bottom/reviewer-bottom.ts | 6 ++--- ts/routes/reviewer/reviewer.svelte | 6 ++--- ts/routes/reviewer/reviewer.ts | 22 +++++++++---------- ts/routes/reviewer/reviewerOuter.svelte | 4 ++-- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte b/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte index 5c66485e0..59747cc5d 100644 --- a/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte +++ b/ts/routes/reviewer/reviewer-bottom/ReviewerBottomOuter.svelte @@ -11,7 +11,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html let reviewerInfo: null | ReturnType = null; onMount(() => { - reviewerInfo = setupBottomBar() + reviewerInfo = setupBottomBar(); }); diff --git a/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts b/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts index bb44dad2b..deedbd4bd 100644 --- a/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts +++ b/ts/routes/reviewer/reviewer-bottom/reviewer-bottom.ts @@ -1,6 +1,6 @@ +import { bridgeCommand } from "@tslib/bridgecommand"; import { writable } from "svelte/store"; import type { AnswerButtonInfo } from "./types"; -import { bridgeCommand } from "@tslib/bridgecommand"; export function setupBottomBar() { /* @@ -77,7 +77,7 @@ export function setupBottomBar() { } */ - // TODO This should probably be a "ready" command now that it is part of the actual reviewer, + // TODO This should probably be a "ready" command now that it is part of the actual reviewer, // Currently this depends on this component mounting after the reviewer which it should but seems hacky. // Maybe use a counter with a counter.subscribe($counter == 2 then call("ready")) bridgeCommand("bottomReady"); @@ -87,4 +87,4 @@ export function setupBottomBar() { remaining, remainingIndex, }; -} \ No newline at end of file +} diff --git a/ts/routes/reviewer/reviewer.svelte b/ts/routes/reviewer/reviewer.svelte index f4fdd37af..aee74e922 100644 --- a/ts/routes/reviewer/reviewer.svelte +++ b/ts/routes/reviewer/reviewer.svelte @@ -1,8 +1,8 @@
@@ -11,6 +11,6 @@ diff --git a/ts/routes/reviewer/reviewer.ts b/ts/routes/reviewer/reviewer.ts index d7d1fa35f..c2f4ea781 100644 --- a/ts/routes/reviewer/reviewer.ts +++ b/ts/routes/reviewer/reviewer.ts @@ -1,18 +1,18 @@ -import { writable } from "svelte/store" -import { preloadAnswerImages } from "../../reviewer/images" +import { writable } from "svelte/store"; +import { preloadAnswerImages } from "../../reviewer/images"; export function setupReviewer() { - const html = writable("") - const cardClass = writable("") + const html = writable(""); + const cardClass = writable(""); function showQuestion(q, a, cc) { - html.set(q) - cardClass.set(cc) - preloadAnswerImages(a) + html.set(q); + cardClass.set(cc); + preloadAnswerImages(a); } - globalThis._showAnswer = html.set - globalThis._showQuestion = showQuestion + globalThis._showAnswer = html.set; + globalThis._showQuestion = showQuestion; - return {html, cardClass} -} \ No newline at end of file + return { html, cardClass }; +} diff --git a/ts/routes/reviewer/reviewerOuter.svelte b/ts/routes/reviewer/reviewerOuter.svelte index 71a818942..c261675f7 100644 --- a/ts/routes/reviewer/reviewerOuter.svelte +++ b/ts/routes/reviewer/reviewerOuter.svelte @@ -7,12 +7,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import { setupReviewer } from "./reviewer"; import Reviewer from "./reviewer.svelte"; - import "../../reviewer/reviewer.scss" + import "../../reviewer/reviewer.scss"; let reviewerInfo: null | ReturnType = null; onMount(() => { - reviewerInfo = setupReviewer() + reviewerInfo = setupReviewer(); });