Greasy Fork is available in English.
Make Duolingo wider and more minimalist, and add useful keyboard shortcuts for the main features of the site.
// ==UserScript==
// @name Duolingo Wide
// @namespace http://tampermonkey.net/
// @version 2.0.3
// @description Make Duolingo wider and more minimalist, and add useful keyboard shortcuts for the main features of the site.
// @author Nekosuki
// @match https://www.duolingo.com/*
// @grant GM_addStyle
// @run-at document-start
// ==/UserScript==
GM_addStyle("div.a5SW0,div._2_lzu{display:none}div._3MT-S{width:100%}div.kHldG{width:20%}");
GM_addStyle("div[data-test='player-end-carousel'] > div > div:first-child{width:100%} div._2Q3-3 {display:none}");
GM_addStyle(".__duowide_langs > :last-child {column-count:3} .__duowide_langs > :last-child > ul {max-height:none} .__duowide_friends a+div {position:absolute}");
GM_addStyle(".__duowide_achievs div._3jMdg {column-count:2} .__duowide_achievs li.f4TL7 {border:none; padding: 0 10px 25px 0} .__duowide_achievs h1._1Cjfg {margin-bottom: 30px !important}");
(function() {
"use strict";
let addStrengthenButton = function() {
let c = document.querySelector("div.mAsUf");
if(c === null || c.firstElementChild.dataset.test != "lingot-store-button") return;
let a = document.querySelector("a[data-test='global-practice']");
a.className = "_3FQrh _1uzK0 _3f25b _2arQ0 _3skMI _2ESN4";
a.style.float = "right";
a.innerHTML = "Practice";
let p = a.cloneNode(true);
p.onclick = function() { a.click(); return false; };
c.replaceChild(p, c.firstChild);
};
let improveProfile = function() {
if(document.querySelector("h1[data-test='profile-username']") == null) return;
let d = document.querySelector("div.a5SW0");
if(d === null || d.firstChild.textContent != "Languages") return;
let e = d.nextElementSibling;
let c = document.querySelector("div._3MT-S").firstChild;
c.firstChild.classList.add("__duowide_achievs");
d.className = "_2hEQd _1E3L7 __duowide_langs";
e.className = "_2hEQd _1E3L7 __duowide_friends";
let info = c.firstChild.firstChild.firstChild.firstChild;
info.removeChild(info.lastChild);
let a = document.createElement("div");
a.className = "_2hEQd _1E3L7";
a.innerHTML = "<div class=\"_2RO1n\"></div>";
a.firstChild.appendChild(info);
c.insertBefore(a, c.firstChild);
c.insertBefore(d, c.lastChild);
c.insertBefore(e, c.lastChild);
let h = c.querySelector("h1._1Cjfg");
if(h === null || h.textContent !== "Achievements") {
info.parentNode.appendChild(c.children[1].firstChild);
c.removeChild(c.children[1]);
}
};
let keyEventListener = function(event) {
if(['input', 'select', 'textarea'].indexOf(document.activeElement.tagName.toLowerCase()) !== -1) return;
if(window.location.pathname === "/practice" || window.location.pathname.match(/^\/skill\/[^/]+\/[^/]+\//)) {
switch(event.keyCode) {
case 68:
let discussSentence = document.querySelector("div.PYCF5 > button:last-child");
if(discussSentence !== null) discussSentence.click();
return;
case 81:
let quitButton = document.querySelector("div.Mlxjr > a._38taa._2Zfkq.cCL9P");
if(quitButton !== null) quitButton.click();
return;
}
}
let tag = null;
switch(event.keyCode) {
case 78: /* N */ newLearningSession(); return;
case 72: /* H */ tag = "home-nav"; break;
case 87: /* W */ tag = "vocab-nav"; break;
case 68: /* D */ tag = "discussion-nav"; break;
case 76: /* L */ tag = "labs-nav"; break;
case 80: /* P */ tag = "global-practice"; break;
case 89: /* Y */ tag = "user-profile"; break;
case 83: /* S */ tag = "sound-settings"; break;
}
let elem = document.querySelector("a[data-test='" + tag + "']");
if(elem !== null) elem.click();
else if(window.location.pathname === "/practice") {
let practiceButton = document.querySelector("button[data-test='secondary-button']");
let timedPracticeButton = document.querySelector("button[data-test='player-next']");
if(event.keyCode == 80) practiceButton.click();
else if(event.keyCode == 84) timedPracticeButton.click();
}
};
let widenCommentSection = function() {
if(window.location.pathname.startsWith("/comment/")) {
document.querySelector("section.page-main.main-right").style.width = "initial";
}
};
let checkForSettings = function() {
let m = document.querySelector("div._3MT-S");
if(m === null) return;
let s = document.querySelector("div._2_lzu");
if(window.location.pathname.startsWith("/settings")) {
m.style.width = "auto";
s.style.display = "block";
} else {
m.style.width = "100%";
s.style.display = "none";
}
};
let init = function() {
document.addEventListener("keyup", keyEventListener);
};
let check = function() {
widenCommentSection();
improveProfile();
addStrengthenButton();
checkForSettings();
};
let newLearningSession = function() {
if(window.location.pathname.startsWith("/skill/")) {
let next = document.querySelector("a[data-test=begin-session-button]");
if(next !== null) next.click();
return;
}
let skills = Array.prototype.slice.call(document.querySelectorAll("a[data-test~=skill-tree-link]"));
let toLearn = skills.filter(a => !a.dataset.test.includes("gold") && !a.dataset.test.includes("purple") && a.firstElementChild.childElementCount == 1);
if(toLearn.length === 0) return;
toLearn[0].click();
};
new MutationObserver(check).observe(document, {childList: true, subtree: true});
init();
})();