fix(anki): regenerate sentence furigana when mined context changes

- Regenerate SentenceFurigana from the final sentence after timing-review expansion or stats-dashboard word mining
- Add a Yomitan parseText-based generator with a 10s timeout and escaped, highlighted output
- Clear stale furigana on failure so templates fall back to Sentence
- Keep existing furigana formatting when the sentence is unchanged
- Document the behavior in the anki-integration and immersion-tracking docs
This commit is contained in:
2026-09-22 21:46:06 -07:00
16 changed files with 489 additions and 18 deletions
+10
View File
@@ -16,6 +16,7 @@ import { requestHachidoriSharing } from './core/services/tokenizer/yomitan-parse
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { generateSentenceFurigana } from './core/services/tokenizer/sentence-furigana';
import {
app,
BrowserWindow,
@@ -5212,6 +5213,13 @@ function createMainWindow(): BrowserWindow {
return window;
}
function generateMiningSentenceFurigana(
text: string,
highlightedText?: string,
): Promise<string | null> {
return generateSentenceFurigana(text, highlightedText, getYomitanParserRuntimeDeps(), logger);
}
function initializeOverlayRuntime(): void {
initializeOverlayRuntimeHandler();
if (!(appState.initialArgs && isHeadlessInitialCommand(appState.initialArgs))) {
@@ -5221,6 +5229,7 @@ function initializeOverlayRuntime(): void {
appState.ankiIntegration?.setKnownWordCacheUpdatedCallback(refreshCurrentSubtitleAnnotations);
appState.ankiIntegration?.setSubtitleMiningContextConsumer(consumePendingSubtitleMiningContext);
appState.ankiIntegration?.setMediaTimingReviewCallback(mediaTimingReviewRuntime.requestReview);
appState.ankiIntegration?.setSentenceFuriganaGenerator(generateMiningSentenceFurigana);
syncOverlayMpvSubtitleSuppression();
}
@@ -6164,6 +6173,7 @@ const { registerIpcRuntimeHandlers } = composeIpcRuntimeHandlers({
appState.ankiIntegration?.setMediaTimingReviewCallback(
mediaTimingReviewRuntime.requestReview,
);
appState.ankiIntegration?.setSentenceFuriganaGenerator(generateMiningSentenceFurigana);
},
getKnownWordCacheStatePath: () => path.join(USER_DATA_PATH, 'known-words-cache.json'),
getCachedMediaPath: (currentVideoPath, kind) =>