Rewrite chapter nesting code

Friendship ended with recursion, chapter stack is my new friend

side effect: fixes popup crash for videos where the first segment is not
a chapter
This commit is contained in:
mini-bomba
2025-09-20 23:11:50 +02:00
parent 7cbb0ec7cf
commit 14d7d79ce7

View File

@@ -60,36 +60,38 @@ export const SegmentListComponent = (props: SegmentListComponentProps) => {
const segmentsWithNesting = React.useMemo(() => { const segmentsWithNesting = React.useMemo(() => {
const result: SegmentWithNesting[] = []; const result: SegmentWithNesting[] = [];
let nbTrailingNonChapters = 0; const chapterStack: SegmentWithNesting[] = [];
function nestChapters(segments: SegmentWithNesting[], seg: SponsorTime, topLevel?: boolean) { for (let seg of props.segments) {
if (seg.actionType === ActionType.Chapter && segments.length) { seg = {...seg};
// trailing non-chapters can only exist at top level // non-chapter, do not nest
const lastElement = segments[segments.length - (topLevel ? nbTrailingNonChapters + 1 : 1)]
if (lastElement.actionType === ActionType.Chapter
&& lastElement.segment[0] <= seg.segment[0]
&& lastElement.segment[1] >= seg.segment[1]) {
if (lastElement.innerChapters){
nestChapters(lastElement.innerChapters, seg);
} else {
lastElement.innerChapters = [seg];
}
} else {
if (topLevel) {
nbTrailingNonChapters = 0;
}
segments.push(seg);
}
} else {
if (seg.actionType !== ActionType.Chapter) { if (seg.actionType !== ActionType.Chapter) {
nbTrailingNonChapters++; result.push(seg);
continue;
} }
// traverse the stack
while (chapterStack.length !== 0) {
// where's Array.prototype.at() :sob:
const lastChapter = chapterStack[chapterStack.length - 1];
// we know lastChapter.startTime <= seg.startTime, as content.ts sorts these
// so only compare endTime - if new ends before last, new is nested inside last
if (lastChapter.segment[1] >= seg.segment[1]) {
lastChapter.innerChapters ??= [];
lastChapter.innerChapters.push(seg);
chapterStack.push(seg);
break;
}
// last did not match, pop it off the stack
chapterStack.pop();
}
// chapter stack not empty = we found a place for the chapter
if (chapterStack.length !== 0) {
continue;
}
// push the chapter to the top-level list and to the stack
result.push(seg);
chapterStack.push(seg);
segments.push(seg);
} }
}
props.segments.forEach((seg) => nestChapters(result, {...seg}, true));
return result; return result;
}, [props.segments]) }, [props.segments])