fix(web): resume an in-progress draft when returning to the index - #7422
sideeffffect wants to merge 3 commits into
Conversation
Typing into a new conversation, visiting another thread, then coming back to the "/" landing dropped the user on a blank composer: the landing always started a fresh draft in the most-recently-active project (ranked by server threads, which ignores unsent drafts), so an in-progress draft in a different project was left parked in the sidebar instead of reopened. The typed text was not destroyed, but "come back and it's blank" reads as losing work. Make the index landing resume the most-recent draft the user has actually invested content in (across projects) before falling back to a fresh draft. Explicit new-thread surfaces (the "+" buttons, hotkeys, palette) still mint fresh, so this only changes the "return home" path. Adds getMostRecentDraftSessionWithContent to the composer draft store, with unit coverage. Claude Opus 4.8 via Claude Code. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review. 📝 WalkthroughWalkthroughThe composer draft store now selects the newest draft with user content. The chat index route resumes that draft when its project exists, and tests cover selection across projects and empty drafts. ChangesDraft session resume
Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The landing page now resumes the newest content-bearing draft when its project exists, otherwise continuing to create a fresh draft. No concrete current-head merge-blocking risk remains. Sequence Diagram(s)sequenceDiagram
participant IndexDraftLanding
participant ComposerDraftStore
participant Projects
participant Router
IndexDraftLanding->>ComposerDraftStore: getMostRecentDraftSessionWithContent()
ComposerDraftStore-->>IndexDraftLanding: ProjectDraftSession or null
IndexDraftLanding->>Projects: verify draft project exists
Projects-->>IndexDraftLanding: matching project or no match
IndexDraftLanding->>Router: replace route with /draft/$draftId
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR introduces new user-facing navigation behavior - automatically resuming drafts with content when returning to the index instead of creating blank ones. While well-tested and scoped, this is a feature change affecting core UX rather than a simple bug fix. You can add or adjust custom eligibility rules. Learn more. |
…ersation-draft # Conflicts: # apps/web/src/routes/_chat.index.tsx
…ersation-draft # Conflicts: # apps/web/src/routes/_chat.index.tsx
Problem
Start a new conversation, type into the composer, click into another thread, then return to the
/landing (the app logo / "Go to threads"): you're dropped on a blank composer. The landing always mints a fresh draft in the most-recently-active project, and project recency is ranked by server threads — which ignores unsent drafts. So an in-progress draft that lives in a different project than the one you just visited is left parked in the sidebar instead of reopened.The text isn't destroyed (invested drafts survive and get a sidebar row, per #5777), but "I came back and my message is gone" is exactly how it reads.
Fix
Make the index landing resume the most-recent draft the user has actually invested content in (across projects) before falling back to starting a fresh draft in the most-recently-active project.
+buttons, hotkeys, command palette) are untouched and still mint fresh — this only changes the "return home" landing, where resuming unsent work is what you'd expect.getMostRecentDraftSessionWithContentto the composer draft store (non-promoted +composerDraftHasUserContent, newest bycreatedAt), with unit coverage.Verification
apps/webtypecheck, lint, andcomposerDraftStore.test.tspass (incl. two new cases: resumes the newest invested draft across projects / ignores empty sessions; returns null when nothing is invested).This is a routing/state change with no static visual; the difference is whether
/reopens your in-progress draft or a blank one. Happy to record a short before/after clip if that's preferred.Claude Opus 4.8 via Claude Code.
Note
Medium Risk
Changes default index routing and which draft opens on “return home,” though explicit new-thread entry points are unchanged and missing projects skip resume.
Overview
Visiting
/no longer always mints a blank draft in the most-recently-active project.IndexDraftLandingnow looks for a resumable in-progress draft first andreplace-navigates to/draft/$draftIdwhen that draft’s project still exists; otherwise it keeps the old behavior of starting a fresh draft in the latest project.The composer draft store gains
getMostRecentDraftSessionWithContent, which picks the newest non-promoting draft session (bycreatedAt) that has real user content viacomposerDraftHasUserContent, including across projects and ignoring empty newer sessions. Unit tests cover cross-project selection and the empty-draft case.Reviewed by Cursor Bugbot for commit 326f2d5. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Resume in-progress drafts when navigating to the index route
getMostRecentDraftSessionWithContentto the composer draft store, which returns the most recently created, non-promoting draft session that has user content across all projects.IndexDraftLandingcomponent in_chat.index.tsxto check for a resumable draft on load; if found and its project still exists, navigates to/draft/$draftIdinstead of creating a new draft.Macroscope summarized 326f2d5.
Summary by CodeRabbit
New Features
Bug Fixes