Skip to content

feat: add playback speed controls and looping to TimeTravelTimeline#2458

Open
25032007 wants to merge 1 commit into
nisshchayarathi:mainfrom
25032007:fix-timetravel-controls
Open

feat: add playback speed controls and looping to TimeTravelTimeline#2458
25032007 wants to merge 1 commit into
nisshchayarathi:mainfrom
25032007:fix-timetravel-controls

Conversation

@25032007

@25032007 25032007 commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Description

This pull request implements user-configurable playback controls for the TimeTravelTimeline component. It introduces a dropdown to dynamically adjust the playback speed multiplier (0.5x, 1x, 2x, 5x) and adds a toggle button to enable auto-looping. When looping is enabled, the timeline automatically restarts from the oldest commit once the latest state is reached, rather than just pausing.

Related Issue

Closes #2453

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • UI/UX improvement
  • Refactor
  • Tests

Screenshots

N/A

Testing

Verified the manual selection of speeds, UI layout of new playback controls using lucide-react icons, and loop functionality behavior.

  • Ran npm run lint
  • Ran npm run build
  • Ran npm run format
  • Ran git diff --check
  • Verified the changed behavior manually, or wrote N/A for documentation-only changes
  • Updated or added tests where appropriate, or wrote N/A with a reason (N/A - UI only changes without business logic changes)

Checklist

  • My changes are focused on the linked issue
  • I have reviewed my own code
  • I have not introduced unrelated formatting or generated-file changes
  • Documentation is updated if needed

Summary by CodeRabbit

Release Notes

  • New Features
    • Added configurable playback speed control (0.5x, 1x, 2x, 5x) to adjust timeline playback rate
    • Added loop toggle functionality to repeat timeline playback from the beginning when reaching the end

@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

@25032007 is attempting to deploy a commit to the Nisshchaya's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the GSSoC'26 Part of GirlScript Summer of Code 2026 label Jun 22, 2026
@github-actions

Copy link
Copy Markdown

🎉 Thanks for your contribution, @25032007!

Your PR has passed our automated GSSoC quality checks. Here's a quick summary:

Check Status
PR description ✅ Provided
PR title ✅ Meaningful
Linked issue ✅ Found
Change size ✅ Looks good (39 lines across 1 file(s))

A maintainer will review your PR soon. Please be patient and available for feedback. 💪

GSSoC'26 automation · Maintainer: @nisshchayarathi

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

TimeTravelTimeline gains two new state values—playbackSpeed (default 1) and isLooping (default false). The setInterval duration becomes 1000 / playbackSpeed, and end-of-timeline behavior either loops back to the first commit or stops and clears selection. The UI adds a Repeat icon loop toggle and a speed <select> with 0.5x, 1x, 2x, and 5x options.

Changes

Configurable Playback Speed and Looping

Layer / File(s) Summary
Playback state and interval logic
src/components/repository/TimeTravelTimeline.tsx
Adds playbackSpeed and isLooping state; updates setInterval to use 1000 / playbackSpeed as duration; conditionally loops back to the first commit or stops and calls onCommitSelect(null) at end of timeline; extends useEffect dependency array to include both new state values.
Loop toggle and speed dropdown UI
src/components/repository/TimeTravelTimeline.tsx
Renders a Repeat-icon loop toggle button and a <select> dropdown with 0.5x, 1x, 2x, 5x options that set isLooping and playbackSpeed respectively.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested labels

feature, level:intermediate

Poem

🐇 Hop through commits, fast or slow,
A loop, a twist—watch history flow!
0.5x to 5x, I set the pace,
The Repeat icon joins the race.
No more stuck at the final stop—
Round and round, I never drop! 🔁

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding playback speed controls and looping functionality to TimeTravelTimeline, which matches the changeset.
Linked Issues check ✅ Passed The PR fulfills all acceptance criteria: playback speed control with 0.5x, 1x, 2x, 5x options is implemented, playIntervalRef respects selected speed via 1000/playbackSpeed calculation, and bonus auto-loop functionality is included.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #2453 objectives: playback speed controls, loop functionality, and UI improvements using lucide-react icons as specified.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


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 and usage tips.

@github-actions

Copy link
Copy Markdown

🎉 Thanks for your contribution, @25032007!

Your PR has passed our automated GSSoC quality checks. Here's a quick summary:

Check Status
PR description ✅ Provided
PR title ✅ Meaningful
Linked issue ✅ Found
Change size ✅ Looks good (39 lines across 1 file(s))

A maintainer will review your PR soon. Please be patient and available for feedback. 💪

GSSoC'26 automation · Maintainer: @nisshchayarathi

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/components/repository/TimeTravelTimeline.tsx`:
- Around line 133-146: The loop toggle button (containing the Repeat icon) and
playback speed select element rely only on title attributes for accessibility,
which is insufficient for screen reader users. Add aria-label attributes to both
controls to explicitly describe their purpose, and add an aria-pressed attribute
to the loop button that reflects the current isLooping state (true when
isLooping is true, false otherwise). This ensures assistive technologies can
properly communicate the control's function and current state to users.
- Around line 63-75: The playback logic in the interval callback does not guard
against empty commit lists when looping is enabled. When isLooping is true and
nextIndex is set to 0, the code proceeds to access
chronologicalCommits[nextIndex].hash without verifying that chronologicalCommits
has any elements, which can cause a runtime crash if the list is empty. Add a
guard check to ensure chronologicalCommits is not empty before attempting to
access chronologicalCommits[nextIndex].hash in the onCommitSelect call. If the
list is empty while looping, either stop playback or skip the selection call to
prevent undefined access.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 00a2524f-d8ed-43a6-a758-e1b3fcf71171

📥 Commits

Reviewing files that changed from the base of the PR and between cd4e69b and 595c648.

📒 Files selected for processing (1)
  • src/components/repository/TimeTravelTimeline.tsx

Comment on lines +63 to +75
if (isLooping) {
nextIndex = 0;
} else {
setIsPlaying(false);
return;
}
}
if (nextIndex === chronologicalCommits.length - 1) {
onCommitSelect(null);
} else {
onCommitSelect(chronologicalCommits[nextIndex].hash);
}
}, 1000); // 1 second per step
}, 1000 / playbackSpeed); // dynamic speed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard loop playback against empty commit lists to avoid runtime crashes.

If commits becomes empty while playback is active and looping is enabled, this path can still execute and access chronologicalCommits[0].hash, which is undefined and can throw.

Proposed fix
 useEffect(() => {
+  if (chronologicalCommits.length === 0) {
+    setIsPlaying(false);
+    return;
+  }
+
   if (isPlaying) {
     playIntervalRef.current = setInterval(() => {
       let nextIndex = currentIndex + 1;
       if (nextIndex >= chronologicalCommits.length) {
         if (isLooping) {
           nextIndex = 0;
         } else {
           setIsPlaying(false);
           return;
         }
       }
       if (nextIndex === chronologicalCommits.length - 1) {
         onCommitSelect(null);
       } else {
         onCommitSelect(chronologicalCommits[nextIndex].hash);
       }
     }, 1000 / playbackSpeed); // dynamic speed
🤖 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/repository/TimeTravelTimeline.tsx` around lines 63 - 75, The
playback logic in the interval callback does not guard against empty commit
lists when looping is enabled. When isLooping is true and nextIndex is set to 0,
the code proceeds to access chronologicalCommits[nextIndex].hash without
verifying that chronologicalCommits has any elements, which can cause a runtime
crash if the list is empty. Add a guard check to ensure chronologicalCommits is
not empty before attempting to access chronologicalCommits[nextIndex].hash in
the onCommitSelect call. If the list is empty while looping, either stop
playback or skip the selection call to prevent undefined access.

Comment on lines +133 to +146
<button
onClick={() => setIsLooping(!isLooping)}
className={`p-2 rounded-full transition-colors ${isLooping ? 'bg-primary/20 text-primary' : 'hover:bg-white/10 text-muted-foreground hover:text-white'}`}
title="Toggle Loop"
>
<Repeat className="h-4 w-4" />
</button>

<select
value={playbackSpeed}
onChange={(e) => setPlaybackSpeed(Number(e.target.value))}
className="bg-transparent text-xs text-muted-foreground hover:text-white cursor-pointer outline-none border border-white/10 rounded px-1 py-1"
title="Playback Speed"
>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add explicit accessibility labels to new playback controls.

The new icon-only loop button and speed select should expose explicit labels/state (aria-label, aria-pressed) instead of relying on title.

Proposed fix
 <button
   onClick={() => setIsLooping(!isLooping)}
+  aria-label="Toggle loop playback"
+  aria-pressed={isLooping}
   className={`p-2 rounded-full transition-colors ${isLooping ? 'bg-primary/20 text-primary' : 'hover:bg-white/10 text-muted-foreground hover:text-white'}`}
   title="Toggle Loop"
 >
   <Repeat className="h-4 w-4" />
 </button>

 <select
   value={playbackSpeed}
   onChange={(e) => setPlaybackSpeed(Number(e.target.value))}
+  aria-label="Playback speed"
   className="bg-transparent text-xs text-muted-foreground hover:text-white cursor-pointer outline-none border border-white/10 rounded px-1 py-1"
   title="Playback Speed"
 >
🤖 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/repository/TimeTravelTimeline.tsx` around lines 133 - 146, The
loop toggle button (containing the Repeat icon) and playback speed select
element rely only on title attributes for accessibility, which is insufficient
for screen reader users. Add aria-label attributes to both controls to
explicitly describe their purpose, and add an aria-pressed attribute to the loop
button that reflects the current isLooping state (true when isLooping is true,
false otherwise). This ensures assistive technologies can properly communicate
the control's function and current state to users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

GSSoC'26 Part of GirlScript Summer of Code 2026

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Add Playback Speed Controls and Looping to TimeTravelTimeline

1 participant