mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-21 12:11:28 -07:00
fix(subtitle-sidebar): address CodeRabbit review
This commit is contained in:
17
src/main.ts
17
src/main.ts
@@ -4056,7 +4056,7 @@ async function extractInternalSubtitleTrackToTempFile(
|
|||||||
videoPath: string,
|
videoPath: string,
|
||||||
track: MpvSubtitleTrackLike,
|
track: MpvSubtitleTrackLike,
|
||||||
): Promise<{ path: string; cleanup: () => Promise<void> } | null> {
|
): Promise<{ path: string; cleanup: () => Promise<void> } | null> {
|
||||||
const ffIndex = typeof track['ff-index'] === 'number' ? track['ff-index'] : null;
|
const ffIndex = parseTrackId(track['ff-index']);
|
||||||
const codec = typeof track.codec === 'string' ? track.codec : null;
|
const codec = typeof track.codec === 'string' ? track.codec : null;
|
||||||
const extension = codecToExtension(codec ?? undefined);
|
const extension = codecToExtension(codec ?? undefined);
|
||||||
if (ffIndex === null || extension === null) {
|
if (ffIndex === null || extension === null) {
|
||||||
@@ -4066,8 +4066,12 @@ async function extractInternalSubtitleTrackToTempFile(
|
|||||||
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'subminer-sidebar-'));
|
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'subminer-sidebar-'));
|
||||||
const outputPath = path.join(tempDir, `track_${ffIndex}.${extension}`);
|
const outputPath = path.join(tempDir, `track_${ffIndex}.${extension}`);
|
||||||
|
|
||||||
|
try {
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
const child = spawn(ffmpegPath, buildFfmpegSubtitleExtractionArgs(videoPath, ffIndex, outputPath));
|
const child = spawn(
|
||||||
|
ffmpegPath,
|
||||||
|
buildFfmpegSubtitleExtractionArgs(videoPath, ffIndex, outputPath),
|
||||||
|
);
|
||||||
let stderr = '';
|
let stderr = '';
|
||||||
child.stderr.on('data', (chunk: Buffer) => {
|
child.stderr.on('data', (chunk: Buffer) => {
|
||||||
stderr += chunk.toString();
|
stderr += chunk.toString();
|
||||||
@@ -4083,6 +4087,10 @@ async function extractInternalSubtitleTrackToTempFile(
|
|||||||
reject(new Error(stderr.trim() || `ffmpeg exited with code ${code ?? 'unknown'}`));
|
reject(new Error(stderr.trim() || `ffmpeg exited with code ${code ?? 'unknown'}`));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
await fs.promises.rm(tempDir, { recursive: true, force: true }).catch(() => undefined);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
path: outputPath,
|
path: outputPath,
|
||||||
@@ -4245,10 +4253,7 @@ const { registerIpcRuntimeHandlers } = composeIpcRuntimeHandlers({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (appState.activeParsedSubtitleSource === resolvedSource.sourceKey) {
|
||||||
appState.activeParsedSubtitleCues.length > 0 &&
|
|
||||||
appState.activeParsedSubtitleSource === resolvedSource.sourceKey
|
|
||||||
) {
|
|
||||||
return {
|
return {
|
||||||
cues: appState.activeParsedSubtitleCues,
|
cues: appState.activeParsedSubtitleCues,
|
||||||
currentTimeSec,
|
currentTimeSec,
|
||||||
|
|||||||
@@ -18,6 +18,15 @@ test('getActiveExternalSubtitleSource returns the active external subtitle path'
|
|||||||
assert.equal(source, 'https://host/subs.ass');
|
assert.equal(source, 'https://host/subs.ass');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('getActiveExternalSubtitleSource normalizes integer-like string track ids', () => {
|
||||||
|
const source = getActiveExternalSubtitleSource(
|
||||||
|
[{ type: 'sub', id: '2', external: true, 'external-filename': ' /tmp/subs.ass ' }],
|
||||||
|
'2',
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(source, '/tmp/subs.ass');
|
||||||
|
});
|
||||||
|
|
||||||
test('getActiveExternalSubtitleSource returns null when the selected track is not external', () => {
|
test('getActiveExternalSubtitleSource returns null when the selected track is not external', () => {
|
||||||
const source = getActiveExternalSubtitleSource(
|
const source = getActiveExternalSubtitleSource(
|
||||||
[{ type: 'sub', id: 2, external: false, 'external-filename': '/tmp/subs.ass' }],
|
[{ type: 'sub', id: 2, external: false, 'external-filename': '/tmp/subs.ass' }],
|
||||||
@@ -70,6 +79,15 @@ test('buildSubtitleSidebarSourceKey uses a stable identifier for internal subtit
|
|||||||
assert.equal(firstKey, 'internal:/media/episode01.mkv:track:3:ff:7');
|
assert.equal(firstKey, 'internal:/media/episode01.mkv:track:3:ff:7');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('buildSubtitleSidebarSourceKey normalizes integer-like string track metadata', () => {
|
||||||
|
const key = buildSubtitleSidebarSourceKey('/media/episode01.mkv', {
|
||||||
|
id: '3',
|
||||||
|
'ff-index': '7',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(key, 'internal:/media/episode01.mkv:track:3:ff:7');
|
||||||
|
});
|
||||||
|
|
||||||
test('buildSubtitleSidebarSourceKey falls back to source path when no track metadata is available', () => {
|
test('buildSubtitleSidebarSourceKey falls back to source path when no track metadata is available', () => {
|
||||||
const key = buildSubtitleSidebarSourceKey('/media/episode01.mkv', null, '/tmp/subtitle.ass');
|
const key = buildSubtitleSidebarSourceKey('/media/episode01.mkv', null, '/tmp/subtitle.ass');
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,8 @@ export function getActiveExternalSubtitleSource(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sid =
|
const sid = parseTrackId(sidRaw);
|
||||||
typeof sidRaw === 'number' ? sidRaw : typeof sidRaw === 'string' ? Number(sidRaw) : null;
|
if (sid === null) {
|
||||||
if (sid == null || !Number.isFinite(sid)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ export function getActiveExternalSubtitleSource(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const track = entry as Record<string, unknown>;
|
const track = entry as Record<string, unknown>;
|
||||||
return track.type === 'sub' && track.id === sid;
|
return track.type === 'sub' && parseTrackId(track.id) === sid && track.external === true;
|
||||||
}) as Record<string, unknown> | undefined;
|
}) as Record<string, unknown> | undefined;
|
||||||
|
|
||||||
const externalFilename =
|
const externalFilename =
|
||||||
|
|||||||
@@ -726,7 +726,6 @@ body.subtitle-sidebar-embedded-open #secondarySubContainer {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 40px;
|
top: 40px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
|
||||||
max-width: min(80%, calc(100vw - var(--subtitle-sidebar-reserved-width) - 24px));
|
max-width: min(80%, calc(100vw - var(--subtitle-sidebar-reserved-width) - 24px));
|
||||||
padding: 10px 18px;
|
padding: 10px 18px;
|
||||||
background: var(--secondary-sub-background-color, transparent);
|
background: var(--secondary-sub-background-color, transparent);
|
||||||
|
|||||||
Reference in New Issue
Block a user