I had some time and interest to tinker on this so I made it show an indicator instead. It should now properly reset the timers when advancing to the next card too.
This goes in the card Front again (edit the JS Api part to have your own email/github this time)
<script>
var frontTimer;
var backTimer;
function initAutoAdvance(options = {}) {
const {
goToAnswerSeconds = 5,
answerSeconds = 5,
// Threshold when to add extra time for ease
easeThreshold = 2.5,
// Amount of ease per which to add/reduce by 1 second
easeStep = 0.5
} = options;
const handlePromise = (val, func) => {
if (typeof val === "object" && val !== null && !!val.then) {
val.then((res) => func(res.value));
} else {
func(val);
}
};
let goToAnswer;
function answerFunc() {
// Add indicator element into a fixed position
const indicator = document.createElement("div");
indicator.style.position = "fixed";
// Positioned at bottom right corner
indicator.style.bottom = "0";
indicator.style.right = "0";
// Size
indicator.style.padding = "10px";
// Black with 50% opacity
indicator.style.background = "rgba(0,0,0,0.5)";
// Large border to make the element circular
indicator.style.borderRadius = "99px";
document.body.appendChild(indicator);
}
function onGoToAnswer(answerWaitTime) {
goToAnswer();
// Start timer for answering
backTimer = setTimeout(answerFunc, answerWaitTime);
}
const startAutoAdvance = (fctVal) => {
clearTimeout(frontTimer);
clearTimeout(backTimer);
handlePromise(fctVal, (fctNum = 0) => {
let goToAnswerWaitTime = goToAnswerSeconds * 1000;
// fct is a number between 1300 and 5000
// We want a multipler between 1 and 5
const fctMult = fctNum / 1000 > 1;
let answerWaitTime = answerSeconds * 1000;
// If fct is missing, it'll be zero
if (fctMult > 1 && easeThreshold > 1 && easeStep > 0) {
// Add extra time if factor is lower than easeMiddle, reduce if higher
const extraTime = (fctMult - easeThreshold) * easeStep * 1000;
goToAnswerWaitTime = goToAnswerWaitTime + extraTime;
answerWaitTime = answerWaitTime + extraTime;
}
// Start timer for showing answer
frontTimer = setTimeout(
() => onGoToAnswer(answerWaitTime),
goToAnswerWaitTime
);
});
};
try {
const jsApiContract = {
version: "0.0.3",
developer: "put_your_own_email_or_github_here"
};
const api = new AnkiDroidJS(jsApiContract);
goToAnswer = showAnswer;
startAutoAdvance(api.ankiGetCardFactor());
} catch (e) {
if (globalThis.ankiPlatform !== "desktop") {
console.log("AnkiDroid API error", e);
} else {
goToAnswer = () => pycmd("ans");
pycmd("AnkiJS.ankiGetCardFactor()", startAutoAdvance);
}
}
}
initAutoAdvance({
// Customize options as you please
goToAnswerSeconds: 4,
answerSeconds: 3,
easeThreshold: 2,
easeStep: 0.7,
});
</script>
In case you’re doing {{FrontSide}} in the card back, the javascript would get run again in the backside which is undesired. To fix that you can add a hidden div in the backside like this:
<div id="backside" style="display:none;"></div>
And then modify the front side code like this:
var isBackside = document.getElementById("backside");
if (!isBackside) {
// Only init autoAdvance in the card front
initAutoAdvance({
// Customize options as you please
goToAnswerSeconds: 4,
answerSeconds: 3,
easeThreshold: 2,
easeStep: 0.7,
});
}
Edit: removed console.log
s