Add admin analytics, metadata collection, and grouped lyric cues

Queue reviewable Whisper drafts from the song list and lyrics editor. Preserve line breaks within one timed cue across editing, saving, reporting, and service views.

Add storage and listening analytics with a durable metadata collector, related-search depth, video limits, thumbnail storage, and a browsable metadata library.
This commit is contained in:
Jonathan Sykes
2026-10-03 07:54:11 +08:00
parent 716b61ffee
commit 2b38717c05
23 changed files with 1181 additions and 48 deletions

View File

@@ -78,3 +78,16 @@ test('YouTube export adds a 0:00 entry only when needed', () => {
assert.strictEqual(LC.activeMarker(items, 60).title, 'Intro');
assert.strictEqual(LC.activeMarker(items, 10), null);
});
test('multiline cues round-trip without adding timestamps or active rows', () => {
const doc = { lines: [{ t: 12, text: 'Because You are God\nYou can do anything', kind: 'line' }, { t: 18, text: 'Next lyric', kind: 'line' }], tags: [] };
const copy = LC.fromText(LC.toText(doc));
assert.deepStrictEqual(copy.lines, doc.lines);
assert.strictEqual(LC.activeIndex(copy.lines, 15, 0), 0);
assert.strictEqual(LC.activeIndex(copy.lines, 18, 0), 1);
assert.strictEqual(LC.timedCount(copy.lines), 2);
const repeated = LC.fromText('[0:12][0:30] Because You are God\n| You can do anything');
assert.strictEqual(repeated.lines.length, 2);
assert.strictEqual(repeated.lines[1].text, doc.lines[0].text);
});