Extra Study: Audio Quiz

Adds the option to change the WK extra study to audio => meaning questions.

当前为 2022-03-14 提交的版本,查看 最新版本

// ==UserScript==
// @name         Extra Study: Audio Quiz
// @namespace    extraStudyAudioQuiz
// @version      1.0
// @description  Adds the option to change the WK extra study to audio => meaning questions.
// @author       Sinyaven
// @license      MIT-0
// @match        https://www.wanikani.com/
// @match        https://www.wanikani.com/dashboard
// @match        https://www.wanikani.com/extra_study/session*
// @match        https://preview.wanikani.com/
// @match        https://preview.wanikani.com/dashboard
// @match        https://preview.wanikani.com/extra_study/session*
// @require      https://greasyfork.org/scripts/441518-wanikani-queue-manipulator/code/WaniKani%20Queue%20Manipulator.js?version=1028290
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
	"use strict";
	/* global $, wkof, wkQueueManipulator */
	/* eslint no-multi-spaces: off */

	if (document.URL.includes("extra_study/session")) {
		if (localStorage.getItem("extraStudyAudioQuiz") !== "true") return;
		onlyVocabQuestions();
		onlyMeaningQuestions();
		turnAllIntoAudioQuestions();
	} else {
		addToggle();
	}

	function onlyVocabQuestions() {
		wkQueueManipulator.filter.push(onlyVocab);
	}

	async function onlyMeaningQuestions() {
		await wkQueueManipulator.jQueryReady();
		$.jStorage.listenKeyChange("questionType", () => {
			if ($.jStorage.get("questionType") !== "meaning") $.jStorage.set("questionType", "meaning");
		});
		$.jStorage.listenKeyChange("currentItem", () => {
			const item = $.jStorage.get("currentItem");
			$.jStorage.set(`e/stats/${item.type[0].toLowerCase()}${item.id}`, {rc: 1});
		});
	}

	async function turnAllIntoAudioQuestions() {
		await wkQueueManipulator.domReady();
		addStudyCss();
		new MutationObserver(m => {
			const answered = m[0].target.classList.contains("correct") || m[0].target.classList.contains("incorrect");
			document.body.classList.toggle("answered", answered);
			if (!answered) document.getElementById("option-audio-player").click();
		}).observe(document.querySelector("#answer-form fieldset"), {attributes: true, attributeFilter: ["class"]});
	}

	async function addToggle() {
		const input = document.createElement("input");
		const label = document.createElement("label");
		input.type = "checkbox";
		input.classList.add("switch");
		label.classList.add("audio-switch-label");
		label.textContent = "Audio Quiz";
		label.append(input);
		input.checked = localStorage.getItem("extraStudyAudioQuiz") === "true";
		input.addEventListener("change", e => localStorage.setItem("extraStudyAudioQuiz", e.target.checked));
		await wkQueueManipulator.domReady();
		addDashboardCss();
		(await wkQueueManipulator.domElementAvailable(document.getElementsByClassName("extra-study")[0], "div")).after(label);
	}

	async function onlyVocab(list) {
		if (!window.wkof) {
			alert("Extra Study: Audio Quiz script requires Wanikani Open Framework.");
			return list;
		}

		wkof.include("ItemData");
		await wkof.ready("ItemData");
		const vocab = await wkof.ItemData.get_items({wk_items: {filters: {item_type: "voc"}}});
		const vocIds = vocab.reduce((result, item) => ((result.add(item.id), result)), new Set());
		return list.filter(id => vocIds.has(id));
	}

	function addDashboardCss() {
		const style = document.createElement("style");
		style.textContent = `
		.extra-study {
			position: relative;
		}

		.extra-study .audio-switch-label {
			position: absolute;
			right: 12px;
			top: 16px;
		}

		.audio-switch-label .switch {
			width: 0;
			margin: 0 1.7em 0 0.4em;
			vertical-align: baseline;
		}

		.switch::before {
			content: "";
			position: absolute;
			width: 1.7em;
			height: 1em;
			border-radius: 1em;
			cursor: pointer;
			background-color: #bdbdbd;
			transition: .2s;
		}

		.switch::after {
			content: "";
			position: absolute;
			width: 1em;
			height: 1em;
			border-radius: 50%;
			background-color: white;
			transition: .2s;
			transform: scale(0.8);
		}

		.switch:checked::before {
			background-color: #59c274;
		}

		.switch:checked::after {
			transform: translateX(0.7em) scale(0.8);
		}`;
		document.head.appendChild(style);
	}

	function addStudyCss() {
		const style = document.createElement("style");
		style.textContent = `
		#character span {
			opacity: 0;
		}

		body.answered #character span {
			opacity: 1;
		}`;
		document.head.appendChild(style);
	}
})();