Skip to content

fix(staged): eliminate timeline flash and animation on project switch#651

Merged
matt2e merged 7 commits intomainfrom
timeline-reloading-on-every-project-switch
Apr 22, 2026
Merged

fix(staged): eliminate timeline flash and animation on project switch#651
matt2e merged 7 commits intomainfrom
timeline-reloading-on-every-project-switch

Conversation

@matt2e
Copy link
Copy Markdown
Contributor

@matt2e matt2e commented Apr 22, 2026

Summary

  • Synchronously hydrate timeline from cache on component remount (e.g. project switch) so the "Looking for changes…" spinner and slide-in animation are never shown for already-cached branches
  • Extract applyCachedTimeline helper to deduplicate cache hydration logic between the synchronous path and loadTimeline()
  • Guard revalidation callbacks with a version counter to discard stale responses

Test plan

  • Switch between projects with cached branches and verify no timeline flash or animation occurs
  • Verify fresh data still loads via revalidation after the cached data is shown
  • Verify branches without cached data still show the loading spinner as before

🤖 Generated with Claude Code

matt2e and others added 3 commits April 22, 2026 17:18
Synchronously hydrate BranchCard timeline state from the module-level
cache during component initialization, before the first render. This
prevents the "Looking for changes…" flash and slide-in animation that
occurred on every project switch because Svelte destroyed and re-created
BranchCard components, resetting timeline to null.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ache hydration

Extract the cache-apply-and-revalidate logic that was duplicated between
the synchronous hydration block and the isInitialLoad path in
loadTimeline() into a shared applyCachedTimeline() helper.

Both call sites now delegate to the same function, eliminating the risk
of the two paths diverging over time. The version-guard semantics are
preserved: applyCachedTimeline uses ++revalidationVersion (pre-increment)
to both bump and capture the version in a single expression, while
loadTimeline() still does its own revalidationVersion++ beforehand to
cancel any prior in-flight revalidation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Change applyCachedTimeline param type from `undefined` to `null` to match
  getBranchTimelineWithRevalidation return type
- Wrap synchronous cache hydration in untrack() since it intentionally reads
  initial prop values only

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@matt2e matt2e requested review from baxen and wesbillman as code owners April 22, 2026 07:51
matt2e and others added 4 commits April 22, 2026 22:03
…he hydration

Read $derived values (isLocal, isRemote, branch, remoteWorkspaceStatus)
into local variables before the untrack() callback so Svelte no longer
warns about capturing initial values of reactive state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…in BranchCard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…key logic

Extract the "is this branch timeline-ready and what's its cache key"
logic into a shared getTimelineKey() helper used by both the synchronous
hydration block and the $effect that triggers loadTimeline(). This
eliminates the risk of the two sites diverging in readiness conditions
or key format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The WorkspaceStatus type is `string | null`, not `string | undefined`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@matt2e matt2e merged commit a823569 into main Apr 22, 2026
5 checks passed
@matt2e matt2e deleted the timeline-reloading-on-every-project-switch branch April 22, 2026 23:14
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