Skip to content

fix: Properly dispose timer to avoid visual double ticks in time tracking - #173

Merged
dkorecko merged 4 commits into
mainfrom
fix/properly-dispose-timer
Jan 2, 2026
Merged

dkorecko merged 4 commits into
mainfrom
fix/properly-dispose-timer

Conversation

@dkorecko

@dkorecko dkorecko commented Jan 2, 2026 •

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • Bug Fixes
    • Improved resource cleanup in the card-editing modal: clipboard handler and timers are now guarded, stopped and cleared before the modal closes, preventing potential memory leaks and unwanted background activity.

✏️ Tip: You can customize this high-level summary in your review settings.

@dkorecko
dkorecko requested a review from Copilot January 2, 2026 16:52
@coderabbitai

coderabbitai Bot commented Jan 2, 2026 •

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The pull request modifies EditCardModal.razor to add null guards and explicit cleanup for _pasteObjRef and _timer. Dispose now only disposes and nulls _pasteObjRef when it is non-null, and stops, disposes, and nulls _timer before calling base.Dispose(). UpdateTimer now stops and disposes any existing _timer before creating a new one, and stops/disposes _timer and returns early when there is no card or targetRecord.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding proper timer disposal to fix visual double ticks in time tracking, which aligns with the AI-generated summary showing explicit timer cleanup was added.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

📜 Recent review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 27de5a8 and 3751e21.

📒 Files selected for processing (1)
  • Ticky.Web/Components/Dialogs/EditCardModal.razor

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.

Copilot AI 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.

Pull request overview

This PR fixes a resource disposal issue in the EditCardModal component by ensuring that the timer is properly stopped and disposed when the component is disposed, preventing visual double ticks in time tracking.

  • Refactored the _pasteObjRef disposal logic to use positive null checks instead of early returns
  • Added proper disposal of _timer to stop it before disposing

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Ticky.Web/Components/Dialogs/EditCardModal.razor

@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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Ticky.Web/Components/Dialogs/EditCardModal.razor (1)

595-613: Resource leak: Timer not disposed before recreating.

The UpdateTimer() method creates a new timer at line 609 without disposing the existing one. If this method is called multiple times while a time record is active (e.g., through UpdateCard() → state changes), multiple timer instances will accumulate, each firing OnTimerTick and causing excess UI updates and memory leaks.

Additionally, lines 601-602 stop the timer but don't dispose it when no active record exists.

🔎 Proposed fix
 private void UpdateTimer()
 {
     var targetRecord = _card?.TimeRecords?.FirstOrDefault(x => x.UserId.Equals(_user.Id) && x.EndedAt == null);

     if(_card is null || targetRecord is null)
     {
         if (_timer is not null)
+        {
             _timer.Stop();
+            _timer.Dispose();
+            _timer = null;
+        }
         return;
     }

     _ongoingTimer = DateTime.Now - targetRecord.StartedAt;
     StateHasChanged();

+    // Dispose existing timer before creating a new one
+    if (_timer is not null)
+    {
+        _timer.Stop();
+        _timer.Dispose();
+    }
+
     _timer = new System.Timers.Timer(1000);
     _timer.Elapsed += OnTimerTick;
     _timer.AutoReset = true;
     _timer.Start();
 }
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between db43ac5 and 0e5386e.

📒 Files selected for processing (1)
  • Ticky.Web/Components/Dialogs/EditCardModal.razor
⏰ 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). (1)
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (2)
Ticky.Web/Components/Dialogs/EditCardModal.razor (2)

516-520: LGTM: Consistent disposal pattern.

The refactor from early return to guarded disposal is functionally equivalent and creates consistency with the timer disposal pattern added below.


522-527: Proper timer cleanup prevents resource leaks.

The timer disposal correctly stops and releases the timer resource when the component is disposed, directly addressing the "double ticks" issue mentioned in the PR title.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jan 2, 2026
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@dkorecko
dkorecko merged commit eba4619 into main Jan 2, 2026
5 checks passed
@dkorecko
dkorecko deleted the fix/properly-dispose-timer branch January 2, 2026 16:58
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.

2 participants