mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-10-21 05:01:26 -07:00
fix(overlay): poll cheap playback state in the open subtitle sidebar (#290)
This commit is contained in:
1 parent
7108e086ba
commit
a6d96e9966
14 files changed
+286
-108
No files matched your search
+44
-76
@@ -92,8 +92,10 @@ import type {
|
||||
SessionActionDispatchRequest,
|
||||
SecondarySubMode,
|
||||
SubtitleData,
|
||||
SubtitleCue,
|
||||
SubtitleMiningContext,
|
||||
SubtitlePosition,
|
||||
SubtitleSidebarPlaybackState,
|
||||
WindowGeometry,
|
||||
} from './types';
|
||||
import { OPEN_ANKI_CARD_ACTION_ID } from './types';
|
||||
@@ -2047,6 +2049,33 @@ const linuxOverlayModeRuntime = createLinuxOverlayModeRuntime({
|
||||
logDebug: (message) => logger.debug(message),
|
||||
});
|
||||
let subtitleSidebarRequestedOpen = false;
|
||||
let subtitleSidebarCuesRef: SubtitleCue[] | null = null;
|
||||
let subtitleSidebarCuesRevision = 0;
|
||||
|
||||
/**
|
||||
* Cheap sidebar state polled ~12x/s while the sidebar is open. Reads only cached state, no
|
||||
* mpv round-trips. `cuesRevision` bumps whenever a new parsed cue array is swapped in, so a
|
||||
* re-parse of the same source still tells the renderer to fetch the full snapshot.
|
||||
*/
|
||||
function getSubtitleSidebarPlaybackState(): SubtitleSidebarPlaybackState {
|
||||
if (appState.activeParsedSubtitleCues !== subtitleSidebarCuesRef) {
|
||||
subtitleSidebarCuesRef = appState.activeParsedSubtitleCues;
|
||||
subtitleSidebarCuesRevision += 1;
|
||||
}
|
||||
return {
|
||||
sourceKey: JSON.stringify([
|
||||
appState.activeParsedSubtitleMediaPath,
|
||||
appState.activeParsedSubtitleSource,
|
||||
]),
|
||||
cuesRevision: subtitleSidebarCuesRevision,
|
||||
currentTimeSec: appState.mpvClient?.currentTimePos ?? null,
|
||||
currentSubtitle: {
|
||||
text: appState.currentSubText,
|
||||
startTime: appState.mpvClient?.currentSubStart ?? null,
|
||||
endTime: appState.mpvClient?.currentSubEnd ?? null,
|
||||
},
|
||||
};
|
||||
}
|
||||
const SEEK_THRESHOLD_SECONDS = 3;
|
||||
const EXPLICIT_SEEK_INTENT_TTL_MS = 2000;
|
||||
let explicitSeekIntentExpiresAtMs = 0;
|
||||
@@ -5850,26 +5879,19 @@ const { registerIpcRuntimeHandlers } = composeIpcRuntimeHandlers({
|
||||
getCurrentSubtitleRaw: () => appState.currentSubText,
|
||||
getCurrentSubtitleAss: () => appState.currentSubAssText,
|
||||
getSubtitleSidebarOpen: () => subtitleSidebarRequestedOpen,
|
||||
getSubtitleSidebarPlaybackState: () => getSubtitleSidebarPlaybackState(),
|
||||
// Full snapshot: resolves the active source over mpv IPC and re-parses it when it changed.
|
||||
// The renderer fetches it on open, on source/cue changes, and on a slow fallback cadence.
|
||||
getSubtitleSidebarSnapshot: async () => {
|
||||
const currentSubtitle = {
|
||||
text: appState.currentSubText,
|
||||
startTime: appState.mpvClient?.currentSubStart ?? null,
|
||||
endTime: appState.mpvClient?.currentSubEnd ?? null,
|
||||
};
|
||||
const currentTimeSec = appState.mpvClient?.currentTimePos ?? null;
|
||||
const config = configService.getConfig().subtitleSidebar;
|
||||
const cachedSnapshot = () => ({
|
||||
...getSubtitleSidebarPlaybackState(),
|
||||
cues: appState.activeParsedSubtitleCues,
|
||||
config,
|
||||
});
|
||||
const client = appState.mpvClient;
|
||||
if (!client?.connected) {
|
||||
return {
|
||||
sourceKey: JSON.stringify([
|
||||
appState.activeParsedSubtitleMediaPath,
|
||||
appState.activeParsedSubtitleSource,
|
||||
]),
|
||||
cues: appState.activeParsedSubtitleCues,
|
||||
currentTimeSec,
|
||||
currentSubtitle,
|
||||
config,
|
||||
};
|
||||
return cachedSnapshot();
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -5883,16 +5905,7 @@ const { registerIpcRuntimeHandlers } = composeIpcRuntimeHandlers({
|
||||
]);
|
||||
const videoPath = typeof videoPathRaw === 'string' ? videoPathRaw : '';
|
||||
if (!videoPath) {
|
||||
return {
|
||||
sourceKey: JSON.stringify([
|
||||
appState.activeParsedSubtitleMediaPath,
|
||||
appState.activeParsedSubtitleSource,
|
||||
]),
|
||||
cues: appState.activeParsedSubtitleCues,
|
||||
currentTimeSec,
|
||||
currentSubtitle,
|
||||
config,
|
||||
};
|
||||
return cachedSnapshot();
|
||||
}
|
||||
if (
|
||||
shouldUseCachedYoutubeParsedCues({
|
||||
@@ -5901,16 +5914,7 @@ const { registerIpcRuntimeHandlers } = composeIpcRuntimeHandlers({
|
||||
cachedCueCount: appState.activeParsedSubtitleCues.length,
|
||||
})
|
||||
) {
|
||||
return {
|
||||
sourceKey: JSON.stringify([
|
||||
appState.activeParsedSubtitleMediaPath,
|
||||
appState.activeParsedSubtitleSource,
|
||||
]),
|
||||
cues: appState.activeParsedSubtitleCues,
|
||||
currentTimeSec,
|
||||
currentSubtitle,
|
||||
config,
|
||||
};
|
||||
return cachedSnapshot();
|
||||
}
|
||||
|
||||
const resolvedSource = await resolveActiveSubtitleSidebarSourceHandler({
|
||||
@@ -5921,30 +5925,12 @@ const { registerIpcRuntimeHandlers } = composeIpcRuntimeHandlers({
|
||||
videoPath,
|
||||
});
|
||||
if (!resolvedSource) {
|
||||
return {
|
||||
sourceKey: JSON.stringify([
|
||||
appState.activeParsedSubtitleMediaPath,
|
||||
appState.activeParsedSubtitleSource,
|
||||
]),
|
||||
cues: appState.activeParsedSubtitleCues,
|
||||
currentTimeSec,
|
||||
currentSubtitle,
|
||||
config,
|
||||
};
|
||||
return cachedSnapshot();
|
||||
}
|
||||
|
||||
try {
|
||||
if (appState.activeParsedSubtitleSource === resolvedSource.sourceKey) {
|
||||
return {
|
||||
sourceKey: JSON.stringify([
|
||||
appState.activeParsedSubtitleMediaPath,
|
||||
appState.activeParsedSubtitleSource,
|
||||
]),
|
||||
cues: appState.activeParsedSubtitleCues,
|
||||
currentTimeSec,
|
||||
currentSubtitle,
|
||||
config,
|
||||
};
|
||||
return cachedSnapshot();
|
||||
}
|
||||
|
||||
const content = await loadSubtitleSourceText(resolvedSource.path);
|
||||
@@ -5952,30 +5938,12 @@ const { registerIpcRuntimeHandlers } = composeIpcRuntimeHandlers({
|
||||
appState.activeParsedSubtitleCues = cues;
|
||||
appState.activeParsedSubtitleSource = resolvedSource.sourceKey;
|
||||
appState.activeParsedSubtitleMediaPath = videoPath || null;
|
||||
return {
|
||||
sourceKey: JSON.stringify([
|
||||
appState.activeParsedSubtitleMediaPath,
|
||||
appState.activeParsedSubtitleSource,
|
||||
]),
|
||||
cues,
|
||||
currentTimeSec,
|
||||
currentSubtitle,
|
||||
config,
|
||||
};
|
||||
return cachedSnapshot();
|
||||
} finally {
|
||||
await resolvedSource.cleanup?.();
|
||||
}
|
||||
} catch {
|
||||
return {
|
||||
sourceKey: JSON.stringify([
|
||||
appState.activeParsedSubtitleMediaPath,
|
||||
appState.activeParsedSubtitleSource,
|
||||
]),
|
||||
cues: appState.activeParsedSubtitleCues,
|
||||
currentTimeSec,
|
||||
currentSubtitle,
|
||||
config,
|
||||
};
|
||||
return cachedSnapshot();
|
||||
}
|
||||
},
|
||||
getPlaybackPaused: () =>
|
||||
|
||||
Reference in new issue
Block a user