Autoplay priming called onSubtitleChange after a cache miss, which only asks
whether the text is new. When the miss came from an invalidation (mining a
card while the line is on screen) the text was unchanged, so nothing was
scheduled and the line stayed unannotated for as long as it was displayed.
refreshCurrentSubtitle checks the cache generation as well, so it re-tokenizes
for the new generation; the resume fallback is kept for the case where it
genuinely has nothing to do.
refreshCurrentSubtitle also returned false for empty text while a run was in
flight, even though that run goes on to emit the empty subtitle. It now
reports the pending emit so callers do not release the prefetch pause early.
The priming tests now drive the real subtitle processing controller instead of
a stub. The previous stub encoded the wrong assumption about unchanged text
and so could not catch either bug.
The repeated-subtitle pause leak was only fixed for ordinary subtitle
changes. Startup autoplay priming and visible-overlay priming pause the same
way and also ignored whether any tokenization was scheduled, so a cache miss
on text the controller already holds (mining a card while the line is on
screen) left prefetching idle for the rest of the cue.
Pause and release are now one operation via pausePrefetchUntilEmit, and both
controller entry points report whether an emit is expected. A repeat arriving
while a run is already in flight keeps the pause, since that run still emits.
Also invalidate the character dictionary lookups centrally from the sync
completion handler instead of at three manager call sites. Ordinary selection
sync never invalidated them, so a stale non-null name candidate list could
skip a newly added name for up to five seconds; a missing list falls back to
the exhaustive scan, but a stale one does not. Ordering matters: the
invalidation runs before the subtitle refreshes so they re-tokenize against
the new dictionary content.
Docs: subtitle-overlay-priming no longer claims every subtitle change calls
onSeek().
onSubtitleChange paused prefetching unconditionally, but the processing
controller returns early when the text matches what it already has. Nothing
is tokenized, so nothing is emitted, so the resume that rides on the emit
never fires and prefetching idles for the rest of the cue. The reachable
trigger is a repeat arriving after a cache invalidation, such as mining a card
while the same line is still on screen.
The controller now reports whether it scheduled processing and the caller
resumes when it did not, so every pause has a matching resume.
Also harden the character-name candidate prefilter: Yomitan collapses emphatic
sequences before matching, so a stretched spelling still resolves to its entry
(ミナァァト matches ミナト). The candidate match now skips small kana and
prolonged marks, which only widens the probe set and so cannot drop a name.