mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-06 19:47:04 +03:00
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:
@@ -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])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user