Skip to content

fix(timeline): carry rounded timecode seconds - #236

Merged
EtienneLescot merged 4 commits into
getopenscreen:mainfrom
arhxam:codex/carry-rounded-timecodes
Aug 4, 2026
Merged

fix(timeline): carry rounded timecode seconds#236
EtienneLescot merged 4 commits into
getopenscreen:mainfrom
arhxam:codex/carry-rounded-timecodes

Conversation

@arhxam

@arhxam arhxam commented Aug 3, 2026

Copy link
Copy Markdown

Summary

  • round timecodes before splitting them into minute and hour fields
  • carry 59.96 seconds to 1:00.0 instead of rendering the invalid 0:60.0
  • avoid overflow for every finite numeric duration, including Number.MAX_VALUE
  • keep the existing junk-input and long-duration formatting behavior

Related issue

No linked issue; found while exercising timeline boundary values.

Type of change

  • Bug fix
  • Feature
  • Enhancement
  • Documentation
  • Refactor / maintenance
  • Performance
  • Security

Release impact

  • Patch
  • Minor
  • Major / breaking change
  • No release note needed

Desktop impact

  • Windows
  • macOS
  • Linux
  • Installer / packaging
  • Not platform-specific

Screenshots / video

Not applicable; unit-level timecode correction.

Testing

  • npx vitest --run src/lib/ai-edition/timeline/format.test.ts (10 passed)
  • npx vitest --run --exclude electron/recording/webm-seek-index.test.ts (1,535 passed)
  • npx tsc --noEmit
  • npx tsc -p tsconfig.test.json --noEmit
  • npm run lint (passes with 11 existing warnings)
  • npm run docs:check
  • npm run i18n:check
  • npx vite build

Summary by CodeRabbit

  • Bug Fixes
    • Improved time formatting when rounding causes seconds to roll over into minutes or hours.
    • Prevented extremely large time values from displaying invalid results.
    • Ensured millisecond-based formatting handles minute carryovers consistently.
    • Standardized timecode and duration displays across the editing interface.
  • Tests
    • Added regression coverage for rounding, carryover behavior, invalid inputs, and large time values.

@arhxam
arhxam requested a review from EtienneLescot as a code owner August 3, 2026 23:11
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The timeline formatters now share rounded time decomposition. The left panel and transport displays use the shared formatting utilities. Regression tests cover rollover, invalid input, and large finite values.

Timeline formatting

Layer / File(s) Summary
Shared rounded time decomposition
src/lib/ai-edition/timeline/format.ts
splitRoundedTime normalizes inputs, rounds to tenths, and carries rounded seconds into total minutes. formatSec and formatSeconds use the helper.
Formatter rollover validation
src/lib/ai-edition/timeline/format.test.ts
Tests cover minute, hour, millisecond, invalid-input, and Number.MAX_VALUE formatting behavior.
Timeline display integration
src/components/ai-edition/LeftPanel.tsx, src/components/ai-edition/TransportBar.tsx
The left panel uses shared rounded decomposition. The transport bar uses formatSec for current time and total duration.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: etiennelescot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix for rounded timecode second carry-over.
Description check ✅ Passed The description covers the required sections, explains the fix, identifies the change type and impact, and lists comprehensive testing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/ai-edition/timeline/format.ts`:
- Around line 13-20: Update splitRoundedTime to avoid multiplying the full
duration by 10: compute whole minutes and the remaining seconds from safe first,
round only the remainder, and carry one minute when the rounded remainder
reaches 60. Preserve zero handling and return finite totalMinutes and seconds
for all finite inputs, including values near Number.MAX_VALUE.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9e1208b7-b946-4551-b08a-ab11bf8f19eb

📥 Commits

Reviewing files that changed from the base of the PR and between 545043d and 191adab.

📒 Files selected for processing (2)
  • src/lib/ai-edition/timeline/format.test.ts
  • src/lib/ai-edition/timeline/format.ts

Comment thread src/lib/ai-edition/timeline/format.ts Outdated
@EtienneLescot
EtienneLescot force-pushed the main branch 2 times, most recently from 89e07a8 to 545043d Compare August 4, 2026 00:00
@arhxam
arhxam force-pushed the codex/carry-rounded-timecodes branch from af50e14 to f2b87c0 Compare August 4, 2026 00:02
@arhxam
arhxam force-pushed the codex/carry-rounded-timecodes branch from f2b87c0 to 193a728 Compare August 4, 2026 00:05

@EtienneLescot EtienneLescot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, and the fix is factored the way I'd have wanted it. splitRoundedTime does the carry once, and — the part that actually matters — formatSeconds now derives hours from totalMinutes instead of re-flooring the raw value. Without that second half formatSeconds(3599.96) would still land on 59:60.0 even with a rounded seconds field. You also stayed inside the boundary the header comment draws and left formatHms/formatTimePadded alone, which is right.

The one thing I want settled before merge is scope. The identical floor-then-round shape lives in two more places this PR doesn't touch, and one of them is the readout users stare at all day:

  • src/components/ai-edition/TransportBar.tsx:9 (formatTC) — feeds the live playhead at line 180.
  • src/components/ai-edition/LeftPanel.tsx:39 (formatTimecode).

Details inline. format.ts is only two of the three copies, so merging this alone means the bug you fixed is still visible in the transport bar. I'm happy either way — sweep them into this PR, or land this and open a follow-up. Say which and I'll merge.

Comment thread src/lib/ai-edition/timeline/format.ts Outdated
Comment thread src/lib/ai-edition/timeline/format.test.ts
EtienneLescot and others added 2 commits August 4, 2026 12:59
format.ts was only two of the three places that floored the minute field off
the raw value while rounding the second field off it separately, so `0:60.0`
stayed renderable in the two this PR had not reached.

TransportBar's `formatTC` was `formatSec` verbatim — same output for every
input, junk guard written differently — so it just goes, and the transport bar
imports the shared one. That is the copy that mattered: it feeds the live
playhead readout, so the bad string showed up there once a minute during
playback, which is the place a user is most likely to actually see it.

LeftPanel's `formatTimecode` is a genuinely different shape (`h:mm:ss.t`, hours
always shown), so it keeps formatting itself rather than being forced into one
of format.ts's two shapes. It now shares `splitRoundedTime`, which is what this
PR added and the only part that must not be re-derived. Fixed a second bug while
there: `padStart(3, "0")` never padded anything, because `(5).toFixed(1)` is
already three characters — a single-digit second rendered `0:00:5.0`.

Also tightened the two `Number.MAX_VALUE` cases. `not.toMatch(/Infinity|NaN/)`
passes against the pre-carry implementation too, so it pinned nothing; asserting
the exact string means a regression is actually caught.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/components/ai-edition/LeftPanel.tsx (1)

44-51: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Add a colocated regression test for formatTimecode.

format.test.ts verifies splitRoundedTime, but it does not verify the component-specific h:mm:ss.t assembly in Line 44-51. A regression in the hour/minute calculation or padStart(4) could reintroduce 0:00:60.0 or 0:00:5.0 while the current tests still pass. Add src/components/ai-edition/LeftPanel.test.tsx with Vitest and jsdom, or move formatTimecode into src/lib/ai-edition/timeline/format.ts and test it there.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ai-edition/LeftPanel.tsx` around lines 44 - 51, Add a
colocated Vitest/jsdom regression test for the component-specific formatTimecode
function in LeftPanel.tsx, covering hour/minute assembly and single-digit
seconds padding so outputs never regress to forms like 0:00:60.0 or 0:00:5.0.
Keep the existing splitRoundedTime tests unchanged and verify representative
formatted timecodes through the exported or otherwise testable formatTimecode
symbol.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/components/ai-edition/LeftPanel.tsx`:
- Around line 44-51: Add a colocated Vitest/jsdom regression test for the
component-specific formatTimecode function in LeftPanel.tsx, covering
hour/minute assembly and single-digit seconds padding so outputs never regress
to forms like 0:00:60.0 or 0:00:5.0. Keep the existing splitRoundedTime tests
unchanged and verify representative formatted timecodes through the exported or
otherwise testable formatTimecode symbol.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c7aa9128-02f7-4bd3-8bf7-5e01534fedc1

📥 Commits

Reviewing files that changed from the base of the PR and between aeff270 and c3f3dea.

📒 Files selected for processing (4)
  • src/components/ai-edition/LeftPanel.tsx
  • src/components/ai-edition/TransportBar.tsx
  • src/lib/ai-edition/timeline/format.test.ts
  • src/lib/ai-edition/timeline/format.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/ai-edition/timeline/format.ts

@EtienneLescot EtienneLescot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Threads cleared and the sweep is in (c3f3dea), CI green. Approving.

The carry factoring was right from the start — deriving hours from totalMinutes rather than re-flooring the raw value is the half that makes formatSeconds(3599.96) land on 1:00:00.0. What this needed was reach: format.ts was two of the three copies, and the one it did not touch feeds the live playhead.

@EtienneLescot
EtienneLescot merged commit 016bc23 into getopenscreen:main Aug 4, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants