From 5238dd79ce73d082888ae65c58bfaa7a4f74536c Mon Sep 17 00:00:00 2001 From: Wiii <156531153+meiiie@users.noreply.github.com> Date: Sun, 26 Apr 2026 23:48:38 +0700 Subject: [PATCH] fix(editor): allow scrolling all audio tracks Allow timeline content to grow with additional audio rows so the existing scroll container can reach lower tracks. --- .../video-editor/timeline/TimelineEditor.tsx | 19 ++++++++++-- .../video-editor/timeline/TimelineWrapper.tsx | 2 +- .../timeline/timelineLayout.test.ts | 31 +++++++++++++++++++ .../video-editor/timeline/timelineLayout.ts | 18 +++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/components/video-editor/timeline/timelineLayout.test.ts create mode 100644 src/components/video-editor/timeline/timelineLayout.ts diff --git a/src/components/video-editor/timeline/TimelineEditor.tsx b/src/components/video-editor/timeline/TimelineEditor.tsx index b4d3d351..b2a97a1e 100644 --- a/src/components/video-editor/timeline/TimelineEditor.tsx +++ b/src/components/video-editor/timeline/TimelineEditor.tsx @@ -60,6 +60,10 @@ import Item from "./Item"; import KeyframeMarkers from "./KeyframeMarkers"; import Row from "./Row"; import TimelineWrapper from "./TimelineWrapper"; +import { + getTimelineContentMinHeightPx, + getTimelineRowsMinHeightPx, +} from "./timelineLayout"; import { type AudioPeaksData, useAudioPeaks } from "./useAudioPeaks"; import { buildInteractionZoomSuggestions } from "./zoomSuggestionUtils"; @@ -702,12 +706,18 @@ function Timeline({ ).sort((left, right) => getAnnotationTrackIndex(left) - getAnnotationTrackIndex(right)), [annotationItems], ); + const timelineRowCount = 2 + annotationRowIds.length + audioRowIds.length; + const timelineRowsMinHeightPx = getTimelineRowsMinHeightPx(timelineRowCount); + const timelineContentMinHeightPx = getTimelineContentMinHeightPx(timelineRowCount); return (
@@ -720,7 +730,10 @@ function Timeline({ keyframes={keyframes} /> -
+
{audioPeaks && } diff --git a/src/components/video-editor/timeline/TimelineWrapper.tsx b/src/components/video-editor/timeline/TimelineWrapper.tsx index 32a94565..fed0431c 100644 --- a/src/components/video-editor/timeline/TimelineWrapper.tsx +++ b/src/components/video-editor/timeline/TimelineWrapper.tsx @@ -375,7 +375,7 @@ export default function TimelineWrapper({ autoScroll={{ enabled: false }} resizeHandleWidth={28} > -
+
{children} {/* Floating tooltip shown during drag/resize */}
{ + it("reserves vertical space for every rendered timeline row", () => { + expect(getTimelineRowsMinHeightPx(5)).toBe(5 * TIMELINE_ROW_MIN_HEIGHT_PX); + expect(getTimelineContentMinHeightPx(5)).toBe( + TIMELINE_AXIS_HEIGHT_PX + 5 * TIMELINE_ROW_MIN_HEIGHT_PX, + ); + }); + + it("ignores invalid row counts", () => { + expect(getTimelineRowsMinHeightPx(-1)).toBe(0); + expect(getTimelineRowsMinHeightPx(Number.NaN)).toBe(0); + expect(getTimelineContentMinHeightPx(Number.POSITIVE_INFINITY)).toBe( + TIMELINE_AXIS_HEIGHT_PX, + ); + }); + + it("floors fractional row counts", () => { + expect(getTimelineRowsMinHeightPx(2.9)).toBe(2 * TIMELINE_ROW_MIN_HEIGHT_PX); + expect(getTimelineContentMinHeightPx(2.9)).toBe( + TIMELINE_AXIS_HEIGHT_PX + 2 * TIMELINE_ROW_MIN_HEIGHT_PX, + ); + }); +}); diff --git a/src/components/video-editor/timeline/timelineLayout.ts b/src/components/video-editor/timeline/timelineLayout.ts new file mode 100644 index 00000000..bdf03a17 --- /dev/null +++ b/src/components/video-editor/timeline/timelineLayout.ts @@ -0,0 +1,18 @@ +export const TIMELINE_AXIS_HEIGHT_PX = 32; +export const TIMELINE_ROW_MIN_HEIGHT_PX = 28; + +function normalizeRowCount(rowCount: number) { + if (!Number.isFinite(rowCount)) { + return 0; + } + + return Math.max(0, Math.floor(rowCount)); +} + +export function getTimelineRowsMinHeightPx(rowCount: number) { + return normalizeRowCount(rowCount) * TIMELINE_ROW_MIN_HEIGHT_PX; +} + +export function getTimelineContentMinHeightPx(rowCount: number) { + return TIMELINE_AXIS_HEIGHT_PX + getTimelineRowsMinHeightPx(rowCount); +}