feat: inline user message editing in timeline (with image)#1683
feat: inline user message editing in timeline (with image)#1683ChrisLally wants to merge 1 commit intopingdotgg:mainfrom
Conversation
|
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 Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
| async () => {}, | ||
| ); | ||
|
|
||
| submitEditUserMessageFnRef.current = async (message: TimelineUserChatMessage) => { |
There was a problem hiding this comment.
🟢 Low components/ChatView.tsx:3035
When a user starts editing message B while message A's edit submission is in progress, submitEditUserMessageFnRef.current awaits waitForThreadMessageRemoval and submitComposerTurn, then calls discardUserMessageEditSession() at line 3064. This clears the edit state for message B even though B was edited after A's submission started, causing the in-progress edit UI for B to disappear unexpectedly.
🤖 Copy this AI Prompt to have your agent fix this:
In file apps/web/src/components/ChatView.tsx around line 3035:
When a user starts editing message B while message A's edit submission is in progress, `submitEditUserMessageFnRef.current` awaits `waitForThreadMessageRemoval` and `submitComposerTurn`, then calls `discardUserMessageEditSession()` at line 3064. This clears the edit state for message B even though B was edited after A's submission started, causing the in-progress edit UI for B to disappear unexpectedly.
Evidence trail:
ChatView.tsx:3030-3066 (submitEditUserMessageFnRef.current function that performs async operations then calls discardUserMessageEditSession without session check), ChatView.tsx:504-515 (discardUserMessageEditSession definition that unconditionally clears all edit state), ChatView.tsx:3146-3164 (onStartEditUserMessage that shows session tracking mechanism exists but is not used in submit flow)
ApprovabilityVerdict: Needs human review This PR adds a new feature allowing users to edit messages inline in the chat timeline with image support. It introduces significant new UI components, state management, and modifies the core message submission flow. New user-facing features of this scope warrant human review. You can customize Macroscope's approvability policy. Learn more. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| .catch(() => undefined); | ||
| } | ||
| if ( | ||
| clearComposerDraft && |
There was a problem hiding this comment.
Failed edit-send leaves orphaned optimistic message in timeline
Medium Severity
When the edit-send flow calls submitComposerTurn with clearComposerDraft: false and the turn start fails, the optimistic message added at line 2814 is never removed. The entire error-recovery block (removing the optimistic message and restoring the composer draft) is gated on clearComposerDraft, but only the draft-restoration part needs that gate. Since the revert already succeeded irreversibly, the user is left with a persistent ghost message in the timeline that no existing cleanup mechanism will remove (the server-sync effect only cleans up messages the server acknowledges, and the thread-change effect only runs on navigation).


What changed
submitComposerTurn+clearComposerDraftfor normal vs edit resend.Why
UI changes
Order of assets:
Before
After
Demo (video)
download.mp4
Checklist
Credits
Inspiration and reference implementation: pingdotgg/t3code#346 — feat: Add inline user message editing (@6crucified). That PR established the core UX and mechanics (inline bubble editor, silent revert, wait for the old message row to disappear, then resend; shared send helper with a flag to preserve vs clear the composer; image attachment handling in the editor).
This change cleans up and adapts that approach for the current codebase:
MessagesTimeline(instead of a monolithicChatViewbubble), the present composer/send pipeline (submitComposerTurn, terminal context handling,deriveDisplayedUserMessageStatefor editable text), and updated tests/harness.Note
Medium Risk
Adds a new edit→silent revert→resend flow that coordinates UI state with thread checkpoint reverts and store synchronization, so timing/edge cases could cause message duplication, lost edits, or leaked blob URLs. Changes are mostly UI/state management but touch the send/revert pipeline.
Overview
Adds inline editing for revert-eligible user messages directly in the timeline, including a textarea editor, image add/remove (file picker + paste), and keyboard shortcuts (Esc cancel, Ctrl/Cmd+Enter send).
Implements an edit resend flow that silently reverts the thread to the message’s checkpoint, waits (with timeout) for the original message to be removed from the store, then re-sends the edited content while leaving the main composer draft untouched via a shared
submitComposerTurnhelper.Introduces new helpers in
ChatView.logic.tsfor store-sync waiting (waitForThreadMessageRemoval) and reconstructing image attachments for editing (materializeMessageImageAttachmentForEdit), and wires new edit-related props throughMessagesTimelinetests and virtualization harness.Written by Cursor Bugbot for commit 7c2f359. This will update automatically on new commits. Configure here.
Note
Add inline editing of user messages with image support in the chat timeline
onRevertToTurnCountis now async and accepts anoptions.confirmflag to skip the confirmation dialog; it returns a boolean indicating success.📊 Macroscope summarized 7c2f359. 5 files reviewed, 2 issues evaluated, 0 issues filtered, 1 comment posted
🗂️ Filtered Issues