Preserve the thread shell while detail loads - #4830
Conversation
- Render a stable loading shell with available project and thread metadata - Add coverage for populated and generic loading states
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
ApprovabilityVerdict: Needs human review This PR introduces new loading state behavior for thread shells and has an unresolved review comment identifying a potential bug where errors during the loading window may be written to the wrong error store, causing error banners to not display correctly. You can customize Macroscope's approvability policy. Learn more. |
- Keep thread metadata visible during message loading - Show sync status and disable composer until details are ready
Dismissing prior approval to re-evaluate 7dd91b5
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
Bugbot Autofix is ON, but a cloud agent failed to start.
Reviewed by Cursor Bugbot for commit 7dd91b5. Configure here.
| const activeThread = activeServerThread ?? localDraftThread; | ||
| const threadError = isServerThread | ||
| ? (localServerError ?? serverThread?.session?.lastError ?? null) | ||
| ? (localServerError ?? activeServerThread?.session?.lastError ?? null) |
There was a problem hiding this comment.
Loading errors use draft store
Medium Severity
While thread detail is loading, activeServerThread/isServerThread can be satisfied by loadingServerThread, but setThreadError still only writes server errors when serverThread is non-null. Failures during that window go to the draft error map, while threadError reads localServerErrorsByThreadKey, so error banners may not appear on the server thread route.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7dd91b5. Configure here.
- Treat the loading thread shell as the active server thread - Preserve error state across thread promotion and add focused coverage
## What's Changed * Simplify files panel header by @juliusmarminge in pingdotgg/t3code#4828 * build(desktop): reduce installed app size by ~300MB by @wukko in pingdotgg/t3code#4824 * Update model version from claude-opus-4-8 to claude-opus-5 by @juliusmarminge in pingdotgg/t3code#4832 * Preserve the thread shell while detail loads by @juliusmarminge in pingdotgg/t3code#4830 * Reduce idle work and disk churn with native resource diagnostics by @juliusmarminge in pingdotgg/t3code#2679 ## New Contributors * @wukko made their first contribution in pingdotgg/t3code#4824 **Full Changelog**: pingdotgg/t3code@v0.0.31-nightly.20260729.944...v0.0.31-nightly.20260729.946 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.31-nightly.20260729.946
Brings in 20 upstream commits including native resource diagnostics (pingdotgg#2679), event-driven Git ref invalidation (pingdotgg#4727), 300MB installer size reduction (pingdotgg#4824), thread-shell preservation while detail loads (pingdotgg#4830), HTTP compression, and the v0.0.30 release prep. Merge resolutions of note: - vcs.ts / ProcessDiagnostics / EventNdjsonLogger: upstream superseded our polling-interval, WMI, and log-batching fixes with better implementations - build-desktop-artifact: kept fork artifact naming + bundled Codex plugin extraResource on top of upstream's size optimizations - ChatView/ChatComposer: both feature sets kept (send-morph/reveal/hydration + thread-shell loading, sendDisabledReason, ThreadSyncStatusPill) - RpcAuthorization: added fork-only shell.revealPath scope - AGENTS.md: kept fork operational rules, took upstream's product sections - ProjectionPipeline: expiry timestamps via DateTime.nowUnsafe (wall clock) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>


What Changed
Why
Opening a thread could temporarily lose the chat layout while its detail snapshot was loading. This keeps the surrounding chat chrome visible, reduces visual disruption, and avoids continuously repainting loading animations.
UI Changes
The thread route now shows a stable header, message placeholders, and composer shell while content loads. Before/after screenshots are not included.
Checklist
Note
Low Risk
UI and loading-state gating only; no auth, persistence, or send-path protocol changes beyond blocking send until detail loads.
Overview
Preserves the chat layout while thread detail is still loading by rendering
ChatViewwhen the route is in a shell-onlyloadingstate, instead of showing a blank view until the detail snapshot arrives.The route computes
threadSyncPhase(loading/syncing/ none) from shell vs detail presence and environment thread status, passes it intoChatView, and shows a staticThreadSyncStatusPill(“Loading messages…” / “Syncing messages…”). While detail is loading,buildLoadingThreadFromShellsupplies anactiveServerThreadwith empty messages so metadata and chrome stay visible; the timeline hides the empty placeholder,onSendis blocked, and the composer getssendDisabledReason(“Messages loading”) wired throughComposerPrimaryActions(disabled state + aria-label).shouldWriteThreadErrorToCurrentServerThreadnow keys offactiveServerThreadso local errors still attach during the shell-derived loading phase. Tests cover shell→thread mapping, sync phase resolution, the status pill, and updated error-write behavior.Reviewed by Cursor Bugbot for commit 145f427. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Preserve the thread shell while detail loads in ChatView
ChatViewearlier when only aThreadShellis available, using a newbuildLoadingThreadFromShellutil to construct a minimalThreadwith empty message/plan/activity collections.resolveThreadSyncPhaseandthreadSyncLabelin threadSync.ts to derive'loading'or'syncing'states from shell/detail presence and thread status.ThreadSyncStatusPillcomponent during loading/syncing phases and hides the empty thread placeholder.'Messages loading'reason (surfaced viaaria-label) while thread detail is loading.Macroscope summarized 145f427.