Skip to content

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

Open
matt2e wants to merge 7 commits intomainfrom
timeline-reloading-on-every-project-switch
Open

fix(staged): eliminate timeline flash and animation on project switch#651
matt2e wants to merge 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) <[email protected]>
…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) <[email protected]>
- 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) <[email protected]>
@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) <[email protected]>
…in BranchCard

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…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) <[email protected]>
The WorkspaceStatus type is `string | null`, not `string | undefined`.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
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