TheDabblingDuck / ankimote

Ankimote is an addon that adds remote control functionality to Anki flashcards
MIT License
25 stars 4 forks source link

Integrating speed focus pause feature into a modifiable command on Ankimote #14

Closed lumberingself closed 3 years ago

lumberingself commented 3 years ago

First of all, thank you so much for this add on. Absolute game changer. In the modifiable commands section on the script for Ankimote, how can a pause button be integrated into the ankimote command from the speed focus (Anking modified version) add on? I'm not sure if it's a command or a hook since its from a seperate add on. Would copying and pasting the script work?

This is the code from the speed focus mode add on for the pause button:

Pause addition

def pause(): if mw.state == 'review': clear_again_timeout() clear_answer_timeout() tooltip('Paused', period=1000)

mw.form.menuTools.addAction('Pause speed focus mode', pause, 'c')

From the Ankimote config md file

"feedback": true, "cmd1-label": "Suspend Card", "cmd1": "mw.reviewer.onSuspendCard()", "cmd2-label": "CMD 2", "cmd2": "showInfo('CMD 2: replace with custom code in the Anki addon config page')", "cmd3-label": "CMD 3", "cmd3": "showInfo('CMD 3: replace with custom code in the Anki addon config page')", "cmd4-label": "CMD 4", "cmd4": "showInfo('CMD 4: replace with custom code in the Anki addon config page')", "cmd5-label": "CMD 5", "cmd5": "mw.web.eval( \"alert('CMD 5: replace with custom code in the Anki addon config page');\" )" }

To allot the pause feature into cmd2 should I just copy the above entire pause code into cmd2 or do I need to convert it somehow? Or is it something to do with js1/js2/js3?

Thank you for this amazing add on and thank you for taking the time to read

TheDabblingDuck commented 3 years ago

if this pausing is the same as clearing timeouts, I provided someone the code on how to do that here: https://old.reddit.com/r/medicalschoolanki/comments/hlrw8m/ankimote_a_remote_to_control_anki_from_your_phone/gaylkc5/?context=3

Otherwise, can you show me where in the speed focus addon code you found that pause function? For seem reason I can't find it in the current code on github.

lumberingself commented 3 years ago

Otherwise, can you show me where in the speed focus addon code you found that pause function? For seem reason I can't find it in the current code on github.

I dont think its in the original code. I downloaded the modiefied version from Anking's website (https://www.ankipalace.com/downloadable-content), I dont think its on github.The original add on only had the speed focus mode (where there'd be an alert and then it'd automatically show the answer and then move on to the next card), AnKing modified it to add a pause feature so that you could take time to read the extra sections if you needed to do so. This is the entire code, I only posted the end part with the pause add on (im not sure if other parts of the script are pertinent im really illiterate with code lol):

-- coding: utf-8 --

""" Anki Add-on: Speed Focus Mode

Based on "Automatically show answer after X seconds" (https://ankiweb.net/shared/info/648362761)

The original author of this add-on is unknown, sadly, but all credit for the original idea goes to them.

Copyright: (c) 2017-2019 Glutanimate https://glutanimate.com/ License: GNU AGPLv3 https://www.gnu.org/licenses/agpl.html """

from future import unicode_literals

import sys import os

from aqt.qt import * from aqt import mw from aqt.reviewer import Reviewer from aqt.deckconf import DeckConf from aqt.forms import dconf from aqt.utils import tooltip

from anki.hooks import addHook, wrap from anki.sound import play

Anki 2.1 support

from anki import version as anki_version anki21 = anki_version.startswith("2.1.") pycmd = "pycmd" if anki21 else "py.link"

determine sound file path

sys_encoding = sys.getfilesystemencoding()

if anki21: addon_path = os.path.dirname(file) else: addon_path = os.path.dirname(file).decode(sys_encoding)

alert_path = os.path.join(addon_path, "sounds", "alert.mp3")

autoalerttimeout originally: autoAgainTimeout = setTimeout(function () { %s("ease3"); }, ms);

autoAgainTimeout = setTimeout(function () { document.querySelector("#defease").click(); }, ms);

def append_html(self, _old): return _old(self) + """

    """ % (pycmd, pycmd, pycmd)

set timeouts for auto-alert and auto-reveal

def set_answer_timeout(self): c = self.mw.col.decks.confForDid(self.card.odid or self.card.did) if c.get('autoAnswer', 0) > 0: self.bottom.web.eval("setAutoAnswer(%d);" % (c['autoAnswer'] 1000)) if c.get('autoAlert', 0) > 0: self.bottom.web.eval("setAutoAlert(%d);" % (c['autoAlert'] 1000))

set timeout for auto-again

def set_again_timeout(self): c = self.mw.col.decks.confForDid(self.card.odid or self.card.did) if c.get('autoAgain', 0) > 0: self.bottom.web.eval("setAutoAgain(%d);" % (c['autoAgain'] * 1000))

clear timeouts for auto-alert and auto-reveal, run on answer reveal

def clear_answer_timeout(): mw.reviewer.bottom.web.eval(""" if (typeof autoAnswerTimeout !== 'undefined') { clearTimeout(autoAnswerTimeout); } if (typeof autoAlertTimeout !== 'undefined') { clearTimeout(autoAlertTimeout); } """)

clear timeout for auto-again, run on next card

def clear_again_timeout(): mw.reviewer.bottom.web.eval(""" if (typeof autoAgainTimeout !== 'undefined') { clearTimeout(autoAgainTimeout); } """)

def setup_ui(self, Dialog): self.maxTaken.setMinimum(3)

grid = QGridLayout()
label1 = QLabel(self.tab_5)
label1.setText(_("Automatically play alert after"))
label2 = QLabel(self.tab_5)
label2.setText(_("seconds"))
self.autoAlert = QSpinBox(self.tab_5)
self.autoAlert.setMinimum(0)
self.autoAlert.setMaximum(3600)
grid.addWidget(label1, 0, 0, 1, 1)
grid.addWidget(self.autoAlert, 0, 1, 1, 1)
grid.addWidget(label2, 0, 2, 1, 1)
self.verticalLayout_6.insertLayout(1, grid)

grid = QGridLayout()
label1 = QLabel(self.tab_5)
label1.setText(_("Automatically show answer after"))
label2 = QLabel(self.tab_5)
label2.setText(_("seconds"))
self.autoAnswer = QSpinBox(self.tab_5)
self.autoAnswer.setMinimum(0)
self.autoAnswer.setMaximum(3600)
grid.addWidget(label1, 0, 0, 1, 1)
grid.addWidget(self.autoAnswer, 0, 1, 1, 1)
grid.addWidget(label2, 0, 2, 1, 1)
self.verticalLayout_6.insertLayout(2, grid)

grid = QGridLayout()
label1 = QLabel(self.tab_5)
label1.setText(_("Automatically rate 'good' after"))
label2 = QLabel(self.tab_5)
label2.setText(_("seconds"))
self.autoAgain = QSpinBox(self.tab_5)
self.autoAgain.setMinimum(0)
self.autoAgain.setMaximum(3600)
grid.addWidget(label1, 0, 0, 1, 1)
grid.addWidget(self.autoAgain, 0, 1, 1, 1)
grid.addWidget(label2, 0, 2, 1, 1)
self.verticalLayout_6.insertLayout(3, grid)

def load_conf(self): f = self.form c = self.conf f.autoAlert.setValue(c.get('autoAlert', 0)) f.autoAnswer.setValue(c.get('autoAnswer', 0)) f.autoAgain.setValue(c.get('autoAgain', 0))

def save_conf(self): f = self.form c = self.conf c['autoAlert'] = f.autoAlert.value() c['autoAnswer'] = f.autoAnswer.value() c['autoAgain'] = f.autoAgain.value()

Sound playback

def linkHandler(self, url, _old): if not url.startswith("autoalert"): return _old(self, url) if not self.mw.col:

collection unloaded, e.g. when called during pre-exit sync

    return
play(alert_path)
c = self.mw.col.decks.confForDid(self.card.odid or self.card.did)
timeout = c.get('autoAlert', 0)
tooltip("Wake up! You have been looking at <br>"
        "the question for <b>{}</b> seconds!".format(timeout),
        period=1000)

Hooks

Reviewer._bottomHTML = wrap(Reviewer._bottomHTML, append_html, 'around') Reviewer._showAnswerButton = wrap( Reviewer._showAnswerButton, set_answer_timeout) Reviewer._showEaseButtons = wrap(Reviewer._showEaseButtons, set_again_timeout) Reviewer._linkHandler = wrap(Reviewer._linkHandler, linkHandler, "around") addHook("showAnswer", clear_answer_timeout) addHook("showQuestion", clear_again_timeout)

dconf.Ui_Dialog.setupUi = wrap(dconf.Ui_Dialog.setupUi, setup_ui) DeckConf.loadConf = wrap(DeckConf.loadConf, load_conf) DeckConf.saveConf = wrap(DeckConf.saveConf, save_conf, 'before')

Pause addition

def pause(): if mw.state == 'review': clear_again_timeout() clear_answer_timeout() tooltip('Paused', period=1000)

mw.form.menuTools.addAction('Pause speed focus mode', pause, 'c')

EDIT: looks like there's a clearing timeout part in this too, didnt know what it meant till you mentioned it lol. Let me try doing what you recommended to the reddit user

EDIT 2: Tried using the code you posted on that comment: "cmd2": "mw.reviewer.bottom.web.eval( \"spdfClearCurrentTimeout();\" )", "cmd2-label": "Pause", But no luck :/

TheDabblingDuck commented 3 years ago

I think this should work - let me know

"cmd2": "for action in mw.form.menuTools.actions(): action.triggered.emit() if action.text()=='Pause speed focus mode' else None", "cmd2-label": "Pause",