From 0f8a4d1a3ad7087450d2d490a30761e9cdff9fac Mon Sep 17 00:00:00 2001 From: Andrew Sanchez Date: Mon, 21 Feb 2022 15:37:26 -0700 Subject: [PATCH] feat/ref: add upload suggestions menu item and refactor (#8) * Refactor. * shared -> collaborative. * Placeholders for upload suggestions menu item and action. * Revert to pyqt5. * Use a proper hook. --- .pre-commit-config.yaml | 1 - ankihub/ankihub_client.py | 5 +-- ankihub/entry_point.py | 4 +- ankihub/gui/editor.py | 15 ++++++-- ankihub/gui/menu.py | 56 +++++++++++++++++++++------- ankihub/gui/tests/test_editor.py | 6 ++- ankihub/register_decks.py | 6 +-- ankihub/tests/test_register_decks.py | 4 +- 8 files changed, 66 insertions(+), 31 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 545ddf0..87bc21f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,6 @@ repos: rev: 5.10.1 hooks: - id: isort - files: "\\.(py)$" - repo: https://github.com/pycqa/flake8 rev: 4.0.1 diff --git a/ankihub/ankihub_client.py b/ankihub/ankihub_client.py index de55bef..e4db641 100644 --- a/ankihub/ankihub_client.py +++ b/ankihub/ankihub_client.py @@ -1,7 +1,6 @@ import json import requests - from ankihub.config import Config @@ -50,7 +49,7 @@ def get(self, url): return requests.get(self.base_url + url, headers=self.headers) def submit_change(self): - print("Submit change") + print("Submitting change") def submit_new_note(self): - print("Submit change") + print("Submitting new note") diff --git a/ankihub/entry_point.py b/ankihub/entry_point.py index 9bf5f4a..de483f1 100644 --- a/ankihub/entry_point.py +++ b/ankihub/entry_point.py @@ -2,13 +2,13 @@ from aqt import gui_hooks, mw from .gui import editor -from .gui.menu import add_ankihub_menu +from .gui.menu import setup_ankihub_menu from .utils import hide_ankihub_field_in_editor def run(): """This is the function that will be run in __init__.py when Anki starts.""" gui_hooks.editor_will_load_note.append(hide_ankihub_field_in_editor) - add_ankihub_menu() + setup_ankihub_menu() editor.setup() return mw diff --git a/ankihub/gui/editor.py b/ankihub/gui/editor.py index 992e94b..4bab424 100644 --- a/ankihub/gui/editor.py +++ b/ankihub/gui/editor.py @@ -1,4 +1,5 @@ -from anki.hooks import addHook, wrap +from anki.hooks import addHook +from aqt import gui_hooks from aqt.editor import Editor from ..ankihub_client import AnkiHubClient @@ -15,6 +16,7 @@ def on_ankihub_button_press(editor: Editor): # fetching the default or by selecting a command from the dropdown menu. command = editor.ankihub_command # Get the current Note ID for passing into the request below. + # TODO This should actually get the ankihub id from the notes first field. _ = editor.note.id client = AnkiHubClient() if command == AnkiHubCommands.CHANGE.value: @@ -54,11 +56,16 @@ def setup_editor_buttons(buttons, editor: Editor): return buttons -def on_bridge_command(editor: Editor, cmd, _old): +def ankihub_message_handler(handled: tuple, cmd, editor: Editor): + """Call on_select_command when a message prefixed with 'ankihub' is received + from the front end. + """ if not cmd.startswith("ankihub"): - return _old(editor, cmd) + return handled _, command_value = cmd.split(":") on_select_command(editor, command_value) + handled = (True, None) + return handled def on_select_command(editor, cmd): @@ -71,7 +78,7 @@ def on_select_command(editor, cmd): def setup(): addHook("setupEditorButtons", setup_editor_buttons) - Editor.onBridgeCmd = wrap(Editor.onBridgeCmd, on_bridge_command, "around") + gui_hooks.webview_did_receive_js_message.append(ankihub_message_handler) Editor.ankihub_command = AnkiHubCommands.CHANGE.value return Editor # We can wrap Editor.__init__ if more complicated logic is needed, such as diff --git a/ankihub/gui/menu.py b/ankihub/gui/menu.py index b9bd4da..0717d34 100644 --- a/ankihub/gui/menu.py +++ b/ankihub/gui/menu.py @@ -1,7 +1,9 @@ +from ankihub.ankihub_client import AnkiHubClient +from ankihub.register_decks import create_collaborative_deck from aqt import mw from aqt.qt import QAction, QMenu, qconnect from aqt.studydeck import StudyDeck -from PyQt6.QtWidgets import ( +from PyQt5.QtWidgets import ( QHBoxLayout, QLabel, QLineEdit, @@ -11,8 +13,11 @@ QWidget, ) -from ankihub.ankihub_client import AnkiHubClient -from ankihub.register_decks import create_shared_deck + +def main_menu_setup(): + ankihub_menu = QMenu("&AnkiHub", parent=mw) + mw.form.menubar.addMenu(ankihub_menu) + return ankihub_menu class AnkiHubLogin(QWidget): @@ -103,7 +108,13 @@ def display_login(cls): return __window -def create_shared_deck_action() -> None: +def ankihub_login_setup(parent): + sign_in_button = QAction("Sign into AnkiHub", mw) + sign_in_button.triggered.connect(AnkiHubLogin.display_login) + parent.addAction(sign_in_button) + + +def create_collaborative_deck_action() -> None: diag = StudyDeck( mw, title="AnkiHub", @@ -115,16 +126,33 @@ def create_shared_deck_action() -> None: if not deck_name: return did = mw.col.decks.id(deck_name) - create_shared_deck(did) + create_collaborative_deck(did) + +def create_collaborative_deck_setup(parent): + q_action = QAction("Create collaborative deck", parent=parent) + qconnect(q_action.triggered, create_collaborative_deck_action) + parent.addAction(q_action) -def add_ankihub_menu() -> None: + +def upload_suggestions_action(): + """Action for uploading suggestions in bulk.""" + # TODO Instantiate AnkiHubClient. + # TODO Query the the note table for mod times that are later than the time + # the last sync. + # TODO Send a request to AnkiHub with the list of modified notes. + + +def upload_suggestions_setup(parent): + """Set up the menu item for uploading suggestions in bulk.""" + q_action = QAction("Upload suggestions to AnkiHub", parent=parent) + qconnect(q_action.triggered, upload_suggestions_action) + parent.addAction(q_action) + + +def setup_ankihub_menu() -> None: """Add top-level AnkiHub menu.""" - ankihub_menu = QMenu("&AnkiHub", parent=mw) - mw.form.menubar.addMenu(ankihub_menu) - _create_shared_deck_action = QAction("Upload Deck", parent=ankihub_menu) - qconnect(_create_shared_deck_action.triggered, create_shared_deck_action) - ankihub_menu.addAction(_create_shared_deck_action) - sign_in_button = QAction("Sign in", mw) - sign_in_button.triggered.connect(AnkiHubLogin.display_login) - ankihub_menu.addAction(sign_in_button) + ankihub_menu = main_menu_setup() + ankihub_login_setup(parent=ankihub_menu) + create_collaborative_deck_setup(parent=ankihub_menu) + upload_suggestions_setup(parent=ankihub_menu) diff --git a/ankihub/gui/tests/test_editor.py b/ankihub/gui/tests/test_editor.py index 2a8abe0..362b1ad 100644 --- a/ankihub/gui/tests/test_editor.py +++ b/ankihub/gui/tests/test_editor.py @@ -11,8 +11,10 @@ def test_editor(anki_session_with_addon: AnkiSession, monkeypatch): assert anki_editor.ankihub_command == "Suggest a change" editor.on_select_command(anki_editor, AnkiHubCommands.NEW.value) assert anki_editor.ankihub_command == "Suggest a new note" - editor.on_bridge_command( - anki_editor, f"ankihub:{AnkiHubCommands.CHANGE.value}", lambda: None + editor.ankihub_message_handler( + (False, None), + f"ankihub:{AnkiHubCommands.CHANGE.value}", + anki_editor, ) assert anki_editor.ankihub_command == "Suggest a change" # Patch the editor so that it has the note attribute, which it will have when diff --git a/ankihub/register_decks.py b/ankihub/register_decks.py index b9f985d..f998693 100644 --- a/ankihub/register_decks.py +++ b/ankihub/register_decks.py @@ -95,12 +95,12 @@ def upload_deck(did: int) -> None: return response -def _create_shared_deck(note_types, did): +def _create_collaborative_deck(note_types, did): modify_notes(note_types) upload_deck(did) -def create_shared_deck(did: int) -> None: +def create_collaborative_deck(did: int) -> None: model_ids = get_note_types_in_deck(did) note_types = [mw.col.models.get(model_id) for model_id in model_ids] names = ", ".join([note["name"] for note in note_types]) @@ -113,6 +113,6 @@ def create_shared_deck(did: int) -> None: tooltip("Cancelled Upload to AnkiHub") return mw.taskman.with_progress( - task=lambda: _create_shared_deck(note_types, did), + task=lambda: _create_collaborative_deck(note_types, did), on_done=lambda future: tooltip("Deck Uploaded to AnkiHub"), ) diff --git a/ankihub/tests/test_register_decks.py b/ankihub/tests/test_register_decks.py index 531c080..2a280fa 100644 --- a/ankihub/tests/test_register_decks.py +++ b/ankihub/tests/test_register_decks.py @@ -49,12 +49,12 @@ def test_modify_note_type(anki_session: AnkiSession) -> None: def test_prepare_to_upload_deck(anki_session: AnkiSession, monkeypatch): - from ankihub.register_decks import create_shared_deck + from ankihub.register_decks import create_collaborative_deck monkeypatch.setattr("ankihub.register_decks.askUser", Mock(return_value=True)) with anki_session.profile_loaded(): with anki_session.deck_installed(anking_deck) as deck_id: - create_shared_deck(deck_id) + create_collaborative_deck(deck_id) def test_populate_id_fields(anki_session: AnkiSession):