diff --git a/src/popup/SegmentListComponent.tsx b/src/popup/SegmentListComponent.tsx index 8ea207e3..1d6aa396 100644 --- a/src/popup/SegmentListComponent.tsx +++ b/src/popup/SegmentListComponent.tsx @@ -60,36 +60,38 @@ export const SegmentListComponent = (props: SegmentListComponentProps) => { const segmentsWithNesting = React.useMemo(() => { const result: SegmentWithNesting[] = []; - let nbTrailingNonChapters = 0; - function nestChapters(segments: SegmentWithNesting[], seg: SponsorTime, topLevel?: boolean) { - if (seg.actionType === ActionType.Chapter && segments.length) { - // trailing non-chapters can only exist at top level - 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) { - nbTrailingNonChapters++; - } - - segments.push(seg); + const chapterStack: SegmentWithNesting[] = []; + for (let seg of props.segments) { + seg = {...seg}; + // non-chapter, do not nest + if (seg.actionType !== ActionType.Chapter) { + 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); + } - props.segments.forEach((seg) => nestChapters(result, {...seg}, true)); return result; }, [props.segments])