feat(dictionary): cache tokens in IndexedDB#844
feat(dictionary): cache tokens in IndexedDB#844killergerbah merged 6 commits intokillergerbah:mainfrom
Conversation
842fba2 to
78bad00
Compare
78bad00 to
ef0283a
Compare
killergerbah
left a comment
There was a problem hiding this comment.
Hey really appreciate the patience. I'm still trying to read and understand everything, so I've left some high level feedback for now. Let me know what you think.
372ab82 to
c07bd96
Compare
c07bd96 to
fae3e2c
Compare
killergerbah
left a comment
There was a problem hiding this comment.
Hey thanks again for the patience. I did another pass and mostly made suggestions to improve readability. I know some of this is probably just stylistic difference, but there's a lot of code with complex logic which I think can be made more readable with low cost. Mostly worried about needing to understand this code when making changes months from now.
| .map((track) => `#${track + 1}`) | ||
| .join(', '), | ||
| })}`; | ||
| msg += ` | ${t('settings.dictionaryBuildModifiedCards', { numCards: numUpdatedCards.toLocaleString('en-US') })}`; |
There was a problem hiding this comment.
Can localization of the progress strings be confined to the dictionary settings form instead? This would require you to model the progress/errors via a data structure but I think this is probably not so difficult as there's a limited number of types of status updates.
While the refactor might be kind of annoying, keeping the front-end and logical concerns separate as a matter of principle will will give us more flexibility to render the progress in different ways on the settings form, without a dependency on this code.
There was a problem hiding this comment.
That very flexibility was what I was trying to avoid. Some messages only makes sense to be displayed in certain states and constructing that seems like it would be complicated. Also some messages don't have translations if it's a random error. We also would need to handle translations in SubtitleColoring as it can log errors whenever tokens updates.
I still think it's worth doing though. I'm thinking of returning an object instead where the keys correspond to the translation key and values to the translation params. As well as a separate field for unspecified errors.
There was a problem hiding this comment.
If you provide both English string + the translation key, you could use the English string for logging in SubtitleColoring. The translation key could be used for display on the settings form.
There was a problem hiding this comment.
But instead of translation key, maybe provide an an enum? That will give us some decoupling of the progress/error type from the loc file.
There was a problem hiding this comment.
I can't get a design that I'm happy with so I think it's best if you make the changes.
There was a problem hiding this comment.
Pushed, let me know if anything looks weird to you
There was a problem hiding this comment.
It looks good, the only issue I noticed is that the elapsed time changes when a build is done and the button is pressed. I think this lies in how the UI is calculating it but it's not a big deal.
I also re-review the rest of the PR as well. Earlier your comment about dictionaryProvider was accurate, we could use DictionaryStorage directly. I'm not sure if it's worth updating though. I could see it being useful for statistics.
There was a problem hiding this comment.
It looks good, the only issue I noticed is that the elapsed time changes when a build is done and the button is pressed. I think this lies in how the UI is calculating it but it's not a big deal.
I briefly tried this and couldn't repro something like what you're describing. All I did was finish a cache build, and then press the button again. But then it just shows you "Anki track(s): #1 | 0 modified card(s)
".
If there is issue that's easy to fix we can clean that up. I also want to note the following we should probably fix before release:
- Leaving the "annotations" tab and coming back will reset the button state, even if a build is in progress, until the next build update is received.
- The button is clickable even if card targeting is not completely set up (e.g. 0 word/sentence fields).
- We should probably add some more helper text to direct the user to setup stuff, if they enabled "colorize subtitles based on Anki maturity." Since some users might expect everything to work without further configuration.
There was a problem hiding this comment.
All I did was finish a cache build, and then press the button again.
It's only when at least a card is built so it shows the elapsed time. The next time the button is pressed the elapsed counter is updated but this is fixed by setting the state to undefined on the button press.
Leaving the "annotations" tab and coming back will reset the button state, even if a build is in progress, until the next build update is received.
Is there an easy fix for this? Otherwise it seems we would need to check the build on page load. But we won't get the updates in all scenarios, such as if they open the website in a new tab. If there isn't an easy fix it should be fine to leave as only the initial build should be long.
The button is clickable even if card targeting is not completely set up (e.g. 0 word/sentence fields).
It can be disabled if no tracks are enabled, but empty fields are okay as that's what will clear the db on the next build. I also don't want anything too distracting if they don't configure it since it's valid to only use local tokens.
I'll address some of these in the local tokens PR and we can discuss more changes then.
There was a problem hiding this comment.
Is there an easy fix for this? Otherwise it seems we would need to check the build on page load.
Probably, just need to put the state somewhere outside the tab maybe
* feat(dictionary): cache tokens in IndexedDB * use anki decks in addition to anki fields * use DictionaryProvider * update DictionaryProvider subscription api and cleanup code * remove _updateSuspendedCards() and cleanup code * Anki cache build state updates are structured --------- Co-authored-by: R-J Lim <kgerbil@gmail.com>
* feat(dictionary): cache tokens in IndexedDB * use anki decks in addition to anki fields * use DictionaryProvider * update DictionaryProvider subscription api and cleanup code * remove _updateSuspendedCards() and cleanup code * Anki cache build state updates are structured --------- Co-authored-by: R-J Lim <kgerbil@gmail.com>
This eliminates the runtime dependency of Anki (though if it's available, it will be used to automatically keep cache in sync). This gives a massive speedup since we no longer need to query Anki as well as Yomitan for the Anki cards (especially sentence cards). Support for local tokens is not exposed to the user in this PR.
DictionaryProvider(works the same asSettingsProvider).meta: Use for tracking the current and previous builds to know if settings changed or build is in processtokens: Stores each word with their lemmas status, etcankiCard: Anki tokens derive their status from this store as we need to track other things like suspended statuscards > modifiedAt. This means we will only trigger a cache build once for a given card during a playback session (though subsequent card triggers will update everything). This covers the main case of collecting a token but tracking more is too inefficient.buildIdso concurrent builds are prevented even in case of shutdowns with no cleanup. Build will expire when completed or if more than 5 minutes has passed since the last update (every few seconds).SubtitlePlayer, it triggers a cache build immediately. This already existed if it was initiated from the extension (such as keybind).AlwaysandNeverwon't trigger cache builds for that track (unless coloring is enabled).SubtitleColoringwill now only reset the cache on settings that affect it, rather than all. It will now also clear the richText that's currently being displayed if the user turns off the features as we rely on it being enabled to update it.Local > Anki word > Anki sentence