mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-11-10 04:46:07 -08:00
feat(dictionary): add Hachidori backend support (#266)
This commit is contained in:
1 parent
e690ffba07
commit
cbaa4626e1
143 files changed
+5564
-305
No files matched your search
@@ -4,6 +4,7 @@ import type {
|
||||
} from '../../core/services/subtitle-prefetch';
|
||||
import type { SubtitleData } from '../../types';
|
||||
import type { SubtitleCue } from '../../types';
|
||||
import { buildOverlapPrefetchCues } from './subtitle-prefetch-overlaps';
|
||||
|
||||
export interface SubtitlePrefetchInitControllerDeps {
|
||||
getCurrentService: () => SubtitlePrefetchService | null;
|
||||
@@ -14,6 +15,7 @@ export interface SubtitlePrefetchInitControllerDeps {
|
||||
tokenizeSubtitle: (text: string) => Promise<SubtitleData | null>;
|
||||
preCacheTokenization: (text: string, data: SubtitleData) => void;
|
||||
hasCachedTokenization?: (text: string) => boolean;
|
||||
getCacheGeneration?: () => number;
|
||||
logInfo: (message: string) => void;
|
||||
logWarn: (message: string) => void;
|
||||
onParsedSubtitleCuesChanged?: (cues: SubtitleCue[] | null, sourceKey: string | null) => void;
|
||||
@@ -32,11 +34,20 @@ export function createSubtitlePrefetchInitController(
|
||||
deps: SubtitlePrefetchInitControllerDeps,
|
||||
): SubtitlePrefetchInitController {
|
||||
let initRevision = 0;
|
||||
// What the running service was built from. Startup fires several inits for one source
|
||||
// (Jellyfin preload seed, sid change, each track-list update); restarting on each would
|
||||
// discard the in-flight tokenization and re-queue the priority window behind it.
|
||||
let activeSource: { key: string; content: string; cues: SubtitleCue[] } | null = null;
|
||||
|
||||
const stopCurrentService = (): void => {
|
||||
deps.getCurrentService()?.stop();
|
||||
deps.setCurrentService(null);
|
||||
activeSource = null;
|
||||
};
|
||||
|
||||
const cancelPendingInit = (): void => {
|
||||
initRevision += 1;
|
||||
deps.getCurrentService()?.stop();
|
||||
deps.setCurrentService(null);
|
||||
stopCurrentService();
|
||||
deps.onParsedSubtitleCuesChanged?.(null, null);
|
||||
};
|
||||
|
||||
@@ -46,14 +57,26 @@ export function createSubtitlePrefetchInitController(
|
||||
sourceKey = sourcePath,
|
||||
): Promise<void> => {
|
||||
const revision = ++initRevision;
|
||||
deps.getCurrentService()?.stop();
|
||||
deps.setCurrentService(null);
|
||||
// The same source may still be current once loaded; keep its service running until then.
|
||||
if (activeSource?.key !== sourceKey) {
|
||||
stopCurrentService();
|
||||
}
|
||||
|
||||
try {
|
||||
const content = await deps.loadSubtitleSourceText(sourcePath);
|
||||
if (revision !== initRevision) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
activeSource?.key === sourceKey &&
|
||||
activeSource.content === content &&
|
||||
deps.getCurrentService()
|
||||
) {
|
||||
// A track change clears the published cues synchronously, so republish them.
|
||||
deps.onParsedSubtitleCuesChanged?.(activeSource.cues, sourceKey);
|
||||
return;
|
||||
}
|
||||
stopCurrentService();
|
||||
|
||||
const cues = deps.parseSubtitleCues(content, sourcePath);
|
||||
if (revision !== initRevision || cues.length === 0) {
|
||||
@@ -66,11 +89,16 @@ export function createSubtitlePrefetchInitController(
|
||||
return;
|
||||
}
|
||||
|
||||
// Overlap cues only feed the cache; the published cue list stays as authored.
|
||||
const prefetchCues = [...cues, ...buildOverlapPrefetchCues(cues)].sort(
|
||||
(a, b) => a.startTime - b.startTime,
|
||||
);
|
||||
const nextService = deps.createSubtitlePrefetchService({
|
||||
cues,
|
||||
cues: prefetchCues,
|
||||
tokenizeSubtitle: (text) => deps.tokenizeSubtitle(text),
|
||||
preCacheTokenization: (text, data) => deps.preCacheTokenization(text, data),
|
||||
hasCachedTokenization: (text) => deps.hasCachedTokenization?.(text) ?? false,
|
||||
getCacheGeneration: deps.getCacheGeneration,
|
||||
});
|
||||
|
||||
if (revision !== initRevision) {
|
||||
@@ -78,6 +106,7 @@ export function createSubtitlePrefetchInitController(
|
||||
}
|
||||
|
||||
deps.setCurrentService(nextService);
|
||||
activeSource = { key: sourceKey, content, cues };
|
||||
deps.onParsedSubtitleCuesChanged?.(cues, sourceKey);
|
||||
nextService.start(currentTimePos);
|
||||
deps.logInfo(
|
||||
@@ -85,6 +114,7 @@ export function createSubtitlePrefetchInitController(
|
||||
);
|
||||
} catch (error) {
|
||||
if (revision === initRevision) {
|
||||
stopCurrentService();
|
||||
deps.onParsedSubtitleCuesChanged?.(null, null);
|
||||
deps.logWarn(`[subtitle-prefetch] failed to initialize: ${(error as Error).message}`);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user