Skip to content

fix(activity): prevent ui flicker on silent reload - #145

Merged
tkhwang merged 1 commit into
mainfrom
feat/activity-reload
Jul 7, 2026
Merged

fix(activity): prevent ui flicker on silent reload#145
tkhwang merged 1 commit into
mainfrom
feat/activity-reload

Conversation

@tkhwang

@tkhwang tkhwang commented Jul 7, 2026

Copy link
Copy Markdown
Owner
  • Introduce shouldShowLoading to control loading state visibility
  • Use loadedRangeRef to track previously loaded range for comparison
  • Skip setSelectedKey(undefined) on silent reloads to preserve user selection
  • Add test for shouldShowLoading function
  • Add test for session key stability during reloads

This change addresses the UX regression where the activity view would flicker and clear user selections during background refreshes triggered by the workspace monitor. Now, only range changes or initial loads will show the loading state and clear selections, while token-only refreshes will update data silently and maintain the selected session.

Refs: #42

Summary by CodeRabbit

  • Bug Fixes
    • Activity loading now stays silent when the same date range refreshes in the background, avoiding brief placeholder flashes.
    • Your current selection in the Activity view is preserved during silent reloads.
    • Range changes still show loading as expected.
  • Tests
    • Added coverage for loading behavior across first load, range changes, and reload-only updates.
    • Added a check to keep session keys stable when ongoing sessions extend over time.

- Introduce `shouldShowLoading` to control loading state visibility
- Use `loadedRangeRef` to track previously loaded range for comparison
- Skip `setSelectedKey(undefined)` on silent reloads to preserve user selection
- Add test for `shouldShowLoading` function
- Add test for session key stability during reloads

This change addresses the UX regression where the activity view would flicker
and clear user selections during background refreshes triggered by the
workspace monitor. Now, only range changes or initial loads will show
the loading state and clear selections, while token-only refreshes
will update data silently and maintain the selected session.

Refs: #42
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a shouldShowLoading helper and a loadedRangeRef to ActivityCalendarView so that background reloads with an unchanged date range skip the loading placeholder and preserve the selected block, while range changes still trigger loading and selection reset. Includes corresponding tests and a design plan document.

Changes

Silent reload behavior

Layer / File(s) Summary
shouldShowLoading helper and range tracking
apps/companion/src/activity/ActivityCalendarView.tsx
Adds useRef import, a shouldShowLoading(loadedRange, nextRange) helper, and a loadedRangeRef to track the previously loaded {from,to} range.
Conditional loading/selection reset in load effect
apps/companion/src/activity/ActivityCalendarView.tsx
Updates the load effect to compute showLoading, conditionally set loading, update loadedRangeRef.current after success, and reset selectedKey only when showLoading is true.
Tests for shouldShowLoading and session key stability
apps/companion/tests/activity-calendar.test.tsx
Adds tests for initial load, range change, and token-only reload scenarios for shouldShowLoading, plus a sessionsFromEvents test confirming session key stability across reloads.
Design plan documentation
docs/plans/0042-companion-activity-silent-reload.md
Documents the root cause, policy decision, task plan, compatibility constraints, and verification log for the change.

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

Sequence Diagram(s)

sequenceDiagram
  participant WorkspaceMonitor
  participant ActivityCalendarView
  participant shouldShowLoading

  WorkspaceMonitor->>ActivityCalendarView: reload token increment
  ActivityCalendarView->>shouldShowLoading: loadedRangeRef.current, loadRange
  shouldShowLoading-->>ActivityCalendarView: showLoading boolean
  alt showLoading true (range changed)
    ActivityCalendarView->>ActivityCalendarView: setLoading(true)
    ActivityCalendarView->>ActivityCalendarView: setSelectedKey(undefined)
  else showLoading false (same range)
    ActivityCalendarView->>ActivityCalendarView: keep loading state and selection
  end
  ActivityCalendarView->>ActivityCalendarView: update loadedRangeRef.current
Loading

Related PRs: None mentioned.

Suggested labels: companion, bugfix

Suggested reviewers: None determined from provided context.

🐰 A calendar block, once picked, stays true,
no flicker of loading when nothing's new,
a ref remembers the range it saw,
silent reloads now follow the law,
hop on, dear session — your key stays with you.

🚥 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 clearly matches the main UX fix: suppressing flicker during silent activity reloads.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/activity-reload

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.

Caution

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

⚠️ Outside diff range comments (1)
apps/companion/src/activity/ActivityCalendarView.tsx (1)

353-383: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep background reload failures non-destructive. In apps/companion/src/activity/ActivityCalendarView.tsx, the catch path still does setError(...) and setEvents([]) even when showLoading is false, so a token-only refresh failure clears the current calendar and drops into the error branch. Only clear the view when the reload is actually taking over the screen, or surface the error without discarding the existing events.

🤖 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 `@apps/companion/src/activity/ActivityCalendarView.tsx` around lines 353 - 383,
The reload handling in ActivityCalendarView should not clear the current
calendar on background refresh failures. In the loadEvents promise chain, adjust
the catch path so that when showLoading is false it does not call setEvents([]),
and only sets the error state or clears the view when the refresh is actually
replacing the screen. Use the existing showLoading flag, loadEvents, and
setError/setEvents logic to keep token-only refresh failures non-destructive.
🧹 Nitpick comments (1)
apps/companion/tests/activity-calendar.test.tsx (1)

314-339: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add coverage for silent-reload failure behavior.

Given the catch handling in ActivityCalendarView.tsx currently clears events regardless of showLoading (see companion comment on that file), a test simulating a token-only reload where loadEvents rejects would catch that regression and guard the intended silent-reload UX going forward.

🤖 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 `@apps/companion/tests/activity-calendar.test.tsx` around lines 314 - 339, Add
a test that covers the silent-reload failure path in
shouldShowLoading/ActivityCalendarView by simulating a reload where only the
reload token changes for the same visible range and loadEvents rejects. Verify
the component does not clear existing events or fall back to the loading
placeholder in this token-only reload case, so the catch behavior in
ActivityCalendarView.tsx is guarded against regressing the silent-reload UX.
🤖 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.

Outside diff comments:
In `@apps/companion/src/activity/ActivityCalendarView.tsx`:
- Around line 353-383: The reload handling in ActivityCalendarView should not
clear the current calendar on background refresh failures. In the loadEvents
promise chain, adjust the catch path so that when showLoading is false it does
not call setEvents([]), and only sets the error state or clears the view when
the refresh is actually replacing the screen. Use the existing showLoading flag,
loadEvents, and setError/setEvents logic to keep token-only refresh failures
non-destructive.

---

Nitpick comments:
In `@apps/companion/tests/activity-calendar.test.tsx`:
- Around line 314-339: Add a test that covers the silent-reload failure path in
shouldShowLoading/ActivityCalendarView by simulating a reload where only the
reload token changes for the same visible range and loadEvents rejects. Verify
the component does not clear existing events or fall back to the loading
placeholder in this token-only reload case, so the catch behavior in
ActivityCalendarView.tsx is guarded against regressing the silent-reload UX.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e8c31098-5ff8-4baf-a9d4-d2a632cdb4b2

📥 Commits

Reviewing files that changed from the base of the PR and between 2ca9759 and 0b3814e.

📒 Files selected for processing (3)
  • apps/companion/src/activity/ActivityCalendarView.tsx
  • apps/companion/tests/activity-calendar.test.tsx
  • docs/plans/0042-companion-activity-silent-reload.md

@tkhwang
tkhwang merged commit d54d87d into main Jul 7, 2026
4 checks passed
@tkhwang
tkhwang deleted the feat/activity-reload branch July 7, 2026 04:54
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.

1 participant