-
Notifications
You must be signed in to change notification settings - Fork 759
improvement: better time formatting for clip track #1005
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Caution Review failedThe pull request is closed. WalkthroughAdds a module-level formatTime(totalSeconds) and replaces inline numeric-second displays in ClipTrack with human-readable durations; removes the local formatter from CutOffsetButton, updates its label to rely on formatTime (no trailing "s"), and adds text-nowrap to the button. No public API changes. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. 📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx (2)
485-485
: Respect segment.timescale when displaying the clip’s duration.Else, sped-up/slowed clips will show source span rather than timeline duration.
- {formatTime(segment.end - segment.start)} + {formatDuration((segment.end - segment.start) / segment.timescale)}Please verify expected output on a segment with timescale ≠ 1.
647-647
: Verify Tailwind support for text-nowrap (or prefer whitespace-nowrap).text-nowrap requires newer Tailwind text-wrap utilities. If your version lacks it, the button may wrap. Using whitespace-nowrap matches the rest of this file.
- "h-7 bg-red-300 text-nowrap hover:bg-red-400 text-xs tabular-nums text-white p-2 flex flex-row items-center transition-colors", + "h-7 bg-red-300 whitespace-nowrap hover:bg-red-400 text-xs tabular-nums text-white p-2 flex flex-row items-center transition-colors",
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
(3 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/desktop/**/*.{ts,tsx}
: In the desktop app, rely on unplugin-icons auto-imports; do not manually import icon modules
Use generated tauri_specta commands/events (commands, events) in the desktop frontend; listen to generated events directly
Use @tanstack/solid-query for server state in the desktop app
Files:
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
{apps/desktop,packages/ui-solid}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Component naming (Solid): components in PascalCase; hooks/utilities in camelCase starting with 'use' where applicable
Files:
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; prefer shared types from packages
**/*.{ts,tsx}
: Use Biome to format/lint TypeScript with a 2-space indent
TypeScript file names should be kebab-case (e.g., user-menu.tsx)
Files:
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
React/Solid components should be named using PascalCase
Files:
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
🧬 Code graph analysis (1)
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx (1)
apps/desktop/src/routes/editor/utils.ts (1)
formatTime
(1-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
function formatTime(totalSeconds: number): string { | ||
const hours = Math.floor(totalSeconds / 3600); | ||
const minutes = Math.floor((totalSeconds % 3600) / 60); | ||
const seconds = Math.floor(totalSeconds % 60); | ||
|
||
if (hours > 0) { | ||
return `${hours}h ${minutes}m ${seconds}s`; | ||
} else if (minutes > 0) { | ||
return `${minutes}m ${seconds}s`; | ||
} else { | ||
return `${seconds}s`; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Fix sub-second rounding and avoid name collision with existing utils.formatTime.
Current logic floors everything (e.g., 0.4s -> "0s"), which is misleading in CutOffsetButton and a UX regression from the prior 0.1s precision. Also, naming this helper formatTime collides conceptually with apps/desktop/src/routes/editor/utils.ts:formatTime (mm:ss[.ff]) and can confuse future readers.
Suggested: rename and improve formatting to preserve tenths under 10s, handle negatives, and keep integer seconds when minutes/hours are present.
-function formatTime(totalSeconds: number): string {
- const hours = Math.floor(totalSeconds / 3600);
- const minutes = Math.floor((totalSeconds % 3600) / 60);
- const seconds = Math.floor(totalSeconds % 60);
-
- if (hours > 0) {
- return `${hours}h ${minutes}m ${seconds}s`;
- } else if (minutes > 0) {
- return `${minutes}m ${seconds}s`;
- } else {
- return `${seconds}s`;
- }
-}
+function formatDuration(totalSeconds: number): string {
+ const sign = totalSeconds < 0 ? "-" : "";
+ const s = Math.abs(totalSeconds);
+ const hours = Math.floor(s / 3600);
+ const minutes = Math.floor((s % 3600) / 60);
+ const secFloat = s % 60;
+ // Mixed units: keep integer seconds to avoid 60s rollovers
+ if (hours > 0) return `${sign}${hours}h ${minutes}m ${Math.floor(secFloat)}s`;
+ if (minutes > 0) return `${sign}${minutes}m ${Math.floor(secFloat)}s`;
+ // Sub-minute: show tenths for <10s, else whole seconds
+ const secs = secFloat < 10 ? Math.round(secFloat * 10) / 10 : Math.round(secFloat);
+ return `${sign}${secs.toFixed(secFloat < 10 ? 1 : 0)}s`;
+}
Follow-up: consider centralizing this in editor/utils as a separate humanizer (e.g., humanizeDuration) to avoid two different “formatTime” semantics.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "PWD: $(pwd)"
echo "Git branch:"
git rev-parse --abbrev-ref HEAD || true
echo
echo "Searching for 'formatTime' occurrences (definitions & calls)..."
rg -n --hidden -S -C2 '\bfunction\s+formatTime\b|\bformatTime\s*\(' || true
echo
echo "Show ClipTrack.tsx if present:"
if [ -f "apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx" ]; then
sed -n '1,240p' apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
else
rg -n --hidden -S 'ClipTrack.tsx' || true
fi
echo
echo "Show editor utils if present (possible other formatTime):"
if [ -f "apps/desktop/src/routes/editor/utils.ts" ]; then
sed -n '1,240p' apps/desktop/src/routes/editor/utils.ts
else
rg -n --hidden -S --glob '!node_modules' 'src/routes/editor/utils.ts|routes/editor/utils.ts|/routes/editor/utils.ts' || true
rg -n --hidden -S -C2 '\bformatTime\b' || true
fi
echo
echo "Search for CutOffsetButton usages:"
rg -n --hidden -S -C3 'CutOffsetButton' || true
echo
echo "Search for existing humanize/formatDuration helpers:"
rg -n --hidden -S -C2 'formatDuration|humanizeDuration|humanizeTime|formatTimeHuman' || true
Length of output: 22669
Fix sub-second rounding and rename local formatTime to avoid collision
- Problem: apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx defines a local formatTime that floors seconds (0.4s -> "0s"), causing a UX regression in CutOffsetButton; it also conceptually collides with apps/desktop/src/routes/editor/utils.ts:formatTime (mm:ss).
- Change: replace the helper in ClipTrack.tsx with the implementation below (renamed to formatDuration and preserving tenths for <10s, handling negatives, keeping integer seconds when minutes/hours present):
-function formatTime(totalSeconds: number): string {
- const hours = Math.floor(totalSeconds / 3600);
- const minutes = Math.floor((totalSeconds % 3600) / 60);
- const seconds = Math.floor(totalSeconds % 60);
-
- if (hours > 0) {
- return `${hours}h ${minutes}m ${seconds}s`;
- } else if (minutes > 0) {
- return `${minutes}m ${seconds}s`;
- } else {
- return `${seconds}s`;
- }
-}
+function formatDuration(totalSeconds: number): string {
+ const sign = totalSeconds < 0 ? "-" : "";
+ const s = Math.abs(totalSeconds);
+ const hours = Math.floor(s / 3600);
+ const minutes = Math.floor((s % 3600) / 60);
+ const secFloat = s % 60;
+ // Mixed units: keep integer seconds to avoid 60s rollovers
+ if (hours > 0) return `${sign}${hours}h ${minutes}m ${Math.floor(secFloat)}s`;
+ if (minutes > 0) return `${sign}${minutes}m ${Math.floor(secFloat)}s`;
+ // Sub-minute: show tenths for <10s, else whole seconds
+ const secs = secFloat < 10 ? Math.round(secFloat * 10) / 10 : Math.round(secFloat);
+ return `${sign}${secs.toFixed(secFloat < 10 ? 1 : 0)}s`;
+}
- Follow-up: centralize as a humanizeDuration function in apps/desktop/src/routes/editor/utils.ts to avoid two different “formatTime” semantics.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
function formatTime(totalSeconds: number): string { | |
const hours = Math.floor(totalSeconds / 3600); | |
const minutes = Math.floor((totalSeconds % 3600) / 60); | |
const seconds = Math.floor(totalSeconds % 60); | |
if (hours > 0) { | |
return `${hours}h ${minutes}m ${seconds}s`; | |
} else if (minutes > 0) { | |
return `${minutes}m ${seconds}s`; | |
} else { | |
return `${seconds}s`; | |
} | |
} | |
function formatDuration(totalSeconds: number): string { | |
const sign = totalSeconds < 0 ? "-" : ""; | |
const s = Math.abs(totalSeconds); | |
const hours = Math.floor(s / 3600); | |
const minutes = Math.floor((s % 3600) / 60); | |
const secFloat = s % 60; | |
// Mixed units: keep integer seconds to avoid 60s rollovers | |
if (hours > 0) return `${sign}${hours}h ${minutes}m ${Math.floor(secFloat)}s`; | |
if (minutes > 0) return `${sign}${minutes}m ${Math.floor(secFloat)}s`; | |
// Sub-minute: show tenths for <10s, else whole seconds | |
const secs = secFloat < 10 ? Math.round(secFloat * 10) / 10 : Math.round(secFloat); | |
return `${sign}${secs.toFixed(secFloat < 10 ? 1 : 0)}s`; | |
} |
🤖 Prompt for AI Agents
In apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx around lines 22–34, the
local formatTime helper floors seconds (producing "0s" for 0.4s) and collides
conceptually with utils.formatTime; rename it to formatDuration, handle negative
values by prefixing '-' and formatting the absolute value, preserve tenths of a
second for durations under 10s (e.g., 0.4s -> "0.4s", 9.8s -> "9.8s"), and keep
integer seconds when minutes or hours are present (hours -> "1h 2m 3s", minutes
-> "2m 3s"); replace Math.floor on seconds with logic that uses one decimal for
<10s and integer seconds otherwise, and then consider centralizing this as
humanizeDuration in apps/desktop/src/routes/editor/utils.ts to avoid duplicate
semantics.
<>{formatTime(props.value)}</> | ||
)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update call site to the renamed formatter.
Aligns with the improved duration formatting and sub-second handling.
- <>{formatTime(props.value)}</>
+ <>{formatDuration(props.value)}</>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<>{formatTime(props.value)}</> | |
)} | |
<>{formatDuration(props.value)}</> | |
)} |
🤖 Prompt for AI Agents
In apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx around lines 655-656,
the call to the old formatter formatTime(props.value) must be updated to the
renamed formatter (formatDuration) to get the improved duration and sub-second
handling; replace the call with formatDuration(props.value) and update or add
the import from the formatter module if necessary so the new function is
available in this file.
This PR improves better formatting for time on the track:
Summary by CodeRabbit
Style
Refactor