Skip to content

Commit c84d5bf

Browse files
nodeeeeeeclaude
andcommitted
Fix scan to show all downloaded videos, not just transcribed ones
The scan now discovers videos from the manifest (all downloaded) in addition to the captions directory. Videos without captions appear with a "(no caption)" badge so the user knows to transcribe first. Previously only transcribed videos (with a caption JSON) were shown, so newly downloaded videos were invisible in the matching UI. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e080246 commit c84d5bf

2 files changed

Lines changed: 42 additions & 11 deletions

File tree

electron/main.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -791,19 +791,45 @@ function registerIpc() {
791791
const alignDir = path.join(base, 'alignment');
792792
const exts = new Set(['.pdf', '.pptx', '.ppt', '.docx', '.doc']);
793793

794-
// Captions
794+
// Videos: discover from manifest (all downloaded) + captions dir
795+
// A video should appear as soon as it's downloaded, not only after transcription.
795796
let captions = [];
797+
const seenStems = new Set();
798+
799+
// Source 1: manifest — all downloaded videos for this course
800+
const mf = path.join(DATA_DIR, 'manifest.json');
801+
if (fs.existsSync(mf)) {
802+
try {
803+
const manifest = JSON.parse(fs.readFileSync(mf, 'utf8'));
804+
for (const [, entry] of Object.entries(manifest)) {
805+
if (entry.status !== 'done' || !entry.path) continue;
806+
// Check video belongs to this course
807+
const vidPath = entry.path;
808+
if (!vidPath.includes(path.sep + String(cid) + path.sep) &&
809+
!vidPath.includes('/' + String(cid) + '/')) continue;
810+
const stem = path.basename(vidPath, path.extname(vidPath));
811+
if (seenStems.has(stem)) continue;
812+
seenStems.add(stem);
813+
const hasCaptions = fs.existsSync(path.join(capDir, stem + '.json'));
814+
const aligned = fs.existsSync(path.join(alignDir, stem + '.json'));
815+
captions.push({ stem, filename: stem + '.json', aligned, transcribed: hasCaptions });
816+
}
817+
} catch {}
818+
}
819+
820+
// Source 2: captions dir — pick up any transcribed videos not in manifest
796821
if (fs.existsSync(capDir)) {
797-
captions = fs.readdirSync(capDir)
798-
.filter(f => f.endsWith('.json'))
799-
.sort()
800-
.map(f => {
801-
const stem = f.replace(/\.json$/, '');
802-
const aligned = fs.existsSync(path.join(alignDir, f));
803-
return { stem, filename: f, aligned };
804-
});
822+
for (const f of fs.readdirSync(capDir).filter(f => f.endsWith('.json')).sort()) {
823+
const stem = f.replace(/\.json$/, '');
824+
if (seenStems.has(stem)) continue;
825+
seenStems.add(stem);
826+
const aligned = fs.existsSync(path.join(alignDir, f));
827+
captions.push({ stem, filename: f, aligned, transcribed: true });
828+
}
805829
}
806830

831+
captions.sort((a, b) => a.stem.localeCompare(b.stem));
832+
807833
// Slides (recursive)
808834
const slides = [];
809835
function walkDir(dir, rel) {

electron/renderer/app.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -723,10 +723,15 @@ function _alignRebuildRows() {
723723
${actionBtn}</div>`;
724724
});
725725

726+
// Transcription badge
727+
const transBadge = row.transcribed === false
728+
? '<span style="font-size:9px;color:var(--c-warn);opacity:0.8;margin-left:4px" title="Not yet transcribed">(no caption)</span>'
729+
: '';
730+
726731
html += `<div style="display:flex;align-items:flex-start;gap:6px;padding:6px 0;border-bottom:1px solid rgba(255,255,255,0.06)">
727732
<button class="icon-btn" title="Remove video" data-action="remove" data-row="${ri}" style="color:var(--c-error);font-size:14px">×</button>
728733
<span style="width:14px;padding-top:4px">${statusIcon}</span>
729-
<span style="width:220px;padding-top:4px;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="${esc(row.title)}">${esc(row.title)}</span>
734+
<span style="width:220px;padding-top:4px;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="${esc(row.title)}">${esc(row.title)}${transBadge}</span>
730735
<span style="padding-top:4px;opacity:0.3">→</span>
731736
<div style="flex:1">${slidesHtml}</div>
732737
</div>`;
@@ -1470,7 +1475,7 @@ async function attachPageHandlers() {
14701475
const suggested = _alignAutoSuggest(cap.stem);
14711476
initSlides = suggested !== '(none)' ? [suggested] : ['(none)'];
14721477
}
1473-
return { stem: cap.stem, title, aligned: cap.aligned, slides: initSlides };
1478+
return { stem: cap.stem, title, aligned: cap.aligned, transcribed: cap.transcribed, slides: initSlides };
14741479
});
14751480

14761481
_alignRebuildRows();

0 commit comments

Comments
 (0)