[Userscript] Wanikani Item Inspector

Version 1.28.1 is available – Please download it at the link in the top post

This fixes bugs in the layout of table mode.

5 Likes

When exporting to Anki, is there any way to transfer the intervals?

1 Like

I have no clue about what are the intervals you are talking about. Please clarify…

If you talk about the SRS intervals used by Wanikani there is no way to export that. But you can configure them manually in Anki. Don’t ask me how because I don’t know.

Oh ok. Thanks for the reply

1 Like

Version 1.29.0 is available – Please download it at the link in the top post

It adds support for turbo events and perform a pair of minor bug fixes (missing css for a pair of filters)

2 Likes

Version 1.29.1 is available – Please download it at the link in the top post

Cleans up edge cases in the startup sequence resulting from the introduction of turbo events processing.

This post is directed to @LupoMikti

I don’t find a thread for the script Show Total Lesson Count - WaniKani so I post this here.

Bug report. I don’t see any total lesson count when this script is executed. What happens?

Hmm, did you get the update for 0.4.0? I pushed it a day or two ago after testing a bunch on my system, but I was occasionally running into an issue where it wouldn’t execute if any other script had an issue.

Edit: I also put the @supportURL metadata in it to direct ppl to the script request thread where I originally posted it.

1 Like

Yes I do. The previous version displayed the total lesson count but it did not support the turbo events.

Ok. It’s still working for me right now, so could you tell me if it works only sometimes or not at all.

1 Like

So far it doesn’t work at all. I will keep you posted if I see erratic behavior.

You should consider making a thread for this script so we can move this discussion there.

1 Like

Yeah, will do. If you want, you can use this version which has all of the console.logs I use for debugging:

Debugging version
// ==UserScript==
// @name         Show Total Lesson Count - WaniKani
// @namespace    http://tampermonkey.net/
// @version      0.4.0e
// @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/what-do-you-want-now-request-extensions-here/3838/1787
// ==/UserScript==

(function() {
    'use strict';

    /* global wkof */

    console.log(`START OF SCRIPT`)

    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;

    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;
    }

    wkof.ready('TurboEvents').then(() => {
        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(() => {
            console.log(`I am from turbo:load`)
            initial_load = stateStarting = true;
            todaysLessonsFrameLoaded = navBarCountFrameLoaded = false;
            _start();
        }, urlList);
        wkof.turbo.on.event.before_frame_render((e) => {
            console.log(`turbo:before-frame-render has fired for "#${e.target.id}"`)
            if (['todays-lessons-frame', 'lesson-and-review-count-frame'].includes(e.target.id)) {
                todaysLessonsFrameLoaded = false;
                navBarCountFrameLoaded = false;
            }
        }, { urls: urlList, noTimeout: true });
        wkof.turbo.on.event.frame_load(async (e) => {
            console.log('turbo:frame-load has fired')
            if (e.target.id === 'todays-lessons-frame') {
                console.log('todays-lessons')
                todaysLessonsFrameLoaded = true;
                await main();
            }
            else if (e.target.id === 'lesson-and-review-count-frame') {
                console.log('nav bar counts')
                navBarCountFrameLoaded = true;
                await main();
            }
            else {
                console.log(e.target.id)
            }
        }, { urls: urlList });
    });

    function _start() {
        console.log(`Starting...`)
        wkof.include('Settings, Menu, Apiv2');
        wkof.ready('Settings, Menu, Apiv2').then(loadSettings).then(insertMenu).then(main);
    }

    function loadSettings() {
        console.log(`Loading settings...`)
        wkBatchSize = wkof.user.preferences.lessons_batch_size;

        let defaults = {
            showTotalOnly: false,
            setOwnPreferredDaily: false,
            preferredDailyAmount: wkBatchSize * 3
        };

        return wkof.Settings.load(scriptId, defaults).then(function(wkof_settings) {settings = wkof_settings;});
    }

    function insertMenu() {
        console.log(`Inserting menu...`)
        let config = {
            name: scriptId,
            submenu: 'Settings',
            title: scriptName,
            on_click: openSettings
        };

        wkof.Menu.insert_script_link(config);
    }

    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". Maximum of batch size * 3. NOTE: this does not actually change the number of available lessons.`,
                    default: wkBatchSize * 3,
                    min: 0,
                    max: wkBatchSize * 3
                }
            }
        };

        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() {
        console.log(`Main function is executing...`)
        if (!settings) {
            console.log('We do not have settings, setting timeout on _start()');
            if (!stateStarting) { stateStarting = true; setTimeout(_start, 50); }
            else console.log(`Did not set timeout due to already being in starting state`);
            return;
        }
        console.log(`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) {
            console.log(`Frame(s) loaded`)
            lessonCountContainers = await getCountContainers();
        }
        else {
            console.log('No frames loaded')
            return;
        }
        let todaysCountForDisplay = todaysLessonsCount;

        if (lessonCountContainers.every(node => node == null)) {
            console.log('No nodes in containers')
            return;
        }
        console.log('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';
        }
    }
})();

I tried this version. there is a single line START OF SCRIPT and no other console.log message. Here are screenshot of the console. there is a bunch of errors from scripts that weren’t updated to the latest dasboard chance but nothing relevant to your script to report.

Ok. I want to get this taken care of before making a dedicated thread announcing the script, but we can continue further talk about it in the script request thread where I originally posted it since that’s more relevant than here. If I had to guess, it might be Niai and Keisei as the culprits as those are two I deliberately have not re-enabled until I make some changes to my forked versions.

1 Like

I don’t know where is this thread so I continue here.

I disabled all scripts that generated console errors to no avail. Niai and Keisei don’t generate errors but I disabled them for the sake of testing. Your script still doesn’t work.

I just remembered that in this personal version I do not @require or load_script the Turbo Events library script. That might be the issue actually. Do you have the script from this thread installed?

1 Like

No I don’t have this script installed.

I think it is better to load_script because it will install the script only once even it load_script is called multiple times in multiple scripts. @require will install it multiple times.

Yes, I followed the recommendation to load_script in the published version, but perhaps something is wrong with it? Since I have the library locally installed to keep it up to date (and not need to do either method) I didn’t test it. I suppose I need to do that. Will report momentarily.

1 Like

I disabled all my scripts one by one in hope to find a culprit to no avail.