- // ==UserScript==
- // @name Show Total Lesson Count - WaniKani
- // @namespace http://tampermonkey.net/
- // @version 0.4.6
- // @description Changes the count of lessons on the Today's Lessons tile to show the total number of available lessons in addition to the number selected for you
- // @license MIT
- // @author LupoMikti
- // @match https://www.wanikani.com/*
- // @grant none
- // @supportURL https://community.wanikani.com/t/userscript-show-total-lesson-count/66776
- // ==/UserScript==
-
- (async function() {
- 'use strict';
-
- /* global wkof */
-
- let scriptId = 'show_total_lesson_count';
- let scriptName = 'Show Total Lesson Count';
- let wkBatchSize = 0;
- let initial_load = true;
- let todaysLessonsCount;
- let settings;
- let stateStarting = false;
- let todaysLessonsFrameLoaded = false;
- let navBarCountFrameLoaded = false;
-
- let debugLogText = `START: ${scriptName} Debug Log:\n`;
- let hasOutputLog = false;
- let mainSource = '';
-
- function addToDebugLog(message) {
- debugLogText += `${new Date().toISOString()}: ${message}\n`;
- }
-
- function printDebugLog() {
- if (!hasOutputLog) console.debug(debugLogText);
- hasOutputLog = true;
- debugLogText = `START: ${scriptName} Debug Log:\n`;
- }
-
- if (!window.wkof) {
- if (confirm(scriptName + ' requires Wanikani Open Framework.\nDo you want to be forwarded to the installation instructions?')) {
- window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549';
- }
- return;
- }
-
- const wkofTurboEventsScriptUrl = 'https://update.greasyfork.org/scripts/501980/1419628/Wanikani%20Open%20Framework%20Turbo%20Events.user.js';
- addToDebugLog(`Attempting to load the TurboEvents library script...`)
- await wkof.load_script(wkofTurboEventsScriptUrl, /* use_cache */ true);
- addToDebugLog(`TurboEvents library script should be loaded in`)
-
- wkof.ready('TurboEvents').then(() => {
- addToDebugLog(`Start of TurboEvents ready callback`)
- let urlList = [wkof.turbo.common.locations.dashboard, wkof.turbo.common.locations.items_pages, /^https:\/\/www\.wanikani\.com\/(settings|level|radicals|kanji|vocabulary)(\/|\?difficulty=).+\/?$/];
-
- wkof.turbo.on.common.urls(() => {
- addToDebugLog(`turbo:load has fired, setting globals and calling _start()`)
- initial_load = stateStarting = true;
- hasOutputLog = todaysLessonsFrameLoaded = navBarCountFrameLoaded = false;
- _start();
- }, urlList);
- wkof.turbo.on.event.before_frame_render((e) => {
- addToDebugLog(`turbo:before-frame-render has fired for "#${e.target.id}"`)
- if (['todays-lessons-frame', 'lesson-and-review-count-frame'].includes(e.target.id)) {
- hasOutputLog = todaysLessonsFrameLoaded = navBarCountFrameLoaded = false;
- }
- }, { urls: urlList, noTimeout: true });
- wkof.turbo.on.event.frame_load(async (e) => {
- addToDebugLog('turbo:frame-load has fired')
- if (e.target.id === 'todays-lessons-frame') {
- addToDebugLog('turbo:frame-load is for "#todays-lessons-frame"')
- todaysLessonsFrameLoaded = true;
- mainSource = `turbo:frame-load for "#todays-lessons-frame"`;
- await main();
- }
- else if (e.target.id === 'lesson-and-review-count-frame') {
- addToDebugLog('turbo:frame-load is for "#lesson-and-review-count-frame"')
- navBarCountFrameLoaded = true;
- mainSource = `turbo:frame-load is for "#lesson-and-review-count-frame"`;
- await main();
- }
- else {
- addToDebugLog(`turbo:frame-load was for "#${e.target.id}", doing nothing...`)
- }
- mainSource = '';
- }, { urls: urlList });
- });
-
- if (settings.enableDebugging) printDebugLog();
-
- function _start() {
- addToDebugLog(`Starting...`)
- wkof.include('Settings, Menu, Apiv2');
- wkof.ready('Settings, Menu, Apiv2').then(loadSettings).then(insertMenu).then(main);
- }
-
- function loadSettings() {
- addToDebugLog(`Loading settings...`)
- wkBatchSize = wkof.user.preferences.lessons_batch_size;
-
- let defaults = {
- showTotalOnly: false,
- setOwnPreferredDaily: false,
- preferredDailyAmount: wkBatchSize * 3,
- enableDebugging: true,
- };
-
- return wkof.Settings.load(scriptId, defaults).then(function(wkof_settings) {settings = wkof_settings;});
- }
-
- function insertMenu() {
- addToDebugLog(`Inserting menu...`)
- let config = {
- name: scriptId,
- submenu: 'Settings',
- title: scriptName,
- on_click: openSettings
- };
-
- wkof.Menu.insert_script_link(config);
- mainSource = `_start() -> loadSettings() -> insertMenu()`;
- }
-
- function openSettings() {
- let config = {
- script_id: scriptId,
- title: scriptName,
- on_save: main,
- content: {
- showTotalOnly: {
- type: 'checkbox',
- label: 'Show Only Total Lesson Count',
- hover_tip: `Changes display between "<today's lesson count> / <total lesson count>" and just "<total lesson count>"`,
- default: false,
- },
- setOwnPreferredDaily: {
- type: 'checkbox',
- label: 'Set Your Own Daily Lesson Count',
- hover_tip: `Choose whether to display the value you set as your daily lesson count or not`,
- default: false,
- },
- preferredDailyAmount: {
- type: 'number',
- label: 'Preferred Daily Lesson Amount',
- hover_tip: `The number you want displayed for "Today's Lessons". If you use the Wanikani setting, set this to match. Maximum of 100. NOTE: this does not actually change the number of available lessons.`,
- default: wkBatchSize * 3,
- min: 0,
- max: 100,
- },
- enableDebugging: {
- type: 'checkbox',
- label: 'Enable console debugging',
- hover_tip: `Enable output of debugging info to console.debug()`,
- default: true,
- }
- }
- };
-
- let dialog = new wkof.Settings(config);
- dialog.open();
- }
-
- async function getCountContainers() {
- let dashboardTileCountContainer = document.querySelector('.todays-lessons__count-text .count-bubble');
- let navBarCountContainer = document.querySelector('.lesson-and-review-count__count');
-
- if (initial_load && (dashboardTileCountContainer || navBarCountContainer)) {
- let container = dashboardTileCountContainer ?? navBarCountContainer;
- todaysLessonsCount = parseInt(container.textContent);
- initial_load = false;
- }
-
- return [dashboardTileCountContainer, navBarCountContainer];
- }
-
- async function main() {
- addToDebugLog(`Main function is executing... source of start: ${mainSource}`)
- if (!settings) {
- addToDebugLog('We do not have settings, setting timeout on _start()');
- if (!stateStarting) { stateStarting = true; setTimeout(_start, 50); }
- else addToDebugLog(`Did not set timeout due to already being in starting state`);
- return;
- }
- addToDebugLog(`We have settings`)
- stateStarting = false;
- let summary_data = await wkof.Apiv2.get_endpoint('summary');
- let totalLessonCount = summary_data.lessons[0].subject_ids.length;
- let lessonCountContainers;
- if (todaysLessonsFrameLoaded || navBarCountFrameLoaded) {
- addToDebugLog(`Frame(s) loaded`)
- lessonCountContainers = await getCountContainers();
- }
- else {
- addToDebugLog('No frames loaded')
- return;
- }
- let todaysCountForDisplay = todaysLessonsCount;
-
- if (lessonCountContainers.every(node => node == null)) {
- addToDebugLog('No nodes in containers')
- return;
- }
- addToDebugLog('At least one container exists')
-
- if (isNaN(todaysLessonsCount)) {
- todaysCountForDisplay = 0;
- }
- else {
- if (settings.setOwnPreferredDaily) todaysCountForDisplay = todaysLessonsCount - (wkBatchSize * 3 - settings.preferredDailyAmount);
- }
-
- if (lessonCountContainers[0]) lessonCountContainers[0].textContent = settings.showTotalOnly ? totalLessonCount : todaysCountForDisplay + ' / ' + totalLessonCount;
- if (lessonCountContainers[1]) lessonCountContainers[1].textContent = settings.showTotalOnly ? totalLessonCount : todaysCountForDisplay;
-
- if (todaysCountForDisplay === 0) {
- // hide the start button if it is not already, TODO: disable nav bar button if it is not already
- let startButton = document.querySelector('.todays-lessons-button--start')
- if (startButton && startButton.checkVisibility()) {
- startButton.style.display = 'none';
- }
- }
-
- // hide "Today's" subtitle
- let lessonSubtitle = document.querySelector('.todays-lessons__subtitle');
-
- if (lessonSubtitle && lessonSubtitle.checkVisibility()) {
- lessonSubtitle.style.display = 'none';
- }
-
- if (settings.enableDebugging) printDebugLog();
- }
- })();