From aa6cf80c428df5c10c3d53d8c6e6731d1f4a1371 Mon Sep 17 00:00:00 2001 From: RisingOrange Date: Thu, 16 Jan 2025 18:04:27 +0100 Subject: [PATCH] fix: Fetch is_premium_or_trialing in background --- ankihub/gui/reviewer.py | 36 +++++++++++++++++++-- ankihub/gui/web/reviewer_buttons.js | 49 +++++++++++++++++++++++------ ankihub/gui/web/templates.py | 10 +----- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/ankihub/gui/reviewer.py b/ankihub/gui/reviewer.py index 281532b28..a550649dd 100644 --- a/ankihub/gui/reviewer.py +++ b/ankihub/gui/reviewer.py @@ -24,6 +24,7 @@ from aqt.webview import AnkiWebPage, WebContent from .. import LOGGER +from ..addon_ankihub_client import AddonAnkiHubClient as AnkiHubClient from ..db import ankihub_db from ..gui.menu import AnkiHubLogin from ..gui.webview import AuthenticationRequestInterceptor, CustomWebPage # noqa: F401 @@ -31,6 +32,7 @@ from ..settings import config, url_login from .config_dialog import get_config_dialog_manager from .js_message_handling import VIEW_NOTE_PYCMD, parse_js_message_kwargs +from .operations import AddonQueryOp from .utils import get_ah_did_of_deck_or_ancestor_deck, using_qt5 from .web.templates import ( get_empty_state_html, @@ -425,15 +427,45 @@ def _inject_ankihub_features_and_setup_sidebar( if not isinstance(context, Reviewer): return + reviewer: Reviewer = context + reviewer_button_js = get_reviewer_buttons_js(theme=_ankihub_theme()) web_content.body += f"" global reviewer_sidebar if not reviewer_sidebar: - reviewer_sidebar = ReviewerSidebar(context) - aqt.mw.reviewer.sidebar = reviewer_sidebar # type: ignore[attr-defined] + reviewer_sidebar = ReviewerSidebar(reviewer) + reviewer.sidebar = reviewer_sidebar # type: ignore[attr-defined] reviewer_sidebar.set_on_auth_failure_hook(_handle_auth_failure) + def on_load_finished(ok: bool): + if ok: + _fetch_is_premium_or_trialing_and_notify_reviewer_buttons() + reviewer.web.loadFinished.disconnect(on_load_finished) + + qconnect(reviewer.web.loadFinished, on_load_finished) + + +def _fetch_is_premium_or_trialing_and_notify_reviewer_buttons() -> None: + """Fetches the user's premium or trialing status in the background and notifies the reviewer buttons + once the status is fetched.""" + + def fetch_is_premium_or_trialing(_) -> bool: + client = AnkiHubClient() + return client.is_premium_or_trialing() + + def notify_reviewer_buttons(is_premium_or_trialing: bool) -> None: + js = _wrap_with_reviewer_buttons_check( + f"ankihubReviewerButtons.updateIsPremiumOrTrialing({'true' if is_premium_or_trialing else 'false'})" + ) + aqt.mw.reviewer.web.eval(js) + + op = AddonQueryOp( + op=fetch_is_premium_or_trialing, success=notify_reviewer_buttons, parent=aqt.mw + ).without_collection() + + op.run_in_background() + def _related_ah_deck_has_note_embeddings(note: Note) -> bool: ah_did_of_note = ankihub_db.ankihub_did_for_anki_nid(note.id) diff --git a/ankihub/gui/web/reviewer_buttons.js b/ankihub/gui/web/reviewer_buttons.js index a22970a0f..d3bbb04de 100644 --- a/ankihub/gui/web/reviewer_buttons.js +++ b/ankihub/gui/web/reviewer_buttons.js @@ -3,7 +3,7 @@ class AnkiHubReviewerButtons { constructor() { this.theme = "{{ THEME }}"; - this.isPremiumOrTrialing = "{{ IS_PREMIUM_OR_TRIALING }}" == "True"; + this.isPremiumOrTrialing = false; this.bbCount = 0; this.faCount = 0; @@ -22,6 +22,8 @@ class AnkiHubReviewerButtons { name: "b&b", iconPath: "/_b&b_icon.svg", iconPathDarkTheme: "/_b&b_icon_dark_theme.svg", + premiumIconPath: null, + premiumIconPathDarkTheme: null, active: false, visible: true, tooltip: "Boards & Beyond", @@ -30,14 +32,18 @@ class AnkiHubReviewerButtons { name: "fa4", iconPath: "/_fa4_icon.svg", iconPathDarkTheme: "/_fa4_icon_dark_theme.svg", + premiumIconPath: null, + premiumIconPathDarkTheme: null, active: false, visible: true, tooltip: "First Aid Forward", }, { name: "chatbot", - iconPath: this.isPremiumOrTrialing ? "/_chatbot_icon.svg" : "/_chatbot_icon_sleeping.svg", - iconPathDarkTheme: this.isPremiumOrTrialing ? null : "/_chatbot_icon_sleeping_dark_theme.svg", + iconPath: "/_chatbot_icon_sleeping.svg", + iconPathDarkTheme: "/_chatbot_icon_sleeping_dark_theme.svg", + premiumIconPath: "/_chatbot_icon.svg", + premiumIconPathDarkTheme: "/_chatbot_icon.svg", active: false, visible: true, tooltip: "AI Chatbot" @@ -90,13 +96,7 @@ class AnkiHubReviewerButtons { buttonElement.id = `ankihub-${buttonData.name}-button`; buttonElement.classList.add("ankihub-reviewer-button"); - this.setButtonStyle( - buttonElement, - ( - this.theme == "dark" && buttonData.iconPathDarkTheme ? - buttonData.iconPathDarkTheme : buttonData.iconPath - ), - ); + this.setButtonStyle(buttonElement, this.iconPath(buttonData.name)); if (buttonData.tooltip) { addTooltip(buttonElement, buttonData.tooltip); @@ -137,6 +137,25 @@ class AnkiHubReviewerButtons { } } + iconPath(buttonName) { + const button = this.buttonsData.find(buttonData => buttonData.name === buttonName); + + if (this.theme == "dark" && button.iconPathDarkTheme) { + if (this.isPremiumOrTrialing && button.premiumIconPathDarkTheme) { + return button.premiumIconPathDarkTheme; + } else { + return button.iconPathDarkTheme; + } + } else { + if (this.isPremiumOrTrialing && button.premiumIconPath) { + return button.premiumIconPath; + } else { + return button.iconPath + } + } + + } + injectReviewerButtonStyleSheet() { const style = document.createElement("style"); style.innerHTML = ` @@ -325,6 +344,14 @@ class AnkiHubReviewerButtons { } } + updateIsPremiumOrTrialing(isPremiumOrTrialing) { + this.isPremiumOrTrialing = isPremiumOrTrialing; + + this.updateButtons( + this.bbCount, this.faCount, this.getVisibleButtons().map(buttonData => buttonData.name) + ); + } + getVisibleButtons() { return this.buttonsData.filter(buttonData => (buttonData.visible)); } @@ -345,6 +372,8 @@ class AnkiHubReviewerButtons { } else { buttonElement.style.borderRadius = "0px"; } + + buttonElement.style.backgroundImage = `url('${this.iconPath(buttonName)}')`; } updateResourceCountIndicators(visibleButtons) { diff --git a/ankihub/gui/web/templates.py b/ankihub/gui/web/templates.py index 2a3773cda..4b7c0de86 100644 --- a/ankihub/gui/web/templates.py +++ b/ankihub/gui/web/templates.py @@ -2,8 +2,6 @@ from jinja2 import Environment, FileSystemLoader, select_autoescape -from ...addon_ankihub_client import AddonAnkiHubClient as AnkiHubClient - TEMPLATES_PATH = (pathlib.Path(__file__).parent).absolute() env = Environment( @@ -25,13 +23,7 @@ def get_header_webview_html( def get_reviewer_buttons_js(theme: str) -> str: - client = AnkiHubClient() - return env.get_template("reviewer_buttons.js").render( - { - "THEME": theme, - "IS_PREMIUM_OR_TRIALING": str(client.is_premium_or_trialing()), - } - ) + return env.get_template("reviewer_buttons.js").render({"THEME": theme}) def get_empty_state_html(theme: str, resource_type: str) -> str: