I think I got export and import into a state I’m satisfied with for a first draft.
For reference, this is how the import dialog looks like, which I’m proud of:
Images
Also, finally managed to face my fears and make related items work. This means the extension now requires an api key (a free one works as well).
The difficulties I ran into for those that like tech writeups
Fetching all items from the api is a long procedure, especially for the first time, when chrome is trying to figure out what the hell you’re trying to do. It takes about 10 seconds, and of course, this isn’t good UX, if the user has to wait 10 seconds between operations, and even the WK team says, that items should be cached aggressively.
So first I tried to put this whole thing into extension local storage. Now, did you know, that storing all items like that is 18 megabytes, out of the 5 you can use? So now I need unlimitedStorage perms as well. That’s fine.
Bigger issue, serializing and deserializing 18 megabytes worth of JSON is also a long operation (not 10 seconds, but more like 5). Waiting 5 seconds between operations is a much better UX, still not very ideal. So I wanted to do something about it.
As a first idea, I wanted to store the items loaded up somewhere. My popup script dies the second the popup closes, my review script lives just as long as the page it is on, my popup scripts were killed alongside my popup. So my choice was a background script (which is funny, because basically every version I think I need a popup script, then it turns out its entirely useless and I delete it). So I created my cache system there, it worked well, the access times went down to 0.5 seconds or so, which is bearable. However, turns out, since Manifest V3, even the background scripts die after a few seconds. This was an issue, the debugging of which I don’t wish on my worst enemies even.
So the background script went the way of the dodo again. And I needed a new method. The main issue is, that parsing 18 megabytes of JSON is hell. So next idea: let’s not do that. Instead I break up the item cache into chunk of 500 items, making them about 1 megabytes in size. Because I can load them individually, and each item should generally take at most 10 or so related items, it’s highly likely I need to load the entire thing, and even then, chrome probably (hopefully) parallelizes. This lowered the cache time to a second usually, which is nice.
Next, when users are adding a bunch of items, though 1 second isn’t much, but it’s annoying, if you need to wait that 1 second a lot of times. So to solve that, I put in another level of cache, actually caching the caches in memory. When a cache instance is loaded and parsed, it gets saved in a volatile cache, so it doesn’t need to be parsed again. This cuts down the lookup times to unnoticable levels.
The current solution is quite nice, decks with 2000 items or so import in a few seconds. The least responsive part of the ui currently is loading deck from storage, but I might address that over time, caching that too, so it doesn’t need to be reparsed over and over again.
For now there’s no way to update a deck you’ve imported from a newer version, but I put in measure to make this possible. If all goes well, you’ll be able to publish a new version of a deck, and whoever has it installed will be able to just pull in the changes without having to reset.
I’ll publish this version (currently 0.1.7.1). There is currently one known limitation, that being, that linking to items not from wanikani inside an exported deck doesn’t work. In the future, I’ll probably disallow intermingling between decks, to make exporting it make actually sense. I’ll probably add item clones in, where you can have a deck contain an item, and another deck contain a clone that doesn’t get placed into lessons, but allows you to link to it.