Skip to content

Commit 14d7d79

Browse files
committed
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
1 parent 7cbb0ec commit 14d7d79

File tree

1 file changed

+29
-27
lines changed

1 file changed

+29
-27
lines changed

src/popup/SegmentListComponent.tsx

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -60,36 +60,38 @@ export const SegmentListComponent = (props: SegmentListComponentProps) => {
6060

6161
const segmentsWithNesting = React.useMemo(() => {
6262
const result: SegmentWithNesting[] = [];
63-
let nbTrailingNonChapters = 0;
64-
function nestChapters(segments: SegmentWithNesting[], seg: SponsorTime, topLevel?: boolean) {
65-
if (seg.actionType === ActionType.Chapter && segments.length) {
66-
// trailing non-chapters can only exist at top level
67-
const lastElement = segments[segments.length - (topLevel ? nbTrailingNonChapters + 1 : 1)]
68-
69-
if (lastElement.actionType === ActionType.Chapter
70-
&& lastElement.segment[0] <= seg.segment[0]
71-
&& lastElement.segment[1] >= seg.segment[1]) {
72-
if (lastElement.innerChapters){
73-
nestChapters(lastElement.innerChapters, seg);
74-
} else {
75-
lastElement.innerChapters = [seg];
76-
}
77-
} else {
78-
if (topLevel) {
79-
nbTrailingNonChapters = 0;
80-
}
81-
82-
segments.push(seg);
83-
}
84-
} else {
85-
if (seg.actionType !== ActionType.Chapter) {
86-
nbTrailingNonChapters++;
63+
const chapterStack: SegmentWithNesting[] = [];
64+
for (let seg of props.segments) {
65+
seg = {...seg};
66+
// non-chapter, do not nest
67+
if (seg.actionType !== ActionType.Chapter) {
68+
result.push(seg);
69+
continue;
70+
}
71+
// traverse the stack
72+
while (chapterStack.length !== 0) {
73+
// where's Array.prototype.at() :sob:
74+
const lastChapter = chapterStack[chapterStack.length - 1];
75+
// we know lastChapter.startTime <= seg.startTime, as content.ts sorts these
76+
// so only compare endTime - if new ends before last, new is nested inside last
77+
if (lastChapter.segment[1] >= seg.segment[1]) {
78+
lastChapter.innerChapters ??= [];
79+
lastChapter.innerChapters.push(seg);
80+
chapterStack.push(seg);
81+
break;
8782
}
88-
89-
segments.push(seg);
83+
// last did not match, pop it off the stack
84+
chapterStack.pop();
9085
}
86+
// chapter stack not empty = we found a place for the chapter
87+
if (chapterStack.length !== 0) {
88+
continue;
89+
}
90+
// push the chapter to the top-level list and to the stack
91+
result.push(seg);
92+
chapterStack.push(seg);
93+
9194
}
92-
props.segments.forEach((seg) => nestChapters(result, {...seg}, true));
9395
return result;
9496
}, [props.segments])
9597

0 commit comments

Comments
 (0)