@@ -40,6 +40,7 @@ import {
4040} from "@/features/tasks/hooks/useMessagingMode" ;
4141import { taskKeys } from "@/features/tasks/hooks/useTasks" ;
4242import {
43+ type MoveDirection ,
4344 type QueuedMessage ,
4445 useMessageQueueStore ,
4546} from "@/features/tasks/stores/messageQueueStore" ;
@@ -109,6 +110,7 @@ export default function TaskDetailScreen() {
109110 getSessionForTask,
110111 setFocusedTaskId,
111112 steerQueuedMessage,
113+ flushQueuedMessagesIfIdle,
112114 stopRun,
113115 } = useTaskSessionStore ( ) ;
114116
@@ -174,6 +176,9 @@ export default function TaskDetailScreen() {
174176
175177 const messagingMode = useMessagingMode ( taskId ) ;
176178 const queuedCount = useQueuedCount ( taskId ) ;
179+ const editingQueuedId = useMessageQueueStore ( ( s ) =>
180+ taskId ? s . editingByTaskId [ taskId ] : undefined ,
181+ ) ;
177182 const toggleMessagingMode = useToggleMessagingMode ( taskId ) ;
178183 const analytics = useAnalytics ( ) ;
179184
@@ -359,6 +364,18 @@ export default function TaskDetailScreen() {
359364 if ( ! taskId ) return ;
360365 Haptics . impactAsync ( Haptics . ImpactFeedbackStyle . Light ) ;
361366
367+ // Saving an in-place edit: overwrite the queued message and release the
368+ // drain hold. If the turn already ended while editing, flush now — the
369+ // turn-end drain won't fire again on its own.
370+ const queue = useMessageQueueStore . getState ( ) ;
371+ const editingId = queue . editingByTaskId [ taskId ] ;
372+ if ( editingId ) {
373+ queue . update ( taskId , editingId , { content : text , attachments } ) ;
374+ queue . clearEditing ( taskId ) ;
375+ flushQueuedMessagesIfIdle ( taskId ) ;
376+ return ;
377+ }
378+
362379 if ( session ?. terminalStatus ) {
363380 handleSendAfterTerminal ( text , attachments ) ;
364381 return ;
@@ -398,6 +415,7 @@ export default function TaskDetailScreen() {
398415 messagingMode ,
399416 handleSendAfterTerminal ,
400417 trackPromptSent ,
418+ flushQueuedMessagesIfIdle ,
401419 ] ,
402420 ) ;
403421
@@ -422,10 +440,13 @@ export default function TaskDetailScreen() {
422440 [ taskId , steerQueuedMessage , trackPromptSent ] ,
423441 ) ;
424442
425- const handleReturnQueuedToComposer = useCallback (
443+ // Pull a queued message into the composer for an in-place edit. It stays in
444+ // the queue at its position (marked as the edit target); the next send saves
445+ // it back rather than sending a new prompt.
446+ const handleEditQueued = useCallback (
426447 ( message : QueuedMessage ) => {
427448 if ( ! taskId ) return ;
428- useMessageQueueStore . getState ( ) . remove ( taskId , message . id ) ;
449+ useMessageQueueStore . getState ( ) . setEditing ( taskId , message . id ) ;
429450 setRestoredDraft ( {
430451 text : message . content ,
431452 attachments : message . attachments ,
@@ -434,10 +455,29 @@ export default function TaskDetailScreen() {
434455 [ taskId ] ,
435456 ) ;
436457
458+ const handleCancelEdit = useCallback ( ( ) => {
459+ if ( ! taskId ) return ;
460+ useMessageQueueStore . getState ( ) . clearEditing ( taskId ) ;
461+ setRestoredDraft ( { text : "" , attachments : [ ] } ) ;
462+ flushQueuedMessagesIfIdle ( taskId ) ;
463+ } , [ taskId , flushQueuedMessagesIfIdle ] ) ;
464+
465+ const handleMoveQueued = useCallback (
466+ ( message : QueuedMessage , direction : MoveDirection ) => {
467+ if ( ! taskId ) return ;
468+ Haptics . selectionAsync ( ) ;
469+ useMessageQueueStore . getState ( ) . move ( taskId , message . id , direction ) ;
470+ } ,
471+ [ taskId ] ,
472+ ) ;
473+
437474 const handleDiscardQueued = useCallback (
438475 ( message : QueuedMessage ) => {
439476 if ( ! taskId ) return ;
477+ const wasEditing =
478+ useMessageQueueStore . getState ( ) . editingByTaskId [ taskId ] === message . id ;
440479 useMessageQueueStore . getState ( ) . remove ( taskId , message . id ) ;
480+ if ( wasEditing ) setRestoredDraft ( { text : "" , attachments : [ ] } ) ;
441481 } ,
442482 [ taskId ] ,
443483 ) ;
@@ -718,13 +758,16 @@ export default function TaskDetailScreen() {
718758 ! session ?. terminalStatus
719759 }
720760 onSteer = { handleSteerQueued }
721- onReturnToComposer = { handleReturnQueuedToComposer }
761+ onEdit = { handleEditQueued }
722762 onDiscard = { handleDiscardQueued }
763+ onMove = { handleMoveQueued }
723764 />
724765 ) : null }
725766 < TaskChatComposer
726767 onSend = { handleSendPrompt }
727768 restoredDraft = { restoredDraft }
769+ editing = { ! ! editingQueuedId }
770+ onCancelEdit = { handleCancelEdit }
728771 onStop = { handleStop }
729772 isUserTurn = { ! ( session ?. isPromptPending ?? true ) }
730773 placeholder = {
0 commit comments