From 83f9d590369bc719c4987712627c537532de4a6f Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 12 Jun 2026 22:39:45 +0530 Subject: [PATCH] fix: format trim times as minutes and seconds --- src/components/TrimControl.tsx | 17 ++++++++++------- src/lib/tests/utils.test.ts | 24 ++++++++++++++++++++++-- src/lib/utils.ts | 13 ++++++++++++- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/components/TrimControl.tsx b/src/components/TrimControl.tsx index d48bdd69..7f760279 100644 --- a/src/components/TrimControl.tsx +++ b/src/components/TrimControl.tsx @@ -3,7 +3,7 @@ import { EditRecipe } from "@/lib/types"; import { useState, useEffect, useRef, useCallback } from "react"; import { AlertCircle } from "lucide-react"; -import { formatDuration } from "@/lib/utils"; +import { formatTrimTime } from "@/lib/utils"; import { useAudioWaveform } from "@/hooks/useAudioWaveform"; import WaveformCanvas from "@/components/WaveformCanvas"; @@ -34,6 +34,9 @@ export default function TrimControl({ recipe, onChange, duration, file }: Props) const clipLength = (recipe.trimEnd ?? duration) - recipe.trimStart; + const formattedStart = formatTrimTime(recipe.trimStart); + const formattedEnd = formatTrimTime(recipe.trimEnd ?? duration); + const formattedDuration = formatTrimTime(duration); const trackRef = useRef(null); const dragging = useRef<"start" | "end" | null>(null); @@ -116,7 +119,7 @@ export default function TrimControl({ recipe, onChange, duration, file }: Props) if (duration > 0 && n >= duration) { setStart(true); setStartErrorMsg( - `Start time must be less than duration (${duration.toFixed(1)}s).` + `Start time must be less than duration (${formattedDuration}).` ); return; } @@ -162,7 +165,7 @@ export default function TrimControl({ recipe, onChange, duration, file }: Props) if (duration > 0 && n > duration + 0.01) { setEnd(true); setEndErrorMsg( - `End time cannot exceed duration (${duration.toFixed(1)}s).`, + `End time cannot exceed duration (${formattedDuration}).`, ); return; } @@ -241,7 +244,7 @@ export default function TrimControl({ recipe, onChange, duration, file }: Props) htmlFor="trim-start" className="font-heading mb-1.5 block text-[10px] font-semibold uppercase tracking-wider text-[var(--muted)]" > - Start (sec) + Start ({formattedStart}) - End (sec) + End ({formattedEnd}) 0 && (

- Clip: {formatDuration(clipLength)} of{" "} - {formatDuration(duration)} + Clip: {formatTrimTime(clipLength)} of{" "} + {formattedDuration}

)} {recipe.trimEnd !== null && diff --git a/src/lib/tests/utils.test.ts b/src/lib/tests/utils.test.ts index 2f8eac85..b9f134ca 100644 --- a/src/lib/tests/utils.test.ts +++ b/src/lib/tests/utils.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from "vitest"; -import { formatBytes, formatDuration } from "../utils"; +import { formatBytes, formatDuration, formatTrimTime } from "../utils"; describe("formatBytes", () => { it("returns '0 Bytes' for zero input", () => { @@ -68,4 +68,24 @@ describe("formatDuration", () => { it("handles negative values", () => { expect(formatDuration(-1)).toBe("0:00"); }); -}); \ No newline at end of file +}); + +describe("formatTrimTime", () => { + it("formats raw seconds as MM:SS.d", () => { + expect(formatTrimTime(65.5)).toBe("01:05.5"); + }); + + it("pads seconds under one minute", () => { + expect(formatTrimTime(5)).toBe("00:05.0"); + }); + + it("preserves one decimal place", () => { + expect(formatTrimTime(12.34)).toBe("00:12.3"); + }); + + it("handles invalid values", () => { + expect(formatTrimTime(NaN)).toBe("00:00.0"); + expect(formatTrimTime(Infinity)).toBe("00:00.0"); + expect(formatTrimTime(-1)).toBe("00:00.0"); + }); +}); diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 14225f59..88d47cf8 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -41,4 +41,15 @@ export function formatDuration(seconds: number): string { } return `${minutes}:${secs.toString().padStart(2, "0")}`; -} \ No newline at end of file +} + +export function formatTrimTime(seconds: number): string { + if (!Number.isFinite(seconds) || seconds < 0) { + return "00:00.0"; + } + + const minutes = Math.floor(seconds / 60); + const secs = (seconds % 60).toFixed(1); + + return `${String(minutes).padStart(2, "0")}:${secs.padStart(4, "0")}`; +}