From 0ef28853fd96c2ec516339c9f6c147003556edac Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sat, 30 Sep 2023 15:38:11 +1000 Subject: [PATCH] Fix TypeError when deck list or overview refreshes during optimal retention Caused by legacy code blocking the main thread. https://forums.ankiweb.net/t/anki-23-10-beta/34912/79 --- pylib/anki/scheduler/dummy.py | 4 ++-- qt/aqt/deckbrowser.py | 19 ++++++++++++++----- qt/aqt/overview.py | 18 ++++++++++++------ 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/pylib/anki/scheduler/dummy.py b/pylib/anki/scheduler/dummy.py index 283d702bc..5732ad346 100644 --- a/pylib/anki/scheduler/dummy.py +++ b/pylib/anki/scheduler/dummy.py @@ -29,5 +29,5 @@ class DummyScheduler(SchedulerBaseWithLegacy): def active_decks(self) -> list[DeckId]: return [] - def counts(self) -> list[int]: - return [0, 0, 0] + def counts(self) -> tuple[int, int, int]: + return (0, 0, 0) diff --git a/qt/aqt/deckbrowser.py b/qt/aqt/deckbrowser.py index 80a2e13b4..f0b91adfd 100644 --- a/qt/aqt/deckbrowser.py +++ b/qt/aqt/deckbrowser.py @@ -146,12 +146,21 @@ class DeckBrowser: def _renderPage(self, reuse: bool = False) -> None: if not reuse: - self._dueTree = self.mw.col.sched.deck_due_tree() - self.__renderPage(None) - return - self.web.evalWithCallback("window.pageYOffset", self.__renderPage) - def __renderPage(self, offset: int) -> None: + def success(tree: DeckTreeNode) -> None: + self._dueTree = tree + self.__renderPage(None) + return + + QueryOp( + parent=self.mw, + op=lambda col: col.sched.deck_due_tree(), + success=success, + ).run_in_background() + else: + self.web.evalWithCallback("window.pageYOffset", self.__renderPage) + + def __renderPage(self, offset: int | None) -> None: content = DeckBrowserContent( tree=self._renderDeckTree(self._dueTree), stats=self._renderStats(), diff --git a/qt/aqt/overview.py b/qt/aqt/overview.py index 9d64b0db6..97251775d 100644 --- a/qt/aqt/overview.py +++ b/qt/aqt/overview.py @@ -12,6 +12,7 @@ from anki.scheduler import UnburyDeck from aqt import gui_hooks from aqt.deckdescription import DeckDescriptionDialog from aqt.deckoptions import display_options_for_deck +from aqt.operations import QueryOp from aqt.operations.scheduling import ( empty_filtered_deck, rebuild_filtered_deck, @@ -61,12 +62,17 @@ class Overview: self.refresh() def refresh(self) -> None: - self._refresh_needed = False - self.mw.col.reset() - self._renderPage() - self._renderBottom() - self.mw.web.setFocus() - gui_hooks.overview_did_refresh(self) + def success(_counts: tuple) -> None: + self._refresh_needed = False + self.mw.col.reset() + self._renderPage() + self._renderBottom() + self.mw.web.setFocus() + gui_hooks.overview_did_refresh(self) + + QueryOp( + parent=self.mw, op=lambda col: col.sched.counts(), success=success + ).run_in_background() def refresh_if_needed(self) -> None: if self._refresh_needed: