mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-04 19:21:33 -07:00
fix(subtitles): release prefetch pause on repeated subtitle events
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.
This commit is contained in:
@@ -495,7 +495,7 @@ const YOMITAN_SCANNING_HELPERS = String.raw`
|
||||
|
||||
// Bump whenever the install script below changes so already-loaded parser
|
||||
// windows re-install the new scan runtime instead of running the stale one.
|
||||
export const YOMITAN_SCAN_RUNTIME_VERSION = 3;
|
||||
export const YOMITAN_SCAN_RUNTIME_VERSION = 4;
|
||||
export const YOMITAN_SCAN_RUNTIME_MISSING_SENTINEL = '__subminer-yomitan-scan-runtime-missing__';
|
||||
|
||||
export interface YomitanScanRequestParams {
|
||||
@@ -731,13 +731,33 @@ ${YOMITAN_SCANNING_HELPERS}
|
||||
? nameCandidateIndex
|
||||
: null;
|
||||
const normalizedText = activeNameCandidateIndex ? convertKatakanaToHiragana(text) : "";
|
||||
// Yomitan collapses emphatic sequences before matching (すっっごーーい →
|
||||
// すごい), so a stretched name still resolves to its entry. Skipping these
|
||||
// characters keeps such spellings candidates; the filter only ever grows
|
||||
// the probe set, so a false positive costs one lookup, never a name.
|
||||
const EMPHATIC_SKIP_CHARS = new Set(["ぁ", "ぃ", "ぅ", "ぇ", "ぉ", "っ", "ゃ", "ゅ", "ょ", "ー"]);
|
||||
function matchesCandidateFormAt(form, position) {
|
||||
let textIndex = position;
|
||||
for (let formIndex = 0; formIndex < form.length; formIndex += 1) {
|
||||
while (
|
||||
textIndex < normalizedText.length &&
|
||||
normalizedText[textIndex] !== form[formIndex] &&
|
||||
EMPHATIC_SKIP_CHARS.has(normalizedText[textIndex])
|
||||
) {
|
||||
textIndex += 1;
|
||||
}
|
||||
if (normalizedText[textIndex] !== form[formIndex]) { return false; }
|
||||
textIndex += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function couldNameStartAt(position, codePoint) {
|
||||
if (!activeNameCandidateIndex) { return true; }
|
||||
if (isHalfwidthKatakanaCodePoint(codePoint)) { return true; }
|
||||
const bucket = activeNameCandidateIndex.byFirstChar.get(normalizedText[position]);
|
||||
if (!bucket) { return false; }
|
||||
for (const form of bucket) {
|
||||
if (normalizedText.startsWith(form, position)) { return true; }
|
||||
if (matchesCandidateFormAt(form, position)) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user