diff --git a/src/components/video-editor/timeline/core/time.test.ts b/src/components/video-editor/timeline/core/time.test.ts index a1a64bd36..9a4de3692 100644 --- a/src/components/video-editor/timeline/core/time.test.ts +++ b/src/components/video-editor/timeline/core/time.test.ts @@ -38,6 +38,15 @@ describe("timeline core/time", () => { expect(formatPlayheadTime(61_400)).toBe("1:01.4"); }); + it("rolls seconds into the next minute when rounding reaches 60", () => { + // 59.95s–59.99s round up to 60.0s and must carry into the minute + // instead of rendering "60.0s" or "1:60.0". + expect(formatPlayheadTime(59_950)).toBe("1:00.0"); + expect(formatPlayheadTime(59_970)).toBe("1:00.0"); + expect(formatPlayheadTime(119_970)).toBe("2:00.0"); + expect(formatPlayheadTime(0)).toBe("0.0s"); + }); + it("normalizes wheel delta by deltaMode", () => { expect(normalizeWheelDeltaToPixels(2, 0)).toBe(2); expect(normalizeWheelDeltaToPixels(2, 1)).toBe(32); diff --git a/src/components/video-editor/timeline/core/time.ts b/src/components/video-editor/timeline/core/time.ts index 7e02f8ed8..01b92eeb6 100644 --- a/src/components/video-editor/timeline/core/time.ts +++ b/src/components/video-editor/timeline/core/time.ts @@ -108,9 +108,13 @@ export function formatTimeLabel(milliseconds: number, intervalMs: number) { } export function formatPlayheadTime(ms: number): string { - const s = ms / 1000; - const min = Math.floor(s / 60); - const sec = s % 60; + // Round to the displayed precision (tenths of a second) before splitting + // into minutes and seconds. Rounding the seconds component on its own lets + // values such as 59.97s render as "60.0" and carry into labels like + // "1:60.0" or "60.0s" instead of rolling over to the next minute. + const tenths = Math.round((ms / 1000) * 10); + const min = Math.floor(tenths / 600); + const sec = (tenths - min * 600) / 10; if (min > 0) return `${min}:${sec.toFixed(1).padStart(4, "0")}`; return `${sec.toFixed(1)}s`; }