Wanikani Open Framework [developer thread]

I’ll apologize in advance for asking, but I’m looking I’m looking to tweak the way the menu is rendered.

I understand that the code I’m looking for is pulled in the menu module that gets pulled into the open framework as a dependency.

Menu:     { url: 'https://greasyfork.org/scripts/38578-wanikani-open-framework-menu-module/code/Wanikani%20Open%20Framework%20-%20Menu%20module.js?version=612205'},

This doesn’t give me a great avenue for making modifications. It seems like perhaps I need to fork the menu module and edit the WKOF to pull my fork instead of the original. Are there alternatives that I’m overlooking?

Edit: Easiest workaround will be to just rename the WKOF “settings” to “configuration”. I could even do that by bolting my own script onto the page as long as I can work out order of execution.

Can you tell me what you’re wanting to achieve? I’m not really sure what you’re asking.

The supported_modules have to be carefully vetted to not break scripts, of course, so the proper process for making changes is to submit a pull request on github. Or, to keep things simpler for both of us, post your changes here, and I can review and merge them.

Are you wanting to make it more convenient to do development on the Menu module for eventual submission? In that case, you can temporarily change the URL to a "file:///..." URL, and add that URL to the nocache variable (which isn’t documented yet, but I’m happy to describe).

If you’re just wanting custom features that don’t affect other scripts, then you could do them outside of the supported_modules mechanism. I can describe some possible methods once I know what you’re wanting to achieve.

I can reduce it down to this: I thought I wanted to move the WKOF section down to the bottom, but I’d be happy to rename “settings” to “configuration”. Even though the two Settings entries are under different sub-headings, having two entries in the main WK menu is confusing for me. Usually I need to run to the menu to get my API key and so I jump to settings and then say “oh this is a sub-menu” and instead of realizing “oh the actual settings I want is down there” I think “settings is the wrong entry name for what I’m seeking” and I end up picking one of the settings synonyms (if you will) like Profile or Tools, before I slow down enough and realize my error.

Also,

That is something I was curious about, yes. It would be nice to develop something using the framework and getting a smooth workflow would be crucial to that.

The Scripts->Settings submenu doesn’t actually exist until a script requests to add itself at a particular location… so it’s actually all of the individual userscripts that are voluntarily locating themselves there. To change it to something like Scripts->Configuration, you’d have to convince all of the script writers to change it in their scripts.


In my personal workflow for wkof development, I have the following userscript instead of wkof itself:

// ==UserScript==
// @name        Wanikani Open Framework (DEBUG)
// @namespace   rfindley
// @description Framework for writing scripts for Wanikani
// @version     1.0.34
// @include     https://www.wanikani.com/*
// @require     file:///M:\projects\wkof\Core_Debug.js
// @copyright   2018+, Robin Findley
// @license     MIT; http://opensource.org/licenses/MIT
// @run-at      document-start
// @grant       none
// ==/UserScript==

So, it’s loading a local version of wkof’s Core.js.
You have to enable TamperMonkey to load local files:

Then, inside my local Core_Debug.js, I’ve changed all of the URLs to local URLs:

	var supported_modules = {
		Apiv2:    { url: 'https://internal-server/wkof/Apiv2.js'},
		ItemData: { url: 'https://internal-server/wkof/ItemData.js'},
		Menu:     { url: 'https://internal-server/wkof/Menu.js'},
		Progress: { url: 'https://internal-server/wkof/Progress.js'},
		Settings: { url: 'https://internal-server/wkof/Settings.js'},
	};

Here ^^^, I’m accessing them via a local web server, but I think file URLs might work. Anyway, I just edit the files in-place, and the web server is mapped to that folder.

As for caching, you can set a variable in localStorage to exclude certain modules:

localStorage['wkof.include.nocache'] = "Menu";

It accepts a comma-separated list of supported_modules that you don’t want it to cache.

There’s also a separate variable for disabling cache on URLs loaded via wkof.load_script(), wkof.load_css(), and wkof.load_file():

localStorage['wkof.load_file.nocache'] = "https://example.com/my-external-style.css";

Again, it accepts a comma-separated list of URLs.

1 Like

Thanks a lot. That gave me a much simpler solution to the nagging issue, and a good path forward when I start developing on top of the framework.

1 Like

@rfindley I am getting an uncaught 304 error in the fetch_endpoint promise when using the updated_after filter and a date before the date of the last update. Maybe you should catch this and resolve the promise with an empty list?

2 Likes

Hey @rfindley I’ve got this feeling that WKOF may be negating the changes I’m making to one of the scripts that rely on it (namely, Kumirei’s heatmap). I noticed there’s a cache/call of the cache at the top. However, there is no “settings” feature/button for WKOF in our dropdown, where I can access the settings for the heatmap or your amazing self-study quiz. If this cache is separate from my browser’s cache (which I have cleared again and again in pursuit of making one simple change work), then is this possibly from data stored in WKOF?

I’m curious. Also, if it is stored in WKOF, can I clear the data/cache somehow? Would you add a “settings” feature for it, even if the only option was “clear cache/data”. (Perhaps another could be "fetch new v2 API key - if that’s not already automatically in the script - for when people change keys… though I don’t believe that happens often…)

!! Maybe related to this (from post 2!)

EDIT: Nevermind… nothing is stored in WKOF acc. to Kumirei. Hmm…

Since I just noticed that it existed I tried using pre_open to add the labels to the color inputs, but their .value all read #000000 at this point. I haven’t noticed anything strange with my previous setup, just adding them after dialog.open() has returned, but I figured maybe it was worth mentioning, in case anyone else would want to access the color values in pre_open.

1 Like

The relevant piece of Settings.js:

case 'color':
	context.config_list[name] = item;
	html += make_label(item);
	value = get_value(context, base, name);
	if (value === undefined) {
		value = (item.default || '#000000');
		set_value(context, base, name, value);
	}
	html += wrap_right('<input id="'+id+'" class="setting" type="color" name="'+name+'">');
	html = wrap_row(html, item.full_width, item.hover_tip);
	break;

It looks like it’s checking the settings value first (get_value()), not seeing a value (or is finding a value of #000000), and reverting to either a default from the config, or #000000.

1 Like

I’m in my final week or two of a contract project, so I should have some time relatively soon to start working on the stuff we’ve been talking about.

3 Likes

Ahh… I see it’s not actually setting the value at that point, it’s only setting the default if it doesn’t exist yet.

The actual relevant code is:

if (typeof context.cfg.pre_open === 'function') context.cfg.pre_open(dialog);
context.reversions = $.extend(true,{},wkof.settings[context.cfg.script_id]);
refresh(context);

It’s using refresh() to populate the values after you make any initial changes in pre_open().

Should I also run refresh() before pre_open() if pre_open() is present?

1 Like

Oh, that would explain it. I think it would make sense to populate the dialogue with the saved settings or defaults before pre_open(). I assume it wouldn’t do any harm to anyone who didn’t want to use the saved settings in their pre_open callback.

Really, no hurry. I have everything working as it is

1 Like

What’s the best way to get all available reviews? I see the summary endpoint gives you the available reviews, but only the IDs. Do I need to then cross-reference that with another endpoint? Or is it better to search assignments and filter by when the review is available?

Hopefully I’m just missing a super obvious easy way to get that information.

1 Like

The summary endpoint gives you subject ids for lessons and reviews. So, you can pass those ids into the subjects endpoint using the ids filter.

There are two ways with OpenFramework:

  1. Like @bladepoint said, look up each item by its subject_id. To do so, create an index of all items by subject_id using wkof.ItemData.get_index(....), or
  2. When you do your wkof.ItemData.get_items(), be sure to include the assignments endpoint, and wkof will automatically cross-reference it. Then you can filter items by their item.assignments.available_at field.

The second one should be faster than a fetch unless you’ve already fetched /summary.

Here’s an example of the 2nd method:

wkof.ItemData.get_items('assignments').then(function(items){
    var now = new Date().getTime();
    available_items = items.filter(function(item) {
        return (item.assignments && (item.assignments.available_at != null) &&
                (new Date(item.assignments.available_at).getTime() < now));
    });
});
1 Like

@rfindley In your scripts using the Settings and Menu feature, it looks like you define the default values in two places: once for the settings and once for the menu. Is there any reason that is necessary? I only define my default settings in one place for Open Framework Additional Filters and I haven’t noticed any side effects.

I’m not sure I understand. Does the Menu module have defaults?

Or do you mean defaults for saved settings versus defaults in the Settings dialog configuration? If that’s what you’re referring to, the reason is that the Settings dialog configuration was written before saved settings code was written. So, the dialog configuration doesn’t really need the settings.

Ah, yes that’s what I was referring to. So you’re saying I don’t need to worry about defaults for the settings dialog, right?


Also, I have a bug to report. When you open settings from within reviews, hitting Enter while in an input, which logically should either save the settings (my preference) or do nothing, actually gives focus to the review input. And then hitting it a second time not surprisingly tries to submit the review since that input now has focus.

That’s a tough bug, because I don’t know what element Wanikani’s keystroke handler is attached to. I encountered a related one where backspacing in the settings dialog performs a backspace in the answer entry field (or Wanikani was blocking backspace, or something like that). I tried to solve it in what little time I had, but ended up putting it on the back burner.

Oh well. It’s a minor issue anyway.